Skip to content

Commit 378e594

Browse files
committed
Define PAKList structure and operations
1 parent 40571ab commit 378e594

File tree

4 files changed

+217
-0
lines changed

4 files changed

+217
-0
lines changed

src/Makefile.am

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,8 @@ libbitcoin_consensus_a_SOURCES = \
361361
primitives/block.h \
362362
primitives/transaction.cpp \
363363
primitives/transaction.h \
364+
primitives/pak.cpp \
365+
primitives/pak.h \
364366
primitives/bitcoin/block.cpp \
365367
primitives/bitcoin/block.h \
366368
primitives/bitcoin/merkleblock.cpp \

src/primitives/block.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <utilstrencodings.h>
1111
#include <crypto/common.h>
1212

13+
1314
bool g_con_blockheightinheader = false;
1415
bool g_signed_blocks = false;
1516

src/primitives/pak.cpp

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
// Copyright (c) 2018-2018 The Elements developers
2+
// Distributed under the MIT software license, see the accompanying
3+
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4+
5+
#include <primitives/pak.h>
6+
7+
namespace {
8+
9+
static secp256k1_context *secp256k1_ctx;
10+
11+
class CSecp256k1Init {
12+
public:
13+
CSecp256k1Init() {
14+
secp256k1_ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY);
15+
}
16+
~CSecp256k1Init() {
17+
secp256k1_context_destroy(secp256k1_ctx);
18+
}
19+
};
20+
static CSecp256k1Init instance_of_csecp256k1;
21+
}
22+
23+
CScript CPAKList::Magic()
24+
{
25+
CScript scriptPubKey;
26+
scriptPubKey.resize(6);
27+
scriptPubKey[0] = OP_RETURN;
28+
scriptPubKey[1] = 0x04;
29+
scriptPubKey[2] = 0xab;
30+
scriptPubKey[3] = 0x22;
31+
scriptPubKey[4] = 0xaa;
32+
scriptPubKey[5] = 0xee;
33+
return scriptPubKey;
34+
}
35+
36+
std::vector<CScript> CPAKList::GenerateCoinbasePAKCommitments() const
37+
{
38+
std::vector<CScript> commitments;
39+
CScript scriptPubKey = CPAKList::Magic();
40+
41+
for (unsigned int i = 0; i < m_offline_keys.size(); i++) {
42+
CScript scriptCommitment(scriptPubKey);
43+
unsigned char pubkey[33];
44+
size_t outputlen = 33;
45+
secp256k1_ec_pubkey_serialize(secp256k1_ctx, pubkey, &outputlen, &m_offline_keys[i], SECP256K1_EC_COMPRESSED);
46+
assert(outputlen == 33);
47+
scriptCommitment << std::vector<unsigned char>(pubkey, pubkey+outputlen);
48+
secp256k1_ec_pubkey_serialize(secp256k1_ctx, pubkey, &outputlen, &m_online_keys[i], SECP256K1_EC_COMPRESSED);
49+
assert(outputlen == 33);
50+
scriptCommitment << std::vector<unsigned char>(pubkey, pubkey+outputlen);
51+
commitments.push_back(scriptCommitment);
52+
}
53+
54+
return commitments;
55+
}
56+
57+
std::vector<CScript> CPAKList::GenerateCoinbasePAKReject() const
58+
{
59+
CScript scriptPubKey = CPAKList::Magic();
60+
61+
std::vector<unsigned char> reject;
62+
reject.push_back('R');
63+
reject.push_back('E');
64+
reject.push_back('J');
65+
reject.push_back('E');
66+
reject.push_back('C');
67+
reject.push_back('T');
68+
69+
scriptPubKey << reject;
70+
71+
std::vector<CScript> commitment;
72+
commitment.push_back(scriptPubKey);
73+
return commitment;
74+
}
75+
76+
void CPAKList::CreateCommitments(std::vector<CScript> &commitments) const
77+
{
78+
if(reject) {
79+
commitments = GenerateCoinbasePAKReject();
80+
} else {
81+
commitments = GenerateCoinbasePAKCommitments();
82+
}
83+
}
84+
85+
bool CPAKList::operator==(const CPAKList &other) const
86+
{
87+
if (this->reject != other.reject) {
88+
return false;
89+
} else if (this->m_offline_keys.size() != other.m_offline_keys.size()) {
90+
return false;
91+
} else {
92+
for (unsigned int i = 0; i < this->m_offline_keys.size(); i++) {
93+
if (memcmp(&this->m_offline_keys[i], &other.m_offline_keys[i], sizeof(secp256k1_pubkey)) != 0 ||
94+
memcmp(&this->m_online_keys[i], &other.m_online_keys[i], sizeof(secp256k1_pubkey)) != 0) {
95+
return false;
96+
}
97+
}
98+
}
99+
return true;
100+
}
101+
102+
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)
103+
{
104+
if(offline_keys_bytes.size() != online_keys_bytes.size()
105+
|| offline_keys_bytes.size() > SECP256K1_WHITELIST_MAX_N_KEYS) {
106+
return false;
107+
}
108+
109+
std::vector<secp256k1_pubkey> offline_keys;
110+
std::vector<secp256k1_pubkey> online_keys;
111+
for (unsigned int i = 0; i < offline_keys_bytes.size(); i++) {
112+
secp256k1_pubkey pubkey1;
113+
secp256k1_pubkey pubkey2;
114+
int ret1 = secp256k1_ec_pubkey_parse(secp256k1_ctx, &pubkey1, &offline_keys_bytes[i][0], offline_keys_bytes[i].size());
115+
int ret2 = secp256k1_ec_pubkey_parse(secp256k1_ctx, &pubkey2, &online_keys_bytes[i][0], online_keys_bytes[i].size());
116+
117+
if (ret1 != 1 || ret2 != 1) {
118+
return false;
119+
}
120+
offline_keys.push_back(pubkey1);
121+
online_keys.push_back(pubkey2);
122+
}
123+
124+
paklist = CPAKList(offline_keys, online_keys, is_reject);
125+
return true;
126+
}
127+
128+
void CPAKList::ToBytes(std::vector<std::vector<unsigned char> >& offline_keys, std::vector<std::vector<unsigned char> >& online_keys, bool &is_reject) const
129+
{
130+
offline_keys.resize(0);
131+
online_keys.resize(0);
132+
133+
for (unsigned int i = 0; i < m_offline_keys.size(); i++) {
134+
unsigned char pubkey[33];
135+
size_t outputlen = 33;
136+
secp256k1_ec_pubkey_serialize(secp256k1_ctx, pubkey, &outputlen, &m_offline_keys[i], SECP256K1_EC_COMPRESSED);
137+
offline_keys.push_back(std::vector<unsigned char>(pubkey, pubkey+outputlen));
138+
secp256k1_ec_pubkey_serialize(secp256k1_ctx, pubkey, &outputlen, &m_online_keys[i], SECP256K1_EC_COMPRESSED);
139+
online_keys.push_back(std::vector<unsigned char>(pubkey, pubkey+outputlen));
140+
}
141+
is_reject = reject;
142+
}
143+
144+

