mirror of
https://github.com/ElementsProject/elements.git
synced 2026-08-14 12:43:40 +02:00
Define PAKList structure and operations
This commit is contained in:
parent
40571ab6d4
commit
378e594617
4 changed files with 217 additions and 0 deletions
|
|
@ -361,6 +361,8 @@ libbitcoin_consensus_a_SOURCES = \
|
|||
primitives/block.h \
|
||||
primitives/transaction.cpp \
|
||||
primitives/transaction.h \
|
||||
primitives/pak.cpp \
|
||||
primitives/pak.h \
|
||||
primitives/bitcoin/block.cpp \
|
||||
primitives/bitcoin/block.h \
|
||||
primitives/bitcoin/merkleblock.cpp \
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
#include <utilstrencodings.h>
|
||||
#include <crypto/common.h>
|
||||
|
||||
|
||||
bool g_con_blockheightinheader = false;
|
||||
bool g_signed_blocks = false;
|
||||
|
||||
|
|
|
|||
144
src/primitives/pak.cpp
Normal file
144
src/primitives/pak.cpp
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
// Copyright (c) 2018-2018 The Elements developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <primitives/pak.h>
|
||||
|
||||
namespace {
|
||||
|
||||
static secp256k1_context *secp256k1_ctx;
|
||||
|
||||
class CSecp256k1Init {
|
||||
public:
|
||||
CSecp256k1Init() {
|
||||
secp256k1_ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY);
|
||||
}
|
||||
~CSecp256k1Init() {
|
||||
secp256k1_context_destroy(secp256k1_ctx);
|
||||
}
|
||||
};
|
||||
static CSecp256k1Init instance_of_csecp256k1;
|
||||
}
|
||||
|
||||
CScript CPAKList::Magic()
|
||||
{
|
||||
CScript scriptPubKey;
|
||||
scriptPubKey.resize(6);
|
||||
scriptPubKey[0] = OP_RETURN;
|
||||
scriptPubKey[1] = 0x04;
|
||||
scriptPubKey[2] = 0xab;
|
||||
scriptPubKey[3] = 0x22;
|
||||
scriptPubKey[4] = 0xaa;
|
||||
scriptPubKey[5] = 0xee;
|
||||
return scriptPubKey;
|
||||
}
|
||||
|
||||
std::vector<CScript> CPAKList::GenerateCoinbasePAKCommitments() const
|
||||
{
|
||||
std::vector<CScript> commitments;
|
||||
CScript scriptPubKey = CPAKList::Magic();
|
||||
|
||||
for (unsigned int i = 0; i < m_offline_keys.size(); i++) {
|
||||
CScript scriptCommitment(scriptPubKey);
|
||||
unsigned char pubkey[33];
|
||||
size_t outputlen = 33;
|
||||
secp256k1_ec_pubkey_serialize(secp256k1_ctx, pubkey, &outputlen, &m_offline_keys[i], SECP256K1_EC_COMPRESSED);
|
||||
assert(outputlen == 33);
|
||||
scriptCommitment << std::vector<unsigned char>(pubkey, pubkey+outputlen);
|
||||
secp256k1_ec_pubkey_serialize(secp256k1_ctx, pubkey, &outputlen, &m_online_keys[i], SECP256K1_EC_COMPRESSED);
|
||||
assert(outputlen == 33);
|
||||
scriptCommitment << std::vector<unsigned char>(pubkey, pubkey+outputlen);
|
||||
commitments.push_back(scriptCommitment);
|
||||
}
|
||||
|
||||
return commitments;
|
||||
}
|
||||
|
||||
std::vector<CScript> CPAKList::GenerateCoinbasePAKReject() const
|
||||
{
|
||||
CScript scriptPubKey = CPAKList::Magic();
|
||||
|
||||
std::vector<unsigned char> reject;
|
||||
reject.push_back('R');
|
||||
reject.push_back('E');
|
||||
reject.push_back('J');
|
||||
reject.push_back('E');
|
||||
reject.push_back('C');
|
||||
reject.push_back('T');
|
||||
|
||||
scriptPubKey << reject;
|
||||
|
||||
std::vector<CScript> commitment;
|
||||
commitment.push_back(scriptPubKey);
|
||||
return commitment;
|
||||
}
|
||||
|
||||
void CPAKList::CreateCommitments(std::vector<CScript> &commitments) const
|
||||
{
|
||||
if(reject) {
|
||||
commitments = GenerateCoinbasePAKReject();
|
||||
} else {
|
||||
commitments = GenerateCoinbasePAKCommitments();
|
||||
}
|
||||
}
|
||||
|
||||
bool CPAKList::operator==(const CPAKList &other) const
|
||||
{
|
||||
if (this->reject != other.reject) {
|
||||
return false;
|
||||
} else if (this->m_offline_keys.size() != other.m_offline_keys.size()) {
|
||||
return false;
|
||||
} else {
|
||||
for (unsigned int i = 0; i < this->m_offline_keys.size(); i++) {
|
||||
if (memcmp(&this->m_offline_keys[i], &other.m_offline_keys[i], sizeof(secp256k1_pubkey)) != 0 ||
|
||||
memcmp(&this->m_online_keys[i], &other.m_online_keys[i], sizeof(secp256k1_pubkey)) != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CPAKList::FromBytes(CPAKList &paklist, std::vector<std::vector<unsigned char> >& offline_keys_bytes, std::vector<std::vector<unsigned char> >& online_keys_bytes, bool is_reject)
|
||||
{
|
||||
if(offline_keys_bytes.size() != online_keys_bytes.size()
|
||||
|| offline_keys_bytes.size() > SECP256K1_WHITELIST_MAX_N_KEYS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<secp256k1_pubkey> offline_keys;
|
||||
std::vector<secp256k1_pubkey> online_keys;
|
||||
for (unsigned int i = 0; i < offline_keys_bytes.size(); i++) {
|
||||
secp256k1_pubkey pubkey1;
|
||||
secp256k1_pubkey pubkey2;
|
||||
int ret1 = secp256k1_ec_pubkey_parse(secp256k1_ctx, &pubkey1, &offline_keys_bytes[i][0], offline_keys_bytes[i].size());
|
||||
int ret2 = secp256k1_ec_pubkey_parse(secp256k1_ctx, &pubkey2, &online_keys_bytes[i][0], online_keys_bytes[i].size());
|
||||
|
||||
if (ret1 != 1 || ret2 != 1) {
|
||||
return false;
|
||||
}
|
||||
offline_keys.push_back(pubkey1);
|
||||
online_keys.push_back(pubkey2);
|
||||
}
|
||||
|
||||
paklist = CPAKList(offline_keys, online_keys, is_reject);
|
||||
return true;
|
||||
}
|
||||
|
||||
void CPAKList::ToBytes(std::vector<std::vector<unsigned char> >& offline_keys, std::vector<std::vector<unsigned char> >& online_keys, bool &is_reject) const
|
||||
{
|
||||
offline_keys.resize(0);
|
||||
online_keys.resize(0);
|
||||
|
||||
for (unsigned int i = 0; i < m_offline_keys.size(); i++) {
|
||||
unsigned char pubkey[33];
|
||||
size_t outputlen = 33;
|
||||
secp256k1_ec_pubkey_serialize(secp256k1_ctx, pubkey, &outputlen, &m_offline_keys[i], SECP256K1_EC_COMPRESSED);
|
||||
offline_keys.push_back(std::vector<unsigned char>(pubkey, pubkey+outputlen));
|
||||
secp256k1_ec_pubkey_serialize(secp256k1_ctx, pubkey, &outputlen, &m_online_keys[i], SECP256K1_EC_COMPRESSED);
|
||||
online_keys.push_back(std::vector<unsigned char>(pubkey, pubkey+outputlen));
|
||||
}
|
||||
is_reject = reject;
|
||||
}
|
||||
|
||||
|
||||
70
src/primitives/pak.h
Normal file
70
src/primitives/pak.h
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
// Copyright (c) 2018-2018 The Elements developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_PRIMITIVES_PAK_H
|
||||
#define BITCOIN_PRIMITIVES_PAK_H
|
||||
|
||||
#include <script/script.h>
|
||||
#include <secp256k1/include/secp256k1_whitelist.h>
|
||||
|
||||
class CPAKList
|
||||
{
|
||||
private:
|
||||
std::vector<secp256k1_pubkey> m_offline_keys;
|
||||
std::vector<secp256k1_pubkey> m_online_keys;
|
||||
bool reject;
|
||||
|
||||
std::vector<CScript> GenerateCoinbasePAKCommitments() const;
|
||||
std::vector<CScript> GenerateCoinbasePAKReject() const;
|
||||
|
||||
public:
|
||||
CPAKList()
|
||||
{
|
||||
reject = true;
|
||||
}
|
||||
/**
|
||||
* Creates a new CPAKList. Requires that the number of offline keys is the same as the number of online keys
|
||||
* and that this number is not larger than SECP256K1_WHITELIST_MAX_N_KEYS.
|
||||
*/
|
||||
CPAKList(std::vector<secp256k1_pubkey> offline_keys, std::vector<secp256k1_pubkey> online_keys, bool reject) :
|
||||
m_offline_keys(offline_keys), m_online_keys(online_keys), reject(reject) {
|
||||
assert(m_offline_keys.size() == m_online_keys.size());
|
||||
assert(m_offline_keys.size() <= SECP256K1_WHITELIST_MAX_N_KEYS);
|
||||
}
|
||||
|
||||
bool operator==(const CPAKList &other) const;
|
||||
bool operator!=(const CPAKList &other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
bool IsReject() const
|
||||
{
|
||||
return reject;
|
||||
}
|
||||
bool IsEmpty() const
|
||||
{
|
||||
return !reject && this->size() == 0;
|
||||
}
|
||||
std::vector<secp256k1_pubkey> OnlineKeys() const
|
||||
{
|
||||
return m_online_keys;
|
||||
}
|
||||
std::vector<secp256k1_pubkey> OfflineKeys() const
|
||||
{
|
||||
return m_offline_keys;
|
||||
}
|
||||
size_t size() const
|
||||
{
|
||||
return m_offline_keys.size();
|
||||
}
|
||||
|
||||
static CScript Magic();
|
||||
/** Produce a list of scripts to add to the coinbase to signal changes in PAK list or rejection of any pak proofs to nodes */
|
||||
void CreateCommitments(std::vector<CScript> &commitments) const;
|
||||
|
||||
static bool FromBytes(CPAKList &paklist, std::vector<std::vector<unsigned char> >& offline_keys, std::vector<std::vector<unsigned char> >& online_keys, bool is_reject);
|
||||
void ToBytes(std::vector<std::vector<unsigned char> >& offline_keys, std::vector<std::vector<unsigned char> >& online_keys, bool &is_reject) const;
|
||||
};
|
||||
|
||||
#endif // BITCOIN_PRIMITIVES_PAK_H
|
||||
Loading…
Add table
Add a link
Reference in a new issue