From 4d6b5321a581548d9cdd6aea2dca56cfd96723ee Mon Sep 17 00:00:00 2001 From: Antoine Poinsot Date: Sun, 5 Dec 2021 13:07:54 +0100 Subject: [PATCH] psbt: implement hash preimages fields --- src/psbt.cpp | 4 ++ src/psbt.h | 116 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 120 insertions(+) diff --git a/src/psbt.cpp b/src/psbt.cpp index 4c9b439815..203e0a0bd3 100644 --- a/src/psbt.cpp +++ b/src/psbt.cpp @@ -153,6 +153,10 @@ void PSBTInput::Merge(const PSBTInput& input) } partial_sigs.insert(input.partial_sigs.begin(), input.partial_sigs.end()); + ripemd160_preimages.insert(input.ripemd160_preimages.begin(), input.ripemd160_preimages.end()); + sha256_preimages.insert(input.sha256_preimages.begin(), input.sha256_preimages.end()); + hash160_preimages.insert(input.hash160_preimages.begin(), input.hash160_preimages.end()); + hash256_preimages.insert(input.hash256_preimages.begin(), input.hash256_preimages.end()); hd_keypaths.insert(input.hd_keypaths.begin(), input.hd_keypaths.end()); unknown.insert(input.unknown.begin(), input.unknown.end()); diff --git a/src/psbt.h b/src/psbt.h index 690d1b3bbd..43b1b249c5 100644 --- a/src/psbt.h +++ b/src/psbt.h @@ -37,6 +37,10 @@ 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_RIPEMD160 = 0x0A; +static constexpr uint8_t PSBT_IN_SHA256 = 0x0B; +static constexpr uint8_t PSBT_IN_HASH160 = 0x0C; +static constexpr uint8_t PSBT_IN_HASH256 = 0x0D; static constexpr uint8_t PSBT_IN_PROPRIETARY = 0xFC; // Output types @@ -171,6 +175,10 @@ struct PSBTInput CScriptWitness final_script_witness; std::map hd_keypaths; std::map partial_sigs; + std::map> ripemd160_preimages; + std::map> sha256_preimages; + std::map> hash160_preimages; + std::map> hash256_preimages; std::map, std::vector> unknown; std::set m_proprietary; std::optional sighash_type; @@ -221,6 +229,30 @@ struct PSBTInput // Write any hd keypaths SerializeHDKeypaths(s, hd_keypaths, CompactSizeWriter(PSBT_IN_BIP32_DERIVATION)); + + // Write any ripemd160 preimage + for (const auto& [hash, preimage] : ripemd160_preimages) { + SerializeToVector(s, CompactSizeWriter(PSBT_IN_RIPEMD160), Span{hash}); + s << preimage; + } + + // Write any sha256 preimage + for (const auto& [hash, preimage] : sha256_preimages) { + SerializeToVector(s, CompactSizeWriter(PSBT_IN_SHA256), Span{hash}); + s << preimage; + } + + // Write any hash160 preimage + for (const auto& [hash, preimage] : hash160_preimages) { + SerializeToVector(s, CompactSizeWriter(PSBT_IN_HASH160), Span{hash}); + s << preimage; + } + + // Write any hash256 preimage + for (const auto& [hash, preimage] : hash256_preimages) { + SerializeToVector(s, CompactSizeWriter(PSBT_IN_HASH256), Span{hash}); + s << preimage; + } } // Write script sig @@ -373,6 +405,90 @@ struct PSBTInput UnserializeFromVector(s, final_script_witness.stack); break; } + case PSBT_IN_RIPEMD160: + { + // Make sure that the key is the size of a ripemd160 hash + 1 + if (key.size() != CRIPEMD160::OUTPUT_SIZE + 1) { + throw std::ios_base::failure("Size of key was not the expected size for the type ripemd160 preimage"); + } + // Read in the hash from key + std::vector hash_vec(key.begin() + 1, key.end()); + uint160 hash(hash_vec); + if (ripemd160_preimages.count(hash) > 0) { + throw std::ios_base::failure("Duplicate Key, input ripemd160 preimage already provided"); + } + + // Read in the preimage from value + std::vector preimage; + s >> preimage; + + // Add to preimages list + ripemd160_preimages.emplace(hash, std::move(preimage)); + break; + } + case PSBT_IN_SHA256: + { + // Make sure that the key is the size of a sha256 hash + 1 + if (key.size() != CSHA256::OUTPUT_SIZE + 1) { + throw std::ios_base::failure("Size of key was not the expected size for the type sha256 preimage"); + } + // Read in the hash from key + std::vector hash_vec(key.begin() + 1, key.end()); + uint256 hash(hash_vec); + if (sha256_preimages.count(hash) > 0) { + throw std::ios_base::failure("Duplicate Key, input sha256 preimage already provided"); + } + + // Read in the preimage from value + std::vector preimage; + s >> preimage; + + // Add to preimages list + sha256_preimages.emplace(hash, std::move(preimage)); + break; + } + case PSBT_IN_HASH160: + { + // Make sure that the key is the size of a hash160 hash + 1 + if (key.size() != CHash160::OUTPUT_SIZE + 1) { + throw std::ios_base::failure("Size of key was not the expected size for the type hash160 preimage"); + } + // Read in the hash from key + std::vector hash_vec(key.begin() + 1, key.end()); + uint160 hash(hash_vec); + if (hash160_preimages.count(hash) > 0) { + throw std::ios_base::failure("Duplicate Key, input hash160 preimage already provided"); + } + + // Read in the preimage from value + std::vector preimage; + s >> preimage; + + // Add to preimages list + hash160_preimages.emplace(hash, std::move(preimage)); + break; + } + case PSBT_IN_HASH256: + { + // Make sure that the key is the size of a hash256 hash + 1 + if (key.size() != CHash256::OUTPUT_SIZE + 1) { + throw std::ios_base::failure("Size of key was not the expected size for the type hash256 preimage"); + } + // Read in the hash from key + std::vector hash_vec(key.begin() + 1, key.end()); + uint256 hash(hash_vec); + if (hash256_preimages.count(hash) > 0) { + throw std::ios_base::failure("Duplicate Key, input hash256 preimage already provided"); + } + + // Read in the preimage from value + std::vector preimage; + s >> preimage; + + // Add to preimages list + hash256_preimages.emplace(hash, std::move(preimage)); + break; + } case PSBT_IN_PROPRIETARY: { PSBTProprietary this_prop;