2022-12-24 23:49:50 +00:00
// Copyright (c) 2009-2022 The Bitcoin Core developers
2019-01-09 02:06:29 -08:00
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
# ifndef BITCOIN_PSBT_H
# define BITCOIN_PSBT_H
2019-02-09 20:51:33 -08:00
# include <node/transaction.h>
2019-03-01 00:25:10 -08:00
# include <policy/feerate.h>
2019-01-09 02:06:29 -08:00
# include <primitives/transaction.h>
# include <pubkey.h>
2019-07-25 11:26:20 -04:00
# include <script/keyorigin.h>
2019-01-09 02:06:29 -08:00
# include <script/sign.h>
2019-06-06 22:52:24 +02:00
# include <script/signingprovider.h>
2019-07-25 11:26:20 -04:00
# include <span.h>
# include <streams.h>
2019-01-09 02:06:29 -08:00
2021-03-15 11:59:05 +08:00
# include <optional>
2019-01-09 02:06:29 -08:00
// Magic bytes
static constexpr uint8_t PSBT_MAGIC_BYTES [ 5 ] = { ' p ' , ' s ' , ' b ' , ' t ' , 0xff } ;
// Global types
static constexpr uint8_t PSBT_GLOBAL_UNSIGNED_TX = 0x00 ;
2019-07-25 11:58:28 -04:00
static constexpr uint8_t PSBT_GLOBAL_XPUB = 0x01 ;
2019-10-02 16:11:34 -04:00
static constexpr uint8_t PSBT_GLOBAL_VERSION = 0xFB ;
2019-10-02 16:45:56 -04:00
static constexpr uint8_t PSBT_GLOBAL_PROPRIETARY = 0xFC ;
2019-01-09 02:06:29 -08:00
// Input types
static constexpr uint8_t PSBT_IN_NON_WITNESS_UTXO = 0x00 ;
static constexpr uint8_t PSBT_IN_WITNESS_UTXO = 0x01 ;
static constexpr uint8_t PSBT_IN_PARTIAL_SIG = 0x02 ;
static constexpr uint8_t PSBT_IN_SIGHASH = 0x03 ;
static constexpr uint8_t PSBT_IN_REDEEMSCRIPT = 0x04 ;
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 ;
2021-12-05 13:07:54 +01:00
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 ;
2021-07-12 17:07:08 -04:00
static constexpr uint8_t PSBT_IN_TAP_KEY_SIG = 0x13 ;
static constexpr uint8_t PSBT_IN_TAP_SCRIPT_SIG = 0x14 ;
static constexpr uint8_t PSBT_IN_TAP_LEAF_SCRIPT = 0x15 ;
static constexpr uint8_t PSBT_IN_TAP_BIP32_DERIVATION = 0x16 ;
static constexpr uint8_t PSBT_IN_TAP_INTERNAL_KEY = 0x17 ;
static constexpr uint8_t PSBT_IN_TAP_MERKLE_ROOT = 0x18 ;
2019-10-02 16:45:56 -04:00
static constexpr uint8_t PSBT_IN_PROPRIETARY = 0xFC ;
2019-01-09 02:06:29 -08:00
// 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 ;
2021-07-12 17:07:08 -04:00
static constexpr uint8_t PSBT_OUT_TAP_INTERNAL_KEY = 0x05 ;
static constexpr uint8_t PSBT_OUT_TAP_TREE = 0x06 ;
static constexpr uint8_t PSBT_OUT_TAP_BIP32_DERIVATION = 0x07 ;
2019-10-02 16:45:56 -04:00
static constexpr uint8_t PSBT_OUT_PROPRIETARY = 0xFC ;
2019-01-09 02:06:29 -08:00
// 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.
static constexpr uint8_t PSBT_SEPARATOR = 0x00 ;
2020-03-26 11:18:52 +01:00
// BIP 174 does not specify a maximum file size, but we set a limit anyway
2020-05-27 10:15:05 -04:00
// to prevent reading a stream indefinitely and running out of memory.
2022-06-07 15:49:03 -05:00
const std : : streamsize MAX_FILE_SIZE_PSBT = 100000000 ; // 100 MB
2020-03-26 11:18:52 +01:00
2019-10-02 16:11:34 -04:00
// PSBT version number
static constexpr uint32_t PSBT_HIGHEST_VERSION = 0 ;
2019-10-02 16:45:56 -04:00
/** 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 ;
}
} ;
2019-07-25 11:26:20 -04:00
// Takes a stream and multiple arguments and serializes them as if first serialized into a vector and then into the stream
// The resulting output into the stream has the total serialized length of all of the objects followed by all objects concatenated with each other.
template < typename Stream , typename . . . X >
void SerializeToVector ( Stream & s , const X & . . . args )
{
2023-11-01 22:33:11 +10:00
SizeComputer sizecomp ;
SerializeMany ( sizecomp , args . . . ) ;
WriteCompactSize ( s , sizecomp . size ( ) ) ;
2019-07-25 11:26:20 -04:00
SerializeMany ( s , args . . . ) ;
}
// Takes a stream and multiple arguments and unserializes them first as a vector then each object individually in the order provided in the arguments
template < typename Stream , typename . . . X >
2023-09-07 19:16:57 +10:00
void UnserializeFromVector ( Stream & s , X & & . . . args )
2019-07-25 11:26:20 -04:00
{
size_t expected_size = ReadCompactSize ( s ) ;
size_t remaining_before = s . size ( ) ;
UnserializeMany ( s , args . . . ) ;
size_t remaining_after = s . size ( ) ;
if ( remaining_after + expected_size ! = remaining_before ) {
throw std : : ios_base : : failure ( " Size of value was not the stated size " ) ;
}
}
2021-07-12 15:31:12 -04:00
// Deserialize bytes of given length from the stream as a KeyOriginInfo
2019-07-25 11:32:13 -04:00
template < typename Stream >
2021-07-12 15:31:12 -04:00
KeyOriginInfo DeserializeKeyOrigin ( Stream & s , uint64_t length )
2019-07-25 11:32:13 -04:00
{
// Read in key path
2021-07-12 15:31:12 -04:00
if ( length % 4 | | length = = 0 ) {
2019-07-25 11:32:13 -04:00
throw std : : ios_base : : failure ( " Invalid length for HD key path " ) ;
}
2021-07-12 15:31:12 -04:00
KeyOriginInfo hd_keypath ;
2019-07-25 11:32:13 -04:00
s > > hd_keypath . fingerprint ;
2021-07-12 15:31:12 -04:00
for ( unsigned int i = 4 ; i < length ; i + = sizeof ( uint32_t ) ) {
2019-07-25 11:32:13 -04:00
uint32_t index ;
s > > index ;
hd_keypath . path . push_back ( index ) ;
}
2021-07-12 15:31:12 -04:00
return hd_keypath ;
}
// Deserialize a length prefixed KeyOriginInfo from a stream
template < typename Stream >
void DeserializeHDKeypath ( Stream & s , KeyOriginInfo & hd_keypath )
{
hd_keypath = DeserializeKeyOrigin ( s , ReadCompactSize ( s ) ) ;
2019-07-25 11:32:13 -04:00
}
2019-07-25 11:26:20 -04:00
// Deserialize HD keypaths into a map
template < typename Stream >
void DeserializeHDKeypaths ( Stream & s , const std : : vector < unsigned char > & key , std : : map < CPubKey , KeyOriginInfo > & hd_keypaths )
{
// Make sure that the key is the size of pubkey + 1
if ( key . size ( ) ! = CPubKey : : SIZE + 1 & & key . size ( ) ! = CPubKey : : COMPRESSED_SIZE + 1 ) {
throw std : : ios_base : : failure ( " Size of key was not the expected size for the type BIP32 keypath " ) ;
}
// Read in the pubkey from key
CPubKey pubkey ( key . begin ( ) + 1 , key . end ( ) ) ;
if ( ! pubkey . IsFullyValid ( ) ) {
throw std : : ios_base : : failure ( " Invalid pubkey " ) ;
}
if ( hd_keypaths . count ( pubkey ) > 0 ) {
throw std : : ios_base : : failure ( " Duplicate Key, pubkey derivation path already provided " ) ;
}
KeyOriginInfo keypath ;
2019-07-25 11:32:13 -04:00
DeserializeHDKeypath ( s , keypath ) ;
2019-07-25 11:26:20 -04:00
// Add to map
hd_keypaths . emplace ( pubkey , std : : move ( keypath ) ) ;
}
2021-07-12 15:31:12 -04:00
// Serialize a KeyOriginInfo to a stream
2019-07-25 11:32:13 -04:00
template < typename Stream >
2021-07-12 15:31:12 -04:00
void SerializeKeyOrigin ( Stream & s , KeyOriginInfo hd_keypath )
2019-07-25 11:32:13 -04:00
{
s < < hd_keypath . fingerprint ;
for ( const auto & path : hd_keypath . path ) {
s < < path ;
}
}
2021-07-12 15:31:12 -04:00
// Serialize a length prefixed KeyOriginInfo to a stream
template < typename Stream >
void SerializeHDKeypath ( Stream & s , KeyOriginInfo hd_keypath )
{
WriteCompactSize ( s , ( hd_keypath . path . size ( ) + 1 ) * sizeof ( uint32_t ) ) ;
SerializeKeyOrigin ( s , hd_keypath ) ;
}
2019-07-25 11:26:20 -04:00
// Serialize HD keypaths to a stream from a map
template < typename Stream >
void SerializeHDKeypaths ( Stream & s , const std : : map < CPubKey , KeyOriginInfo > & hd_keypaths , CompactSizeWriter type )
{
2022-12-16 10:53:55 +00:00
for ( const auto & keypath_pair : hd_keypaths ) {
2019-07-25 11:26:20 -04:00
if ( ! keypath_pair . first . IsValid ( ) ) {
throw std : : ios_base : : failure ( " Invalid CPubKey being serialized " ) ;
}
SerializeToVector ( s , type , Span { keypath_pair . first } ) ;
2019-07-25 11:32:13 -04:00
SerializeHDKeypath ( s , keypath_pair . second ) ;
2019-07-25 11:26:20 -04:00
}
}
2019-01-09 02:06:29 -08:00
/** A structure for PSBTs which contain per-input information */
struct PSBTInput
{
CTransactionRef non_witness_utxo ;
CTxOut witness_utxo ;
CScript redeem_script ;
CScript witness_script ;
CScript final_script_sig ;
CScriptWitness final_script_witness ;
std : : map < CPubKey , KeyOriginInfo > hd_keypaths ;
std : : map < CKeyID , SigPair > partial_sigs ;
2021-12-05 13:07:54 +01:00
std : : map < uint160 , std : : vector < unsigned char > > ripemd160_preimages ;
std : : map < uint256 , std : : vector < unsigned char > > sha256_preimages ;
std : : map < uint160 , std : : vector < unsigned char > > hash160_preimages ;
std : : map < uint256 , std : : vector < unsigned char > > hash256_preimages ;
2021-07-12 17:07:08 -04:00
// Taproot fields
std : : vector < unsigned char > m_tap_key_sig ;
std : : map < std : : pair < XOnlyPubKey , uint256 > , std : : vector < unsigned char > > m_tap_script_sigs ;
2022-08-19 10:40:28 -04:00
std : : map < std : : pair < std : : vector < unsigned char > , int > , std : : set < std : : vector < unsigned char > , ShortestVectorFirstComparator > > m_tap_scripts ;
2021-07-12 17:07:08 -04:00
std : : map < XOnlyPubKey , std : : pair < std : : set < uint256 > , KeyOriginInfo > > m_tap_bip32_paths ;
XOnlyPubKey m_tap_internal_key ;
uint256 m_tap_merkle_root ;
2019-01-09 02:06:29 -08:00
std : : map < std : : vector < unsigned char > , std : : vector < unsigned char > > unknown ;
2019-10-02 16:45:56 -04:00
std : : set < PSBTProprietary > m_proprietary ;
2021-11-15 13:54:01 -05:00
std : : optional < int > sighash_type ;
2019-01-09 02:06:29 -08:00
bool IsNull ( ) const ;
void FillSignatureData ( SignatureData & sigdata ) const ;
void FromSignatureData ( const SignatureData & sigdata ) ;
void Merge ( const PSBTInput & input ) ;
PSBTInput ( ) { }
template < typename Stream >
inline void Serialize ( Stream & s ) const {
// Write the utxo
if ( non_witness_utxo ) {
2019-10-02 15:49:33 -04:00
SerializeToVector ( s , CompactSizeWriter ( PSBT_IN_NON_WITNESS_UTXO ) ) ;
2023-09-07 19:16:57 +10:00
SerializeToVector ( s , TX_NO_WITNESS ( non_witness_utxo ) ) ;
2020-06-04 23:43:43 -04:00
}
if ( ! witness_utxo . IsNull ( ) ) {
2019-10-02 15:49:33 -04:00
SerializeToVector ( s , CompactSizeWriter ( PSBT_IN_WITNESS_UTXO ) ) ;
2019-01-09 02:06:29 -08:00
SerializeToVector ( s , witness_utxo ) ;
}
if ( final_script_sig . empty ( ) & & final_script_witness . IsNull ( ) ) {
// Write any partial signatures
for ( auto sig_pair : partial_sigs ) {
2019-10-02 15:49:33 -04:00
SerializeToVector ( s , CompactSizeWriter ( PSBT_IN_PARTIAL_SIG ) , Span { sig_pair . second . first } ) ;
2019-01-09 02:06:29 -08:00
s < < sig_pair . second . second ;
}
// Write the sighash type
2021-11-15 13:54:01 -05:00
if ( sighash_type ! = std : : nullopt ) {
2019-10-02 15:49:33 -04:00
SerializeToVector ( s , CompactSizeWriter ( PSBT_IN_SIGHASH ) ) ;
2021-11-15 13:54:01 -05:00
SerializeToVector ( s , * sighash_type ) ;
2019-01-09 02:06:29 -08:00
}
// Write the redeem script
if ( ! redeem_script . empty ( ) ) {
2019-10-02 15:49:33 -04:00
SerializeToVector ( s , CompactSizeWriter ( PSBT_IN_REDEEMSCRIPT ) ) ;
2019-01-09 02:06:29 -08:00
s < < redeem_script ;
}
// Write the witness script
if ( ! witness_script . empty ( ) ) {
2019-10-02 15:49:33 -04:00
SerializeToVector ( s , CompactSizeWriter ( PSBT_IN_WITNESSSCRIPT ) ) ;
2019-01-09 02:06:29 -08:00
s < < witness_script ;
}
// Write any hd keypaths
2019-10-02 15:49:33 -04:00
SerializeHDKeypaths ( s , hd_keypaths , CompactSizeWriter ( PSBT_IN_BIP32_DERIVATION ) ) ;
2021-12-05 13:07:54 +01:00
// 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 ;
}
2021-07-12 17:07:08 -04:00
// Write taproot key sig
if ( ! m_tap_key_sig . empty ( ) ) {
SerializeToVector ( s , PSBT_IN_TAP_KEY_SIG ) ;
s < < m_tap_key_sig ;
}
// Write taproot script sigs
for ( const auto & [ pubkey_leaf , sig ] : m_tap_script_sigs ) {
const auto & [ xonly , leaf_hash ] = pubkey_leaf ;
SerializeToVector ( s , PSBT_IN_TAP_SCRIPT_SIG , xonly , leaf_hash ) ;
s < < sig ;
}
// Write taproot leaf scripts
for ( const auto & [ leaf , control_blocks ] : m_tap_scripts ) {
const auto & [ script , leaf_ver ] = leaf ;
for ( const auto & control_block : control_blocks ) {
SerializeToVector ( s , PSBT_IN_TAP_LEAF_SCRIPT , Span { control_block } ) ;
std : : vector < unsigned char > value_v ( script . begin ( ) , script . end ( ) ) ;
value_v . push_back ( ( uint8_t ) leaf_ver ) ;
s < < value_v ;
}
}
// Write taproot bip32 keypaths
for ( const auto & [ xonly , leaf_origin ] : m_tap_bip32_paths ) {
const auto & [ leaf_hashes , origin ] = leaf_origin ;
SerializeToVector ( s , PSBT_IN_TAP_BIP32_DERIVATION , xonly ) ;
std : : vector < unsigned char > value ;
2023-11-16 12:59:43 +01:00
VectorWriter s_value { value , 0 } ;
2021-07-12 17:07:08 -04:00
s_value < < leaf_hashes ;
SerializeKeyOrigin ( s_value , origin ) ;
s < < value ;
}
// Write taproot internal key
if ( ! m_tap_internal_key . IsNull ( ) ) {
SerializeToVector ( s , PSBT_IN_TAP_INTERNAL_KEY ) ;
s < < ToByteVector ( m_tap_internal_key ) ;
}
// Write taproot merkle root
if ( ! m_tap_merkle_root . IsNull ( ) ) {
SerializeToVector ( s , PSBT_IN_TAP_MERKLE_ROOT ) ;
SerializeToVector ( s , m_tap_merkle_root ) ;
}
2019-01-09 02:06:29 -08:00
}
// Write script sig
if ( ! final_script_sig . empty ( ) ) {
2019-10-02 15:49:33 -04:00
SerializeToVector ( s , CompactSizeWriter ( PSBT_IN_SCRIPTSIG ) ) ;
2019-01-09 02:06:29 -08:00
s < < final_script_sig ;
}
// write script witness
if ( ! final_script_witness . IsNull ( ) ) {
2019-10-02 15:49:33 -04:00
SerializeToVector ( s , CompactSizeWriter ( PSBT_IN_SCRIPTWITNESS ) ) ;
2019-01-09 02:06:29 -08:00
SerializeToVector ( s , final_script_witness . stack ) ;
}
2019-10-02 16:45:56 -04:00
// Write proprietary things
for ( const auto & entry : m_proprietary ) {
s < < entry . key ;
s < < entry . value ;
}
2019-01-09 02:06:29 -08:00
// Write unknown things
for ( auto & entry : unknown ) {
s < < entry . first ;
s < < entry . second ;
}
s < < PSBT_SEPARATOR ;
}
template < typename Stream >
inline void Unserialize ( Stream & s ) {
2019-09-06 20:54:00 +02:00
// Used for duplicate key detection
std : : set < std : : vector < unsigned char > > key_lookup ;
2019-01-09 02:06:29 -08:00
// Read loop
bool found_sep = false ;
while ( ! s . empty ( ) ) {
// Read
std : : vector < unsigned char > key ;
s > > key ;
// the key is empty if that was actually a separator byte
// This is a special case for key lengths 0 as those are not allowed (except for separator)
if ( key . empty ( ) ) {
found_sep = true ;
break ;
}
2019-10-02 15:49:33 -04:00
// Type is compact size uint at beginning of key
2023-11-17 16:32:29 +01:00
SpanReader skey { key } ;
2019-10-02 15:49:33 -04:00
uint64_t type = ReadCompactSize ( skey ) ;
2019-01-09 02:06:29 -08:00
// Do stuff based on type
switch ( type ) {
case PSBT_IN_NON_WITNESS_UTXO :
{
2019-09-06 20:54:00 +02:00
if ( ! key_lookup . emplace ( key ) . second ) {
2019-01-09 02:06:29 -08:00
throw std : : ios_base : : failure ( " Duplicate Key, input non-witness utxo already provided " ) ;
} else if ( key . size ( ) ! = 1 ) {
throw std : : ios_base : : failure ( " Non-witness utxo key is more than one byte type " ) ;
}
// Set the stream to unserialize with witness since this is always a valid network transaction
2023-09-07 19:16:57 +10:00
UnserializeFromVector ( s , TX_WITH_WITNESS ( non_witness_utxo ) ) ;
2019-01-09 02:06:29 -08:00
break ;
}
case PSBT_IN_WITNESS_UTXO :
2019-09-06 20:54:00 +02:00
if ( ! key_lookup . emplace ( key ) . second ) {
2019-01-09 02:06:29 -08:00
throw std : : ios_base : : failure ( " Duplicate Key, input witness utxo already provided " ) ;
} else if ( key . size ( ) ! = 1 ) {
throw std : : ios_base : : failure ( " Witness utxo key is more than one byte type " ) ;
}
UnserializeFromVector ( s , witness_utxo ) ;
break ;
case PSBT_IN_PARTIAL_SIG :
{
// Make sure that the key is the size of pubkey + 1
2018-04-12 13:30:04 -07:00
if ( key . size ( ) ! = CPubKey : : SIZE + 1 & & key . size ( ) ! = CPubKey : : COMPRESSED_SIZE + 1 ) {
2019-01-09 02:06:29 -08:00
throw std : : ios_base : : failure ( " Size of key was not the expected size for the type partial signature pubkey " ) ;
}
// Read in the pubkey from key
CPubKey pubkey ( key . begin ( ) + 1 , key . end ( ) ) ;
if ( ! pubkey . IsFullyValid ( ) ) {
throw std : : ios_base : : failure ( " Invalid pubkey " ) ;
}
if ( partial_sigs . count ( pubkey . GetID ( ) ) > 0 ) {
throw std : : ios_base : : failure ( " Duplicate Key, input partial signature for pubkey already provided " ) ;
}
// Read in the signature from value
std : : vector < unsigned char > sig ;
s > > sig ;
// Add to list
partial_sigs . emplace ( pubkey . GetID ( ) , SigPair ( pubkey , std : : move ( sig ) ) ) ;
break ;
}
case PSBT_IN_SIGHASH :
2019-09-06 20:54:00 +02:00
if ( ! key_lookup . emplace ( key ) . second ) {
2019-01-09 02:06:29 -08:00
throw std : : ios_base : : failure ( " Duplicate Key, input sighash type already provided " ) ;
} else if ( key . size ( ) ! = 1 ) {
throw std : : ios_base : : failure ( " Sighash type key is more than one byte type " ) ;
}
2021-11-15 13:54:01 -05:00
int sighash ;
UnserializeFromVector ( s , sighash ) ;
sighash_type = sighash ;
2019-01-09 02:06:29 -08:00
break ;
case PSBT_IN_REDEEMSCRIPT :
{
2019-09-06 20:54:00 +02:00
if ( ! key_lookup . emplace ( key ) . second ) {
2019-01-09 02:06:29 -08:00
throw std : : ios_base : : failure ( " Duplicate Key, input redeemScript already provided " ) ;
} else if ( key . size ( ) ! = 1 ) {
throw std : : ios_base : : failure ( " Input redeemScript key is more than one byte type " ) ;
}
s > > redeem_script ;
break ;
}
case PSBT_IN_WITNESSSCRIPT :
{
2019-09-06 20:54:00 +02:00
if ( ! key_lookup . emplace ( key ) . second ) {
2019-01-09 02:06:29 -08:00
throw std : : ios_base : : failure ( " Duplicate Key, input witnessScript already provided " ) ;
} else if ( key . size ( ) ! = 1 ) {
throw std : : ios_base : : failure ( " Input witnessScript key is more than one byte type " ) ;
}
s > > witness_script ;
break ;
}
case PSBT_IN_BIP32_DERIVATION :
{
DeserializeHDKeypaths ( s , key , hd_keypaths ) ;
break ;
}
case PSBT_IN_SCRIPTSIG :
{
2019-09-06 20:54:00 +02:00
if ( ! key_lookup . emplace ( key ) . second ) {
2019-01-09 02:06:29 -08:00
throw std : : ios_base : : failure ( " Duplicate Key, input final scriptSig already provided " ) ;
} else if ( key . size ( ) ! = 1 ) {
throw std : : ios_base : : failure ( " Final scriptSig key is more than one byte type " ) ;
}
s > > final_script_sig ;
break ;
}
case PSBT_IN_SCRIPTWITNESS :
{
2019-09-06 20:54:00 +02:00
if ( ! key_lookup . emplace ( key ) . second ) {
2019-01-09 02:06:29 -08:00
throw std : : ios_base : : failure ( " Duplicate Key, input final scriptWitness already provided " ) ;
} else if ( key . size ( ) ! = 1 ) {
throw std : : ios_base : : failure ( " Final scriptWitness key is more than one byte type " ) ;
}
UnserializeFromVector ( s , final_script_witness . stack ) ;
break ;
}
2021-12-05 13:07:54 +01:00
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 < unsigned char > 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 < unsigned char > 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 < unsigned char > 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 < unsigned char > 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 < unsigned char > 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 < unsigned char > 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 < unsigned char > 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 < unsigned char > preimage ;
s > > preimage ;
// Add to preimages list
hash256_preimages . emplace ( hash , std : : move ( preimage ) ) ;
break ;
}
2021-07-12 17:07:08 -04:00
case PSBT_IN_TAP_KEY_SIG :
{
if ( ! key_lookup . emplace ( key ) . second ) {
throw std : : ios_base : : failure ( " Duplicate Key, input Taproot key signature already provided " ) ;
} else if ( key . size ( ) ! = 1 ) {
throw std : : ios_base : : failure ( " Input Taproot key signature key is more than one byte type " ) ;
}
s > > m_tap_key_sig ;
if ( m_tap_key_sig . size ( ) < 64 ) {
throw std : : ios_base : : failure ( " Input Taproot key path signature is shorter than 64 bytes " ) ;
} else if ( m_tap_key_sig . size ( ) > 65 ) {
throw std : : ios_base : : failure ( " Input Taproot key path signature is longer than 65 bytes " ) ;
}
break ;
}
case PSBT_IN_TAP_SCRIPT_SIG :
{
if ( ! key_lookup . emplace ( key ) . second ) {
throw std : : ios_base : : failure ( " Duplicate Key, input Taproot script signature already provided " ) ;
} else if ( key . size ( ) ! = 65 ) {
throw std : : ios_base : : failure ( " Input Taproot script signature key is not 65 bytes " ) ;
}
2023-11-17 16:32:29 +01:00
SpanReader s_key { Span { key } . subspan ( 1 ) } ;
2021-07-12 17:07:08 -04:00
XOnlyPubKey xonly ;
uint256 hash ;
s_key > > xonly ;
s_key > > hash ;
std : : vector < unsigned char > sig ;
s > > sig ;
if ( sig . size ( ) < 64 ) {
throw std : : ios_base : : failure ( " Input Taproot script path signature is shorter than 64 bytes " ) ;
} else if ( sig . size ( ) > 65 ) {
throw std : : ios_base : : failure ( " Input Taproot script path signature is longer than 65 bytes " ) ;
}
m_tap_script_sigs . emplace ( std : : make_pair ( xonly , hash ) , sig ) ;
break ;
}
case PSBT_IN_TAP_LEAF_SCRIPT :
{
if ( ! key_lookup . emplace ( key ) . second ) {
throw std : : ios_base : : failure ( " Duplicate Key, input Taproot leaf script already provided " ) ;
} else if ( key . size ( ) < 34 ) {
throw std : : ios_base : : failure ( " Taproot leaf script key is not at least 34 bytes " ) ;
} else if ( ( key . size ( ) - 2 ) % 32 ! = 0 ) {
throw std : : ios_base : : failure ( " Input Taproot leaf script key's control block size is not valid " ) ;
}
std : : vector < unsigned char > script_v ;
s > > script_v ;
if ( script_v . empty ( ) ) {
throw std : : ios_base : : failure ( " Input Taproot leaf script must be at least 1 byte " ) ;
}
uint8_t leaf_ver = script_v . back ( ) ;
script_v . pop_back ( ) ;
2022-08-19 10:40:28 -04:00
const auto leaf_script = std : : make_pair ( script_v , ( int ) leaf_ver ) ;
2021-07-12 17:07:08 -04:00
m_tap_scripts [ leaf_script ] . insert ( std : : vector < unsigned char > ( key . begin ( ) + 1 , key . end ( ) ) ) ;
break ;
}
case PSBT_IN_TAP_BIP32_DERIVATION :
{
if ( ! key_lookup . emplace ( key ) . second ) {
throw std : : ios_base : : failure ( " Duplicate Key, input Taproot BIP32 keypath already provided " ) ;
} else if ( key . size ( ) ! = 33 ) {
throw std : : ios_base : : failure ( " Input Taproot BIP32 keypath key is not at 33 bytes " ) ;
}
2023-11-17 16:32:29 +01:00
SpanReader s_key { Span { key } . subspan ( 1 ) } ;
2021-07-12 17:07:08 -04:00
XOnlyPubKey xonly ;
s_key > > xonly ;
std : : set < uint256 > leaf_hashes ;
uint64_t value_len = ReadCompactSize ( s ) ;
size_t before_hashes = s . size ( ) ;
s > > leaf_hashes ;
size_t after_hashes = s . size ( ) ;
size_t hashes_len = before_hashes - after_hashes ;
2022-08-09 17:20:23 -04:00
if ( hashes_len > value_len ) {
throw std : : ios_base : : failure ( " Input Taproot BIP32 keypath has an invalid length " ) ;
}
2021-07-12 17:07:08 -04:00
size_t origin_len = value_len - hashes_len ;
m_tap_bip32_paths . emplace ( xonly , std : : make_pair ( leaf_hashes , DeserializeKeyOrigin ( s , origin_len ) ) ) ;
break ;
}
case PSBT_IN_TAP_INTERNAL_KEY :
{
if ( ! key_lookup . emplace ( key ) . second ) {
throw std : : ios_base : : failure ( " Duplicate Key, input Taproot internal key already provided " ) ;
} else if ( key . size ( ) ! = 1 ) {
throw std : : ios_base : : failure ( " Input Taproot internal key key is more than one byte type " ) ;
}
UnserializeFromVector ( s , m_tap_internal_key ) ;
break ;
}
case PSBT_IN_TAP_MERKLE_ROOT :
{
if ( ! key_lookup . emplace ( key ) . second ) {
throw std : : ios_base : : failure ( " Duplicate Key, input Taproot merkle root already provided " ) ;
} else if ( key . size ( ) ! = 1 ) {
throw std : : ios_base : : failure ( " Input Taproot merkle root key is more than one byte type " ) ;
}
UnserializeFromVector ( s , m_tap_merkle_root ) ;
break ;
}
2019-10-02 16:45:56 -04:00
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 ;
}
2019-01-09 02:06:29 -08:00
// Unknown stuff
default :
if ( unknown . count ( key ) > 0 ) {
throw std : : ios_base : : failure ( " Duplicate Key, key for unknown value already provided " ) ;
}
// Read in the value
std : : vector < unsigned char > val_bytes ;
s > > val_bytes ;
unknown . emplace ( std : : move ( key ) , std : : move ( val_bytes ) ) ;
break ;
}
}
if ( ! found_sep ) {
throw std : : ios_base : : failure ( " Separator is missing at the end of an input map " ) ;
}
}
template < typename Stream >
PSBTInput ( deserialize_type , Stream & s ) {
Unserialize ( s ) ;
}
} ;
/** A structure for PSBTs which contains per output information */
struct PSBTOutput
{
CScript redeem_script ;
CScript witness_script ;
std : : map < CPubKey , KeyOriginInfo > hd_keypaths ;
2021-07-12 17:07:08 -04:00
XOnlyPubKey m_tap_internal_key ;
2022-08-19 10:40:28 -04:00
std : : vector < std : : tuple < uint8_t , uint8_t , std : : vector < unsigned char > > > m_tap_tree ;
2021-07-12 17:07:08 -04:00
std : : map < XOnlyPubKey , std : : pair < std : : set < uint256 > , KeyOriginInfo > > m_tap_bip32_paths ;
2019-01-09 02:06:29 -08:00
std : : map < std : : vector < unsigned char > , std : : vector < unsigned char > > unknown ;
2019-10-02 16:45:56 -04:00
std : : set < PSBTProprietary > m_proprietary ;
2019-01-09 02:06:29 -08:00
bool IsNull ( ) const ;
void FillSignatureData ( SignatureData & sigdata ) const ;
void FromSignatureData ( const SignatureData & sigdata ) ;
void Merge ( const PSBTOutput & output ) ;
PSBTOutput ( ) { }
template < typename Stream >
inline void Serialize ( Stream & s ) const {
// Write the redeem script
if ( ! redeem_script . empty ( ) ) {
2019-10-02 15:49:33 -04:00
SerializeToVector ( s , CompactSizeWriter ( PSBT_OUT_REDEEMSCRIPT ) ) ;
2019-01-09 02:06:29 -08:00
s < < redeem_script ;
}
// Write the witness script
if ( ! witness_script . empty ( ) ) {
2019-10-02 15:49:33 -04:00
SerializeToVector ( s , CompactSizeWriter ( PSBT_OUT_WITNESSSCRIPT ) ) ;
2019-01-09 02:06:29 -08:00
s < < witness_script ;
}
// Write any hd keypaths
2019-10-02 15:49:33 -04:00
SerializeHDKeypaths ( s , hd_keypaths , CompactSizeWriter ( PSBT_OUT_BIP32_DERIVATION ) ) ;
2019-01-09 02:06:29 -08:00
2019-10-02 16:45:56 -04:00
// Write proprietary things
for ( const auto & entry : m_proprietary ) {
s < < entry . key ;
s < < entry . value ;
}
2021-07-12 17:07:08 -04:00
// Write taproot internal key
if ( ! m_tap_internal_key . IsNull ( ) ) {
SerializeToVector ( s , PSBT_OUT_TAP_INTERNAL_KEY ) ;
s < < ToByteVector ( m_tap_internal_key ) ;
}
// Write taproot tree
2022-08-16 21:17:43 -04:00
if ( ! m_tap_tree . empty ( ) ) {
2021-07-12 17:07:08 -04:00
SerializeToVector ( s , PSBT_OUT_TAP_TREE ) ;
std : : vector < unsigned char > value ;
2023-11-16 12:59:43 +01:00
VectorWriter s_value { value , 0 } ;
2022-08-16 21:17:43 -04:00
for ( const auto & [ depth , leaf_ver , script ] : m_tap_tree ) {
2021-07-12 17:07:08 -04:00
s_value < < depth ;
s_value < < leaf_ver ;
s_value < < script ;
}
s < < value ;
}
// Write taproot bip32 keypaths
for ( const auto & [ xonly , leaf ] : m_tap_bip32_paths ) {
const auto & [ leaf_hashes , origin ] = leaf ;
SerializeToVector ( s , PSBT_OUT_TAP_BIP32_DERIVATION , xonly ) ;
std : : vector < unsigned char > value ;
2023-11-16 12:59:43 +01:00
VectorWriter s_value { value , 0 } ;
2021-07-12 17:07:08 -04:00
s_value < < leaf_hashes ;
SerializeKeyOrigin ( s_value , origin ) ;
s < < value ;
}
2019-01-09 02:06:29 -08:00
// Write unknown things
for ( auto & entry : unknown ) {
s < < entry . first ;
s < < entry . second ;
}
s < < PSBT_SEPARATOR ;
}
template < typename Stream >
inline void Unserialize ( Stream & s ) {
2019-09-06 20:54:00 +02:00
// Used for duplicate key detection
std : : set < std : : vector < unsigned char > > key_lookup ;
2019-01-09 02:06:29 -08:00
// Read loop
bool found_sep = false ;
while ( ! s . empty ( ) ) {
// Read
std : : vector < unsigned char > key ;
s > > key ;
// the key is empty if that was actually a separator byte
// This is a special case for key lengths 0 as those are not allowed (except for separator)
if ( key . empty ( ) ) {
found_sep = true ;
break ;
}
2019-10-02 15:49:33 -04:00
// Type is compact size uint at beginning of key
2023-11-17 16:32:29 +01:00
SpanReader skey { key } ;
2019-10-02 15:49:33 -04:00
uint64_t type = ReadCompactSize ( skey ) ;
2019-01-09 02:06:29 -08:00
// Do stuff based on type
switch ( type ) {
case PSBT_OUT_REDEEMSCRIPT :
{
2019-09-06 20:54:00 +02:00
if ( ! key_lookup . emplace ( key ) . second ) {
2019-01-09 02:06:29 -08:00
throw std : : ios_base : : failure ( " Duplicate Key, output redeemScript already provided " ) ;
} else if ( key . size ( ) ! = 1 ) {
throw std : : ios_base : : failure ( " Output redeemScript key is more than one byte type " ) ;
}
s > > redeem_script ;
break ;
}
case PSBT_OUT_WITNESSSCRIPT :
{
2019-09-06 20:54:00 +02:00
if ( ! key_lookup . emplace ( key ) . second ) {
2019-01-09 02:06:29 -08:00
throw std : : ios_base : : failure ( " Duplicate Key, output witnessScript already provided " ) ;
} else if ( key . size ( ) ! = 1 ) {
throw std : : ios_base : : failure ( " Output witnessScript key is more than one byte type " ) ;
}
s > > witness_script ;
break ;
}
case PSBT_OUT_BIP32_DERIVATION :
{
DeserializeHDKeypaths ( s , key , hd_keypaths ) ;
break ;
}
2021-07-12 17:07:08 -04:00
case PSBT_OUT_TAP_INTERNAL_KEY :
{
if ( ! key_lookup . emplace ( key ) . second ) {
throw std : : ios_base : : failure ( " Duplicate Key, output Taproot internal key already provided " ) ;
} else if ( key . size ( ) ! = 1 ) {
throw std : : ios_base : : failure ( " Output Taproot internal key key is more than one byte type " ) ;
}
UnserializeFromVector ( s , m_tap_internal_key ) ;
break ;
}
case PSBT_OUT_TAP_TREE :
{
if ( ! key_lookup . emplace ( key ) . second ) {
throw std : : ios_base : : failure ( " Duplicate Key, output Taproot tree already provided " ) ;
} else if ( key . size ( ) ! = 1 ) {
throw std : : ios_base : : failure ( " Output Taproot tree key is more than one byte type " ) ;
}
std : : vector < unsigned char > tree_v ;
s > > tree_v ;
2023-11-17 16:32:29 +01:00
SpanReader s_tree { tree_v } ;
2022-08-16 12:09:27 -07:00
if ( s_tree . empty ( ) ) {
throw std : : ios_base : : failure ( " Output Taproot tree must not be empty " ) ;
}
2022-08-16 21:17:43 -04:00
TaprootBuilder builder ;
2021-07-12 17:07:08 -04:00
while ( ! s_tree . empty ( ) ) {
uint8_t depth ;
uint8_t leaf_ver ;
2022-08-19 10:40:28 -04:00
std : : vector < unsigned char > script ;
2021-07-12 17:07:08 -04:00
s_tree > > depth ;
s_tree > > leaf_ver ;
s_tree > > script ;
2022-06-30 11:08:44 -04:00
if ( depth > TAPROOT_CONTROL_MAX_NODE_COUNT ) {
throw std : : ios_base : : failure ( " Output Taproot tree has as leaf greater than Taproot maximum depth " ) ;
}
if ( ( leaf_ver & ~ TAPROOT_LEAF_MASK ) ! = 0 ) {
throw std : : ios_base : : failure ( " Output Taproot tree has a leaf with an invalid leaf version " ) ;
}
2023-10-04 13:53:40 +02:00
m_tap_tree . emplace_back ( depth , leaf_ver , script ) ;
2022-10-03 09:37:27 +01:00
builder . Add ( ( int ) depth , script , ( int ) leaf_ver , /*track=*/ true ) ;
2021-07-12 17:07:08 -04:00
}
2022-08-16 21:17:43 -04:00
if ( ! builder . IsComplete ( ) ) {
2021-07-12 17:07:08 -04:00
throw std : : ios_base : : failure ( " Output Taproot tree is malformed " ) ;
}
break ;
}
case PSBT_OUT_TAP_BIP32_DERIVATION :
{
if ( ! key_lookup . emplace ( key ) . second ) {
throw std : : ios_base : : failure ( " Duplicate Key, output Taproot BIP32 keypath already provided " ) ;
} else if ( key . size ( ) ! = 33 ) {
throw std : : ios_base : : failure ( " Output Taproot BIP32 keypath key is not at 33 bytes " ) ;
}
2022-10-19 15:16:04 -05:00
XOnlyPubKey xonly ( uint256 ( Span < uint8_t > ( key ) . last ( 32 ) ) ) ;
2021-07-12 17:07:08 -04:00
std : : set < uint256 > leaf_hashes ;
uint64_t value_len = ReadCompactSize ( s ) ;
size_t before_hashes = s . size ( ) ;
s > > leaf_hashes ;
size_t after_hashes = s . size ( ) ;
size_t hashes_len = before_hashes - after_hashes ;
2022-07-25 18:45:43 +02:00
if ( hashes_len > value_len ) {
throw std : : ios_base : : failure ( " Output Taproot BIP32 keypath has an invalid length " ) ;
}
2021-07-12 17:07:08 -04:00
size_t origin_len = value_len - hashes_len ;
m_tap_bip32_paths . emplace ( xonly , std : : make_pair ( leaf_hashes , DeserializeKeyOrigin ( s , origin_len ) ) ) ;
break ;
}
2019-10-02 16:45:56 -04:00
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 ;
}
2019-01-09 02:06:29 -08:00
// Unknown stuff
default : {
if ( unknown . count ( key ) > 0 ) {
throw std : : ios_base : : failure ( " Duplicate Key, key for unknown value already provided " ) ;
}
// Read in the value
std : : vector < unsigned char > val_bytes ;
s > > val_bytes ;
unknown . emplace ( std : : move ( key ) , std : : move ( val_bytes ) ) ;
break ;
}
}
}
if ( ! found_sep ) {
throw std : : ios_base : : failure ( " Separator is missing at the end of an output map " ) ;
}
}
template < typename Stream >
PSBTOutput ( deserialize_type , Stream & s ) {
Unserialize ( s ) ;
}
} ;
/** A version of CTransaction with the PSBT format*/
struct PartiallySignedTransaction
{
2021-03-15 10:41:30 +08:00
std : : optional < CMutableTransaction > tx ;
2019-07-25 11:58:28 -04:00
// We use a vector of CExtPubKey in the event that there happens to be the same KeyOriginInfos for different CExtPubKeys
// Note that this map swaps the key and values from the serialization
std : : map < KeyOriginInfo , std : : set < CExtPubKey > > m_xpubs ;
2019-01-09 02:06:29 -08:00
std : : vector < PSBTInput > inputs ;
std : : vector < PSBTOutput > outputs ;
std : : map < std : : vector < unsigned char > , std : : vector < unsigned char > > unknown ;
2019-10-02 16:11:34 -04:00
std : : optional < uint32_t > m_version ;
2019-10-02 16:45:56 -04:00
std : : set < PSBTProprietary > m_proprietary ;
2019-01-09 02:06:29 -08:00
bool IsNull ( ) const ;
2021-01-04 17:21:29 -05:00
uint32_t GetVersion ( ) const ;
2019-01-29 22:51:56 -08:00
/** Merge psbt into this. The two psbts must have the same underlying CTransaction (i.e. the
* same actual Bitcoin transaction . ) Returns true if the merge succeeded , false otherwise . */
2020-11-26 09:05:59 +00:00
[ [ nodiscard ] ] bool Merge ( const PartiallySignedTransaction & psbt ) ;
2018-07-20 18:24:16 -07:00
bool AddInput ( const CTxIn & txin , PSBTInput & psbtin ) ;
bool AddOutput ( const CTxOut & txout , const PSBTOutput & psbtout ) ;
2019-01-09 02:06:29 -08:00
PartiallySignedTransaction ( ) { }
explicit PartiallySignedTransaction ( const CMutableTransaction & tx ) ;
2018-07-31 17:56:47 -07:00
/**
* Finds the UTXO for a given input index
*
* @ param [ out ] utxo The UTXO of the input if found
* @ param [ in ] input_index Index of the input to retrieve the UTXO of
* @ return Whether the UTXO for the specified input was found
*/
bool GetInputUTXO ( CTxOut & utxo , int input_index ) const ;
2019-01-09 02:06:29 -08:00
template < typename Stream >
inline void Serialize ( Stream & s ) const {
// magic bytes
s < < PSBT_MAGIC_BYTES ;
// unsigned tx flag
2019-10-02 15:49:33 -04:00
SerializeToVector ( s , CompactSizeWriter ( PSBT_GLOBAL_UNSIGNED_TX ) ) ;
2019-01-09 02:06:29 -08:00
// Write serialized tx to a stream
2023-09-07 19:16:57 +10:00
SerializeToVector ( s , TX_NO_WITNESS ( * tx ) ) ;
2019-01-09 02:06:29 -08:00
2019-07-25 11:58:28 -04:00
// Write xpubs
for ( const auto & xpub_pair : m_xpubs ) {
for ( const auto & xpub : xpub_pair . second ) {
unsigned char ser_xpub [ BIP32_EXTKEY_WITH_VERSION_SIZE ] ;
xpub . EncodeWithVersion ( ser_xpub ) ;
// Note that the serialization swaps the key and value
// The xpub is the key (for uniqueness) while the path is the value
SerializeToVector ( s , PSBT_GLOBAL_XPUB , ser_xpub ) ;
SerializeHDKeypath ( s , xpub_pair . first ) ;
}
}
2019-10-02 16:11:34 -04:00
// PSBT version
2021-01-04 17:21:29 -05:00
if ( GetVersion ( ) > 0 ) {
2019-10-02 16:11:34 -04:00
SerializeToVector ( s , CompactSizeWriter ( PSBT_GLOBAL_VERSION ) ) ;
SerializeToVector ( s , * m_version ) ;
}
2019-10-02 16:45:56 -04:00
// Write proprietary things
for ( const auto & entry : m_proprietary ) {
s < < entry . key ;
s < < entry . value ;
}
2019-01-09 02:06:29 -08:00
// Write the unknown things
for ( auto & entry : unknown ) {
s < < entry . first ;
s < < entry . second ;
}
// Separator
s < < PSBT_SEPARATOR ;
// Write inputs
for ( const PSBTInput & input : inputs ) {
s < < input ;
}
// Write outputs
for ( const PSBTOutput & output : outputs ) {
s < < output ;
}
}
template < typename Stream >
inline void Unserialize ( Stream & s ) {
// Read the magic bytes
uint8_t magic [ 5 ] ;
s > > magic ;
if ( ! std : : equal ( magic , magic + 5 , PSBT_MAGIC_BYTES ) ) {
throw std : : ios_base : : failure ( " Invalid PSBT magic bytes " ) ;
}
2019-09-06 20:54:00 +02:00
// Used for duplicate key detection
std : : set < std : : vector < unsigned char > > key_lookup ;
2019-07-25 11:58:28 -04:00
// Track the global xpubs we have already seen. Just for sanity checking
std : : set < CExtPubKey > global_xpubs ;
2019-01-09 02:06:29 -08:00
// Read global data
bool found_sep = false ;
while ( ! s . empty ( ) ) {
// Read
std : : vector < unsigned char > key ;
s > > key ;
// the key is empty if that was actually a separator byte
// This is a special case for key lengths 0 as those are not allowed (except for separator)
if ( key . empty ( ) ) {
found_sep = true ;
break ;
}
2019-10-02 15:49:33 -04:00
// Type is compact size uint at beginning of key
2023-11-17 16:32:29 +01:00
SpanReader skey { key } ;
2019-10-02 15:49:33 -04:00
uint64_t type = ReadCompactSize ( skey ) ;
2019-01-09 02:06:29 -08:00
// Do stuff based on type
switch ( type ) {
case PSBT_GLOBAL_UNSIGNED_TX :
{
2019-09-06 20:54:00 +02:00
if ( ! key_lookup . emplace ( key ) . second ) {
2019-01-09 02:06:29 -08:00
throw std : : ios_base : : failure ( " Duplicate Key, unsigned tx already provided " ) ;
} else if ( key . size ( ) ! = 1 ) {
throw std : : ios_base : : failure ( " Global unsigned tx key is more than one byte type " ) ;
}
CMutableTransaction mtx ;
// Set the stream to serialize with non-witness since this should always be non-witness
2023-09-07 19:16:57 +10:00
UnserializeFromVector ( s , TX_NO_WITNESS ( mtx ) ) ;
2019-01-09 02:06:29 -08:00
tx = std : : move ( mtx ) ;
// Make sure that all scriptSigs and scriptWitnesses are empty
for ( const CTxIn & txin : tx - > vin ) {
if ( ! txin . scriptSig . empty ( ) | | ! txin . scriptWitness . IsNull ( ) ) {
throw std : : ios_base : : failure ( " Unsigned tx does not have empty scriptSigs and scriptWitnesses. " ) ;
}
}
break ;
}
2019-07-25 11:58:28 -04:00
case PSBT_GLOBAL_XPUB :
{
if ( key . size ( ) ! = BIP32_EXTKEY_WITH_VERSION_SIZE + 1 ) {
throw std : : ios_base : : failure ( " Size of key was not the expected size for the type global xpub " ) ;
}
// Read in the xpub from key
CExtPubKey xpub ;
xpub . DecodeWithVersion ( & key . data ( ) [ 1 ] ) ;
if ( ! xpub . pubkey . IsFullyValid ( ) ) {
throw std : : ios_base : : failure ( " Invalid pubkey " ) ;
}
if ( global_xpubs . count ( xpub ) > 0 ) {
throw std : : ios_base : : failure ( " Duplicate key, global xpub already provided " ) ;
}
global_xpubs . insert ( xpub ) ;
// Read in the keypath from stream
KeyOriginInfo keypath ;
DeserializeHDKeypath ( s , keypath ) ;
// Note that we store these swapped to make searches faster.
// Serialization uses xpub -> keypath to enqure key uniqueness
if ( m_xpubs . count ( keypath ) = = 0 ) {
// Make a new set to put the xpub in
m_xpubs [ keypath ] = { xpub } ;
} else {
// Insert xpub into existing set
m_xpubs [ keypath ] . insert ( xpub ) ;
}
break ;
}
2019-10-02 16:11:34 -04:00
case PSBT_GLOBAL_VERSION :
{
if ( m_version ) {
throw std : : ios_base : : failure ( " Duplicate Key, version already provided " ) ;
} else if ( key . size ( ) ! = 1 ) {
throw std : : ios_base : : failure ( " Global version key is more than one byte type " ) ;
}
uint32_t v ;
UnserializeFromVector ( s , v ) ;
m_version = v ;
if ( * m_version > PSBT_HIGHEST_VERSION ) {
throw std : : ios_base : : failure ( " Unsupported version number " ) ;
}
break ;
}
2019-10-02 16:45:56 -04:00
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 ;
}
2019-01-09 02:06:29 -08:00
// Unknown stuff
default : {
if ( unknown . count ( key ) > 0 ) {
throw std : : ios_base : : failure ( " Duplicate Key, key for unknown value already provided " ) ;
}
// Read in the value
std : : vector < unsigned char > val_bytes ;
s > > val_bytes ;
unknown . emplace ( std : : move ( key ) , std : : move ( val_bytes ) ) ;
}
}
}
if ( ! found_sep ) {
throw std : : ios_base : : failure ( " Separator is missing at the end of the global map " ) ;
}
// Make sure that we got an unsigned tx
if ( ! tx ) {
2023-01-30 10:46:15 -05:00
throw std : : ios_base : : failure ( " No unsigned transaction was provided " ) ;
2019-01-09 02:06:29 -08:00
}
// Read input data
unsigned int i = 0 ;
while ( ! s . empty ( ) & & i < tx - > vin . size ( ) ) {
PSBTInput input ;
s > > input ;
inputs . push_back ( input ) ;
// Make sure the non-witness utxo matches the outpoint
if ( input . non_witness_utxo & & input . non_witness_utxo - > GetHash ( ) ! = tx - > vin [ i ] . prevout . hash ) {
throw std : : ios_base : : failure ( " Non-witness UTXO does not match outpoint hash " ) ;
}
+ + i ;
}
// Make sure that the number of inputs matches the number of inputs in the transaction
if ( inputs . size ( ) ! = tx - > vin . size ( ) ) {
throw std : : ios_base : : failure ( " Inputs provided does not match the number of inputs in transaction. " ) ;
}
// Read output data
i = 0 ;
while ( ! s . empty ( ) & & i < tx - > vout . size ( ) ) {
PSBTOutput output ;
s > > output ;
outputs . push_back ( output ) ;
+ + i ;
}
// Make sure that the number of outputs matches the number of outputs in the transaction
if ( outputs . size ( ) ! = tx - > vout . size ( ) ) {
throw std : : ios_base : : failure ( " Outputs provided does not match the number of outputs in transaction. " ) ;
}
}
template < typename Stream >
PartiallySignedTransaction ( deserialize_type , Stream & s ) {
Unserialize ( s ) ;
}
} ;
2019-03-01 00:25:10 -08:00
enum class PSBTRole {
2019-11-19 14:35:14 -05:00
CREATOR ,
2019-03-01 00:25:10 -08:00
UPDATER ,
SIGNER ,
FINALIZER ,
EXTRACTOR
} ;
std : : string PSBTRoleName ( PSBTRole role ) ;
2021-03-03 16:47:44 -08:00
/** Compute a PrecomputedTransactionData object from a psbt. */
PrecomputedTransactionData PrecomputePSBTData ( const PartiallySignedTransaction & psbt ) ;
2022-07-12 10:37:27 -04:00
/** Checks whether a PSBTInput is already signed by checking for non-null finalized fields. */
2019-03-01 00:25:10 -08:00
bool PSBTInputSigned ( const PSBTInput & input ) ;
2019-01-09 02:06:29 -08:00
2022-07-12 10:37:27 -04:00
/** Checks whether a PSBTInput is already signed by doing script verification using final fields. */
bool PSBTInputSignedAndVerified ( const PartiallySignedTransaction psbt , unsigned int input_index , const PrecomputedTransactionData * txdata ) ;
2021-03-03 16:47:44 -08:00
/** Signs a PSBTInput, verifying that all provided data matches what is being signed.
*
* txdata should be the output of PrecomputePSBTData ( which can be shared across
* multiple SignPSBTInput calls ) . If it is nullptr , a dummy signature will be created .
* */
2021-07-20 21:24:56 -04:00
bool SignPSBTInput ( const SigningProvider & provider , PartiallySignedTransaction & psbt , int index , const PrecomputedTransactionData * txdata , int sighash = SIGHASH_ALL , SignatureData * out_sigdata = nullptr , bool finalize = true ) ;
2019-01-09 02:06:29 -08:00
2022-08-23 15:24:00 -04:00
/** Reduces the size of the PSBT by dropping unnecessary `non_witness_utxos` (i.e. complete previous transactions) from a psbt when all inputs are segwit v1. */
void RemoveUnnecessaryTransactions ( PartiallySignedTransaction & psbtx , const int & sighash_type ) ;
2020-05-29 01:25:04 -07:00
/** Counts the unsigned inputs of a PSBT. */
size_t CountPSBTUnsignedInputs ( const PartiallySignedTransaction & psbt ) ;
2019-02-16 15:49:36 -08:00
/** Updates a PSBTOutput with information from provider.
*
* This fills in the redeem_script , witness_script , and hd_keypaths where possible .
*/
void UpdatePSBTOutput ( const SigningProvider & provider , PartiallySignedTransaction & psbt , int index ) ;
2019-01-09 03:08:32 -08:00
/**
* Finalizes a PSBT if possible , combining partial signatures .
*
2020-01-16 18:23:35 -08:00
* @ param [ in , out ] psbtx PartiallySignedTransaction to finalize
2019-01-09 03:08:32 -08:00
* return True if the PSBT is now complete , false otherwise
*/
bool FinalizePSBT ( PartiallySignedTransaction & psbtx ) ;
/**
* Finalizes a PSBT if possible , and extracts it to a CMutableTransaction if it could be finalized .
*
2020-01-16 18:23:35 -08:00
* @ param [ in ] psbtx PartiallySignedTransaction
2019-01-09 03:08:32 -08:00
* @ param [ out ] result CMutableTransaction representing the complete transaction , if successful
* @ return True if we successfully extracted the transaction , false otherwise
*/
bool FinalizeAndExtractPSBT ( PartiallySignedTransaction & psbtx , CMutableTransaction & result ) ;
/**
* Combines PSBTs with the same underlying transaction , resulting in a single PSBT with all partial signatures from each input .
*
2020-01-16 18:23:35 -08:00
* @ param [ out ] out the combined PSBT , if successful
2019-01-09 03:08:32 -08:00
* @ param [ in ] psbtxs the PSBTs to combine
2019-02-14 10:01:06 -05:00
* @ return error ( OK if we successfully combined the transactions , other error if they were not compatible )
2019-01-09 03:08:32 -08:00
*/
2020-11-26 09:05:59 +00:00
[ [ nodiscard ] ] TransactionError CombinePSBTs ( PartiallySignedTransaction & out , const std : : vector < PartiallySignedTransaction > & psbtxs ) ;
2019-01-09 03:08:32 -08:00
2019-03-05 18:55:40 -08:00
//! Decode a base64ed PSBT into a PartiallySignedTransaction
2020-11-26 09:05:59 +00:00
[ [ nodiscard ] ] bool DecodeBase64PSBT ( PartiallySignedTransaction & decoded_psbt , const std : : string & base64_psbt , std : : string & error ) ;
2019-03-05 18:55:40 -08:00
//! Decode a raw (binary blob) PSBT into a PartiallySignedTransaction
2022-04-04 13:19:49 -04:00
[ [ nodiscard ] ] bool DecodeRawPSBT ( PartiallySignedTransaction & decoded_psbt , Span < const std : : byte > raw_psbt , std : : string & error ) ;
2019-03-05 18:55:40 -08:00
2019-01-09 02:06:29 -08:00
# endif // BITCOIN_PSBT_H