From aebe758e54802ead664a3c8b694fe0b447e01724 Mon Sep 17 00:00:00 2001 From: Andrew Chow Date: Wed, 2 Oct 2019 16:45:56 -0400 Subject: [PATCH] Implement PSBT proprietary type --- src/psbt.h | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/src/psbt.h b/src/psbt.h index 46cfaf5f97..9390b38eee 100644 --- a/src/psbt.h +++ b/src/psbt.h @@ -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; @@ -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. @@ -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 identifier; + std::vector key; + std::vector 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 { @@ -61,6 +80,7 @@ struct PSBTInput std::map hd_keypaths; std::map partial_sigs; std::map, std::vector> unknown; + std::set m_proprietary; std::optional sighash_type; bool IsNull() const; @@ -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; @@ -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) { @@ -286,6 +326,7 @@ struct PSBTOutput CScript witness_script; std::map hd_keypaths; std::map, std::vector> unknown; + std::set m_proprietary; bool IsNull() const; void FillSignatureData(SignatureData& sigdata) const; @@ -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; @@ -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) { @@ -403,6 +464,7 @@ struct PartiallySignedTransaction std::vector outputs; std::map, std::vector> unknown; std::optional m_version; + std::set m_proprietary; bool IsNull() const; uint32_t GetVersion() const; @@ -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; @@ -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) {