Skip to content

Commit aebe758

Browse files
committed
Implement PSBT proprietary type
1 parent 10ba0b5 commit aebe758

File tree

1 file changed

+82
-0
lines changed

1 file changed

+82
-0
lines changed

src/psbt.h

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ static constexpr uint8_t PSBT_MAGIC_BYTES[5] = {'p', 's', 'b', 't', 0xff};
2121
// Global types
2222
static constexpr uint8_t PSBT_GLOBAL_UNSIGNED_TX = 0x00;
2323
static constexpr uint8_t PSBT_GLOBAL_VERSION = 0xFB;
24+
static constexpr uint8_t PSBT_GLOBAL_PROPRIETARY = 0xFC;
2425

2526
// Input types
2627
static constexpr uint8_t PSBT_IN_NON_WITNESS_UTXO = 0x00;
@@ -32,11 +33,13 @@ static constexpr uint8_t PSBT_IN_WITNESSSCRIPT = 0x05;
3233
static constexpr uint8_t PSBT_IN_BIP32_DERIVATION = 0x06;
3334
static constexpr uint8_t PSBT_IN_SCRIPTSIG = 0x07;
3435
static constexpr uint8_t PSBT_IN_SCRIPTWITNESS = 0x08;
36+
static constexpr uint8_t PSBT_IN_PROPRIETARY = 0xFC;
3537

3638
// Output types
3739
static constexpr uint8_t PSBT_OUT_REDEEMSCRIPT = 0x00;
3840
static constexpr uint8_t PSBT_OUT_WITNESSSCRIPT = 0x01;
3941
static constexpr uint8_t PSBT_OUT_BIP32_DERIVATION = 0x02;
42+
static constexpr uint8_t PSBT_OUT_PROPRIETARY = 0xFC;
4043

4144
// The separator is 0x00. Reading this in means that the unserializer can interpret it
4245
// as a 0 length key which indicates that this is the separator. The separator has no value.
@@ -49,6 +52,22 @@ const std::streamsize MAX_FILE_SIZE_PSBT = 100000000; // 100 MiB
4952
// PSBT version number
5053
static constexpr uint32_t PSBT_HIGHEST_VERSION = 0;
5154

55+
/** A structure for PSBT proprietary types */
56+
struct PSBTProprietary
57+
{
58+
uint64_t subtype;
59+
std::vector<unsigned char> identifier;
60+
std::vector<unsigned char> key;
61+
std::vector<unsigned char> value;
62+
63+
bool operator<(const PSBTProprietary &b) const {
64+
return key < b.key;
65+
}
66+
bool operator==(const PSBTProprietary &b) const {
67+
return key == b.key;
68+
}
69+
};
70+
5271
/** A structure for PSBTs which contain per-input information */
5372
struct PSBTInput
5473
{
@@ -61,6 +80,7 @@ struct PSBTInput
6180
std::map<CPubKey, KeyOriginInfo> hd_keypaths;
6281
std::map<CKeyID, SigPair> partial_sigs;
6382
std::map<std::vector<unsigned char>, std::vector<unsigned char>> unknown;
83+
std::set<PSBTProprietary> m_proprietary;
6484
std::optional<int> sighash_type;
6585

6686
bool IsNull() const;
@@ -122,6 +142,12 @@ struct PSBTInput
122142
SerializeToVector(s, final_script_witness.stack);
123143
}
124144

145+
// Write proprietary things
146+
for (const auto& entry : m_proprietary) {
147+
s << entry.key;
148+
s << entry.value;
149+
}
150+
125151
// Write unknown things
126152
for (auto& entry : unknown) {
127153
s << entry.first;
@@ -255,6 +281,20 @@ struct PSBTInput
255281
UnserializeFromVector(s, final_script_witness.stack);
256282
break;
257283
}
284+
case PSBT_IN_PROPRIETARY:
285+
{
286+
PSBTProprietary this_prop;
287+
skey >> this_prop.identifier;
288+
this_prop.subtype = ReadCompactSize(skey);
289+
this_prop.key = key;
290+
291+
if (m_proprietary.count(this_prop) > 0) {
292+
throw std::ios_base::failure("Duplicate Key, proprietary key already found");
293+
}
294+
s >> this_prop.value;
295+
m_proprietary.insert(this_prop);
296+
break;
297+
}
258298
// Unknown stuff
259299
default:
260300
if (unknown.count(key) > 0) {
@@ -286,6 +326,7 @@ struct PSBTOutput
286326
CScript witness_script;
287327
std::map<CPubKey, KeyOriginInfo> hd_keypaths;
288328
std::map<std::vector<unsigned char>, std::vector<unsigned char>> unknown;
329+
std::set<PSBTProprietary> m_proprietary;
289330

290331
bool IsNull() const;
291332
void FillSignatureData(SignatureData& sigdata) const;
@@ -310,6 +351,12 @@ struct PSBTOutput
310351
// Write any hd keypaths
311352
SerializeHDKeypaths(s, hd_keypaths, CompactSizeWriter(PSBT_OUT_BIP32_DERIVATION));
312353

354+
// Write proprietary things
355+
for (const auto& entry : m_proprietary) {
356+
s << entry.key;
357+
s << entry.value;
358+
}
359+
313360
// Write unknown things
314361
for (auto& entry : unknown) {
315362
s << entry.first;
@@ -370,6 +417,20 @@ struct PSBTOutput
370417
DeserializeHDKeypaths(s, key, hd_keypaths);
371418
break;
372419
}
420+
case PSBT_OUT_PROPRIETARY:
421+
{
422+
PSBTProprietary this_prop;
423+
skey >> this_prop.identifier;
424+
this_prop.subtype = ReadCompactSize(skey);
425+
this_prop.key = key;
426+
427+
if (m_proprietary.count(this_prop) > 0) {
428+
throw std::ios_base::failure("Duplicate Key, proprietary key already found");
429+
}
430+
s >> this_prop.value;
431+
m_proprietary.insert(this_prop);
432+
break;
433+
}
373434
// Unknown stuff
374435
default: {
375436
if (unknown.count(key) > 0) {
@@ -403,6 +464,7 @@ struct PartiallySignedTransaction
403464
std::vector<PSBTOutput> outputs;
404465
std::map<std::vector<unsigned char>, std::vector<unsigned char>> unknown;
405466
std::optional<uint32_t> m_version;
467+
std::set<PSBTProprietary> m_proprietary;
406468

407469
bool IsNull() const;
408470
uint32_t GetVersion() const;
@@ -442,6 +504,12 @@ struct PartiallySignedTransaction
442504
SerializeToVector(s, *m_version);
443505
}
444506

507+
// Write proprietary things
508+
for (const auto& entry : m_proprietary) {
509+
s << entry.key;
510+
s << entry.value;
511+
}
512+
445513
// Write the unknown things
446514
for (auto& entry : unknown) {
447515
s << entry.first;
@@ -529,6 +597,20 @@ struct PartiallySignedTransaction
529597
}
530598
break;
531599
}
600+
case PSBT_GLOBAL_PROPRIETARY:
601+
{
602+
PSBTProprietary this_prop;
603+
skey >> this_prop.identifier;
604+
this_prop.subtype = ReadCompactSize(skey);
605+
this_prop.key = key;
606+
607+
if (m_proprietary.count(this_prop) > 0) {
608+
throw std::ios_base::failure("Duplicate Key, proprietary key already found");
609+
}
610+
s >> this_prop.value;
611+
m_proprietary.insert(this_prop);
612+
break;
613+
}
532614
// Unknown stuff
533615
default: {
534616
if (unknown.count(key) > 0) {

0 commit comments

Comments
 (0)