@@ -21,6 +21,7 @@ static constexpr uint8_t PSBT_MAGIC_BYTES[5] = {'p', 's', 'b', 't', 0xff};
21
21
// Global types
22
22
static constexpr uint8_t PSBT_GLOBAL_UNSIGNED_TX = 0x00 ;
23
23
static constexpr uint8_t PSBT_GLOBAL_VERSION = 0xFB ;
24
+ static constexpr uint8_t PSBT_GLOBAL_PROPRIETARY = 0xFC ;
24
25
25
26
// Input types
26
27
static constexpr uint8_t PSBT_IN_NON_WITNESS_UTXO = 0x00 ;
@@ -32,11 +33,13 @@ static constexpr uint8_t PSBT_IN_WITNESSSCRIPT = 0x05;
32
33
static constexpr uint8_t PSBT_IN_BIP32_DERIVATION = 0x06 ;
33
34
static constexpr uint8_t PSBT_IN_SCRIPTSIG = 0x07 ;
34
35
static constexpr uint8_t PSBT_IN_SCRIPTWITNESS = 0x08 ;
36
+ static constexpr uint8_t PSBT_IN_PROPRIETARY = 0xFC ;
35
37
36
38
// Output types
37
39
static constexpr uint8_t PSBT_OUT_REDEEMSCRIPT = 0x00 ;
38
40
static constexpr uint8_t PSBT_OUT_WITNESSSCRIPT = 0x01 ;
39
41
static constexpr uint8_t PSBT_OUT_BIP32_DERIVATION = 0x02 ;
42
+ static constexpr uint8_t PSBT_OUT_PROPRIETARY = 0xFC ;
40
43
41
44
// The separator is 0x00. Reading this in means that the unserializer can interpret it
42
45
// 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
49
52
// PSBT version number
50
53
static constexpr uint32_t PSBT_HIGHEST_VERSION = 0 ;
51
54
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
+
52
71
/* * A structure for PSBTs which contain per-input information */
53
72
struct PSBTInput
54
73
{
@@ -61,6 +80,7 @@ struct PSBTInput
61
80
std::map<CPubKey, KeyOriginInfo> hd_keypaths;
62
81
std::map<CKeyID, SigPair> partial_sigs;
63
82
std::map<std::vector<unsigned char >, std::vector<unsigned char >> unknown;
83
+ std::set<PSBTProprietary> m_proprietary;
64
84
std::optional<int > sighash_type;
65
85
66
86
bool IsNull () const ;
@@ -122,6 +142,12 @@ struct PSBTInput
122
142
SerializeToVector (s, final_script_witness.stack );
123
143
}
124
144
145
+ // Write proprietary things
146
+ for (const auto & entry : m_proprietary) {
147
+ s << entry.key ;
148
+ s << entry.value ;
149
+ }
150
+
125
151
// Write unknown things
126
152
for (auto & entry : unknown) {
127
153
s << entry.first ;
@@ -255,6 +281,20 @@ struct PSBTInput
255
281
UnserializeFromVector (s, final_script_witness.stack );
256
282
break ;
257
283
}
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
+ }
258
298
// Unknown stuff
259
299
default :
260
300
if (unknown.count (key) > 0 ) {
@@ -286,6 +326,7 @@ struct PSBTOutput
286
326
CScript witness_script;
287
327
std::map<CPubKey, KeyOriginInfo> hd_keypaths;
288
328
std::map<std::vector<unsigned char >, std::vector<unsigned char >> unknown;
329
+ std::set<PSBTProprietary> m_proprietary;
289
330
290
331
bool IsNull () const ;
291
332
void FillSignatureData (SignatureData& sigdata) const ;
@@ -310,6 +351,12 @@ struct PSBTOutput
310
351
// Write any hd keypaths
311
352
SerializeHDKeypaths (s, hd_keypaths, CompactSizeWriter (PSBT_OUT_BIP32_DERIVATION));
312
353
354
+ // Write proprietary things
355
+ for (const auto & entry : m_proprietary) {
356
+ s << entry.key ;
357
+ s << entry.value ;
358
+ }
359
+
313
360
// Write unknown things
314
361
for (auto & entry : unknown) {
315
362
s << entry.first ;
@@ -370,6 +417,20 @@ struct PSBTOutput
370
417
DeserializeHDKeypaths (s, key, hd_keypaths);
371
418
break ;
372
419
}
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
+ }
373
434
// Unknown stuff
374
435
default : {
375
436
if (unknown.count (key) > 0 ) {
@@ -403,6 +464,7 @@ struct PartiallySignedTransaction
403
464
std::vector<PSBTOutput> outputs;
404
465
std::map<std::vector<unsigned char >, std::vector<unsigned char >> unknown;
405
466
std::optional<uint32_t > m_version;
467
+ std::set<PSBTProprietary> m_proprietary;
406
468
407
469
bool IsNull () const ;
408
470
uint32_t GetVersion () const ;
@@ -442,6 +504,12 @@ struct PartiallySignedTransaction
442
504
SerializeToVector (s, *m_version);
443
505
}
444
506
507
+ // Write proprietary things
508
+ for (const auto & entry : m_proprietary) {
509
+ s << entry.key ;
510
+ s << entry.value ;
511
+ }
512
+
445
513
// Write the unknown things
446
514
for (auto & entry : unknown) {
447
515
s << entry.first ;
@@ -529,6 +597,20 @@ struct PartiallySignedTransaction
529
597
}
530
598
break ;
531
599
}
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
+ }
532
614
// Unknown stuff
533
615
default : {
534
616
if (unknown.count (key) > 0 ) {
0 commit comments