src/primitives/pak.h

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
// Copyright (c) 2018-2018 The Elements developers
2+
// Distributed under the MIT software license, see the accompanying
3+
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4+
5+
#ifndef BITCOIN_PRIMITIVES_PAK_H
6+
#define BITCOIN_PRIMITIVES_PAK_H
7+
8+
#include <script/script.h>
9+
#include <secp256k1/include/secp256k1_whitelist.h>
10+
11+
class CPAKList
12+
{
13+
private:
14+
std::vector<secp256k1_pubkey> m_offline_keys;
15+
std::vector<secp256k1_pubkey> m_online_keys;
16+
bool reject;
17+
18+
std::vector<CScript> GenerateCoinbasePAKCommitments() const;
19+
std::vector<CScript> GenerateCoinbasePAKReject() const;
20+
21+
public:
22+
CPAKList()
23+
{
24+
reject = true;
25+
}
26+
/**
27+
* Creates a new CPAKList. Requires that the number of offline keys is the same as the number of online keys
28+
* and that this number is not larger than SECP256K1_WHITELIST_MAX_N_KEYS.
29+
*/
30+
CPAKList(std::vector<secp256k1_pubkey> offline_keys, std::vector<secp256k1_pubkey> online_keys, bool reject) :
31+
m_offline_keys(offline_keys), m_online_keys(online_keys), reject(reject) {
32+
assert(m_offline_keys.size() == m_online_keys.size());
33+
assert(m_offline_keys.size() <= SECP256K1_WHITELIST_MAX_N_KEYS);
34+
}
35+
36+
bool operator==(const CPAKList &other) const;
37+
bool operator!=(const CPAKList &other) const
38+
{
39+
return !(*this == other);
40+
}
41+
bool IsReject() const
42+
{
43+
return reject;
44+
}
45+
bool IsEmpty() const
46+
{
47+
return !reject && this->size() == 0;
48+
}
49+
std::vector<secp256k1_pubkey> OnlineKeys() const
50+
{
51+
return m_online_keys;
52+
}
53+
std::vector<secp256k1_pubkey> OfflineKeys() const
54+
{
55+
return m_offline_keys;
56+
}
57+
size_t size() const
58+
{
59+
return m_offline_keys.size();
60+
}
61+
62+
static CScript Magic();
63+
/** Produce a list of scripts to add to the coinbase to signal changes in PAK list or rejection of any pak proofs to nodes */
64+
void CreateCommitments(std::vector<CScript> &commitments) const;
65+
66+
static bool FromBytes(CPAKList &paklist, std::vector<std::vector<unsigned char> >& offline_keys, std::vector<std::vector<unsigned char> >& online_keys, bool is_reject);
67+
void ToBytes(std::vector<std::vector<unsigned char> >& offline_keys, std::vector<std::vector<unsigned char> >& online_keys, bool &is_reject) const;
68+
};
69+
70+
#endif // BITCOIN_PRIMITIVES_PAK_H

0 commit comments

Comments
 (0)