Skip to content

Commit

Permalink
Implement PSBT proprietary type
Browse files Browse the repository at this point in the history
  • Loading branch information
achow101 committed Dec 10, 2021
1 parent 10ba0b5 commit aebe758
Showing 1 changed file with 82 additions and 0 deletions.
82 changes: 82 additions & 0 deletions src/psbt.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ static constexpr uint8_t PSBT_MAGIC_BYTES[5] = {'p', 's', 'b', 't', 0xff};
// Global types
static constexpr uint8_t PSBT_GLOBAL_UNSIGNED_TX = 0x00;
static constexpr uint8_t PSBT_GLOBAL_VERSION = 0xFB;
static constexpr uint8_t PSBT_GLOBAL_PROPRIETARY = 0xFC;

// Input types
static constexpr uint8_t PSBT_IN_NON_WITNESS_UTXO = 0x00;
Expand All @@ -32,11 +33,13 @@ static constexpr uint8_t PSBT_IN_WITNESSSCRIPT = 0x05;
static constexpr uint8_t PSBT_IN_BIP32_DERIVATION = 0x06;
static constexpr uint8_t PSBT_IN_SCRIPTSIG = 0x07;
static constexpr uint8_t PSBT_IN_SCRIPTWITNESS = 0x08;
static constexpr uint8_t PSBT_IN_PROPRIETARY = 0xFC;

// Output types
static constexpr uint8_t PSBT_OUT_REDEEMSCRIPT = 0x00;
static constexpr uint8_t PSBT_OUT_WITNESSSCRIPT = 0x01;
static constexpr uint8_t PSBT_OUT_BIP32_DERIVATION = 0x02;
static constexpr uint8_t PSBT_OUT_PROPRIETARY = 0xFC;

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

/** A structure for PSBT proprietary types */
struct PSBTProprietary
{
uint64_t subtype;
std::vector<unsigned char> identifier;
std::vector<unsigned char> key;
std::vector<unsigned char> value;

bool operator<(const PSBTProprietary &b) const {
return key < b.key;
}
bool operator==(const PSBTProprietary &b) const {
return key == b.key;
}
};

/** A structure for PSBTs which contain per-input information */
struct PSBTInput
{
Expand All @@ -61,6 +80,7 @@ struct PSBTInput
std::map<CPubKey, KeyOriginInfo> hd_keypaths;
std::map<CKeyID, SigPair> partial_sigs;
std::map<std::vector<unsigned char>, std::vector<unsigned char>> unknown;
std::set<PSBTProprietary> m_proprietary;
std::optional<int> sighash_type;

bool IsNull() const;
Expand Down Expand Up @@ -122,6 +142,12 @@ struct PSBTInput
SerializeToVector(s, final_script_witness.stack);
}

// Write proprietary things
for (const auto& entry : m_proprietary) {
s << entry.key;
s << entry.value;
}

// Write unknown things
for (auto& entry : unknown) {
s << entry.first;
Expand Down Expand Up @@ -255,6 +281,20 @@ struct PSBTInput
UnserializeFromVector(s, final_script_witness.stack);
break;
}
case PSBT_IN_PROPRIETARY:
{
PSBTProprietary this_prop;
skey >> this_prop.identifier;
this_prop.subtype = ReadCompactSize(skey);
this_prop.key = key;

if (m_proprietary.count(this_prop) > 0) {
throw std::ios_base::failure("Duplicate Key, proprietary key already found");
}
s >> this_prop.value;
m_proprietary.insert(this_prop);
break;
}
// Unknown stuff
default:
if (unknown.count(key) > 0) {
Expand Down Expand Up @@ -286,6 +326,7 @@ struct PSBTOutput
CScript witness_script;
std::map<CPubKey, KeyOriginInfo> hd_keypaths;
std::map<std::vector<unsigned char>, std::vector<unsigned char>> unknown;
std::set<PSBTProprietary> m_proprietary;

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

// Write proprietary things
for (const auto& entry : m_proprietary) {
s << entry.key;
s << entry.value;
}

// Write unknown things
for (auto& entry : unknown) {
s << entry.first;
Expand Down Expand Up @@ -370,6 +417,20 @@ struct PSBTOutput
DeserializeHDKeypaths(s, key, hd_keypaths);
break;
}
case PSBT_OUT_PROPRIETARY:
{
PSBTProprietary this_prop;
skey >> this_prop.identifier;
this_prop.subtype = ReadCompactSize(skey);
this_prop.key = key;

if (m_proprietary.count(this_prop) > 0) {
throw std::ios_base::failure("Duplicate Key, proprietary key already found");
}
s >> this_prop.value;
m_proprietary.insert(this_prop);
break;
}
// Unknown stuff
default: {
if (unknown.count(key) > 0) {
Expand Down Expand Up @@ -403,6 +464,7 @@ struct PartiallySignedTransaction
std::vector<PSBTOutput> outputs;
std::map<std::vector<unsigned char>, std::vector<unsigned char>> unknown;
std::optional<uint32_t> m_version;
std::set<PSBTProprietary> m_proprietary;

bool IsNull() const;
uint32_t GetVersion() const;
Expand Down Expand Up @@ -442,6 +504,12 @@ struct PartiallySignedTransaction
SerializeToVector(s, *m_version);
}

// Write proprietary things
for (const auto& entry : m_proprietary) {
s << entry.key;
s << entry.value;
}

// Write the unknown things
for (auto& entry : unknown) {
s << entry.first;
Expand Down Expand Up @@ -529,6 +597,20 @@ struct PartiallySignedTransaction
}
break;
}
case PSBT_GLOBAL_PROPRIETARY:
{
PSBTProprietary this_prop;
skey >> this_prop.identifier;
this_prop.subtype = ReadCompactSize(skey);
this_prop.key = key;

if (m_proprietary.count(this_prop) > 0) {
throw std::ios_base::failure("Duplicate Key, proprietary key already found");
}
s >> this_prop.value;
m_proprietary.insert(this_prop);
break;
}
// Unknown stuff
default: {
if (unknown.count(key) > 0) {
Expand Down

0 comments on commit aebe758

Please sign in to comment.