diff --git a/packages/wasm-utxo/cli/bip-0174.mediawiki b/packages/wasm-utxo/cli/bip-0174.mediawiki new file mode 100644 index 00000000..de666221 --- /dev/null +++ b/packages/wasm-utxo/cli/bip-0174.mediawiki @@ -0,0 +1,1229 @@ +
+  BIP: 174
+  Layer: Applications
+  Title: Partially Signed Bitcoin Transaction Format
+  Author: Ava Chow 
+  Comments-Summary: No comments yet.
+  Comments-URI: https://github.com/bitcoin/bips/wiki/Comments:BIP-0174
+  Status: Final
+  Type: Standards Track
+  Created: 2017-07-12
+  License: BSD-2-Clause
+
+ +==Introduction== + +===Abstract=== + +This document proposes a binary transaction format which contains the information +necessary for a signer to produce signatures for the transaction and holds the +signatures for an input while the input does not have a complete set of signatures. +The signer can be offline as all necessary information will be provided in the +transaction. + +The generic format is described here in addition to the specification for version 0 +of this format. + +===Copyright=== + +This BIP is licensed under the 2-clause BSD license. + +===Motivation=== + +Creating unsigned or partially signed transactions to be passed around to multiple +signers is currently implementation dependent, making it hard for people who use +different wallet software from being able to easily do so. One of the goals of this +document is to create a standard and extensible format that can be used between clients to allow +people to pass around the same transaction to sign and combine their signatures. The +format is also designed to be easily extended for future use which is harder to do +with existing transaction formats. + +Signing transactions also requires users to have access to the UTXOs being spent. This transaction +format will allow offline signers such as air-gapped wallets and hardware wallets +to be able to sign transactions without needing direct access to the UTXO set and without +risk of being defrauded. + +==Specification== + +The Partially Signed Bitcoin Transaction (PSBT) format consists of key-value maps. +Each map consists of a sequence of key-value records, terminated by a 0x00 byte '''Why +is the separator here 0x00 instead of 0xff?''' +The separator here is used to distinguish between each chunk of data. A separator of 0x00 would mean that +the unserializer can read it as a key length of 0, which would never occur with actual keys. It can thus +be used as a separator and allow for easier unserializer implementation.. + + + := * * + := 0x70 0x73 0x62 0x74 0xFF + := * 0x00 + := * 0x00 + := * 0x00 + := + := + := + +Where: + +; +: A [https://en.bitcoin.it/wiki/Protocol_documentation#Variable_length_integer compact size] unsigned integer representing the type. This compact size unsigned integer must be minimally encoded, i.e. if the value can be represented using one byte, it must be represented as one byte. There can be multiple entries with the same within a specific , but the must be unique. +; +: The compact size unsigned integer containing the combined length of and +; +: The compact size unsigned integer containing the length of . +; +: Magic bytes which are ASCII for psbt '''Why use 4 bytes for psbt?''' The +transaction format needed to start with a 5 byte header which uniquely identifies +it. The first bytes were chosen to be the ASCII for psbt because that stands for +Partially Signed Bitcoin Transaction. followed by a separator of 0xFF'''Why Use a separator after the magic bytes?''' The separator +is part of the 5 byte header for PSBT. This byte is a separator of 0xff because +this will cause any non-PSBT unserializer to fail to properly unserialize the PSBT +as a normal transaction. Likewise, since the 5 byte header is fixed, no transaction +in the non-PSBT format will be able to be unserialized by a PSBT unserializer.. This integer must be serialized in most significant byte order. + +The currently defined global types are as follows: + +{| +! Name +! +! +! Description +! +! Description +! Versions Requiring Inclusion +! Versions Requiring Exclusion +! Versions Allowing Inclusion +! Parent BIP +|- +| Unsigned Transaction +| PSBT_GLOBAL_UNSIGNED_TX = 0x00 +| None +| No key data +| +| The transaction in network serialization. The scriptSigs and witnesses for each input must be empty. The transaction must be in the old serialization format (without witnesses). +| 0 +| 2 +| 0 +| 174 +|- +| Extended Public Key +| PSBT_GLOBAL_XPUB = 0x01 +| +| The 78 byte serialized extended public key as defined by BIP 32. Extended public keys are those that can be used to derive public keys used in the inputs and outputs of this transaction. It should be the public key at the highest hardened derivation index so that the unhardened child keys used in the transaction can be derived. +| <4 byte fingerprint> <32-bit little endian uint path element>* +| The master key fingerprint as defined by BIP 32 concatenated with the derivation path of the public key. The derivation path is represented as 32-bit little endian unsigned integer indexes concatenated with each other. The number of 32 bit unsigned integer indexes must match the depth provided in the extended public key. +| +| +| 0, 2 +| 174 +|- +| Transaction Version +| PSBT_GLOBAL_TX_VERSION = 0x02 +| None +| No key data +| <32-bit little endian int version> +| The 32-bit little endian signed integer representing the version number of the transaction being created. Note that this is not the same as the PSBT version number specified by the PSBT_GLOBAL_VERSION field. +| 2 +| 0 +| 2 +| [[bip-0370.mediawiki|370]] +|- +| Fallback Locktime +| PSBT_GLOBAL_FALLBACK_LOCKTIME = 0x03 +| None +| No key data +| <32-bit little endian uint locktime> +| The 32-bit little endian unsigned integer representing the transaction locktime to use if no inputs specify a required locktime. +| +| 0 +| 2 +| [[bip-0370.mediawiki|370]] +|- +| Input Count +| PSBT_GLOBAL_INPUT_COUNT = 0x04 +| None +| No key data +| +| Compact size unsigned integer representing the number of inputs in this PSBT. +| 2 +| 0 +| 2 +| [[bip-0370.mediawiki|370]] +|- +| Output Count +| PSBT_GLOBAL_OUTPUT_COUNT = 0x05 +| None +| No key data +| +| Compact size unsigned integer representing the number of outputs in this PSBT. +| 2 +| 0 +| 2 +| [[bip-0370.mediawiki|370]] +|- +| Transaction Modifiable Flags +| PSBT_GLOBAL_TX_MODIFIABLE = 0x06 +| None +| No key data +| <8-bit uint flags> +| An 8 bit little endian unsigned integer as a bitfield for various transaction modification flags. Bit 0 is the Inputs Modifiable Flag and indicates whether inputs can be modified. Bit 1 is the Outputs Modifiable Flag and indicates whether outputs can be modified. Bit 2 is the Has SIGHASH_SINGLE flag and indicates whether the transaction has a SIGHASH_SINGLE signature who's input and output pairing must be preserved. Bit 2 essentially indicates that the Constructor must iterate the inputs to determine whether and how to add an input. +| +| 0 +| 2 +| [[bip-0370.mediawiki|370]] +|- +| Silent Payment Global ECDH Share +| PSBT_GLOBAL_SP_ECDH_SHARE = 0x07 +| <33 byte scan key> +| The scan key that this ECDH share is for. +| <33 byte share> +| An ECDH share for a scan key. The ECDH shared is computed with ''a * B_scan'', where ''a'' is the sum of all private keys of all eligible inputs, and ''B_scan'' is the scan key of a recipient. +| +| 0 +| 2 +| [[bip-0375.mediawiki|375]] +|- +| Silent Payment Global DLEQ Proof +| PSBT_GLOBAL_SP_DLEQ = 0x08 +| <33 byte scan key> +| The scan key that this proof covers. +| <64-byte proof> +| A BIP374 DLEQ proof computed for the matching ECDH share. +| +| 0 +| 2 +| [[bip-0375.mediawiki|375]] +|- +| PSBT Version Number +| PSBT_GLOBAL_VERSION = 0xFB +| None +| No key data +| <32-bit little endian uint version> +| The 32-bit little endian unsigned integer representing the version number of this PSBT. If omitted, the version number is 0. +| +| +| 0, 2 +| 174 +|- +| Proprietary Use Type +| PSBT_GLOBAL_PROPRIETARY = 0xFC +| +| Compact size unsigned integer of the length of the identifier, followed by identifier prefix, followed by a compact size unsigned integer subtype, followed by the key data itself. +| +| Any value data as defined by the proprietary type user. +| +| +| 0, 2 +| 174 +|} + +The currently defined per-input types are defined as follows: + +{| +! Name +! +! +! Description +! +! Description +! Versions Requiring Inclusion +! Versions Requiring Exclusion +! Versions Allowing Inclusion +! Parent BIP +|- +| Non-Witness UTXO +| PSBT_IN_NON_WITNESS_UTXO = 0x00 +| None +| No key data +| +| The transaction in network serialization format the current input spends from. This should be present for inputs that spend non-segwit outputs and can be present for inputs that spend segwit outputs. An input can have both PSBT_IN_NON_WITNESS_UTXO and PSBT_IN_WITNESS_UTXO. '''Why can both UTXO types be provided?''' Many wallets began requiring the full previous transaction (i.e. PSBT_IN_NON_WITNESS_UTXO) for segwit inputs when PSBT was already in use. In order to be compatible with software which were expecting PSBT_IN_WITNESS_UTXO, both UTXO types must be allowed. +| +| +| 0, 2 +| 174 +|- +| Witness UTXO +| PSBT_IN_WITNESS_UTXO = 0x01 +| None +| No key data +| <64-bit little endian int amount> +| The entire transaction output in network serialization which the current input spends from. This should only be present for inputs which spend segwit outputs, including P2SH embedded ones. An input can have both PSBT_IN_NON_WITNESS_UTXO and PSBT_IN_WITNESS_UTXO +| +| +| 0, 2 +| 174 +|- +| Partial Signature +| PSBT_IN_PARTIAL_SIG = 0x02 +| +| The public key which corresponds to this signature. +| +| The signature as would be pushed to the stack from a scriptSig or witness. The signature should be a valid ECDSA signature corresponding to the pubkey that would return true when verified and not a value that would return false or be invalid otherwise (such as a NULLDUMMY). +| +| +| 0, 2 +| 174 +|- +| Sighash Type +| PSBT_IN_SIGHASH_TYPE = 0x03 +| None +| No key data +| <32-bit little endian uint sighash type> +| The 32-bit unsigned integer specifying the sighash type to be used for this input. Signatures for this input must use the sighash type, finalizers must fail to finalize inputs which have signatures that do not match the specified sighash type. Signers who cannot produce signatures with the sighash type must not provide a signature. +| +| +| 0, 2 +| 174 +|- +| Redeem Script +| PSBT_IN_REDEEM_SCRIPT = 0x04 +| None +| No key data +| +| The redeemScript for this input if it has one. +| +| +| 0, 2 +| 174 +|- +| Witness Script +| PSBT_IN_WITNESS_SCRIPT = 0x05 +| None +| No key data +| +| The witnessScript for this input if it has one. +| +| +| 0, 2 +| 174 +|- +| BIP 32 Derivation Path +| PSBT_IN_BIP32_DERIVATION = 0x06 +| +| The public key +| <4 byte fingerprint> <32-bit little endian uint path element>* +| The master key fingerprint as defined by BIP 32 concatenated with the derivation path of the public key. The derivation path is represented as 32 bit unsigned integer indexes concatenated with each other. Public keys are those that will be needed to sign this input. +| +| +| 0, 2 +| 174 +|- +| Finalized scriptSig +| PSBT_IN_FINAL_SCRIPTSIG = 0x07 +| None +| No key data +| +| The Finalized scriptSig contains a fully constructed scriptSig with signatures and any other scripts necessary for the input to pass validation. +| +| +| 0, 2 +| 174 +|- +| Finalized scriptWitness +| PSBT_IN_FINAL_SCRIPTWITNESS = 0x08 +| None +| No key data +| +| The Finalized scriptWitness contains a fully constructed scriptWitness with signatures and any other scripts necessary for the input to pass validation. +| +| +| 0, 2 +| 174 +|- +| Proof-of-reserves commitment +| PSBT_IN_POR_COMMITMENT = 0x09 +| None +| No key data +| +| The UTF-8 encoded commitment message string for the proof-of-reserves. See [[bip-0127.mediawiki|BIP 127]] for more information. +| +| +| 0, 2 +| [[bip-0127.mediawiki|127]] +|- +| RIPEMD160 preimage +| PSBT_IN_RIPEMD160 = 0x0a +| <20-byte hash> +| The resulting hash of the preimage +| +| The hash preimage, encoded as a byte vector, which must equal the key when run through the RIPEMD160 algorithm +| +| +| 0, 2 +| 174 +|- +| SHA256 preimage +| PSBT_IN_SHA256 = 0x0b +| <32-byte hash> +| The resulting hash of the preimage +| +| The hash preimage, encoded as a byte vector, which must equal the key when run through the SHA256 algorithm +| +| +| 0, 2 +| 174 +|- +| HASH160 preimage +| PSBT_IN_HASH160 = 0x0c +| <20-byte hash> +| The resulting hash of the preimage +| +| The hash preimage, encoded as a byte vector, which must equal the key when run through the SHA256 algorithm followed by the RIPEMD160 algorithm +| +| +| 0, 2 +| 174 +|- +| HASH256 preimage +| PSBT_IN_HASH256 = 0x0d +| <32-byte hash> +| The resulting hash of the preimage +| +| The hash preimage, encoded as a byte vector, which must equal the key when run through the SHA256 algorithm twice +| +| +| 0, 2 +| 174 +|- +| Previous TXID +| PSBT_IN_PREVIOUS_TXID = 0x0e +| None +| No key data +| <32 byte txid> +| 32 byte txid of the previous transaction whose output at PSBT_IN_OUTPUT_INDEX is being spent. +| 2 +| 0 +| 2 +| [[bip-0370.mediawiki|370]] +|- +| Spent Output Index +| PSBT_IN_OUTPUT_INDEX = 0x0f +| None +| No key data +| <32-bit little endian uint index> +| 32 bit little endian integer representing the index of the output being spent in the transaction with the txid of PSBT_IN_PREVIOUS_TXID. +| 2 +| 0 +| 2 +| [[bip-0370.mediawiki|370]] +|- +| Sequence Number +| PSBT_IN_SEQUENCE = 0x10 +| None +| No key data +| <32-bit little endian uint sequence> +| The 32 bit unsigned little endian integer for the sequence number of this input. If omitted, the sequence number is assumed to be the final sequence number (0xffffffff). +| +| 0 +| 2 +| [[bip-0370.mediawiki|370]] +|- +| Required Time-based Locktime +| PSBT_IN_REQUIRED_TIME_LOCKTIME = 0x11 +| None +| No key data +| <32-bit little endian uint locktime> +| 32 bit unsigned little endian integer greater than or equal to 500000000 representing the minimum Unix timestamp that this input requires to be set as the transaction's lock time. +| +| 0 +| 2 +| [[bip-0370.mediawiki|370]] +|- +| Required Height-based Locktime +| PSBT_IN_REQUIRED_HEIGHT_LOCKTIME = 0x12 +| None +| No key data +| <32-bit uint locktime> +| 32 bit unsigned little endian integer less than 500000000 representing the minimum block height that this input requires to be set as the transaction's lock time. +| +| 0 +| 2 +| [[bip-0370.mediawiki|370]] +|- +| Taproot Key Spend Signature +| PSBT_IN_TAP_KEY_SIG = 0x13 +| None +| No key data +| <64 or 65 byte signature> +| The 64 or 65 byte Schnorr signature for key path spending a Taproot output. Finalizers should remove this field after PSBT_IN_FINAL_SCRIPTWITNESS is constructed. +| +| +| 0, 2 +| [[bip-0371.mediawiki|371]] +|- +| Taproot Script Spend Signature +| PSBT_IN_TAP_SCRIPT_SIG = 0x14 +| <32 byte xonlypubkey> +| A 32 byte X-only public key involved in a leaf script concatenated with the 32 byte hash of the leaf it is part of. +| <64 or 65 byte signature> +| The 64 or 65 byte Schnorr signature for this pubkey and leaf combination. Finalizers should remove this field after PSBT_IN_FINAL_SCRIPTWITNESS is constructed. +| +| +| 0, 2 +| [[bip-0371.mediawiki|371]] +|- +| Taproot Leaf Script +| PSBT_IN_TAP_LEAF_SCRIPT = 0x15 +| +| The control block for this leaf as specified in BIP 341. The control block contains the merkle tree path to this leaf. +| <8-bit uint leaf version> +| The script for this leaf as would be provided in the witness stack followed by the single byte leaf version. Note that the leaves included in this field should be those that the signers of this input are expected to be able to sign for. Finalizers should remove this field after PSBT_IN_FINAL_SCRIPTWITNESS is constructed. +| +| +| 0, 2 +| [[bip-0371.mediawiki|371]] +|- +| Taproot Key BIP 32 Derivation Path +| PSBT_IN_TAP_BIP32_DERIVATION = 0x16 +| <32 byte xonlypubkey> +| A 32 byte X-only public key involved in this input. It may be the output key, the internal key, or a key present in a leaf script. +| <32 byte leaf hash>* <4 byte fingerprint> <32-bit little endian uint path element>* +| A compact size unsigned integer representing the number of leaf hashes, followed by a list of leaf hashes, followed by the 4 byte master key fingerprint concatenated with the derivation path of the public key. The derivation path is represented as 32-bit little endian unsigned integer indexes concatenated with each other. Public keys are those needed to spend this output. The leaf hashes are of the leaves which involve this public key. The internal key does not have leaf hashes, so can be indicated with a hashes len of 0. Finalizers should remove this field after PSBT_IN_FINAL_SCRIPTWITNESS is constructed. +| +| +| 0, 2 +| [[bip-0371.mediawiki|371]] +|- +| Taproot Internal Key +| PSBT_IN_TAP_INTERNAL_KEY = 0x17 +| None +| No key data +| <32 byte xonlypubkey> +| The X-only pubkey used as the internal key in this output. Finalizers should remove this field after PSBT_IN_FINAL_SCRIPTWITNESS is constructed. +| +| +| 0, 2 +| [[bip-0371.mediawiki|371]] +|- +| Taproot Merkle Root +| PSBT_IN_TAP_MERKLE_ROOT = 0x18 +| None +| No key data +| <32-byte hash> +| The 32 byte Merkle root hash. Finalizers should remove this field after PSBT_IN_FINAL_SCRIPTWITNESS is constructed. +| +| +| 0, 2 +| [[bip-0371.mediawiki|371]] +|- +| MuSig2 Participant Public Keys +| PSBT_IN_MUSIG2_PARTICIPANT_PUBKEYS = 0x1a +| <33 byte plain aggregate pubkey> +| The MuSig2 aggregate plain public key from the KeyAgg algorithm. This key may or may not +be in the script directly (as x-only). It may instead be a parent public key from which the public keys in the +script were derived. +| <33 byte compressed pubkey>* +| A list of the compressed public keys of the participants in the MuSig2 aggregate key in the order +required for aggregation. If sorting was done, then the keys must be in the sorted order. +| +| +| 0, 2 +| [[bip-0373.mediawiki|373]] +|- +| MuSig2 Public Nonce +| PSBT_IN_MUSIG2_PUB_NONCE = 0x1b +| <33 byte compressed pubkey> <33 byte plain pubkey> <32 byte hash or omitted> +| The compressed public key of the participant providing this nonce, followed by the plain public +key the participant is providing the nonce for, followed by the BIP 341 tapleaf hash of +the Taproot leaf script that will be signed. If the aggregate key is the taproot internal key or the +taproot output key, then the tapleaf hash must be omitted. The plain public key must be +the key found in the script and not the aggregate public key that it was derived from, if it was +derived from an aggregate key. +| <66 byte public nonce> +| The public nonce produced by the NonceGen algorithm. +| +| +| 0, 2 +| [[bip-0373.mediawiki|373]] +|- +| MuSig2 Participant Partial Signature +| PSBT_IN_MUSIG2_PARTIAL_SIG = 0x1c +| <33 byte compressed pubkey> <33 byte plain pubkey> <32 byte hash or omitted> +| The compressed public key of the participant providing this partial signature, followed by the +plain public key the participant is providing the signature for, followed by the BIP 341 tapleaf hash +of the Taproot leaf script that will be signed. If the aggregate key is the taproot internal key or +the taproot output key, then the tapleaf hash must be omitted. Note that the plain public key must +be the key found in the script and not the aggregate public key that it was derived from, if it was +derived from an aggregate key. +| <32 byte partial signature> +| The partial signature produced by the Sign algorithm. +| +| +| 0, 2 +| [[bip-0373.mediawiki|373]] +|- +| Silent Payment Input ECDH Share +| PSBT_IN_SP_ECDH_SHARE = 0x1d +| <33 byte scan key> +| The scan key that this ECDH share is for. +| <33 byte share> +| An ECDH share for a scan key. The ECDH shared is computed with ''a * B_scan'', where ''a'' is the private key of the corresponding prevout public key, and ''B_scan'' is the scan key of a recipient. +| +| 0 +| 2 +| [[bip-0375.mediawiki|375]] +|- +| Silent Payment Input DLEQ Proof +| PSBT_IN_SP_DLEQ = 0x1e +| <33 byte scan key> +| The scan key that this proof covers. +| <64-byte proof> +| A BIP374 DLEQ proof computed for the matching ECDH share. +| +| 0 +| 2 +| [[bip-0375.mediawiki|375]] +|- +| Proprietary Use Type +| PSBT_IN_PROPRIETARY = 0xFC +| +| Compact size unsigned integer of the length of the identifier, followed by identifier prefix, followed by a compact size unsigned integer subtype, followed by the key data itself. +| +| Any value data as defined by the proprietary type user. +| +| +| 0, 2 +| 174 +|} + +The currently defined per-output '''Why do we need per-output data?''' Per-output data allows signers +to verify that the outputs are going to the intended recipient. The output data can also be use by signers to +determine which outputs are change outputs and verify that the change is returning to the correct place. types are defined as follows: + +{| +! Name +! +! +! Description +! +! Description +! Versions Requiring Inclusion +! Versions Requiring Exclusion +! Versions Allowing Inclusion +! Parent BIP +|- +| Redeem Script +| PSBT_OUT_REDEEM_SCRIPT = 0x00 +| None +| No key data +| +| The redeemScript for this output if it has one. +| +| +| 0, 2 +| 174 +|- +| Witness Script +| PSBT_OUT_WITNESS_SCRIPT = 0x01 +| None +| No key data +| +| The witnessScript for this output if it has one. +| +| +| 0, 2 +| 174 +|- +| BIP 32 Derivation Path +| PSBT_OUT_BIP32_DERIVATION = 0x02 +| +| The public key +| <4 byte fingerprint> <32-bit little endian uint path element>* +| The master key fingerprint concatenated with the derivation path of the public key. The derivation path is represented as 32-bit little endian unsigned integer indexes concatenated with each other. Public keys are those needed to spend this output. +| +| +| 0, 2 +| 174 +|- +| Output Amount +| PSBT_OUT_AMOUNT = 0x03 +| None +| No key data +| <64-bit int amount> +| 64 bit signed little endian integer representing the output's amount in satoshis. +| 2 +| 0 +| 2 +| [[bip-0370.mediawiki|370]] +|- +| Output Script +| PSBT_OUT_SCRIPT = 0x04 +| None +| No key data +| +| The script for this output, also known as the scriptPubKey. Must be omitted in PSBTv0. Must be provided in PSBTv2 if not sending to a BIP352 silent payment address, otherwise may be omitted. +| +| 0 +| 2 +| [[bip-0370.mediawiki|370]], [[bip-0375.mediawiki|375]] +|- +| Taproot Internal Key +| PSBT_OUT_TAP_INTERNAL_KEY = 0x05 +| None +| No key data +| <32 byte xonlypubkey> +| The X-only pubkey used as the internal key in this output. +| +| +| 0, 2 +| [[bip-0371.mediawiki|371]] +|- +| Taproot Tree +| PSBT_OUT_TAP_TREE = 0x06 +| None +| No key data +| {<8-bit uint depth> <8-bit uint leaf version> }* +| One or more tuples representing the depth, leaf version, and script for a leaf in the Taproot tree, allowing the entire tree to be reconstructed. The tuples must be in depth first search order so that the tree is correctly reconstructed. Each tuple is an 8-bit unsigned integer representing the depth in the Taproot tree for this script, an 8-bit unsigned integer representing the leaf version, the length of the script as a compact size unsigned integer, and the script itself. +| +| +| 0, 2 +| [[bip-0371.mediawiki|371]] +|- +| Taproot Key BIP 32 Derivation Path +| PSBT_OUT_TAP_BIP32_DERIVATION = 0x07 +| <32 byte xonlypubkey> +| A 32 byte X-only public key involved in this output. It may be the output key, the internal key, or a key present in a leaf script. +| <32 byte leaf hash>* <4 byte fingerprint> <32-bit little endian uint path element>* +| A compact size unsigned integer representing the number of leaf hashes, followed by a list of leaf hashes, followed by the 4 byte master key fingerprint concatenated with the derivation path of the public key. The derivation path is represented as 32-bit little endian unsigned integer indexes concatenated with each other. Public keys are those needed to spend this output. The leaf hashes are of the leaves which involve this public key. The internal key does not have leaf hashes, so can be indicated with a hashes len of 0. Finalizers should remove this field after PSBT_IN_FINAL_SCRIPTWITNESS is constructed. +| +| +| 0, 2 +| [[bip-0371.mediawiki|371]] +|- +| MuSig2 Participant Public Keys +| PSBT_OUT_MUSIG2_PARTICIPANT_PUBKEYS = 0x08 +| <33 byte plain aggregate pubkey> +| The MuSig2 aggregate plain public key from the KeyAgg algorithm. This key may or may not +be in the script directly. It may instead be a parent public key from which the public keys in the +script were derived. +| <33 byte compressed pubkey>* +| A list of the compressed public keys of the participants in the MuSig2 aggregate key in the order +required for aggregation. If sorting was done, then the keys must be in the sorted order. +| +| +| 0, 2 +| [[bip-0373.mediawiki|373]] +|- +| Silent Payment Data +| PSBT_OUT_SP_V0_INFO = 0x09 +| None +| No key data +| <33 byte scan key> <33 byte spend key> +| The scan and spend public keys from the silent payments address. +| +| 0 +| 2 +| [[bip-0375.mediawiki|375]] +|- +| Silent Payment Label +| PSBT_OUT_SP_V0_LABEL = 0x0a +| None +| No key data +| <32-bit little endian uint label> +| The label to use to compute the spend key of the silent payments address to verify change. +| +| 0 +| 2 +| [[bip-0375.mediawiki|375]] +|- +| BIP 353 DNSSEC proof +| PSBT_OUT_DNSSEC_PROOF = 0x35 +| None +| No key data +| <1-byte-length-prefixed BIP 353 human-readable name> +| A BIP 353 human-readable name (without the ₿ prefix), prefixed by a 1-byte length. +Followed by an [[https://www.rfc-editor.org/rfc/rfc9102.html#name-dnssec-authentication-chain|RFC 9102 DNSSEC AuthenticationChain]] (i.e. a series of DNS Resource Records in no particular order) providing a DNSSEC proof to a BIP 353 DNS TXT record. +| +| +| 0, 2 +| [[bip-0353.mediawiki|353]] +|- +| Proprietary Use Type +| PSBT_OUT_PROPRIETARY = 0xFC +| +| Compact size unsigned integer of the length of the identifier, followed by identifier prefix, followed by a compact size unsigned integer subtype, followed by the key data itself. +| +| Any value data as defined by the proprietary type user. +| +| +| 0, 2 +| 174 +|} + +Types can be skipped when they are unnecessary. For example, if an input is a witness +input, then it should not have a Non-Witness UTXO key-value pair. + +If the signer encounters key-value pairs that it does not understand, it must +pass those key-value pairs through when re-serializing the transaction. + +All keys must have the data that they specify. If any key or value does not match the +specified format for that type, the PSBT must be considered invalid. For example, any +key that has no data except for the type specifier must only have the type specifier in +the key. + +===Handling Duplicated Keys=== + +Keys within each scope should never be duplicated; all keys in the format are unique. PSBTs containing duplicate keys are invalid. However implementers +will still need to handle events where keys are duplicated when combining transactions with duplicated fields. In this event, the software may choose +whichever value it wishes.'''Why can the values be arbitrarily chosen?''' When there are duplicated keys, the values that can be chosen will either be +valid or invalid. If the values are invalid, a signer would simply produce an invalid signature and the final transaction itself would be invalid. If the +values are valid, then it does not matter which is chosen as either way the transaction is still valid. + +===Proprietary Use Type=== + +For all global, per-input, and per-output maps, the type 0xFC is reserved for proprietary use. +The proprietary use type requires keys that follow the type with a compact size unsigned integer representing the length of the string identifier, followed by the string identifier, then a subtype, and finally any key data. + +The identifier can be any variable length string that software can use to identify whether the particular data in the proprietary type can be used by it. +It can also be the empty string although this is not recommended. + +The subtype is defined by the proprietary type user and can mean whatever they want it to mean. +The subtype must also be a compact size unsigned integer in the same form as the normal types. +The key data and value data are defined by the proprietary type user. + +The proprietary use type is for private use by individuals and organizations who wish to use PSBT in their processes. +It is useful when there are additional data that they need attached to a PSBT but such data are not useful or available for the general public. +The proprietary use type is not to be used by any public specification and there is no expectation that any publicly available software be able to understand any specific meanings of it and the subtypes. +This type must be used for internal processes only. + +==Version 0== + +Partially Signed Bitcoin Transactions version 0 is the first version of the PSBT format. +Version 0 PSBTs must either omit PSBT_GLOBAL_VERSION or include it and set it to 0. +Version 0 PSBTs must include PSBT_GLOBAL_UNSIGNED_TX, if omitted, the PSBT is invalid. + +==Roles== + +Using the transaction format involves many different roles. Multiple roles can be handled by a single entity, but each role is specialized in what it should be capable of doing. + +===Creator=== + +The Creator creates a new PSBT. It must create an unsigned transaction and place it in the PSBT. +The Creator must create empty input and output fields. + +===Updater=== + +The Updater must only accept a PSBT. +The Updater adds information to the PSBT that it has access to. If it has the UTXO for an input, it should add it to the PSBT. +The Updater should also add redeemScripts, witnessScripts, and BIP 32 derivation paths to the input and output data if it knows them. + +A single entity is likely to be both a Creator and Updater. + +===Signer=== + +The Signer must only accept a PSBT. +The Signer must only use the UTXOs provided in the PSBT to produce signatures for inputs. +Before signing a non-witness input, the Signer must verify that the TXID of the non-witness UTXO matches the TXID specified in the unsigned transaction. +Before signing a witness input, the Signer must verify that the witnessScript (if provided) matches the hash specified in the UTXO or the redeemScript, and the redeemScript (if provided) matches the hash in the UTXO. +The Signer may choose to fail to sign a segwit input if a non-witness UTXO is not provided. '''Why would non-witness UTXOs be provided for segwit inputs?''' The sighash algorithm for Segwit specified in BIP 143 is known to have an issue where an attacker could trick a user to sending Bitcoin to fees if they are able to convince the user to sign a malicious transaction multiple times. This is possible because the amounts in PSBT_IN_WITNESS_UTXO of other segwit inputs can be modified without effecting the signature for a particular input. In order to prevent this kind of attack, many wallets are requiring that the full previous transaction (i.e. PSBT_IN_NON_WITNESS_UTXO) be provided to ensure that the amounts of other inputs are not being tampered with. +The Signer should not need any additional data sources, as all necessary information is provided in the PSBT format. +The Signer must only add data to a PSBT. +Any signatures created by the Signer must be added as a "Partial Signature" key-value pair for the respective input it relates to. +If a Signer cannot sign a transaction, it must not add a Partial Signature. + +The Signer can additionally compute the addresses and values being sent, and the transaction fee, optionally showing this data to the user as a confirmation of intent and the consequences of signing the PSBT. + +Signers do not need to sign for all possible input types. For example, a signer may choose to only sign Segwit inputs. + +A single entity is likely to be both a Signer and an Updater as it can update a PSBT with necessary information prior to signing it. + +====Data Signers Check For==== + +For a Signer to only produce valid signatures for what it expects to sign, it must check that the following conditions are true: + +* If a non-witness UTXO is provided, its hash must match the hash specified in the prevout +* If a witness UTXO is provided, no non-witness signature may be created +* If a redeemScript is provided, the scriptPubKey must be for that redeemScript +* If a witnessScript is provided, the scriptPubKey or the redeemScript must be for that witnessScript +* If a sighash type is provided, the signer must check that the sighash is acceptable. If unacceptable, they must fail. +* If a sighash type is not provided, the signer should sign using SIGHASH_ALL, but may use any sighash type they wish. + +=====Simple Signer Algorithm===== + +A simple signer can use the following algorithm to determine what and how to sign + +
+sign_witness(script_code, i):
+    for key, sighash_type in psbt.inputs[i].items:
+        if sighash_type == None:
+            sighash_type = SIGHASH_ALL
+        if IsMine(key) and IsAcceptable(sighash_type):
+            sign(witness_sighash(script_code, i, input))
+
+sign_non_witness(script_code, i):
+    for key, sighash_type in psbt.inputs[i].items:
+        if sighash_type == None:
+            sighash_type = SIGHASH_ALL
+        if IsMine(key) and IsAcceptable(sighash_type):
+            sign(non_witness_sighash(script_code, i, input))
+
+for input, i in enumerate(psbt.inputs):
+    if witness_utxo.exists:
+        if redeemScript.exists:
+            assert(witness_utxo.scriptPubKey == P2SH(redeemScript))
+            script = redeemScript
+        else:
+            script = witness_utxo.scriptPubKey
+        if IsP2WPKH(script):
+            sign_witness(P2PKH(script[2:22]), i)
+        else if IsP2WSH(script):
+            assert(script == P2WSH(witnessScript))
+            sign_witness(witnessScript, i)
+    else if non_witness_utxo.exists:
+        assert(sha256d(non_witness_utxo) == psbt.tx.input[i].prevout.hash)
+        if redeemScript.exists:
+            assert(non_witness_utxo.vout[psbt.tx.input[i].prevout.n].scriptPubKey == P2SH(redeemScript))
+            sign_non_witness(redeemScript, i)
+        else:
+            sign_non_witness(non_witness_utxo.vout[psbt.tx.input[i].prevout.n].scriptPubKey, i)
+    else:
+        assert False
+
+ +====Change Detection==== + +Signers may wish to display the inputs and outputs to users for extra verification. +In such displays, signers may wish to identify which outputs are change outputs in order to omit them to avoid additional user confusion. +In order to detect change, a signer can use the BIP 32 derivation paths provided in inputs and outputs as well as the extended public keys provided globally. + +For a single key output, a signer can observe whether the master fingerprint for the public key for that output belongs to itself. +If it does, it can then derive the public key at the specified derivation path and check whether that key is the one present in that output. + +For outputs involving multiple keys, a signer can first examine the inputs that it is signing. +It should determine the general pattern of the script and internally produce a representation of the policy that the script represents. +Such a policy can include things like how many keys are present, what order they are in, how many signers are necessary, which signers are required, etc. +The signer can then use the BIP 32 derivation paths for each of the pubkeys to find which global extended public key is the one that can derive that particular public key. +To do so, the signer would extract the derivation path to the highest hardened index and use that to lookup the public key with that index and master fingerprint. +The signer would construct this script policy with extended public keys for all of the inputs and outputs. +Change outputs would then be identified as being the outputs which have the same script policy as the inputs that are being signed. + +===Combiner=== + +The Combiner can accept 1 or many PSBTs. +The Combiner must merge them into one PSBT (if possible), or fail. +The resulting PSBT must contain all of the key-value pairs from each of the PSBTs. +The Combiner must remove any duplicate key-value pairs, in accordance with the specification. It can pick arbitrarily when conflicts occur. +A Combiner must not combine two different PSBTs. PSBTs can be uniquely identified by 0x00 global transaction typed key-value pair. +For every type that a Combiner understands, it may refuse to combine PSBTs if it detects that there will be inconsistencies or conflicts for that type in the combined PSBT. + +The Combiner does not need to know how to interpret scripts in order to combine PSBTs. It can do so without understanding scripts or the network serialization format. + +In general, the result of a Combiner combining two PSBTs from independent participants A and B should be functionally equivalent to a result obtained from processing the original PSBT by A and then B in a sequence. +Or, for participants performing fA(psbt) and fB(psbt): Combine(fA(psbt), fB(psbt)) == fA(fB(psbt)) == fB(fA(psbt)) + +===Input Finalizer=== + +The Input Finalizer must only accept a PSBT. +For each input, the Input Finalizer determines if the input has enough data to pass validation. If it does, it must construct the 0x07 Finalized scriptSig and 0x08 Finalized scriptWitness and place them into the input key-value map. +If scriptSig is empty for an input, 0x07 should remain unset rather than assigned an empty array. +Likewise, if no scriptWitness exists for an input, 0x08 should remain unset rather than assigned an empty array. +All other data except the UTXO and unknown fields in the input key-value map should be cleared from the PSBT. The UTXO should be kept to allow Transaction Extractors to verify the final network serialized transaction. + +===Transaction Extractor=== + +The Transaction Extractor must only accept a PSBT. +It checks whether all inputs have complete scriptSigs and scriptWitnesses by checking for the presence of 0x07 Finalized scriptSig and 0x08 Finalized scriptWitness typed records. If they do, the Transaction Extractor should construct complete scriptSigs and scriptWitnesses and encode them into network serialized transactions. Otherwise the Extractor must not modify the PSBT. +The Extractor should produce a fully valid, network serialized transaction if all inputs are complete. + +The Transaction Extractor does not need to know how to interpret scripts in order to extract the network serialized transaction. However it may be able to in order to validate the network serialized transaction at the same time. + +A single entity is likely to be both a Transaction Extractor and an Input Finalizer. + +==Encoding== + +A PSBT can be represented in two ways: in binary (as a file) or as a Base64 string using the encoding described in [https://tools.ietf.org/html/rfc4648#section-4 RFC4648]. + +Binary PSBT files should use the .psbt file extension. +A MIME type name will be added to this document once one has been registered. + +==Extensibility== + +The Partially Signed Transaction format can be extended in the future by adding +new types for key-value pairs. Backwards compatibility will still be maintained as those new +types will be ignored and passed-through by signers which do not know about them. + +===Version Numbers=== + +The Version number field exists only as a safeguard in the event that a backwards incompatible change is introduced to PSBT. +If a parser encounters a version number it does not recognize, it should exit immediately as this indicates that the PSBT will contain types that it does not know about and cannot be ignored. +Current PSBTs are Version 0. Any PSBT that does not have the version field is version 0. +It is not expected that any backwards incompatible change will be introduced to PSBT, so it is not expected that the version field will ever actually be seen. + +Updaters and combiners that need to add a version number to a PSBT should use the highest version number required. +For example, if a combiner sees two PSBTs for the same transaction, one with version 0, and the other with version 1, then it should combine them and produce a PSBT with version 1. +If an updater is updating a PSBT and needs to add a field that is only available in version 1, then it should set the PSBT version number to 1 unless a version higher than that is already specified. + +===Procedure For New Fields=== + +New fields should first be proposed on the bitcoin-dev mailing list. +If a field requires significant description as to its usage, it should be accompanied by a separate BIP. +The field must be added to the field listing tables in the Specification section. +Although some PSBT version 0 implementations encode types as uint8_t rather than compact size, +it is still safe to add >0xFD fields to PSBT 0, because these old parsers ignore +unknown fields, and is prefixed by its length. + +===Procedure For New Versions=== + +New PSBT versions must be described in a separate BIP. +The BIP may reference this BIP and any components of PSBT version 0 that are retained in the new version. +Any new fields described in the new version must be added to the field listing tables in the Specification section. + +==Compatibility== + +This transaction format is designed so that it is unable to be properly unserialized +by normal transaction unserializers. Likewise, a normal transaction will not be +able to be unserialized by an unserializer for the PSBT format. + +==Examples== + +===Manual CoinJoin Workflow=== + + + +===2-of-3 Multisig Workflow=== + + + +==Test Vectors== + +The following are invalid PSBTs: + +* Case: Network transaction, not PSBT format +** Bytes in Hex:
0200000001268171371edff285e937adeea4b37b78000c0566cbb3ad64641713ca42171bf6000000006a473044022070b2245123e6bf474d60c5b50c043d4c691a5d2435f09a34a7662a9dc251790a022001329ca9dacf280bdf30740ec0390422422c81cb45839457aeb76fc12edd95b3012102657d118d3357b8e0f4c2cd46db7b39f6d9c38d9a70abcb9b2de5dc8dbfe4ce31feffffff02d3dff505000000001976a914d0c59903c5bac2868760e90fd521a4665aa7652088ac00e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787b32e1300
+** Base64 String:
AgAAAAEmgXE3Ht/yhek3re6ks3t4AAwFZsuzrWRkFxPKQhcb9gAAAABqRzBEAiBwsiRRI+a/R01gxbUMBD1MaRpdJDXwmjSnZiqdwlF5CgIgATKcqdrPKAvfMHQOwDkEIkIsgctFg5RXrrdvwS7dlbMBIQJlfRGNM1e44PTCzUbbezn22cONmnCry5st5dyNv+TOMf7///8C09/1BQAAAAAZdqkU0MWZA8W6woaHYOkP1SGkZlqnZSCIrADh9QUAAAAAF6kUNUXm4zuDLEcFDyTT7rk8nAOUi8eHsy4TAA==
+ +* Case: PSBT missing outputs +** Bytes in Hex:
70736274ff0100750200000001268171371edff285e937adeea4b37b78000c0566cbb3ad64641713ca42171bf60000000000feffffff02d3dff505000000001976a914d0c59903c5bac2868760e90fd521a4665aa7652088ac00e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787b32e1300000100fda5010100000000010289a3c71eab4d20e0371bbba4cc698fa295c9463afa2e397f8533ccb62f9567e50100000017160014be18d152a9b012039daf3da7de4f53349eecb985ffffffff86f8aa43a71dff1448893a530a7237ef6b4608bbb2dd2d0171e63aec6a4890b40100000017160014fe3e9ef1a745e974d902c4355943abcb34bd5353ffffffff0200c2eb0b000000001976a91485cff1097fd9e008bb34af709c62197b38978a4888ac72fef84e2c00000017a914339725ba21efd62ac753a9bcd067d6c7a6a39d05870247304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c012103d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f210502483045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01210223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab30000000000
+** Base64 String:
cHNidP8BAHUCAAAAASaBcTce3/KF6Tet7qSze3gADAVmy7OtZGQXE8pCFxv2AAAAAAD+////AtPf9QUAAAAAGXapFNDFmQPFusKGh2DpD9UhpGZap2UgiKwA4fUFAAAAABepFDVF5uM7gyxHBQ8k0+65PJwDlIvHh7MuEwAAAQD9pQEBAAAAAAECiaPHHqtNIOA3G7ukzGmPopXJRjr6Ljl/hTPMti+VZ+UBAAAAFxYAFL4Y0VKpsBIDna89p95PUzSe7LmF/////4b4qkOnHf8USIk6UwpyN+9rRgi7st0tAXHmOuxqSJC0AQAAABcWABT+Pp7xp0XpdNkCxDVZQ6vLNL1TU/////8CAMLrCwAAAAAZdqkUhc/xCX/Z4Ai7NK9wnGIZeziXikiIrHL++E4sAAAAF6kUM5cluiHv1irHU6m80GfWx6ajnQWHAkcwRAIgJxK+IuAnDzlPVoMR3HyppolwuAJf3TskAinwf4pfOiQCIAGLONfc0xTnNMkna9b7QPZzMlvEuqFEyADS8vAtsnZcASED0uFWdJQbrUqZY3LLh+GFbTZSYG2YVi/jnF6efkE/IQUCSDBFAiEA0SuFLYXc2WHS9fSrZgZU327tzHlMDDPOXMMJ/7X85Y0CIGczio4OFyXBl/saiK9Z9R5E5CVbIBZ8hoQDHAXR8lkqASECI7cr7vCWXRC+B3jv7NYfysb3mk6haTkzgHNEZPhPKrMAAAAAAA==
+ +* Case: PSBT where one input has a filled scriptSig in the unsigned tx +** Bytes in Hex:
70736274ff0100fd0a010200000002ab0949a08c5af7c49b8212f417e2f15ab3f5c33dcf153821a8139f877a5b7be4000000006a47304402204759661797c01b036b25928948686218347d89864b719e1f7fcf57d1e511658702205309eabf56aa4d8891ffd111fdf1336f3a29da866d7f8486d75546ceedaf93190121035cdc61fc7ba971c0b501a646a2a83b102cb43881217ca682dc86e2d73fa88292feffffffab0949a08c5af7c49b8212f417e2f15ab3f5c33dcf153821a8139f877a5b7be40100000000feffffff02603bea0b000000001976a914768a40bbd740cbe81d988e71de2a4d5c71396b1d88ac8e240000000000001976a9146f4620b553fa095e721b9ee0efe9fa039cca459788ac00000000000001012000e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787010416001485d13537f2e265405a34dbafa9e3dda01fb82308000000
+** Base64 String:
cHNidP8BAP0KAQIAAAACqwlJoIxa98SbghL0F+LxWrP1wz3PFTghqBOfh3pbe+QAAAAAakcwRAIgR1lmF5fAGwNrJZKJSGhiGDR9iYZLcZ4ff89X0eURZYcCIFMJ6r9Wqk2Ikf/REf3xM286KdqGbX+EhtdVRs7tr5MZASEDXNxh/HupccC1AaZGoqg7ECy0OIEhfKaC3Ibi1z+ogpL+////qwlJoIxa98SbghL0F+LxWrP1wz3PFTghqBOfh3pbe+QBAAAAAP7///8CYDvqCwAAAAAZdqkUdopAu9dAy+gdmI5x3ipNXHE5ax2IrI4kAAAAAAAAGXapFG9GILVT+glechue4O/p+gOcykWXiKwAAAAAAAABASAA4fUFAAAAABepFDVF5uM7gyxHBQ8k0+65PJwDlIvHhwEEFgAUhdE1N/LiZUBaNNuvqePdoB+4IwgAAAA=
+ +* Case: PSBT where inputs and outputs are provided but without an unsigned tx +** Bytes in Hex:
70736274ff000100fda5010100000000010289a3c71eab4d20e0371bbba4cc698fa295c9463afa2e397f8533ccb62f9567e50100000017160014be18d152a9b012039daf3da7de4f53349eecb985ffffffff86f8aa43a71dff1448893a530a7237ef6b4608bbb2dd2d0171e63aec6a4890b40100000017160014fe3e9ef1a745e974d902c4355943abcb34bd5353ffffffff0200c2eb0b000000001976a91485cff1097fd9e008bb34af709c62197b38978a4888ac72fef84e2c00000017a914339725ba21efd62ac753a9bcd067d6c7a6a39d05870247304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c012103d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f210502483045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01210223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab30000000000
+** Base64 String:
cHNidP8AAQD9pQEBAAAAAAECiaPHHqtNIOA3G7ukzGmPopXJRjr6Ljl/hTPMti+VZ+UBAAAAFxYAFL4Y0VKpsBIDna89p95PUzSe7LmF/////4b4qkOnHf8USIk6UwpyN+9rRgi7st0tAXHmOuxqSJC0AQAAABcWABT+Pp7xp0XpdNkCxDVZQ6vLNL1TU/////8CAMLrCwAAAAAZdqkUhc/xCX/Z4Ai7NK9wnGIZeziXikiIrHL++E4sAAAAF6kUM5cluiHv1irHU6m80GfWx6ajnQWHAkcwRAIgJxK+IuAnDzlPVoMR3HyppolwuAJf3TskAinwf4pfOiQCIAGLONfc0xTnNMkna9b7QPZzMlvEuqFEyADS8vAtsnZcASED0uFWdJQbrUqZY3LLh+GFbTZSYG2YVi/jnF6efkE/IQUCSDBFAiEA0SuFLYXc2WHS9fSrZgZU327tzHlMDDPOXMMJ/7X85Y0CIGczio4OFyXBl/saiK9Z9R5E5CVbIBZ8hoQDHAXR8lkqASECI7cr7vCWXRC+B3jv7NYfysb3mk6haTkzgHNEZPhPKrMAAAAAAA==
+ +* Case: PSBT with duplicate keys in an input +** Bytes in Hex:
70736274ff0100750200000001268171371edff285e937adeea4b37b78000c0566cbb3ad64641713ca42171bf60000000000feffffff02d3dff505000000001976a914d0c59903c5bac2868760e90fd521a4665aa7652088ac00e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787b32e1300000100fda5010100000000010289a3c71eab4d20e0371bbba4cc698fa295c9463afa2e397f8533ccb62f9567e50100000017160014be18d152a9b012039daf3da7de4f53349eecb985ffffffff86f8aa43a71dff1448893a530a7237ef6b4608bbb2dd2d0171e63aec6a4890b40100000017160014fe3e9ef1a745e974d902c4355943abcb34bd5353ffffffff0200c2eb0b000000001976a91485cff1097fd9e008bb34af709c62197b38978a4888ac72fef84e2c00000017a914339725ba21efd62ac753a9bcd067d6c7a6a39d05870247304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c012103d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f210502483045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01210223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab30000000001003f0200000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffff010000000000000000036a010000000000000000
+** Base64 String:
cHNidP8BAHUCAAAAASaBcTce3/KF6Tet7qSze3gADAVmy7OtZGQXE8pCFxv2AAAAAAD+////AtPf9QUAAAAAGXapFNDFmQPFusKGh2DpD9UhpGZap2UgiKwA4fUFAAAAABepFDVF5uM7gyxHBQ8k0+65PJwDlIvHh7MuEwAAAQD9pQEBAAAAAAECiaPHHqtNIOA3G7ukzGmPopXJRjr6Ljl/hTPMti+VZ+UBAAAAFxYAFL4Y0VKpsBIDna89p95PUzSe7LmF/////4b4qkOnHf8USIk6UwpyN+9rRgi7st0tAXHmOuxqSJC0AQAAABcWABT+Pp7xp0XpdNkCxDVZQ6vLNL1TU/////8CAMLrCwAAAAAZdqkUhc/xCX/Z4Ai7NK9wnGIZeziXikiIrHL++E4sAAAAF6kUM5cluiHv1irHU6m80GfWx6ajnQWHAkcwRAIgJxK+IuAnDzlPVoMR3HyppolwuAJf3TskAinwf4pfOiQCIAGLONfc0xTnNMkna9b7QPZzMlvEuqFEyADS8vAtsnZcASED0uFWdJQbrUqZY3LLh+GFbTZSYG2YVi/jnF6efkE/IQUCSDBFAiEA0SuFLYXc2WHS9fSrZgZU327tzHlMDDPOXMMJ/7X85Y0CIGczio4OFyXBl/saiK9Z9R5E5CVbIBZ8hoQDHAXR8lkqASECI7cr7vCWXRC+B3jv7NYfysb3mk6haTkzgHNEZPhPKrMAAAAAAQA/AgAAAAH//////////////////////////////////////////wAAAAAA/////wEAAAAAAAAAAANqAQAAAAAAAAAA
+ +* Case: PSBT with invalid global transaction typed key +** Bytes in Hex:
70736274ff020001550200000001279a2323a5dfb51fc45f220fa58b0fc13e1e3342792a85d7e36cd6333b5cbc390000000000ffffffff01a05aea0b000000001976a914ffe9c0061097cc3b636f2cb0460fa4fc427d2b4588ac0000000000010120955eea0b0000000017a9146345200f68d189e1adc0df1c4d16ea8f14c0dbeb87220203b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd4646304302200424b58effaaa694e1559ea5c93bbfd4a89064224055cdf070b6771469442d07021f5c8eb0fea6516d60b8acb33ad64ede60e8785bfb3aa94b99bdf86151db9a9a010104220020771fd18ad459666dd49f3d564e3dbc42f4c84774e360ada16816a8ed488d5681010547522103b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd462103de55d1e1dac805e3f8a58c1fbf9b94c02f3dbaafe127fefca4995f26f82083bd52ae220603b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd4610b4a6ba67000000800000008004000080220603de55d1e1dac805e3f8a58c1fbf9b94c02f3dbaafe127fefca4995f26f82083bd10b4a6ba670000008000000080050000800000
+** Base64 String:
cHNidP8CAAFVAgAAAAEnmiMjpd+1H8RfIg+liw/BPh4zQnkqhdfjbNYzO1y8OQAAAAAA/////wGgWuoLAAAAABl2qRT/6cAGEJfMO2NvLLBGD6T8Qn0rRYisAAAAAAABASCVXuoLAAAAABepFGNFIA9o0YnhrcDfHE0W6o8UwNvrhyICA7E0HMunaDtq9PEjjNbpfnFn1Wn6xH8eSNR1QYRDVb1GRjBDAiAEJLWO/6qmlOFVnqXJO7/UqJBkIkBVzfBwtncUaUQtBwIfXI6w/qZRbWC4rLM61k7eYOh4W/s6qUuZvfhhUduamgEBBCIAIHcf0YrUWWZt1J89Vk49vEL0yEd042CtoWgWqO1IjVaBAQVHUiEDsTQcy6doO2r08SOM1ul+cWfVafrEfx5I1HVBhENVvUYhA95V0eHayAXj+KWMH7+blMAvPbqv4Sf+/KSZXyb4IIO9Uq4iBgOxNBzLp2g7avTxI4zW6X5xZ9Vp+sR/HkjUdUGEQ1W9RhC0prpnAAAAgAAAAIAEAACAIgYD3lXR4drIBeP4pYwfv5uUwC89uq/hJ/78pJlfJvggg70QtKa6ZwAAAIAAAACABQAAgAAA
+ +* Case: PSBT with invalid input witness utxo typed key +** Bytes in Hex:
70736274ff0100550200000001279a2323a5dfb51fc45f220fa58b0fc13e1e3342792a85d7e36cd6333b5cbc390000000000ffffffff01a05aea0b000000001976a914ffe9c0061097cc3b636f2cb0460fa4fc427d2b4588ac000000000002010020955eea0b0000000017a9146345200f68d189e1adc0df1c4d16ea8f14c0dbeb87220203b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd4646304302200424b58effaaa694e1559ea5c93bbfd4a89064224055cdf070b6771469442d07021f5c8eb0fea6516d60b8acb33ad64ede60e8785bfb3aa94b99bdf86151db9a9a010104220020771fd18ad459666dd49f3d564e3dbc42f4c84774e360ada16816a8ed488d5681010547522103b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd462103de55d1e1dac805e3f8a58c1fbf9b94c02f3dbaafe127fefca4995f26f82083bd52ae220603b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd4610b4a6ba67000000800000008004000080220603de55d1e1dac805e3f8a58c1fbf9b94c02f3dbaafe127fefca4995f26f82083bd10b4a6ba670000008000000080050000800000
+** Base64 String:
cHNidP8BAFUCAAAAASeaIyOl37UfxF8iD6WLD8E+HjNCeSqF1+Ns1jM7XLw5AAAAAAD/////AaBa6gsAAAAAGXapFP/pwAYQl8w7Y28ssEYPpPxCfStFiKwAAAAAAAIBACCVXuoLAAAAABepFGNFIA9o0YnhrcDfHE0W6o8UwNvrhyICA7E0HMunaDtq9PEjjNbpfnFn1Wn6xH8eSNR1QYRDVb1GRjBDAiAEJLWO/6qmlOFVnqXJO7/UqJBkIkBVzfBwtncUaUQtBwIfXI6w/qZRbWC4rLM61k7eYOh4W/s6qUuZvfhhUduamgEBBCIAIHcf0YrUWWZt1J89Vk49vEL0yEd042CtoWgWqO1IjVaBAQVHUiEDsTQcy6doO2r08SOM1ul+cWfVafrEfx5I1HVBhENVvUYhA95V0eHayAXj+KWMH7+blMAvPbqv4Sf+/KSZXyb4IIO9Uq4iBgOxNBzLp2g7avTxI4zW6X5xZ9Vp+sR/HkjUdUGEQ1W9RhC0prpnAAAAgAAAAIAEAACAIgYD3lXR4drIBeP4pYwfv5uUwC89uq/hJ/78pJlfJvggg70QtKa6ZwAAAIAAAACABQAAgAAA
+ +* Case: PSBT with invalid pubkey length for input partial signature typed key +** Bytes in Hex:
70736274ff0100550200000001279a2323a5dfb51fc45f220fa58b0fc13e1e3342792a85d7e36cd6333b5cbc390000000000ffffffff01a05aea0b000000001976a914ffe9c0061097cc3b636f2cb0460fa4fc427d2b4588ac0000000000010120955eea0b0000000017a9146345200f68d189e1adc0df1c4d16ea8f14c0dbeb87210203b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd46304302200424b58effaaa694e1559ea5c93bbfd4a89064224055cdf070b6771469442d07021f5c8eb0fea6516d60b8acb33ad64ede60e8785bfb3aa94b99bdf86151db9a9a010104220020771fd18ad459666dd49f3d564e3dbc42f4c84774e360ada16816a8ed488d5681010547522103b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd462103de55d1e1dac805e3f8a58c1fbf9b94c02f3dbaafe127fefca4995f26f82083bd52ae220603b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd4610b4a6ba67000000800000008004000080220603de55d1e1dac805e3f8a58c1fbf9b94c02f3dbaafe127fefca4995f26f82083bd10b4a6ba670000008000000080050000800000
+** Base64 String:
cHNidP8BAFUCAAAAASeaIyOl37UfxF8iD6WLD8E+HjNCeSqF1+Ns1jM7XLw5AAAAAAD/////AaBa6gsAAAAAGXapFP/pwAYQl8w7Y28ssEYPpPxCfStFiKwAAAAAAAEBIJVe6gsAAAAAF6kUY0UgD2jRieGtwN8cTRbqjxTA2+uHIQIDsTQcy6doO2r08SOM1ul+cWfVafrEfx5I1HVBhENVvUYwQwIgBCS1jv+qppThVZ6lyTu/1KiQZCJAVc3wcLZ3FGlELQcCH1yOsP6mUW1guKyzOtZO3mDoeFv7OqlLmb34YVHbmpoBAQQiACB3H9GK1FlmbdSfPVZOPbxC9MhHdONgraFoFqjtSI1WgQEFR1IhA7E0HMunaDtq9PEjjNbpfnFn1Wn6xH8eSNR1QYRDVb1GIQPeVdHh2sgF4/iljB+/m5TALz26r+En/vykmV8m+CCDvVKuIgYDsTQcy6doO2r08SOM1ul+cWfVafrEfx5I1HVBhENVvUYQtKa6ZwAAAIAAAACABAAAgCIGA95V0eHayAXj+KWMH7+blMAvPbqv4Sf+/KSZXyb4IIO9ELSmumcAAACAAAAAgAUAAIAAAA==
+ +* Case: PSBT with invalid redeemscript typed key +** Bytes in Hex:
70736274ff0100550200000001279a2323a5dfb51fc45f220fa58b0fc13e1e3342792a85d7e36cd6333b5cbc390000000000ffffffff01a05aea0b000000001976a914ffe9c0061097cc3b636f2cb0460fa4fc427d2b4588ac0000000000010120955eea0b0000000017a9146345200f68d189e1adc0df1c4d16ea8f14c0dbeb87220203b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd4646304302200424b58effaaa694e1559ea5c93bbfd4a89064224055cdf070b6771469442d07021f5c8eb0fea6516d60b8acb33ad64ede60e8785bfb3aa94b99bdf86151db9a9a01020400220020771fd18ad459666dd49f3d564e3dbc42f4c84774e360ada16816a8ed488d5681010547522103b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd462103de55d1e1dac805e3f8a58c1fbf9b94c02f3dbaafe127fefca4995f26f82083bd52ae220603b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd4610b4a6ba67000000800000008004000080220603de55d1e1dac805e3f8a58c1fbf9b94c02f3dbaafe127fefca4995f26f82083bd10b4a6ba670000008000000080050000800000
+** Base64 String:
cHNidP8BAFUCAAAAASeaIyOl37UfxF8iD6WLD8E+HjNCeSqF1+Ns1jM7XLw5AAAAAAD/////AaBa6gsAAAAAGXapFP/pwAYQl8w7Y28ssEYPpPxCfStFiKwAAAAAAAEBIJVe6gsAAAAAF6kUY0UgD2jRieGtwN8cTRbqjxTA2+uHIgIDsTQcy6doO2r08SOM1ul+cWfVafrEfx5I1HVBhENVvUZGMEMCIAQktY7/qqaU4VWepck7v9SokGQiQFXN8HC2dxRpRC0HAh9cjrD+plFtYLisszrWTt5g6Hhb+zqpS5m9+GFR25qaAQIEACIAIHcf0YrUWWZt1J89Vk49vEL0yEd042CtoWgWqO1IjVaBAQVHUiEDsTQcy6doO2r08SOM1ul+cWfVafrEfx5I1HVBhENVvUYhA95V0eHayAXj+KWMH7+blMAvPbqv4Sf+/KSZXyb4IIO9Uq4iBgOxNBzLp2g7avTxI4zW6X5xZ9Vp+sR/HkjUdUGEQ1W9RhC0prpnAAAAgAAAAIAEAACAIgYD3lXR4drIBeP4pYwfv5uUwC89uq/hJ/78pJlfJvggg70QtKa6ZwAAAIAAAACABQAAgAAA
+ +* Case: PSBT with invalid witnessscript typed key +** Bytes in Hex:
70736274ff0100550200000001279a2323a5dfb51fc45f220fa58b0fc13e1e3342792a85d7e36cd6333b5cbc390000000000ffffffff01a05aea0b000000001976a914ffe9c0061097cc3b636f2cb0460fa4fc427d2b4588ac0000000000010120955eea0b0000000017a9146345200f68d189e1adc0df1c4d16ea8f14c0dbeb87220203b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd4646304302200424b58effaaa694e1559ea5c93bbfd4a89064224055cdf070b6771469442d07021f5c8eb0fea6516d60b8acb33ad64ede60e8785bfb3aa94b99bdf86151db9a9a010104220020771fd18ad459666dd49f3d564e3dbc42f4c84774e360ada16816a8ed488d568102050047522103b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd462103de55d1e1dac805e3f8a58c1fbf9b94c02f3dbaafe127fefca4995f26f82083bd52ae220603b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd4610b4a6ba67000000800000008004000080220603de55d1e1dac805e3f8a58c1fbf9b94c02f3dbaafe127fefca4995f26f82083bd10b4a6ba670000008000000080050000800000
+** Base64 String:
cHNidP8BAFUCAAAAASeaIyOl37UfxF8iD6WLD8E+HjNCeSqF1+Ns1jM7XLw5AAAAAAD/////AaBa6gsAAAAAGXapFP/pwAYQl8w7Y28ssEYPpPxCfStFiKwAAAAAAAEBIJVe6gsAAAAAF6kUY0UgD2jRieGtwN8cTRbqjxTA2+uHIgIDsTQcy6doO2r08SOM1ul+cWfVafrEfx5I1HVBhENVvUZGMEMCIAQktY7/qqaU4VWepck7v9SokGQiQFXN8HC2dxRpRC0HAh9cjrD+plFtYLisszrWTt5g6Hhb+zqpS5m9+GFR25qaAQEEIgAgdx/RitRZZm3Unz1WTj28QvTIR3TjYK2haBao7UiNVoECBQBHUiEDsTQcy6doO2r08SOM1ul+cWfVafrEfx5I1HVBhENVvUYhA95V0eHayAXj+KWMH7+blMAvPbqv4Sf+/KSZXyb4IIO9Uq4iBgOxNBzLp2g7avTxI4zW6X5xZ9Vp+sR/HkjUdUGEQ1W9RhC0prpnAAAAgAAAAIAEAACAIgYD3lXR4drIBeP4pYwfv5uUwC89uq/hJ/78pJlfJvggg70QtKa6ZwAAAIAAAACABQAAgAAA
+ +* Case: PSBT with invalid pubkey in input BIP 32 derivation paths typed key +** Bytes in Hex:
70736274ff0100550200000001279a2323a5dfb51fc45f220fa58b0fc13e1e3342792a85d7e36cd6333b5cbc390000000000ffffffff01a05aea0b000000001976a914ffe9c0061097cc3b636f2cb0460fa4fc427d2b4588ac0000000000010120955eea0b0000000017a9146345200f68d189e1adc0df1c4d16ea8f14c0dbeb87220203b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd4646304302200424b58effaaa694e1559ea5c93bbfd4a89064224055cdf070b6771469442d07021f5c8eb0fea6516d60b8acb33ad64ede60e8785bfb3aa94b99bdf86151db9a9a010104220020771fd18ad459666dd49f3d564e3dbc42f4c84774e360ada16816a8ed488d5681010547522103b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd462103de55d1e1dac805e3f8a58c1fbf9b94c02f3dbaafe127fefca4995f26f82083bd52ae210603b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd10b4a6ba67000000800000008004000080220603de55d1e1dac805e3f8a58c1fbf9b94c02f3dbaafe127fefca4995f26f82083bd10b4a6ba670000008000000080050000800000
+** Base64 String:
cHNidP8BAFUCAAAAASeaIyOl37UfxF8iD6WLD8E+HjNCeSqF1+Ns1jM7XLw5AAAAAAD/////AaBa6gsAAAAAGXapFP/pwAYQl8w7Y28ssEYPpPxCfStFiKwAAAAAAAEBIJVe6gsAAAAAF6kUY0UgD2jRieGtwN8cTRbqjxTA2+uHIgIDsTQcy6doO2r08SOM1ul+cWfVafrEfx5I1HVBhENVvUZGMEMCIAQktY7/qqaU4VWepck7v9SokGQiQFXN8HC2dxRpRC0HAh9cjrD+plFtYLisszrWTt5g6Hhb+zqpS5m9+GFR25qaAQEEIgAgdx/RitRZZm3Unz1WTj28QvTIR3TjYK2haBao7UiNVoEBBUdSIQOxNBzLp2g7avTxI4zW6X5xZ9Vp+sR/HkjUdUGEQ1W9RiED3lXR4drIBeP4pYwfv5uUwC89uq/hJ/78pJlfJvggg71SriEGA7E0HMunaDtq9PEjjNbpfnFn1Wn6xH8eSNR1QYRDVb0QtKa6ZwAAAIAAAACABAAAgCIGA95V0eHayAXj+KWMH7+blMAvPbqv4Sf+/KSZXyb4IIO9ELSmumcAAACAAAAAgAUAAIAAAA==
+ +* Case: PSBT with invalid non-witness utxo typed key +** Bytes in Hex:
70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f0000000000020000bb0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f6187650000000107da00473044022074018ad4180097b873323c0015720b3684cc8123891048e7dbcd9b55ad679c99022073d369b740e3eb53dcefa33823c8070514ca55a7dd9544f157c167913261118c01483045022100f61038b308dc1da865a34852746f015772934208c6d24454393cd99bdf2217770220056e675a675a6d0a02b85b14e5e29074d8a25a9b5760bea2816f661910a006ea01475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752ae0001012000c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e8870107232200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b20289030108da0400473044022062eb7a556107a7c73f45ac4ab5a1dddf6f7075fb1275969a7f383efff784bcb202200c05dbb7470dbf2f08557dd356c7325c1ed30913e996cd3840945db12228da5f01473044022065f45ba5998b59a27ffe1a7bed016af1f1f90d54b3aa8f7450aa5f56a25103bd02207f724703ad1edb96680b284b56d4ffcb88f7fb759eabbe08aa30f29b851383d20147522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae00220203a9a4c37f5996d3aa25dbac6b570af0650394492942460b354753ed9eeca5877110d90c6a4f000000800000008004000080002202027f6399757d2eff55a136ad02c684b1838b6556e5f1b6b34282a94b6b5005109610d90c6a4f00000080000000800500008000
+** Base64 String:
cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAIAALsCAAAAAarXOTEBi9JfhK5AC2iEi+CdtwbqwqwYKYur7nGrZW+LAAAAAEhHMEQCIFj2/HxqM+GzFUjUgcgmwBW9MBNarULNZ3kNq2bSrSQ7AiBKHO0mBMZzW2OT5bQWkd14sA8MWUL7n3UYVvqpOBV9ugH+////AoDw+gIAAAAAF6kUD7lGNCFpa4LIM68kHHjBfdveSTSH0PIKJwEAAAAXqRQpynT4oI+BmZQoGFyXtdhS5AY/YYdlAAAAAQfaAEcwRAIgdAGK1BgAl7hzMjwAFXILNoTMgSOJEEjn282bVa1nnJkCIHPTabdA4+tT3O+jOCPIBwUUylWn3ZVE8VfBZ5EyYRGMAUgwRQIhAPYQOLMI3B2oZaNIUnRvAVdyk0IIxtJEVDk82ZvfIhd3AiAFbmdaZ1ptCgK4WxTl4pB02KJam1dgvqKBb2YZEKAG6gFHUiEClYO/Oa4KYJdHrRma3dY0+mEIVZ1sXNObTCGD8auW4H8hAtq2H/SaFNtqfQKwzR+7ePxLGDErW05U2uTbovv+9TbXUq4AAQEgAMLrCwAAAAAXqRS39fr0Dj1ApaRZsds1NfK3L6kh6IcBByMiACCMI1MXN0O1ld+0oHtyuo5C43l9p06H/n2ddJfjsgKJAwEI2gQARzBEAiBi63pVYQenxz9FrEq1od3fb3B1+xJ1lpp/OD7/94S8sgIgDAXbt0cNvy8IVX3TVscyXB7TCRPpls04QJRdsSIo2l8BRzBEAiBl9FulmYtZon/+GnvtAWrx8fkNVLOqj3RQql9WolEDvQIgf3JHA60e25ZoCyhLVtT/y4j3+3Weq74IqjDym4UTg9IBR1IhAwidwQx6xttU+RMpr2FzM9s4jOrQwjH3IzedG5kDCwLcIQI63ZBPPW3PWd25BrDe4jUpt/+57VDl6GFRkmhgIh8Oc1KuACICA6mkw39ZltOqJdusa1cK8GUDlEkpQkYLNUdT7Z7spYdxENkMak8AAACAAAAAgAQAAIAAIgICf2OZdX0u/1WhNq0CxoSxg4tlVuXxtrNCgqlLa1AFEJYQ2QxqTwAAAIAAAACABQAAgAA=
+ +* Case: PSBT with invalid final scriptsig typed key +** Bytes in Hex:
70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f00000000000100bb0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f618765000000020700da00473044022074018ad4180097b873323c0015720b3684cc8123891048e7dbcd9b55ad679c99022073d369b740e3eb53dcefa33823c8070514ca55a7dd9544f157c167913261118c01483045022100f61038b308dc1da865a34852746f015772934208c6d24454393cd99bdf2217770220056e675a675a6d0a02b85b14e5e29074d8a25a9b5760bea2816f661910a006ea01475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752ae0001012000c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e8870107232200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b20289030108da0400473044022062eb7a556107a7c73f45ac4ab5a1dddf6f7075fb1275969a7f383efff784bcb202200c05dbb7470dbf2f08557dd356c7325c1ed30913e996cd3840945db12228da5f01473044022065f45ba5998b59a27ffe1a7bed016af1f1f90d54b3aa8f7450aa5f56a25103bd02207f724703ad1edb96680b284b56d4ffcb88f7fb759eabbe08aa30f29b851383d20147522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae00220203a9a4c37f5996d3aa25dbac6b570af0650394492942460b354753ed9eeca5877110d90c6a4f000000800000008004000080002202027f6399757d2eff55a136ad02c684b1838b6556e5f1b6b34282a94b6b5005109610d90c6a4f00000080000000800500008000
+** Base64 String:
cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAACBwDaAEcwRAIgdAGK1BgAl7hzMjwAFXILNoTMgSOJEEjn282bVa1nnJkCIHPTabdA4+tT3O+jOCPIBwUUylWn3ZVE8VfBZ5EyYRGMAUgwRQIhAPYQOLMI3B2oZaNIUnRvAVdyk0IIxtJEVDk82ZvfIhd3AiAFbmdaZ1ptCgK4WxTl4pB02KJam1dgvqKBb2YZEKAG6gFHUiEClYO/Oa4KYJdHrRma3dY0+mEIVZ1sXNObTCGD8auW4H8hAtq2H/SaFNtqfQKwzR+7ePxLGDErW05U2uTbovv+9TbXUq4AAQEgAMLrCwAAAAAXqRS39fr0Dj1ApaRZsds1NfK3L6kh6IcBByMiACCMI1MXN0O1ld+0oHtyuo5C43l9p06H/n2ddJfjsgKJAwEI2gQARzBEAiBi63pVYQenxz9FrEq1od3fb3B1+xJ1lpp/OD7/94S8sgIgDAXbt0cNvy8IVX3TVscyXB7TCRPpls04QJRdsSIo2l8BRzBEAiBl9FulmYtZon/+GnvtAWrx8fkNVLOqj3RQql9WolEDvQIgf3JHA60e25ZoCyhLVtT/y4j3+3Weq74IqjDym4UTg9IBR1IhAwidwQx6xttU+RMpr2FzM9s4jOrQwjH3IzedG5kDCwLcIQI63ZBPPW3PWd25BrDe4jUpt/+57VDl6GFRkmhgIh8Oc1KuACICA6mkw39ZltOqJdusa1cK8GUDlEkpQkYLNUdT7Z7spYdxENkMak8AAACAAAAAgAQAAIAAIgICf2OZdX0u/1WhNq0CxoSxg4tlVuXxtrNCgqlLa1AFEJYQ2QxqTwAAAIAAAACABQAAgAA=
+ +* Case: PSBT with invalid final script witness typed key +** Bytes in Hex:
70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f00000000000100bb0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f6187650000000107da00473044022074018ad4180097b873323c0015720b3684cc8123891048e7dbcd9b55ad679c99022073d369b740e3eb53dcefa33823c8070514ca55a7dd9544f157c167913261118c01483045022100f61038b308dc1da865a34852746f015772934208c6d24454393cd99bdf2217770220056e675a675a6d0a02b85b14e5e29074d8a25a9b5760bea2816f661910a006ea01475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752ae0001012000c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e8870107232200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b2028903020800da0400473044022062eb7a556107a7c73f45ac4ab5a1dddf6f7075fb1275969a7f383efff784bcb202200c05dbb7470dbf2f08557dd356c7325c1ed30913e996cd3840945db12228da5f01473044022065f45ba5998b59a27ffe1a7bed016af1f1f90d54b3aa8f7450aa5f56a25103bd02207f724703ad1edb96680b284b56d4ffcb88f7fb759eabbe08aa30f29b851383d20147522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae00220203a9a4c37f5996d3aa25dbac6b570af0650394492942460b354753ed9eeca5877110d90c6a4f000000800000008004000080002202027f6399757d2eff55a136ad02c684b1838b6556e5f1b6b34282a94b6b5005109610d90c6a4f00000080000000800500008000
+** Base64 String:
cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAABB9oARzBEAiB0AYrUGACXuHMyPAAVcgs2hMyBI4kQSOfbzZtVrWecmQIgc9Npt0Dj61Pc76M4I8gHBRTKVafdlUTxV8FnkTJhEYwBSDBFAiEA9hA4swjcHahlo0hSdG8BV3KTQgjG0kRUOTzZm98iF3cCIAVuZ1pnWm0KArhbFOXikHTYolqbV2C+ooFvZhkQoAbqAUdSIQKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfyEC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtdSrgABASAAwusLAAAAABepFLf1+vQOPUClpFmx2zU18rcvqSHohwEHIyIAIIwjUxc3Q7WV37Sge3K6jkLjeX2nTof+fZ10l+OyAokDAggA2gQARzBEAiBi63pVYQenxz9FrEq1od3fb3B1+xJ1lpp/OD7/94S8sgIgDAXbt0cNvy8IVX3TVscyXB7TCRPpls04QJRdsSIo2l8BRzBEAiBl9FulmYtZon/+GnvtAWrx8fkNVLOqj3RQql9WolEDvQIgf3JHA60e25ZoCyhLVtT/y4j3+3Weq74IqjDym4UTg9IBR1IhAwidwQx6xttU+RMpr2FzM9s4jOrQwjH3IzedG5kDCwLcIQI63ZBPPW3PWd25BrDe4jUpt/+57VDl6GFRkmhgIh8Oc1KuACICA6mkw39ZltOqJdusa1cK8GUDlEkpQkYLNUdT7Z7spYdxENkMak8AAACAAAAAgAQAAIAAIgICf2OZdX0u/1WhNq0CxoSxg4tlVuXxtrNCgqlLa1AFEJYQ2QxqTwAAAIAAAACABQAAgAA=
+ +* Case: PSBT with invalid pubkey in output BIP 32 derivation paths typed key +** Bytes in Hex:
70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f00000000000100bb0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f6187650000000107da00473044022074018ad4180097b873323c0015720b3684cc8123891048e7dbcd9b55ad679c99022073d369b740e3eb53dcefa33823c8070514ca55a7dd9544f157c167913261118c01483045022100f61038b308dc1da865a34852746f015772934208c6d24454393cd99bdf2217770220056e675a675a6d0a02b85b14e5e29074d8a25a9b5760bea2816f661910a006ea01475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752ae0001012000c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e8870107232200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b20289030108da0400473044022062eb7a556107a7c73f45ac4ab5a1dddf6f7075fb1275969a7f383efff784bcb202200c05dbb7470dbf2f08557dd356c7325c1ed30913e996cd3840945db12228da5f01473044022065f45ba5998b59a27ffe1a7bed016af1f1f90d54b3aa8f7450aa5f56a25103bd02207f724703ad1edb96680b284b56d4ffcb88f7fb759eabbe08aa30f29b851383d20147522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae00210203a9a4c37f5996d3aa25dbac6b570af0650394492942460b354753ed9eeca58710d90c6a4f000000800000008004000080002202027f6399757d2eff55a136ad02c684b1838b6556e5f1b6b34282a94b6b5005109610d90c6a4f00000080000000800500008000
+** Base64 String:
cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAABB9oARzBEAiB0AYrUGACXuHMyPAAVcgs2hMyBI4kQSOfbzZtVrWecmQIgc9Npt0Dj61Pc76M4I8gHBRTKVafdlUTxV8FnkTJhEYwBSDBFAiEA9hA4swjcHahlo0hSdG8BV3KTQgjG0kRUOTzZm98iF3cCIAVuZ1pnWm0KArhbFOXikHTYolqbV2C+ooFvZhkQoAbqAUdSIQKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfyEC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtdSrgABASAAwusLAAAAABepFLf1+vQOPUClpFmx2zU18rcvqSHohwEHIyIAIIwjUxc3Q7WV37Sge3K6jkLjeX2nTof+fZ10l+OyAokDAQjaBABHMEQCIGLrelVhB6fHP0WsSrWh3d9vcHX7EnWWmn84Pv/3hLyyAiAMBdu3Rw2/LwhVfdNWxzJcHtMJE+mWzThAlF2xIijaXwFHMEQCIGX0W6WZi1mif/4ae+0BavHx+Q1Us6qPdFCqX1aiUQO9AiB/ckcDrR7blmgLKEtW1P/LiPf7dZ6rvgiqMPKbhROD0gFHUiEDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtwhAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zUq4AIQIDqaTDf1mW06ol26xrVwrwZQOUSSlCRgs1R1PtnuylhxDZDGpPAAAAgAAAAIAEAACAACICAn9jmXV9Lv9VoTatAsaEsYOLZVbl8bazQoKpS2tQBRCWENkMak8AAACAAAAAgAUAAIAA
+ +* Case: PSBT with invalid input sighash type typed key +** Bytes in Hex:
70736274ff0100730200000001301ae986e516a1ec8ac5b4bc6573d32f83b465e23ad76167d68b38e730b4dbdb0000000000ffffffff02747b01000000000017a91403aa17ae882b5d0d54b25d63104e4ffece7b9ea2876043993b0000000017a914b921b1ba6f722e4bfa83b6557a3139986a42ec8387000000000001011f00ca9a3b00000000160014d2d94b64ae08587eefc8eeb187c601e939f9037c0203000100000000010016001462e9e982fff34dd8239610316b090cd2a3b747cb000100220020876bad832f1d168015ed41232a9ea65a1815d9ef13c0ef8759f64b5b2b278a65010125512103b7ce23a01c5b4bf00a642537cdfabb315b668332867478ef51309d2bd57f8a8751ae00
+** Base64 String:
cHNidP8BAHMCAAAAATAa6YblFqHsisW0vGVz0y+DtGXiOtdhZ9aLOOcwtNvbAAAAAAD/////AnR7AQAAAAAAF6kUA6oXrogrXQ1Usl1jEE5P/s57nqKHYEOZOwAAAAAXqRS5IbG6b3IuS/qDtlV6MTmYakLsg4cAAAAAAAEBHwDKmjsAAAAAFgAU0tlLZK4IWH7vyO6xh8YB6Tn5A3wCAwABAAAAAAEAFgAUYunpgv/zTdgjlhAxawkM0qO3R8sAAQAiACCHa62DLx0WgBXtQSMqnqZaGBXZ7xPA74dZ9ktbKyeKZQEBJVEhA7fOI6AcW0vwCmQlN836uzFbZoMyhnR471EwnSvVf4qHUa4A
+ +* Case: PSBT with invalid output redeemScript typed key +** Bytes in Hex:
70736274ff0100730200000001301ae986e516a1ec8ac5b4bc6573d32f83b465e23ad76167d68b38e730b4dbdb0000000000ffffffff02747b01000000000017a91403aa17ae882b5d0d54b25d63104e4ffece7b9ea2876043993b0000000017a914b921b1ba6f722e4bfa83b6557a3139986a42ec8387000000000001011f00ca9a3b00000000160014d2d94b64ae08587eefc8eeb187c601e939f9037c0002000016001462e9e982fff34dd8239610316b090cd2a3b747cb000100220020876bad832f1d168015ed41232a9ea65a1815d9ef13c0ef8759f64b5b2b278a65010125512103b7ce23a01c5b4bf00a642537cdfabb315b668332867478ef51309d2bd57f8a8751ae00
+** Base64 String:
cHNidP8BAHMCAAAAATAa6YblFqHsisW0vGVz0y+DtGXiOtdhZ9aLOOcwtNvbAAAAAAD/////AnR7AQAAAAAAF6kUA6oXrogrXQ1Usl1jEE5P/s57nqKHYEOZOwAAAAAXqRS5IbG6b3IuS/qDtlV6MTmYakLsg4cAAAAAAAEBHwDKmjsAAAAAFgAU0tlLZK4IWH7vyO6xh8YB6Tn5A3wAAgAAFgAUYunpgv/zTdgjlhAxawkM0qO3R8sAAQAiACCHa62DLx0WgBXtQSMqnqZaGBXZ7xPA74dZ9ktbKyeKZQEBJVEhA7fOI6AcW0vwCmQlN836uzFbZoMyhnR471EwnSvVf4qHUa4A
+ +* Case: PSBT with invalid output witnessScript typed key +** Bytes in Hex:
70736274ff0100730200000001301ae986e516a1ec8ac5b4bc6573d32f83b465e23ad76167d68b38e730b4dbdb0000000000ffffffff02747b01000000000017a91403aa17ae882b5d0d54b25d63104e4ffece7b9ea2876043993b0000000017a914b921b1ba6f722e4bfa83b6557a3139986a42ec8387000000000001011f00ca9a3b00000000160014d2d94b64ae08587eefc8eeb187c601e939f9037c00010016001462e9e982fff34dd8239610316b090cd2a3b747cb000100220020876bad832f1d168015ed41232a9ea65a1815d9ef13c0ef8759f64b5b2b278a6521010025512103b7ce23a01c5b4bf00a642537cdfabb315b668332867478ef51309d06d57f8a8751ae00
+** Base64 String:
cHNidP8BAHMCAAAAATAa6YblFqHsisW0vGVz0y+DtGXiOtdhZ9aLOOcwtNvbAAAAAAD/////AnR7AQAAAAAAF6kUA6oXrogrXQ1Usl1jEE5P/s57nqKHYEOZOwAAAAAXqRS5IbG6b3IuS/qDtlV6MTmYakLsg4cAAAAAAAEBHwDKmjsAAAAAFgAU0tlLZK4IWH7vyO6xh8YB6Tn5A3wAAQAWABRi6emC//NN2COWEDFrCQzSo7dHywABACIAIIdrrYMvHRaAFe1BIyqeploYFdnvE8Dvh1n2S1srJ4plIQEAJVEhA7fOI6AcW0vwCmQlN836uzFbZoMyhnR471EwnQbVf4qHUa4A
+ +* Case: PSBT with unsigned tx serialized with witness serialization format +** Bytes in Hex:
70736274ff01007802000000000101268171371edff285e937adeea4b37b78000c0566cbb3ad64641713ca42171bf60000000000feffffff02d3dff505000000001976a914d0c59903c5bac2868760e90fd521a4665aa7652088ac00e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc78700b32e1300000100fda5010100000000010289a3c71eab4d20e0371bbba4cc698fa295c9463afa2e397f8533ccb62f9567e50100000017160014be18d152a9b012039daf3da7de4f53349eecb985ffffffff86f8aa43a71dff1448893a530a7237ef6b4608bbb2dd2d0171e63aec6a4890b40100000017160014fe3e9ef1a745e974d902c4355943abcb34bd5353ffffffff0200c2eb0b000000001976a91485cff1097fd9e008bb34af709c62197b38978a4888ac72fef84e2c00000017a914339725ba21efd62ac753a9bcd067d6c7a6a39d05870247304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c012103d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f210502483045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01210223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab300000000000000
+** Base64 String:
cHNidP8BAHgCAAAAAAEBJoFxNx7f8oXpN63upLN7eAAMBWbLs61kZBcTykIXG/YAAAAAAP7///8C09/1BQAAAAAZdqkU0MWZA8W6woaHYOkP1SGkZlqnZSCIrADh9QUAAAAAF6kUNUXm4zuDLEcFDyTT7rk8nAOUi8eHALMuEwAAAQD9pQEBAAAAAAECiaPHHqtNIOA3G7ukzGmPopXJRjr6Ljl/hTPMti+VZ+UBAAAAFxYAFL4Y0VKpsBIDna89p95PUzSe7LmF/////4b4qkOnHf8USIk6UwpyN+9rRgi7st0tAXHmOuxqSJC0AQAAABcWABT+Pp7xp0XpdNkCxDVZQ6vLNL1TU/////8CAMLrCwAAAAAZdqkUhc/xCX/Z4Ai7NK9wnGIZeziXikiIrHL++E4sAAAAF6kUM5cluiHv1irHU6m80GfWx6ajnQWHAkcwRAIgJxK+IuAnDzlPVoMR3HyppolwuAJf3TskAinwf4pfOiQCIAGLONfc0xTnNMkna9b7QPZzMlvEuqFEyADS8vAtsnZcASED0uFWdJQbrUqZY3LLh+GFbTZSYG2YVi/jnF6efkE/IQUCSDBFAiEA0SuFLYXc2WHS9fSrZgZU327tzHlMDDPOXMMJ/7X85Y0CIGczio4OFyXBl/saiK9Z9R5E5CVbIBZ8hoQDHAXR8lkqASECI7cr7vCWXRC+B3jv7NYfysb3mk6haTkzgHNEZPhPKrMAAAAAAAAA
+ +The following are valid PSBTs: + +* Case: PSBT with one P2PKH input. Outputs are empty +** Bytes in Hex:
70736274ff0100750200000001268171371edff285e937adeea4b37b78000c0566cbb3ad64641713ca42171bf60000000000feffffff02d3dff505000000001976a914d0c59903c5bac2868760e90fd521a4665aa7652088ac00e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787b32e1300000100fda5010100000000010289a3c71eab4d20e0371bbba4cc698fa295c9463afa2e397f8533ccb62f9567e50100000017160014be18d152a9b012039daf3da7de4f53349eecb985ffffffff86f8aa43a71dff1448893a530a7237ef6b4608bbb2dd2d0171e63aec6a4890b40100000017160014fe3e9ef1a745e974d902c4355943abcb34bd5353ffffffff0200c2eb0b000000001976a91485cff1097fd9e008bb34af709c62197b38978a4888ac72fef84e2c00000017a914339725ba21efd62ac753a9bcd067d6c7a6a39d05870247304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c012103d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f210502483045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01210223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab300000000000000
+** Base64 String:
cHNidP8BAHUCAAAAASaBcTce3/KF6Tet7qSze3gADAVmy7OtZGQXE8pCFxv2AAAAAAD+////AtPf9QUAAAAAGXapFNDFmQPFusKGh2DpD9UhpGZap2UgiKwA4fUFAAAAABepFDVF5uM7gyxHBQ8k0+65PJwDlIvHh7MuEwAAAQD9pQEBAAAAAAECiaPHHqtNIOA3G7ukzGmPopXJRjr6Ljl/hTPMti+VZ+UBAAAAFxYAFL4Y0VKpsBIDna89p95PUzSe7LmF/////4b4qkOnHf8USIk6UwpyN+9rRgi7st0tAXHmOuxqSJC0AQAAABcWABT+Pp7xp0XpdNkCxDVZQ6vLNL1TU/////8CAMLrCwAAAAAZdqkUhc/xCX/Z4Ai7NK9wnGIZeziXikiIrHL++E4sAAAAF6kUM5cluiHv1irHU6m80GfWx6ajnQWHAkcwRAIgJxK+IuAnDzlPVoMR3HyppolwuAJf3TskAinwf4pfOiQCIAGLONfc0xTnNMkna9b7QPZzMlvEuqFEyADS8vAtsnZcASED0uFWdJQbrUqZY3LLh+GFbTZSYG2YVi/jnF6efkE/IQUCSDBFAiEA0SuFLYXc2WHS9fSrZgZU327tzHlMDDPOXMMJ/7X85Y0CIGczio4OFyXBl/saiK9Z9R5E5CVbIBZ8hoQDHAXR8lkqASECI7cr7vCWXRC+B3jv7NYfysb3mk6haTkzgHNEZPhPKrMAAAAAAAAA
+ +* Case: PSBT with one P2PKH input and one P2SH-P2WPKH input. First input is signed and finalized. Outputs are empty +** Bytes in Hex:
70736274ff0100a00200000002ab0949a08c5af7c49b8212f417e2f15ab3f5c33dcf153821a8139f877a5b7be40000000000feffffffab0949a08c5af7c49b8212f417e2f15ab3f5c33dcf153821a8139f877a5b7be40100000000feffffff02603bea0b000000001976a914768a40bbd740cbe81d988e71de2a4d5c71396b1d88ac8e240000000000001976a9146f4620b553fa095e721b9ee0efe9fa039cca459788ac000000000001076a47304402204759661797c01b036b25928948686218347d89864b719e1f7fcf57d1e511658702205309eabf56aa4d8891ffd111fdf1336f3a29da866d7f8486d75546ceedaf93190121035cdc61fc7ba971c0b501a646a2a83b102cb43881217ca682dc86e2d73fa882920001012000e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787010416001485d13537f2e265405a34dbafa9e3dda01fb82308000000
+** Base64 String:
cHNidP8BAKACAAAAAqsJSaCMWvfEm4IS9Bfi8Vqz9cM9zxU4IagTn4d6W3vkAAAAAAD+////qwlJoIxa98SbghL0F+LxWrP1wz3PFTghqBOfh3pbe+QBAAAAAP7///8CYDvqCwAAAAAZdqkUdopAu9dAy+gdmI5x3ipNXHE5ax2IrI4kAAAAAAAAGXapFG9GILVT+glechue4O/p+gOcykWXiKwAAAAAAAEHakcwRAIgR1lmF5fAGwNrJZKJSGhiGDR9iYZLcZ4ff89X0eURZYcCIFMJ6r9Wqk2Ikf/REf3xM286KdqGbX+EhtdVRs7tr5MZASEDXNxh/HupccC1AaZGoqg7ECy0OIEhfKaC3Ibi1z+ogpIAAQEgAOH1BQAAAAAXqRQ1RebjO4MsRwUPJNPuuTycA5SLx4cBBBYAFIXRNTfy4mVAWjTbr6nj3aAfuCMIAAAA
+ +* Case: PSBT with one P2PKH input which has a non-final scriptSig and has a sighash type specified. Outputs are empty +** Bytes in Hex:
70736274ff0100750200000001268171371edff285e937adeea4b37b78000c0566cbb3ad64641713ca42171bf60000000000feffffff02d3dff505000000001976a914d0c59903c5bac2868760e90fd521a4665aa7652088ac00e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787b32e1300000100fda5010100000000010289a3c71eab4d20e0371bbba4cc698fa295c9463afa2e397f8533ccb62f9567e50100000017160014be18d152a9b012039daf3da7de4f53349eecb985ffffffff86f8aa43a71dff1448893a530a7237ef6b4608bbb2dd2d0171e63aec6a4890b40100000017160014fe3e9ef1a745e974d902c4355943abcb34bd5353ffffffff0200c2eb0b000000001976a91485cff1097fd9e008bb34af709c62197b38978a4888ac72fef84e2c00000017a914339725ba21efd62ac753a9bcd067d6c7a6a39d05870247304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c012103d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f210502483045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01210223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab30000000001030401000000000000
+** Base64 String:
cHNidP8BAHUCAAAAASaBcTce3/KF6Tet7qSze3gADAVmy7OtZGQXE8pCFxv2AAAAAAD+////AtPf9QUAAAAAGXapFNDFmQPFusKGh2DpD9UhpGZap2UgiKwA4fUFAAAAABepFDVF5uM7gyxHBQ8k0+65PJwDlIvHh7MuEwAAAQD9pQEBAAAAAAECiaPHHqtNIOA3G7ukzGmPopXJRjr6Ljl/hTPMti+VZ+UBAAAAFxYAFL4Y0VKpsBIDna89p95PUzSe7LmF/////4b4qkOnHf8USIk6UwpyN+9rRgi7st0tAXHmOuxqSJC0AQAAABcWABT+Pp7xp0XpdNkCxDVZQ6vLNL1TU/////8CAMLrCwAAAAAZdqkUhc/xCX/Z4Ai7NK9wnGIZeziXikiIrHL++E4sAAAAF6kUM5cluiHv1irHU6m80GfWx6ajnQWHAkcwRAIgJxK+IuAnDzlPVoMR3HyppolwuAJf3TskAinwf4pfOiQCIAGLONfc0xTnNMkna9b7QPZzMlvEuqFEyADS8vAtsnZcASED0uFWdJQbrUqZY3LLh+GFbTZSYG2YVi/jnF6efkE/IQUCSDBFAiEA0SuFLYXc2WHS9fSrZgZU327tzHlMDDPOXMMJ/7X85Y0CIGczio4OFyXBl/saiK9Z9R5E5CVbIBZ8hoQDHAXR8lkqASECI7cr7vCWXRC+B3jv7NYfysb3mk6haTkzgHNEZPhPKrMAAAAAAQMEAQAAAAAAAA==
+ +* Case: PSBT with one P2PKH input and one P2SH-P2WPKH input both with non-final scriptSigs. P2SH-P2WPKH input's redeemScript is available. Outputs filled. +** Bytes in Hex:
70736274ff0100a00200000002ab0949a08c5af7c49b8212f417e2f15ab3f5c33dcf153821a8139f877a5b7be40000000000feffffffab0949a08c5af7c49b8212f417e2f15ab3f5c33dcf153821a8139f877a5b7be40100000000feffffff02603bea0b000000001976a914768a40bbd740cbe81d988e71de2a4d5c71396b1d88ac8e240000000000001976a9146f4620b553fa095e721b9ee0efe9fa039cca459788ac00000000000100df0200000001268171371edff285e937adeea4b37b78000c0566cbb3ad64641713ca42171bf6000000006a473044022070b2245123e6bf474d60c5b50c043d4c691a5d2435f09a34a7662a9dc251790a022001329ca9dacf280bdf30740ec0390422422c81cb45839457aeb76fc12edd95b3012102657d118d3357b8e0f4c2cd46db7b39f6d9c38d9a70abcb9b2de5dc8dbfe4ce31feffffff02d3dff505000000001976a914d0c59903c5bac2868760e90fd521a4665aa7652088ac00e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787b32e13000001012000e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787010416001485d13537f2e265405a34dbafa9e3dda01fb8230800220202ead596687ca806043edc3de116cdf29d5e9257c196cd055cf698c8d02bf24e9910b4a6ba670000008000000080020000800022020394f62be9df19952c5587768aeb7698061ad2c4a25c894f47d8c162b4d7213d0510b4a6ba6700000080010000800200008000
+** Base64 String:
cHNidP8BAKACAAAAAqsJSaCMWvfEm4IS9Bfi8Vqz9cM9zxU4IagTn4d6W3vkAAAAAAD+////qwlJoIxa98SbghL0F+LxWrP1wz3PFTghqBOfh3pbe+QBAAAAAP7///8CYDvqCwAAAAAZdqkUdopAu9dAy+gdmI5x3ipNXHE5ax2IrI4kAAAAAAAAGXapFG9GILVT+glechue4O/p+gOcykWXiKwAAAAAAAEA3wIAAAABJoFxNx7f8oXpN63upLN7eAAMBWbLs61kZBcTykIXG/YAAAAAakcwRAIgcLIkUSPmv0dNYMW1DAQ9TGkaXSQ18Jo0p2YqncJReQoCIAEynKnazygL3zB0DsA5BCJCLIHLRYOUV663b8Eu3ZWzASECZX0RjTNXuOD0ws1G23s59tnDjZpwq8ubLeXcjb/kzjH+////AtPf9QUAAAAAGXapFNDFmQPFusKGh2DpD9UhpGZap2UgiKwA4fUFAAAAABepFDVF5uM7gyxHBQ8k0+65PJwDlIvHh7MuEwAAAQEgAOH1BQAAAAAXqRQ1RebjO4MsRwUPJNPuuTycA5SLx4cBBBYAFIXRNTfy4mVAWjTbr6nj3aAfuCMIACICAurVlmh8qAYEPtw94RbN8p1eklfBls0FXPaYyNAr8k6ZELSmumcAAACAAAAAgAIAAIAAIgIDlPYr6d8ZlSxVh3aK63aYBhrSxKJciU9H2MFitNchPQUQtKa6ZwAAAIABAACAAgAAgAA=
+ +* Case: PSBT with one P2SH-P2WSH input of a 2-of-2 multisig, redeemScript, witnessScript, and keypaths are available. Contains one signature. +** Bytes in Hex:
70736274ff0100550200000001279a2323a5dfb51fc45f220fa58b0fc13e1e3342792a85d7e36cd6333b5cbc390000000000ffffffff01a05aea0b000000001976a914ffe9c0061097cc3b636f2cb0460fa4fc427d2b4588ac0000000000010120955eea0b0000000017a9146345200f68d189e1adc0df1c4d16ea8f14c0dbeb87220203b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd4646304302200424b58effaaa694e1559ea5c93bbfd4a89064224055cdf070b6771469442d07021f5c8eb0fea6516d60b8acb33ad64ede60e8785bfb3aa94b99bdf86151db9a9a010104220020771fd18ad459666dd49f3d564e3dbc42f4c84774e360ada16816a8ed488d5681010547522103b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd462103de55d1e1dac805e3f8a58c1fbf9b94c02f3dbaafe127fefca4995f26f82083bd52ae220603b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd4610b4a6ba67000000800000008004000080220603de55d1e1dac805e3f8a58c1fbf9b94c02f3dbaafe127fefca4995f26f82083bd10b4a6ba670000008000000080050000800000
+** Base64 String:
cHNidP8BAFUCAAAAASeaIyOl37UfxF8iD6WLD8E+HjNCeSqF1+Ns1jM7XLw5AAAAAAD/////AaBa6gsAAAAAGXapFP/pwAYQl8w7Y28ssEYPpPxCfStFiKwAAAAAAAEBIJVe6gsAAAAAF6kUY0UgD2jRieGtwN8cTRbqjxTA2+uHIgIDsTQcy6doO2r08SOM1ul+cWfVafrEfx5I1HVBhENVvUZGMEMCIAQktY7/qqaU4VWepck7v9SokGQiQFXN8HC2dxRpRC0HAh9cjrD+plFtYLisszrWTt5g6Hhb+zqpS5m9+GFR25qaAQEEIgAgdx/RitRZZm3Unz1WTj28QvTIR3TjYK2haBao7UiNVoEBBUdSIQOxNBzLp2g7avTxI4zW6X5xZ9Vp+sR/HkjUdUGEQ1W9RiED3lXR4drIBeP4pYwfv5uUwC89uq/hJ/78pJlfJvggg71SriIGA7E0HMunaDtq9PEjjNbpfnFn1Wn6xH8eSNR1QYRDVb1GELSmumcAAACAAAAAgAQAAIAiBgPeVdHh2sgF4/iljB+/m5TALz26r+En/vykmV8m+CCDvRC0prpnAAAAgAAAAIAFAACAAAA=
+ +* Case: PSBT with one P2WSH input of a 2-of-2 multisig. witnessScript, keypaths, and global xpubs are available. Contains no signatures. Outputs filled. +** Bytes in Hex:
70736274ff01005202000000019dfc6628c26c5899fe1bd3dc338665bfd55d7ada10f6220973df2d386dec12760100000000ffffffff01f03dcd1d000000001600147b3a00bfdc14d27795c2b74901d09da6ef133579000000004f01043587cf02da3fd0088000000097048b1ad0445b1ec8275517727c87b4e4ebc18a203ffa0f94c01566bd38e9000351b743887ee1d40dc32a6043724f2d6459b3b5a4d73daec8fbae0472f3bc43e20cd90c6a4fae000080000000804f01043587cf02da3fd00880000001b90452427139cd78c2cff2444be353cd58605e3e513285e528b407fae3f6173503d30a5e97c8adbc557dac2ad9a7e39c1722ebac69e668b6f2667cc1d671c83cab0cd90c6a4fae000080010000800001012b0065cd1d000000002200202c5486126c4978079a814e13715d65f36459e4d6ccaded266d0508645bafa6320105475221029da12cdb5b235692b91536afefe5c91c3ab9473d8e43b533836ab456299c88712103372b34234ed7cf9c1fea5d05d441557927be9542b162eb02e1ab2ce80224c00b52ae2206029da12cdb5b235692b91536afefe5c91c3ab9473d8e43b533836ab456299c887110d90c6a4fae0000800000008000000000220603372b34234ed7cf9c1fea5d05d441557927be9542b162eb02e1ab2ce80224c00b10d90c6a4fae0000800100008000000000002202039eff1f547a1d5f92dfa2ba7af6ac971a4bd03ba4a734b03156a256b8ad3a1ef910ede45cc500000080000000800100008000
+** Base64 String:
cHNidP8BAFICAAAAAZ38ZijCbFiZ/hvT3DOGZb/VXXraEPYiCXPfLTht7BJ2AQAAAAD/////AfA9zR0AAAAAFgAUezoAv9wU0neVwrdJAdCdpu8TNXkAAAAATwEENYfPAto/0AiAAAAAlwSLGtBEWx7IJ1UXcnyHtOTrwYogP/oPlMAVZr046QADUbdDiH7h1A3DKmBDck8tZFmztaTXPa7I+64EcvO8Q+IM2QxqT64AAIAAAACATwEENYfPAto/0AiAAAABuQRSQnE5zXjCz/JES+NTzVhgXj5RMoXlKLQH+uP2FzUD0wpel8itvFV9rCrZp+OcFyLrrGnmaLbyZnzB1nHIPKsM2QxqT64AAIABAACAAAEBKwBlzR0AAAAAIgAgLFSGEmxJeAeagU4TcV1l82RZ5NbMre0mbQUIZFuvpjIBBUdSIQKdoSzbWyNWkrkVNq/v5ckcOrlHPY5DtTODarRWKZyIcSEDNys0I07Xz5wf6l0F1EFVeSe+lUKxYusC4ass6AIkwAtSriIGAp2hLNtbI1aSuRU2r+/lyRw6uUc9jkO1M4NqtFYpnIhxENkMak+uAACAAAAAgAAAAAAiBgM3KzQjTtfPnB/qXQXUQVV5J76VQrFi6wLhqyzoAiTACxDZDGpPrgAAgAEAAIAAAAAAACICA57/H1R6HV+S36K6evaslxpL0DukpzSwMVaiVritOh75EO3kXMUAAACAAAAAgAEAAIAA
+ +* Case: PSBT with unknown types in the inputs. +** Bytes in Hex:
70736274ff01003f0200000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffff010000000000000000036a010000000000000af00102030405060708090f0102030405060708090a0b0c0d0e0f0000
+** Base64 String:
cHNidP8BAD8CAAAAAf//////////////////////////////////////////AAAAAAD/////AQAAAAAAAAAAA2oBAAAAAAAACvABAgMEBQYHCAkPAQIDBAUGBwgJCgsMDQ4PAAA=
+ +* Case: PSBT with `PSBT_GLOBAL_XPUB`. +** Bytes in Hex:
70736274ff01009d0100000002710ea76ab45c5cb6438e607e59cc037626981805ae9e0dfd9089012abb0be5350100000000ffffffff190994d6a8b3c8c82ccbcfb2fba4106aa06639b872a8d447465c0d42588d6d670000000000ffffffff0200e1f505000000001976a914b6bc2c0ee5655a843d79afedd0ccc3f7dd64340988ac605af405000000001600141188ef8e4ce0449eaac8fb141cbf5a1176e6a088000000004f010488b21e039e530cac800000003dbc8a5c9769f031b17e77fea1518603221a18fd18f2b9a54c6c8c1ac75cbc3502f230584b155d1c7f1cd45120a653c48d650b431b67c5b2c13f27d7142037c1691027569c503100008000000080000000800001011f00e1f5050000000016001433b982f91b28f160c920b4ab95e58ce50dda3a4a220203309680f33c7de38ea6a47cd4ecd66f1f5a49747c6ffb8808ed09039243e3ad5c47304402202d704ced830c56a909344bd742b6852dccd103e963bae92d38e75254d2bb424502202d86c437195df46c0ceda084f2a291c3da2d64070f76bf9b90b195e7ef28f77201220603309680f33c7de38ea6a47cd4ecd66f1f5a49747c6ffb8808ed09039243e3ad5c1827569c5031000080000000800000008000000000010000000001011f00e1f50500000000160014388fb944307eb77ef45197d0b0b245e079f011de220202c777161f73d0b7c72b9ee7bde650293d13f095bc7656ad1f525da5fd2e10b11047304402204cb1fb5f869c942e0e26100576125439179ae88dca8a9dc3ba08f7953988faa60220521f49ca791c27d70e273c9b14616985909361e25be274ea200d7e08827e514d01220602c777161f73d0b7c72b9ee7bde650293d13f095bc7656ad1f525da5fd2e10b1101827569c5031000080000000800000008000000000000000000000220202d20ca502ee289686d21815bd43a80637b0698e1fbcdbe4caed445f6c1a0a90ef1827569c50310000800000008000000080000000000400000000
+** Base64 String:
cHNidP8BAJ0BAAAAAnEOp2q0XFy2Q45gflnMA3YmmBgFrp4N/ZCJASq7C+U1AQAAAAD/////GQmU1qizyMgsy8+y+6QQaqBmObhyqNRHRlwNQliNbWcAAAAAAP////8CAOH1BQAAAAAZdqkUtrwsDuVlWoQ9ea/t0MzD991kNAmIrGBa9AUAAAAAFgAUEYjvjkzgRJ6qyPsUHL9aEXbmoIgAAAAATwEEiLIeA55TDKyAAAAAPbyKXJdp8DGxfnf+oVGGAyIaGP0Y8rmlTGyMGsdcvDUC8jBYSxVdHH8c1FEgplPEjWULQxtnxbLBPyfXFCA3wWkQJ1acUDEAAIAAAACAAAAAgAABAR8A4fUFAAAAABYAFDO5gvkbKPFgySC0q5XljOUN2jpKIgIDMJaA8zx9446mpHzU7NZvH1pJdHxv+4gI7QkDkkPjrVxHMEQCIC1wTO2DDFapCTRL10K2hS3M0QPpY7rpLTjnUlTSu0JFAiAthsQ3GV30bAztoITyopHD2i1kBw92v5uQsZXn7yj3cgEiBgMwloDzPH3jjqakfNTs1m8fWkl0fG/7iAjtCQOSQ+OtXBgnVpxQMQAAgAAAAIAAAACAAAAAAAEAAAAAAQEfAOH1BQAAAAAWABQ4j7lEMH63fvRRl9CwskXgefAR3iICAsd3Fh9z0LfHK57nveZQKT0T8JW8dlatH1Jdpf0uELEQRzBEAiBMsftfhpyULg4mEAV2ElQ5F5rojcqKncO6CPeVOYj6pgIgUh9JynkcJ9cOJzybFGFphZCTYeJb4nTqIA1+CIJ+UU0BIgYCx3cWH3PQt8crnue95lApPRPwlbx2Vq0fUl2l/S4QsRAYJ1acUDEAAIAAAACAAAAAgAAAAAAAAAAAAAAiAgLSDKUC7iiWhtIYFb1DqAY3sGmOH7zb5MrtRF9sGgqQ7xgnVpxQMQAAgAAAAIAAAACAAAAAAAQAAAAA
+ +* Case: PSBT with global unsigned tx that has 0 inputs and 0 outputs +** Bytes in Hex:
70736274ff01000a0000000000000000000000
+** Base64 String:
cHNidP8BAAoAAAAAAAAAAAAAAA==
+ +* Case: PSBT with 0 inputs +** Bytes in Hex:
70736274ff01004c020000000002d3dff505000000001976a914d0c59903c5bac2868760e90fd521a4665aa7652088ac00e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787b32e1300000000
+** Base64 String:
cHNidP8BAEwCAAAAAALT3/UFAAAAABl2qRTQxZkDxbrChodg6Q/VIaRmWqdlIIisAOH1BQAAAAAXqRQ1RebjO4MsRwUPJNPuuTycA5SLx4ezLhMAAAAA
+ +Fails Signer checks + +* Case: A Witness UTXO is provided for a non-witness input +** Bytes in Hex:
70736274ff0100a00200000002ab0949a08c5af7c49b8212f417e2f15ab3f5c33dcf153821a8139f877a5b7be40000000000feffffffab0949a08c5af7c49b8212f417e2f15ab3f5c33dcf153821a8139f877a5b7be40100000000feffffff02603bea0b000000001976a914768a40bbd740cbe81d988e71de2a4d5c71396b1d88ac8e240000000000001976a9146f4620b553fa095e721b9ee0efe9fa039cca459788ac0000000000010122d3dff505000000001976a914d48ed3110b94014cb114bd32d6f4d066dc74256b88ac0001012000e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787010416001485d13537f2e265405a34dbafa9e3dda01fb8230800220202ead596687ca806043edc3de116cdf29d5e9257c196cd055cf698c8d02bf24e9910b4a6ba670000008000000080020000800022020394f62be9df19952c5587768aeb7698061ad2c4a25c894f47d8c162b4d7213d0510b4a6ba6700000080010000800200008000
+** Base64 String:
cHNidP8BAKACAAAAAqsJSaCMWvfEm4IS9Bfi8Vqz9cM9zxU4IagTn4d6W3vkAAAAAAD+////qwlJoIxa98SbghL0F+LxWrP1wz3PFTghqBOfh3pbe+QBAAAAAP7///8CYDvqCwAAAAAZdqkUdopAu9dAy+gdmI5x3ipNXHE5ax2IrI4kAAAAAAAAGXapFG9GILVT+glechue4O/p+gOcykWXiKwAAAAAAAEBItPf9QUAAAAAGXapFNSO0xELlAFMsRS9Mtb00GbcdCVriKwAAQEgAOH1BQAAAAAXqRQ1RebjO4MsRwUPJNPuuTycA5SLx4cBBBYAFIXRNTfy4mVAWjTbr6nj3aAfuCMIACICAurVlmh8qAYEPtw94RbN8p1eklfBls0FXPaYyNAr8k6ZELSmumcAAACAAAAAgAIAAIAAIgIDlPYr6d8ZlSxVh3aK63aYBhrSxKJciU9H2MFitNchPQUQtKa6ZwAAAIABAACAAgAAgAA=
+ +* Case: redeemScript with non-witness UTXO does not match the scriptPubKey +** Bytes in Hex:
70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f00000000000100bb0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f618765000000220202dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d7483045022100f61038b308dc1da865a34852746f015772934208c6d24454393cd99bdf2217770220056e675a675a6d0a02b85b14e5e29074d8a25a9b5760bea2816f661910a006ea01010304010000000104475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752af2206029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f10d90c6a4f000000800000008000000080220602dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d710d90c6a4f0000008000000080010000800001012000c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e8872202023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e73473044022065f45ba5998b59a27ffe1a7bed016af1f1f90d54b3aa8f7450aa5f56a25103bd02207f724703ad1edb96680b284b56d4ffcb88f7fb759eabbe08aa30f29b851383d2010103040100000001042200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b2028903010547522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae2206023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7310d90c6a4f000000800000008003000080220603089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc10d90c6a4f00000080000000800200008000220203a9a4c37f5996d3aa25dbac6b570af0650394492942460b354753ed9eeca5877110d90c6a4f000000800000008004000080002202027f6399757d2eff55a136ad02c684b1838b6556e5f1b6b34282a94b6b5005109610d90c6a4f00000080000000800500008000
+** Base64 String:
cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAAiAgLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU210gwRQIhAPYQOLMI3B2oZaNIUnRvAVdyk0IIxtJEVDk82ZvfIhd3AiAFbmdaZ1ptCgK4WxTl4pB02KJam1dgvqKBb2YZEKAG6gEBAwQBAAAAAQRHUiEClYO/Oa4KYJdHrRma3dY0+mEIVZ1sXNObTCGD8auW4H8hAtq2H/SaFNtqfQKwzR+7ePxLGDErW05U2uTbovv+9TbXUq8iBgKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfxDZDGpPAAAAgAAAAIAAAACAIgYC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtcQ2QxqTwAAAIAAAACAAQAAgAABASAAwusLAAAAABepFLf1+vQOPUClpFmx2zU18rcvqSHohyICAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zRzBEAiBl9FulmYtZon/+GnvtAWrx8fkNVLOqj3RQql9WolEDvQIgf3JHA60e25ZoCyhLVtT/y4j3+3Weq74IqjDym4UTg9IBAQMEAQAAAAEEIgAgjCNTFzdDtZXftKB7crqOQuN5fadOh/59nXSX47ICiQMBBUdSIQMIncEMesbbVPkTKa9hczPbOIzq0MIx9yM3nRuZAwsC3CECOt2QTz1tz1nduQaw3uI1Kbf/ue1Q5ehhUZJoYCIfDnNSriIGAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zENkMak8AAACAAAAAgAMAAIAiBgMIncEMesbbVPkTKa9hczPbOIzq0MIx9yM3nRuZAwsC3BDZDGpPAAAAgAAAAIACAACAACICA6mkw39ZltOqJdusa1cK8GUDlEkpQkYLNUdT7Z7spYdxENkMak8AAACAAAAAgAQAAIAAIgICf2OZdX0u/1WhNq0CxoSxg4tlVuXxtrNCgqlLa1AFEJYQ2QxqTwAAAIAAAACABQAAgAA=
+ +* Case: redeemScript with witness UTXO does not match the scriptPubKey +** Bytes in Hex:
70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f00000000000100bb0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f618765000000220202dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d7483045022100f61038b308dc1da865a34852746f015772934208c6d24454393cd99bdf2217770220056e675a675a6d0a02b85b14e5e29074d8a25a9b5760bea2816f661910a006ea01010304010000000104475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752ae2206029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f10d90c6a4f000000800000008000000080220602dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d710d90c6a4f0000008000000080010000800001012000c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e8872202023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e73473044022065f45ba5998b59a27ffe1a7bed016af1f1f90d54b3aa8f7450aa5f56a25103bd02207f724703ad1edb96680b284b56d4ffcb88f7fb759eabbe08aa30f29b851383d2010103040100000001042200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b2028900010547522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae2206023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7310d90c6a4f000000800000008003000080220603089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc10d90c6a4f00000080000000800200008000220203a9a4c37f5996d3aa25dbac6b570af0650394492942460b354753ed9eeca5877110d90c6a4f000000800000008004000080002202027f6399757d2eff55a136ad02c684b1838b6556e5f1b6b34282a94b6b5005109610d90c6a4f00000080000000800500008000
+** Base64 String:
cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAAiAgLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU210gwRQIhAPYQOLMI3B2oZaNIUnRvAVdyk0IIxtJEVDk82ZvfIhd3AiAFbmdaZ1ptCgK4WxTl4pB02KJam1dgvqKBb2YZEKAG6gEBAwQBAAAAAQRHUiEClYO/Oa4KYJdHrRma3dY0+mEIVZ1sXNObTCGD8auW4H8hAtq2H/SaFNtqfQKwzR+7ePxLGDErW05U2uTbovv+9TbXUq4iBgKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfxDZDGpPAAAAgAAAAIAAAACAIgYC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtcQ2QxqTwAAAIAAAACAAQAAgAABASAAwusLAAAAABepFLf1+vQOPUClpFmx2zU18rcvqSHohyICAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zRzBEAiBl9FulmYtZon/+GnvtAWrx8fkNVLOqj3RQql9WolEDvQIgf3JHA60e25ZoCyhLVtT/y4j3+3Weq74IqjDym4UTg9IBAQMEAQAAAAEEIgAgjCNTFzdDtZXftKB7crqOQuN5fadOh/59nXSX47ICiQABBUdSIQMIncEMesbbVPkTKa9hczPbOIzq0MIx9yM3nRuZAwsC3CECOt2QTz1tz1nduQaw3uI1Kbf/ue1Q5ehhUZJoYCIfDnNSriIGAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zENkMak8AAACAAAAAgAMAAIAiBgMIncEMesbbVPkTKa9hczPbOIzq0MIx9yM3nRuZAwsC3BDZDGpPAAAAgAAAAIACAACAACICA6mkw39ZltOqJdusa1cK8GUDlEkpQkYLNUdT7Z7spYdxENkMak8AAACAAAAAgAQAAIAAIgICf2OZdX0u/1WhNq0CxoSxg4tlVuXxtrNCgqlLa1AFEJYQ2QxqTwAAAIAAAACABQAAgAA=
+ +* Case: witnessScript with witness UTXO does not match the redeemScript +** Bytes in Hex:
70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f00000000000100bb0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f618765000000220202dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d7483045022100f61038b308dc1da865a34852746f015772934208c6d24454393cd99bdf2217770220056e675a675a6d0a02b85b14e5e29074d8a25a9b5760bea2816f661910a006ea01010304010000000104475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752ae2206029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f10d90c6a4f000000800000008000000080220602dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d710d90c6a4f0000008000000080010000800001012000c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e8872202023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e73473044022065f45ba5998b59a27ffe1a7bed016af1f1f90d54b3aa8f7450aa5f56a25103bd02207f724703ad1edb96680b284b56d4ffcb88f7fb759eabbe08aa30f29b851383d2010103040100000001042200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b2028903010547522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ad2206023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7310d90c6a4f000000800000008003000080220603089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc10d90c6a4f00000080000000800200008000220203a9a4c37f5996d3aa25dbac6b570af0650394492942460b354753ed9eeca5877110d90c6a4f000000800000008004000080002202027f6399757d2eff55a136ad02c684b1838b6556e5f1b6b34282a94b6b5005109610d90c6a4f00000080000000800500008000
+** Base64 String:
cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAAiAgLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU210gwRQIhAPYQOLMI3B2oZaNIUnRvAVdyk0IIxtJEVDk82ZvfIhd3AiAFbmdaZ1ptCgK4WxTl4pB02KJam1dgvqKBb2YZEKAG6gEBAwQBAAAAAQRHUiEClYO/Oa4KYJdHrRma3dY0+mEIVZ1sXNObTCGD8auW4H8hAtq2H/SaFNtqfQKwzR+7ePxLGDErW05U2uTbovv+9TbXUq4iBgKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfxDZDGpPAAAAgAAAAIAAAACAIgYC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtcQ2QxqTwAAAIAAAACAAQAAgAABASAAwusLAAAAABepFLf1+vQOPUClpFmx2zU18rcvqSHohyICAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zRzBEAiBl9FulmYtZon/+GnvtAWrx8fkNVLOqj3RQql9WolEDvQIgf3JHA60e25ZoCyhLVtT/y4j3+3Weq74IqjDym4UTg9IBAQMEAQAAAAEEIgAgjCNTFzdDtZXftKB7crqOQuN5fadOh/59nXSX47ICiQMBBUdSIQMIncEMesbbVPkTKa9hczPbOIzq0MIx9yM3nRuZAwsC3CECOt2QTz1tz1nduQaw3uI1Kbf/ue1Q5ehhUZJoYCIfDnNSrSIGAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zENkMak8AAACAAAAAgAMAAIAiBgMIncEMesbbVPkTKa9hczPbOIzq0MIx9yM3nRuZAwsC3BDZDGpPAAAAgAAAAIACAACAACICA6mkw39ZltOqJdusa1cK8GUDlEkpQkYLNUdT7Z7spYdxENkMak8AAACAAAAAgAQAAIAAIgICf2OZdX0u/1WhNq0CxoSxg4tlVuXxtrNCgqlLa1AFEJYQ2QxqTwAAAIAAAACABQAAgAA=
+ +The private keys in the tests below are derived from the following master private key: + +* Extended Private Key:
tprv8ZgxMBicQKsPd9TeAdPADNnSyH9SSUUbTVeFszDE23Ki6TBB5nCefAdHkK8Fm3qMQR6sHwA56zqRmKmxnHk37JkiFzvncDqoKmPWubu7hDF
+** Seed:
cUkG8i1RFfWGWy5ziR11zJ5V4U4W3viSFCfyJmZnvQaUsd1xuF3T
+ +A creator creating a PSBT for a transaction which creates the following outputs: + +* scriptPubKey: 0014d85c2b71d0060b09c9886aeb815e50991dda124d, Amount: 1.49990000 +* scriptPubKey: 001400aea9a2e5f0f876a588df5546e8742d1d87008f, Amount: 1.00000000 + +and spends the following inputs: + +* TXID: 75ddabb27b8845f5247975c8a5ba7c6f336c4570708ebe230caf6db5217ae858, Index: 0 +* TXID: 1dea7cd05979072a3578cab271c02244ea8a090bbb46aa680a65ecd027048d83, Index: 1 + +must create this PSBT: +* Bytes in Hex:
70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f000000000000000000
+* Base64 String:
cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAAAAAA=
+ +Given the above PSBT, an updater with only the following: + +* Redeem Scripts: +** 5221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752ae +** 00208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b2028903 +* Witness Scripts: +** 522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae +* Previous Transactions: +**
0200000000010158e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd7501000000171600145f275f436b09a8cc9a2eb2a2f528485c68a56323feffffff02d8231f1b0100000017a914aed962d6654f9a2b36608eb9d64d2b260db4f1118700c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e88702483045022100a22edcc6e5bc511af4cc4ae0de0fcd75c7e04d8c1c3a8aa9d820ed4b967384ec02200642963597b9b1bc22c75e9f3e117284a962188bf5e8a74c895089046a20ad770121035509a48eb623e10aace8bfd0212fdb8a8e5af3c94b0b133b95e114cab89e4f7965000000
+**
0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f618765000000
+* Public Keys +** Key: 029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f, Derivation Path: m/0'/0'/0' +** Key: 02dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d7, Derivation Path: m/0'/0'/1' +** Key: 03089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc, Derivation Path: m/0'/0'/2' +** Key: 023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e73, Derivation Path: m/0'/0'/3' +** Key: 03a9a4c37f5996d3aa25dbac6b570af0650394492942460b354753ed9eeca58771, Derivation Path: m/0'/0'/4' +** Key: 027f6399757d2eff55a136ad02c684b1838b6556e5f1b6b34282a94b6b50051096, Derivation Path: m/0'/0'/5' + +Must create this PSBT: + +* Bytes in Hex:
70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f00000000000100bb0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f6187650000000104475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752ae2206029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f10d90c6a4f000000800000008000000080220602dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d710d90c6a4f0000008000000080010000800001012000c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e88701042200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b2028903010547522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae2206023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7310d90c6a4f000000800000008003000080220603089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc10d90c6a4f00000080000000800200008000220203a9a4c37f5996d3aa25dbac6b570af0650394492942460b354753ed9eeca5877110d90c6a4f000000800000008004000080002202027f6399757d2eff55a136ad02c684b1838b6556e5f1b6b34282a94b6b5005109610d90c6a4f00000080000000800500008000
+* Base64 String:
cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAABBEdSIQKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfyEC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtdSriIGApWDvzmuCmCXR60Zmt3WNPphCFWdbFzTm0whg/GrluB/ENkMak8AAACAAAAAgAAAAIAiBgLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU21xDZDGpPAAAAgAAAAIABAACAAAEBIADC6wsAAAAAF6kUt/X69A49QKWkWbHbNTXyty+pIeiHAQQiACCMI1MXN0O1ld+0oHtyuo5C43l9p06H/n2ddJfjsgKJAwEFR1IhAwidwQx6xttU+RMpr2FzM9s4jOrQwjH3IzedG5kDCwLcIQI63ZBPPW3PWd25BrDe4jUpt/+57VDl6GFRkmhgIh8Oc1KuIgYCOt2QTz1tz1nduQaw3uI1Kbf/ue1Q5ehhUZJoYCIfDnMQ2QxqTwAAAIAAAACAAwAAgCIGAwidwQx6xttU+RMpr2FzM9s4jOrQwjH3IzedG5kDCwLcENkMak8AAACAAAAAgAIAAIAAIgIDqaTDf1mW06ol26xrVwrwZQOUSSlCRgs1R1Ptnuylh3EQ2QxqTwAAAIAAAACABAAAgAAiAgJ/Y5l1fS7/VaE2rQLGhLGDi2VW5fG2s0KCqUtrUAUQlhDZDGpPAAAAgAAAAIAFAACAAA==
+ +An updater which adds SIGHASH_ALL to the above PSBT must create this PSBT: + +* Bytes in Hex:
70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f00000000000100bb0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f618765000000010304010000000104475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752ae2206029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f10d90c6a4f000000800000008000000080220602dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d710d90c6a4f0000008000000080010000800001012000c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e8870103040100000001042200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b2028903010547522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae2206023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7310d90c6a4f000000800000008003000080220603089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc10d90c6a4f00000080000000800200008000220203a9a4c37f5996d3aa25dbac6b570af0650394492942460b354753ed9eeca5877110d90c6a4f000000800000008004000080002202027f6399757d2eff55a136ad02c684b1838b6556e5f1b6b34282a94b6b5005109610d90c6a4f00000080000000800500008000
+* Base64 String:
cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAABAwQBAAAAAQRHUiEClYO/Oa4KYJdHrRma3dY0+mEIVZ1sXNObTCGD8auW4H8hAtq2H/SaFNtqfQKwzR+7ePxLGDErW05U2uTbovv+9TbXUq4iBgKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfxDZDGpPAAAAgAAAAIAAAACAIgYC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtcQ2QxqTwAAAIAAAACAAQAAgAABASAAwusLAAAAABepFLf1+vQOPUClpFmx2zU18rcvqSHohwEDBAEAAAABBCIAIIwjUxc3Q7WV37Sge3K6jkLjeX2nTof+fZ10l+OyAokDAQVHUiEDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtwhAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zUq4iBgI63ZBPPW3PWd25BrDe4jUpt/+57VDl6GFRkmhgIh8OcxDZDGpPAAAAgAAAAIADAACAIgYDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtwQ2QxqTwAAAIAAAACAAgAAgAAiAgOppMN/WZbTqiXbrGtXCvBlA5RJKUJGCzVHU+2e7KWHcRDZDGpPAAAAgAAAAIAEAACAACICAn9jmXV9Lv9VoTatAsaEsYOLZVbl8bazQoKpS2tQBRCWENkMak8AAACAAAAAgAUAAIAA
+ +Given the above updated PSBT, a signer that supports SIGHASH_ALL for P2PKH and P2WPKH spends and uses RFC6979 for nonce generation and has the following keys: +* cP53pDbR5WtAD8dYAW9hhTjuvvTVaEiQBdrz9XPrgLBeRFiyCbQr (m/0'/0'/0') +* cR6SXDoyfQrcp4piaiHE97Rsgta9mNhGTen9XeonVgwsh4iSgw6d (m/0'/0'/2') +must create this PSBT: + +* Bytes in Hex:
70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f00000000000100bb0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f6187650000002202029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f473044022074018ad4180097b873323c0015720b3684cc8123891048e7dbcd9b55ad679c99022073d369b740e3eb53dcefa33823c8070514ca55a7dd9544f157c167913261118c01010304010000000104475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752ae2206029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f10d90c6a4f000000800000008000000080220602dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d710d90c6a4f0000008000000080010000800001012000c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e887220203089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc473044022062eb7a556107a7c73f45ac4ab5a1dddf6f7075fb1275969a7f383efff784bcb202200c05dbb7470dbf2f08557dd356c7325c1ed30913e996cd3840945db12228da5f010103040100000001042200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b2028903010547522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae2206023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7310d90c6a4f000000800000008003000080220603089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc10d90c6a4f00000080000000800200008000220203a9a4c37f5996d3aa25dbac6b570af0650394492942460b354753ed9eeca5877110d90c6a4f000000800000008004000080002202027f6399757d2eff55a136ad02c684b1838b6556e5f1b6b34282a94b6b5005109610d90c6a4f00000080000000800500008000
+* Base64 String:
cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAAiAgKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgf0cwRAIgdAGK1BgAl7hzMjwAFXILNoTMgSOJEEjn282bVa1nnJkCIHPTabdA4+tT3O+jOCPIBwUUylWn3ZVE8VfBZ5EyYRGMAQEDBAEAAAABBEdSIQKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfyEC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtdSriIGApWDvzmuCmCXR60Zmt3WNPphCFWdbFzTm0whg/GrluB/ENkMak8AAACAAAAAgAAAAIAiBgLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU21xDZDGpPAAAAgAAAAIABAACAAAEBIADC6wsAAAAAF6kUt/X69A49QKWkWbHbNTXyty+pIeiHIgIDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtxHMEQCIGLrelVhB6fHP0WsSrWh3d9vcHX7EnWWmn84Pv/3hLyyAiAMBdu3Rw2/LwhVfdNWxzJcHtMJE+mWzThAlF2xIijaXwEBAwQBAAAAAQQiACCMI1MXN0O1ld+0oHtyuo5C43l9p06H/n2ddJfjsgKJAwEFR1IhAwidwQx6xttU+RMpr2FzM9s4jOrQwjH3IzedG5kDCwLcIQI63ZBPPW3PWd25BrDe4jUpt/+57VDl6GFRkmhgIh8Oc1KuIgYCOt2QTz1tz1nduQaw3uI1Kbf/ue1Q5ehhUZJoYCIfDnMQ2QxqTwAAAIAAAACAAwAAgCIGAwidwQx6xttU+RMpr2FzM9s4jOrQwjH3IzedG5kDCwLcENkMak8AAACAAAAAgAIAAIAAIgIDqaTDf1mW06ol26xrVwrwZQOUSSlCRgs1R1Ptnuylh3EQ2QxqTwAAAIAAAACABAAAgAAiAgJ/Y5l1fS7/VaE2rQLGhLGDi2VW5fG2s0KCqUtrUAUQlhDZDGpPAAAAgAAAAIAFAACAAA==
+ +Given the above updated PSBT, a signer with the following keys: +* cT7J9YpCwY3AVRFSjN6ukeEeWY6mhpbJPxRaDaP5QTdygQRxP9Au (m/0'/0'/1') +* cNBc3SWUip9PPm1GjRoLEJT6T41iNzCYtD7qro84FMnM5zEqeJsE (m/0'/0'/3') +must create this PSBT: + +* Bytes in Hex:
70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f00000000000100bb0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f618765000000220202dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d7483045022100f61038b308dc1da865a34852746f015772934208c6d24454393cd99bdf2217770220056e675a675a6d0a02b85b14e5e29074d8a25a9b5760bea2816f661910a006ea01010304010000000104475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752ae2206029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f10d90c6a4f000000800000008000000080220602dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d710d90c6a4f0000008000000080010000800001012000c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e8872202023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e73473044022065f45ba5998b59a27ffe1a7bed016af1f1f90d54b3aa8f7450aa5f56a25103bd02207f724703ad1edb96680b284b56d4ffcb88f7fb759eabbe08aa30f29b851383d2010103040100000001042200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b2028903010547522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae2206023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7310d90c6a4f000000800000008003000080220603089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc10d90c6a4f00000080000000800200008000220203a9a4c37f5996d3aa25dbac6b570af0650394492942460b354753ed9eeca5877110d90c6a4f000000800000008004000080002202027f6399757d2eff55a136ad02c684b1838b6556e5f1b6b34282a94b6b5005109610d90c6a4f00000080000000800500008000
+* Base64 String:
cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAAiAgLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU210gwRQIhAPYQOLMI3B2oZaNIUnRvAVdyk0IIxtJEVDk82ZvfIhd3AiAFbmdaZ1ptCgK4WxTl4pB02KJam1dgvqKBb2YZEKAG6gEBAwQBAAAAAQRHUiEClYO/Oa4KYJdHrRma3dY0+mEIVZ1sXNObTCGD8auW4H8hAtq2H/SaFNtqfQKwzR+7ePxLGDErW05U2uTbovv+9TbXUq4iBgKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfxDZDGpPAAAAgAAAAIAAAACAIgYC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtcQ2QxqTwAAAIAAAACAAQAAgAABASAAwusLAAAAABepFLf1+vQOPUClpFmx2zU18rcvqSHohyICAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zRzBEAiBl9FulmYtZon/+GnvtAWrx8fkNVLOqj3RQql9WolEDvQIgf3JHA60e25ZoCyhLVtT/y4j3+3Weq74IqjDym4UTg9IBAQMEAQAAAAEEIgAgjCNTFzdDtZXftKB7crqOQuN5fadOh/59nXSX47ICiQMBBUdSIQMIncEMesbbVPkTKa9hczPbOIzq0MIx9yM3nRuZAwsC3CECOt2QTz1tz1nduQaw3uI1Kbf/ue1Q5ehhUZJoYCIfDnNSriIGAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zENkMak8AAACAAAAAgAMAAIAiBgMIncEMesbbVPkTKa9hczPbOIzq0MIx9yM3nRuZAwsC3BDZDGpPAAAAgAAAAIACAACAACICA6mkw39ZltOqJdusa1cK8GUDlEkpQkYLNUdT7Z7spYdxENkMak8AAACAAAAAgAQAAIAAIgICf2OZdX0u/1WhNq0CxoSxg4tlVuXxtrNCgqlLa1AFEJYQ2QxqTwAAAIAAAACABQAAgAA=
+ +Given both of the above PSBTs, a combiner must create this PSBT: + +* Bytes in Hex:
70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f00000000000100bb0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f6187650000002202029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f473044022074018ad4180097b873323c0015720b3684cc8123891048e7dbcd9b55ad679c99022073d369b740e3eb53dcefa33823c8070514ca55a7dd9544f157c167913261118c01220202dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d7483045022100f61038b308dc1da865a34852746f015772934208c6d24454393cd99bdf2217770220056e675a675a6d0a02b85b14e5e29074d8a25a9b5760bea2816f661910a006ea01010304010000000104475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752ae2206029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f10d90c6a4f000000800000008000000080220602dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d710d90c6a4f0000008000000080010000800001012000c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e887220203089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc473044022062eb7a556107a7c73f45ac4ab5a1dddf6f7075fb1275969a7f383efff784bcb202200c05dbb7470dbf2f08557dd356c7325c1ed30913e996cd3840945db12228da5f012202023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e73473044022065f45ba5998b59a27ffe1a7bed016af1f1f90d54b3aa8f7450aa5f56a25103bd02207f724703ad1edb96680b284b56d4ffcb88f7fb759eabbe08aa30f29b851383d2010103040100000001042200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b2028903010547522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae2206023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7310d90c6a4f000000800000008003000080220603089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc10d90c6a4f00000080000000800200008000220203a9a4c37f5996d3aa25dbac6b570af0650394492942460b354753ed9eeca5877110d90c6a4f000000800000008004000080002202027f6399757d2eff55a136ad02c684b1838b6556e5f1b6b34282a94b6b5005109610d90c6a4f00000080000000800500008000
+* Base64 String:
cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAAiAgKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgf0cwRAIgdAGK1BgAl7hzMjwAFXILNoTMgSOJEEjn282bVa1nnJkCIHPTabdA4+tT3O+jOCPIBwUUylWn3ZVE8VfBZ5EyYRGMASICAtq2H/SaFNtqfQKwzR+7ePxLGDErW05U2uTbovv+9TbXSDBFAiEA9hA4swjcHahlo0hSdG8BV3KTQgjG0kRUOTzZm98iF3cCIAVuZ1pnWm0KArhbFOXikHTYolqbV2C+ooFvZhkQoAbqAQEDBAEAAAABBEdSIQKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfyEC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtdSriIGApWDvzmuCmCXR60Zmt3WNPphCFWdbFzTm0whg/GrluB/ENkMak8AAACAAAAAgAAAAIAiBgLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU21xDZDGpPAAAAgAAAAIABAACAAAEBIADC6wsAAAAAF6kUt/X69A49QKWkWbHbNTXyty+pIeiHIgIDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtxHMEQCIGLrelVhB6fHP0WsSrWh3d9vcHX7EnWWmn84Pv/3hLyyAiAMBdu3Rw2/LwhVfdNWxzJcHtMJE+mWzThAlF2xIijaXwEiAgI63ZBPPW3PWd25BrDe4jUpt/+57VDl6GFRkmhgIh8Oc0cwRAIgZfRbpZmLWaJ//hp77QFq8fH5DVSzqo90UKpfVqJRA70CIH9yRwOtHtuWaAsoS1bU/8uI9/t1nqu+CKow8puFE4PSAQEDBAEAAAABBCIAIIwjUxc3Q7WV37Sge3K6jkLjeX2nTof+fZ10l+OyAokDAQVHUiEDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtwhAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zUq4iBgI63ZBPPW3PWd25BrDe4jUpt/+57VDl6GFRkmhgIh8OcxDZDGpPAAAAgAAAAIADAACAIgYDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtwQ2QxqTwAAAIAAAACAAgAAgAAiAgOppMN/WZbTqiXbrGtXCvBlA5RJKUJGCzVHU+2e7KWHcRDZDGpPAAAAgAAAAIAEAACAACICAn9jmXV9Lv9VoTatAsaEsYOLZVbl8bazQoKpS2tQBRCWENkMak8AAACAAAAAgAUAAIAA
+ +Given the above PSBT, an input finalizer must create this PSBT: + +* Bytes in Hex:
70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f00000000000100bb0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f6187650000000107da00473044022074018ad4180097b873323c0015720b3684cc8123891048e7dbcd9b55ad679c99022073d369b740e3eb53dcefa33823c8070514ca55a7dd9544f157c167913261118c01483045022100f61038b308dc1da865a34852746f015772934208c6d24454393cd99bdf2217770220056e675a675a6d0a02b85b14e5e29074d8a25a9b5760bea2816f661910a006ea01475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752ae0001012000c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e8870107232200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b20289030108da0400473044022062eb7a556107a7c73f45ac4ab5a1dddf6f7075fb1275969a7f383efff784bcb202200c05dbb7470dbf2f08557dd356c7325c1ed30913e996cd3840945db12228da5f01473044022065f45ba5998b59a27ffe1a7bed016af1f1f90d54b3aa8f7450aa5f56a25103bd02207f724703ad1edb96680b284b56d4ffcb88f7fb759eabbe08aa30f29b851383d20147522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae00220203a9a4c37f5996d3aa25dbac6b570af0650394492942460b354753ed9eeca5877110d90c6a4f000000800000008004000080002202027f6399757d2eff55a136ad02c684b1838b6556e5f1b6b34282a94b6b5005109610d90c6a4f00000080000000800500008000
+* Base64 String:
cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAABB9oARzBEAiB0AYrUGACXuHMyPAAVcgs2hMyBI4kQSOfbzZtVrWecmQIgc9Npt0Dj61Pc76M4I8gHBRTKVafdlUTxV8FnkTJhEYwBSDBFAiEA9hA4swjcHahlo0hSdG8BV3KTQgjG0kRUOTzZm98iF3cCIAVuZ1pnWm0KArhbFOXikHTYolqbV2C+ooFvZhkQoAbqAUdSIQKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfyEC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtdSrgABASAAwusLAAAAABepFLf1+vQOPUClpFmx2zU18rcvqSHohwEHIyIAIIwjUxc3Q7WV37Sge3K6jkLjeX2nTof+fZ10l+OyAokDAQjaBABHMEQCIGLrelVhB6fHP0WsSrWh3d9vcHX7EnWWmn84Pv/3hLyyAiAMBdu3Rw2/LwhVfdNWxzJcHtMJE+mWzThAlF2xIijaXwFHMEQCIGX0W6WZi1mif/4ae+0BavHx+Q1Us6qPdFCqX1aiUQO9AiB/ckcDrR7blmgLKEtW1P/LiPf7dZ6rvgiqMPKbhROD0gFHUiEDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtwhAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zUq4AIgIDqaTDf1mW06ol26xrVwrwZQOUSSlCRgs1R1Ptnuylh3EQ2QxqTwAAAIAAAACABAAAgAAiAgJ/Y5l1fS7/VaE2rQLGhLGDi2VW5fG2s0KCqUtrUAUQlhDZDGpPAAAAgAAAAIAFAACAAA==
+ +Given the above PSBT, a transaction extractor must create this Bitcoin transaction: + +* Bytes in Hex:
0200000000010258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd7500000000da00473044022074018ad4180097b873323c0015720b3684cc8123891048e7dbcd9b55ad679c99022073d369b740e3eb53dcefa33823c8070514ca55a7dd9544f157c167913261118c01483045022100f61038b308dc1da865a34852746f015772934208c6d24454393cd99bdf2217770220056e675a675a6d0a02b85b14e5e29074d8a25a9b5760bea2816f661910a006ea01475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752aeffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d01000000232200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b2028903ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f000400473044022062eb7a556107a7c73f45ac4ab5a1dddf6f7075fb1275969a7f383efff784bcb202200c05dbb7470dbf2f08557dd356c7325c1ed30913e996cd3840945db12228da5f01473044022065f45ba5998b59a27ffe1a7bed016af1f1f90d54b3aa8f7450aa5f56a25103bd02207f724703ad1edb96680b284b56d4ffcb88f7fb759eabbe08aa30f29b851383d20147522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae00000000
+ +Given these two PSBTs with unknown key-value pairs: +* Bytes in Hex:
70736274ff01003f0200000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffff010000000000000000036a0100000000000af00102030405060708090f0102030405060708090a0b0c0d0e0f000af00102030405060708090f0102030405060708090a0b0c0d0e0f000af00102030405060708090f0102030405060708090a0b0c0d0e0f00
+** Base64 String:
cHNidP8BAD8CAAAAAf//////////////////////////////////////////AAAAAAD/////AQAAAAAAAAAAA2oBAAAAAAAK8AECAwQFBgcICQ8BAgMEBQYHCAkKCwwNDg8ACvABAgMEBQYHCAkPAQIDBAUGBwgJCgsMDQ4PAArwAQIDBAUGBwgJDwECAwQFBgcICQoLDA0ODwA=
+ +* Bytes in Hex:
70736274ff01003f0200000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffff010000000000000000036a0100000000000af00102030405060708100f0102030405060708090a0b0c0d0e0f000af00102030405060708100f0102030405060708090a0b0c0d0e0f000af00102030405060708100f0102030405060708090a0b0c0d0e0f00
+** Base64 String:
cHNidP8BAD8CAAAAAf//////////////////////////////////////////AAAAAAD/////AQAAAAAAAAAAA2oBAAAAAAAK8AECAwQFBgcIEA8BAgMEBQYHCAkKCwwNDg8ACvABAgMEBQYHCBAPAQIDBAUGBwgJCgsMDQ4PAArwAQIDBAUGBwgQDwECAwQFBgcICQoLDA0ODwA=
+ +A combiner which orders keys lexicographically must produce the following PSBT: + +* Bytes in Hex:
70736274ff01003f0200000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffff010000000000000000036a0100000000000af00102030405060708090f0102030405060708090a0b0c0d0e0f0af00102030405060708100f0102030405060708090a0b0c0d0e0f000af00102030405060708090f0102030405060708090a0b0c0d0e0f0af00102030405060708100f0102030405060708090a0b0c0d0e0f000af00102030405060708090f0102030405060708090a0b0c0d0e0f0af00102030405060708100f0102030405060708090a0b0c0d0e0f00
+* Base64 String:
cHNidP8BAD8CAAAAAf//////////////////////////////////////////AAAAAAD/////AQAAAAAAAAAAA2oBAAAAAAAK8AECAwQFBgcICQ8BAgMEBQYHCAkKCwwNDg8K8AECAwQFBgcIEA8BAgMEBQYHCAkKCwwNDg8ACvABAgMEBQYHCAkPAQIDBAUGBwgJCgsMDQ4PCvABAgMEBQYHCBAPAQIDBAUGBwgJCgsMDQ4PAArwAQIDBAUGBwgJDwECAwQFBgcICQoLDA0ODwrwAQIDBAUGBwgQDwECAwQFBgcICQoLDA0ODwA=
+ +==Rationale== + + + +==Reference implementation== + +The reference implementation of the PSBT format is available at https://github.com/achow101/bitcoin/tree/psbt. + +==Acknowledgements== + +Special thanks to Pieter Wuille for suggesting that such a transaction format should be made +and for coming up with the name and abbreviation of PSBT. + +Thanks to Pieter Wuille, Gregory Maxwell, Jonathan Underwood, Daniel Cousens and those who commented on the bitcoin-dev mailing list for additional comments +and suggestions for improving this proposal. diff --git a/packages/wasm-utxo/cli/src/format/fixtures.rs b/packages/wasm-utxo/cli/src/format/fixtures.rs index 034073c7..220019e6 100644 --- a/packages/wasm-utxo/cli/src/format/fixtures.rs +++ b/packages/wasm-utxo/cli/src/format/fixtures.rs @@ -1,117 +1,75 @@ +#[cfg(test)] use super::tree::{node_to_string_with_scheme, ColorScheme}; +#[cfg(test)] use crate::node::Node; +#[cfg(test)] use std::env; +#[cfg(test)] use std::fs; +#[cfg(test)] use std::io::{self, Write}; -use std::path::PathBuf; -/// Generate a tree representation of a Node without colors -pub fn generate_tree_text(node: &Node) -> Result { - // Use the no-color scheme for consistent fixture output +/// Ensure the generated tree output matches the fixture file +/// If the fixture doesn't exist, it will be created +#[cfg(test)] +pub fn assert_tree_matches_fixture(node: &Node, name: &str) -> Result<(), io::Error> { let no_color_scheme = ColorScheme::no_color(); - node_to_string_with_scheme(node, &no_color_scheme) -} - -/// Generate a tree representation of a Node with a specific color scheme -pub fn generate_tree_text_with_scheme( - node: &Node, - color_scheme: &ColorScheme, -) -> Result { - node_to_string_with_scheme(node, color_scheme) -} + let generated = node_to_string_with_scheme(node, &no_color_scheme)?; -/// Returns the path to the fixture directory -pub fn fixtures_directory() -> PathBuf { let project_dir = env::current_dir().expect("Failed to get current directory"); - project_dir.join("tests").join("fixtures") -} - -/// Write tree output to a fixture file -pub fn write_fixture(name: &str, content: &str) -> Result<(), io::Error> { - let fixtures_dir = fixtures_directory(); - fs::create_dir_all(&fixtures_dir)?; - + let fixtures_dir = project_dir.join("test").join("fixtures"); let fixture_path = fixtures_dir.join(format!("{}.txt", name)); - // Write the content to the file - let mut file = fs::File::create(&fixture_path)?; - file.write_all(content.as_bytes())?; + if fixture_path.exists() { + let fixture_content = fs::read_to_string(&fixture_path)?; + // Compare the generated output to the fixture + assert_eq!( + generated, fixture_content, + "Generated tree output doesn't match fixture file: {}", + name + ); + } else { + // Create the fixture if it doesn't exist + fs::create_dir_all(&fixtures_dir)?; + let mut file = fs::File::create(&fixture_path)?; + file.write_all(generated.as_bytes())?; + println!("Created new fixture: {}.txt", name); + } Ok(()) } -/// Read the content of a fixture file if it exists -pub fn read_fixture(name: &str) -> Result, io::Error> { - let fixture_path = fixtures_directory().join(format!("{}.txt", name)); +/// Assert tree matches fixture, updating if needed or requested +#[cfg(test)] +pub fn assert_or_update_fixture(node: &Node, name: &str) -> Result<(), io::Error> { + let no_color_scheme = ColorScheme::no_color(); + let generated = node_to_string_with_scheme(node, &no_color_scheme)?; - if fixture_path.exists() { - let content = fs::read_to_string(&fixture_path)?; - Ok(Some(content)) - } else { - Ok(None) - } -} + let project_dir = env::current_dir().expect("Failed to get current directory"); + let fixtures_dir = project_dir.join("test").join("fixtures"); + let fixture_path = fixtures_dir.join(format!("{}.txt", name)); -/// Ensure the generated tree output matches the fixture file -/// If the fixture doesn't exist, it will be created -pub fn assert_tree_matches_fixture(node: &Node, name: &str) -> Result<(), io::Error> { - let generated = generate_tree_text(node)?; + let update_fixtures = env::var("UPDATE_FIXTURES").is_ok(); - match read_fixture(name)? { - Some(fixture_content) => { - // Compare the generated output to the fixture + if fixture_path.exists() { + let fixture_content = fs::read_to_string(&fixture_path)?; + if update_fixtures || generated != fixture_content { + let mut file = fs::File::create(&fixture_path)?; + file.write_all(generated.as_bytes())?; + println!("Updated fixture: {}.txt", name); + } else { assert_eq!( generated, fixture_content, "Generated tree output doesn't match fixture file: {}", name ); } - None => { - // Create the fixture if it doesn't exist - write_fixture(name, &generated)?; - println!("Created new fixture: {}.txt", name); - } - } - - Ok(()) -} - -/// Force update of a fixture file with new content -pub fn update_fixture(node: &Node, name: &str) -> Result<(), io::Error> { - let generated = generate_tree_text(node)?; - write_fixture(name, &generated) -} - -// Environment variable to force fixture updates -const UPDATE_FIXTURES_ENV: &str = "UPDATE_FIXTURES"; - -/// Check if fixtures should be updated -pub fn should_update_fixtures() -> bool { - env::var(UPDATE_FIXTURES_ENV).is_ok() -} - -/// Assert tree matches fixture, updating if needed or requested -pub fn assert_or_update_fixture(node: &Node, name: &str) -> Result<(), io::Error> { - let generated = generate_tree_text(node)?; - - match read_fixture(name)? { - Some(fixture_content) => { - if should_update_fixtures() || generated != fixture_content { - write_fixture(name, &generated)?; - println!("Updated fixture: {}.txt", name); - } else { - assert_eq!( - generated, fixture_content, - "Generated tree output doesn't match fixture file: {}", - name - ); - } - } - None => { - // Create the fixture if it doesn't exist - write_fixture(name, &generated)?; - println!("Created new fixture: {}.txt", name); - } + } else { + // Create the fixture if it doesn't exist + fs::create_dir_all(&fixtures_dir)?; + let mut file = fs::File::create(&fixture_path)?; + file.write_all(generated.as_bytes())?; + println!("Created new fixture: {}.txt", name); } Ok(()) diff --git a/packages/wasm-utxo/cli/src/format/mod.rs b/packages/wasm-utxo/cli/src/format/mod.rs index 2c11eee2..61170f2d 100644 --- a/packages/wasm-utxo/cli/src/format/mod.rs +++ b/packages/wasm-utxo/cli/src/format/mod.rs @@ -3,7 +3,4 @@ pub mod fixtures; mod tests; mod tree; -pub use tree::{ - add_node_to_tree, add_node_to_tree_with_scheme, format_primitive_for_tree, node_to_string, - node_to_string_with_scheme, render_tree, render_tree_with_scheme, ColorScheme, -}; +pub use tree::{render_tree_with_scheme, ColorScheme}; diff --git a/packages/wasm-utxo/cli/src/format/tests.rs b/packages/wasm-utxo/cli/src/format/tests.rs index 03370dc3..f84a4058 100644 --- a/packages/wasm-utxo/cli/src/format/tests.rs +++ b/packages/wasm-utxo/cli/src/format/tests.rs @@ -1,114 +1,110 @@ -#[cfg(test)] -mod tests { - use crate::format::fixtures::assert_or_update_fixture; - use crate::node::{Node, Primitive}; - use num_bigint::BigInt; - - #[test] - fn test_simple_tree() -> std::io::Result<()> { - // Create a simple tree - let child1 = Node::new("name", Primitive::String("Alice".to_string())); - let child2 = Node::new("age", Primitive::U8(30)); - let child3 = Node::new("active", Primitive::Boolean(true)); - - let mut parent = Node::new("person", Primitive::None); - parent.add_child(child1); - parent.add_child(child2); - parent.add_child(child3); - - // Check against fixture - assert_or_update_fixture(&parent, "simple_tree")?; - Ok(()) - } - - #[test] - fn test_complex_tree() -> std::io::Result<()> { - // Create a more complex tree - let address_street = Node::new("street", Primitive::String("123 Main St".to_string())); - let address_city = Node::new("city", Primitive::String("Anytown".to_string())); - let address_zip = Node::new("zip", Primitive::U16(12345)); - - let mut address = Node::new("address", Primitive::None); - address.add_child(address_street); - address.add_child(address_city); - address.add_child(address_zip); - - let phone1 = Node::new("home", Primitive::String("555-1234".to_string())); - let phone2 = Node::new("work", Primitive::String("555-5678".to_string())); - - let mut phones = Node::new("phones", Primitive::None); - phones.add_child(phone1); - phones.add_child(phone2); - - let account_number = Node::new( - "number", - Primitive::Integer(BigInt::parse_bytes(b"9876543210123456", 10).unwrap()), - ); - let account_balance = Node::new("balance", Primitive::I32(5000)); - - let mut account = Node::new("account", Primitive::None); - account.add_child(account_number); - account.add_child(account_balance); - - let name = Node::new("name", Primitive::String("John Doe".to_string())); - let age = Node::new("age", Primitive::U8(35)); - - let mut person = Node::new("person", Primitive::None); - person.add_child(name); - person.add_child(age); - person.add_child(address); - person.add_child(phones); - person.add_child(account); - - // Check against fixture - assert_or_update_fixture(&person, "complex_tree")?; - Ok(()) - } - - #[test] - fn test_buffer_display() -> std::io::Result<()> { - // Test how binary data is formatted in the tree - let small_buffer = Node::new("small", Primitive::Buffer(vec![1, 2, 3, 4])); - assert_or_update_fixture(&small_buffer, "small_buffer")?; - - let large_buffer = Node::new("large", Primitive::Buffer((0..100).collect())); - assert_or_update_fixture(&large_buffer, "large_buffer")?; - - Ok(()) - } - - #[test] - fn test_numeric_types() -> std::io::Result<()> { - // Create a tree with all the numeric types - let mut numbers = Node::new("numbers", Primitive::None); - - // Add signed integers - numbers.add_child(Node::new("i8_min", Primitive::I8(i8::MIN))); - numbers.add_child(Node::new("i8_max", Primitive::I8(i8::MAX))); - numbers.add_child(Node::new("i16_min", Primitive::I16(i16::MIN))); - numbers.add_child(Node::new("i16_max", Primitive::I16(i16::MAX))); - numbers.add_child(Node::new("i32_min", Primitive::I32(i32::MIN))); - numbers.add_child(Node::new("i32_max", Primitive::I32(i32::MAX))); - numbers.add_child(Node::new("i64_min", Primitive::I64(i64::MIN))); - numbers.add_child(Node::new("i64_max", Primitive::I64(i64::MAX))); - - // Add unsigned integers - numbers.add_child(Node::new("u8_max", Primitive::U8(u8::MAX))); - numbers.add_child(Node::new("u16_max", Primitive::U16(u16::MAX))); - numbers.add_child(Node::new("u32_max", Primitive::U32(u32::MAX))); - numbers.add_child(Node::new("u64_max", Primitive::U64(u64::MAX))); - - // Add a big integer - numbers.add_child(Node::new( - "bigint", - Primitive::Integer( - BigInt::parse_bytes(b"12345678901234567890123456789012345678901234567890", 10) - .unwrap(), - ), - )); - - // Check against fixture - assert_or_update_fixture(&numbers, "numeric_types")?; - Ok(()) - } +use crate::format::fixtures::assert_or_update_fixture; +use crate::node::{Node, Primitive}; +use num_bigint::BigInt; + +#[test] +fn test_simple_tree() -> std::io::Result<()> { + // Create a simple tree + let child1 = Node::new("name", Primitive::String("Alice".to_string())); + let child2 = Node::new("age", Primitive::U8(30)); + let child3 = Node::new("active", Primitive::Boolean(true)); + + let mut parent = Node::new("person", Primitive::None); + parent.add_child(child1); + parent.add_child(child2); + parent.add_child(child3); + + // Check against fixture + assert_or_update_fixture(&parent, "simple_tree")?; + Ok(()) +} + +#[test] +fn test_complex_tree() -> std::io::Result<()> { + // Create a more complex tree + let address_street = Node::new("street", Primitive::String("123 Main St".to_string())); + let address_city = Node::new("city", Primitive::String("Anytown".to_string())); + let address_zip = Node::new("zip", Primitive::U16(12345)); + + let mut address = Node::new("address", Primitive::None); + address.add_child(address_street); + address.add_child(address_city); + address.add_child(address_zip); + + let phone1 = Node::new("home", Primitive::String("555-1234".to_string())); + let phone2 = Node::new("work", Primitive::String("555-5678".to_string())); + + let mut phones = Node::new("phones", Primitive::None); + phones.add_child(phone1); + phones.add_child(phone2); + + let account_number = Node::new( + "number", + Primitive::Integer(BigInt::parse_bytes(b"9876543210123456", 10).unwrap()), + ); + let account_balance = Node::new("balance", Primitive::I32(5000)); + + let mut account = Node::new("account", Primitive::None); + account.add_child(account_number); + account.add_child(account_balance); + + let name = Node::new("name", Primitive::String("John Doe".to_string())); + let age = Node::new("age", Primitive::U8(35)); + + let mut person = Node::new("person", Primitive::None); + person.add_child(name); + person.add_child(age); + person.add_child(address); + person.add_child(phones); + person.add_child(account); + + // Check against fixture + assert_or_update_fixture(&person, "complex_tree")?; + Ok(()) +} + +#[test] +fn test_buffer_display() -> std::io::Result<()> { + // Test how binary data is formatted in the tree + let small_buffer = Node::new("small", Primitive::Buffer(vec![1, 2, 3, 4])); + assert_or_update_fixture(&small_buffer, "small_buffer")?; + + let large_buffer = Node::new("large", Primitive::Buffer((0..100).collect())); + assert_or_update_fixture(&large_buffer, "large_buffer")?; + + Ok(()) +} + +#[test] +fn test_numeric_types() -> std::io::Result<()> { + // Create a tree with all the numeric types + let mut numbers = Node::new("numbers", Primitive::None); + + // Add signed integers + numbers.add_child(Node::new("i8_min", Primitive::I8(i8::MIN))); + numbers.add_child(Node::new("i8_max", Primitive::I8(i8::MAX))); + numbers.add_child(Node::new("i16_min", Primitive::I16(i16::MIN))); + numbers.add_child(Node::new("i16_max", Primitive::I16(i16::MAX))); + numbers.add_child(Node::new("i32_min", Primitive::I32(i32::MIN))); + numbers.add_child(Node::new("i32_max", Primitive::I32(i32::MAX))); + numbers.add_child(Node::new("i64_min", Primitive::I64(i64::MIN))); + numbers.add_child(Node::new("i64_max", Primitive::I64(i64::MAX))); + + // Add unsigned integers + numbers.add_child(Node::new("u8_max", Primitive::U8(u8::MAX))); + numbers.add_child(Node::new("u16_max", Primitive::U16(u16::MAX))); + numbers.add_child(Node::new("u32_max", Primitive::U32(u32::MAX))); + numbers.add_child(Node::new("u64_max", Primitive::U64(u64::MAX))); + + // Add a big integer + numbers.add_child(Node::new( + "bigint", + Primitive::Integer( + BigInt::parse_bytes(b"12345678901234567890123456789012345678901234567890", 10).unwrap(), + ), + )); + + // Check against fixture + assert_or_update_fixture(&numbers, "numeric_types")?; + Ok(()) } diff --git a/packages/wasm-utxo/cli/src/format/tree.rs b/packages/wasm-utxo/cli/src/format/tree.rs index b09bf1c0..a39ce328 100644 --- a/packages/wasm-utxo/cli/src/format/tree.rs +++ b/packages/wasm-utxo/cli/src/format/tree.rs @@ -1,6 +1,8 @@ use crate::node::{Node, Primitive}; use colored::*; -use ptree::{print_tree, TreeBuilder}; +use ptree::print_tree; +#[cfg(test)] +use ptree::TreeBuilder; use std::borrow::Cow; use std::io; @@ -46,30 +48,6 @@ impl ColorScheme { } } - /// High contrast color scheme for better visibility - pub fn high_contrast() -> Self { - Self { - label_style: |s| s.bold().bright_white().to_string(), - value_style: |s| s.to_string(), - buffer_style: |s| s.bright_cyan().to_string(), - numeric_style: |s| s.bright_yellow().to_string(), - string_style: |s| s.bright_green().to_string(), - boolean_style: |s| s.bright_magenta().to_string(), - } - } - - /// Minimal color scheme with subtle styling - pub fn minimal() -> Self { - Self { - label_style: |s| s.dimmed().to_string(), - value_style: |s| s.to_string(), - buffer_style: |s| s.blue().to_string(), - numeric_style: |s| s.to_string(), - string_style: |s| s.to_string(), - boolean_style: |s| s.to_string(), - } - } - /// Apply appropriate styling to a primitive value based on its type pub fn style_primitive(&self, primitive: &Primitive, formatted_value: &str) -> String { match primitive { @@ -149,7 +127,8 @@ pub fn format_primitive_for_tree(primitive: &Primitive) -> String { } /// Render a Node tree to a string with the specified color scheme -pub fn node_to_string_with_scheme( +#[cfg(test)] +pub(super) fn node_to_string_with_scheme( node: &Node, color_scheme: &ColorScheme, ) -> Result { @@ -173,17 +152,9 @@ pub fn node_to_string_with_scheme( Ok(String::from_utf8_lossy(&output).to_string()) } -/// Render a Node tree to a string (using default color scheme for backward compatibility) -pub fn node_to_string(node: &Node) -> Result { - node_to_string_with_scheme(node, &ColorScheme::default()) -} - /// Helper function to add a node and its children to a tree with color scheme -pub fn add_node_to_tree_with_scheme( - tree: &mut TreeBuilder, - node: &Node, - color_scheme: &ColorScheme, -) { +#[cfg(test)] +fn add_node_to_tree_with_scheme(tree: &mut TreeBuilder, node: &Node, color_scheme: &ColorScheme) { let styled_label = (color_scheme.label_style)(&node.label); let value_str = format_primitive_for_tree(&node.value); let styled_value = color_scheme.style_primitive(&node.value, &value_str); @@ -197,18 +168,8 @@ pub fn add_node_to_tree_with_scheme( tree.end_child(); } -/// Helper function to add a node and its children to a tree (using default color scheme for backward compatibility) -pub fn add_node_to_tree(tree: &mut TreeBuilder, node: &Node) { - add_node_to_tree_with_scheme(tree, node, &ColorScheme::default()); -} - /// Render a Node tree to the terminal with the specified color scheme pub fn render_tree_with_scheme(node: &Node, color_scheme: &ColorScheme) -> Result<(), io::Error> { let tree_item = NodeTreeItem { node, color_scheme }; print_tree(&tree_item) } - -/// Render a Node tree to the terminal (using default color scheme for backward compatibility) -pub fn render_tree(node: &Node) -> Result<(), io::Error> { - render_tree_with_scheme(node, &ColorScheme::default()) -} diff --git a/packages/wasm-utxo/cli/src/input.rs b/packages/wasm-utxo/cli/src/input.rs new file mode 100644 index 00000000..02afbad5 --- /dev/null +++ b/packages/wasm-utxo/cli/src/input.rs @@ -0,0 +1,42 @@ +use anyhow::{Context, Result}; +use base64::Engine; +use std::fs; +use std::io::{self, Read}; +use std::path::PathBuf; + +/// Decode input bytes, attempting to interpret as base64, hex, or raw bytes +pub fn decode_input(raw_bytes: &[u8]) -> Result> { + // Try to interpret as text first (for base64/hex encoded input) + if let Ok(text) = std::str::from_utf8(raw_bytes) { + let trimmed = text.trim(); + + // Try hex first (more common format) + if let Ok(decoded) = hex::decode(trimmed) { + return Ok(decoded); + } + + // Try base64 + if let Ok(decoded) = base64::engine::general_purpose::STANDARD.decode(trimmed) { + return Ok(decoded); + } + } + + // Fall back to raw bytes + Ok(raw_bytes.to_vec()) +} + +/// Read bytes from a file path or stdin (if path is "-") +pub fn read_input_bytes(path: &PathBuf, file_type: &str) -> Result> { + if path.to_str() == Some("-") { + // Read from stdin + let mut buffer = Vec::new(); + io::stdin() + .read_to_end(&mut buffer) + .context("Failed to read from stdin")?; + Ok(buffer) + } else { + // Read from file + fs::read(path) + .with_context(|| format!("Failed to read {} file: {}", file_type, path.display())) + } +} diff --git a/packages/wasm-utxo/cli/src/main.rs b/packages/wasm-utxo/cli/src/main.rs index aaa7314e..cd19e9ca 100644 --- a/packages/wasm-utxo/cli/src/main.rs +++ b/packages/wasm-utxo/cli/src/main.rs @@ -3,9 +3,14 @@ use clap::{Parser, Subcommand}; mod address; mod format; +mod input; mod node; -mod parse_node; +mod parse; mod psbt; +mod tx; + +#[cfg(test)] +pub mod test_utils; #[derive(Parser)] #[command(name = "wasm-utxo-cli")] @@ -28,6 +33,11 @@ enum Commands { #[command(subcommand)] command: psbt::PsbtCommand, }, + /// Transaction parsing and inspection operations + Tx { + #[command(subcommand)] + command: tx::TxCommand, + }, } fn main() -> Result<()> { @@ -36,5 +46,6 @@ fn main() -> Result<()> { match cli.command { Commands::Address { command } => address::handle_command(command), Commands::Psbt { command } => psbt::handle_command(command), + Commands::Tx { command } => tx::handle_command(command), } } diff --git a/packages/wasm-utxo/cli/src/node.rs b/packages/wasm-utxo/cli/src/node.rs index 34e50627..5cbdbab9 100644 --- a/packages/wasm-utxo/cli/src/node.rs +++ b/packages/wasm-utxo/cli/src/node.rs @@ -82,6 +82,7 @@ impl Node { } } + #[cfg(test)] pub fn with_children(label: impl Into, value: Primitive, children: Vec) -> Self { Self { label: label.into(), @@ -94,15 +95,11 @@ impl Node { self.children.push(child); } - pub fn with_child(mut self, child: Node) -> Self { - self.children.push(child); - self - } - pub fn extend(&mut self, nodes: impl IntoIterator) { self.children.extend(nodes); } + #[cfg(test)] pub fn child_count(&self) -> usize { self.children.len() } diff --git a/packages/wasm-utxo/cli/src/parse/mod.rs b/packages/wasm-utxo/cli/src/parse/mod.rs new file mode 100644 index 00000000..ab908bd2 --- /dev/null +++ b/packages/wasm-utxo/cli/src/parse/mod.rs @@ -0,0 +1,5 @@ +pub mod node; +pub mod node_raw; + +pub use node::{parse_psbt_bytes_internal, parse_tx_bytes_internal}; +pub use node_raw::parse_psbt_bytes_raw; diff --git a/packages/wasm-utxo/cli/src/parse_node.rs b/packages/wasm-utxo/cli/src/parse/node.rs similarity index 89% rename from packages/wasm-utxo/cli/src/parse_node.rs rename to packages/wasm-utxo/cli/src/parse/node.rs index d8557298..5519cb74 100644 --- a/packages/wasm-utxo/cli/src/parse_node.rs +++ b/packages/wasm-utxo/cli/src/parse/node.rs @@ -103,7 +103,7 @@ pub fn psbt_to_node(psbt: &Psbt, network: Network) -> Node { psbt_node.add_child(xpubs_to_node(&psbt.xpub)); - if psbt.proprietary.len() > 0 { + if !psbt.proprietary.is_empty() { let mut proprietary_node = Node::new("proprietary", Primitive::U64(psbt.proprietary.len() as u64)); proprietary_node.extend(proprietary_to_nodes(&psbt.proprietary)); @@ -177,7 +177,7 @@ pub fn psbt_to_node(psbt: &Psbt, network: Network) -> Node { input_node.extend(bip32_derivations_to_nodes(&input.bip32_derivation)); - if input.proprietary.len() > 0 { + if !input.proprietary.is_empty() { let mut prop_node = Node::new( "proprietary", Primitive::U64(input.proprietary.len() as u64), @@ -203,7 +203,7 @@ pub fn psbt_to_node(psbt: &Psbt, network: Network) -> Node { output_node.add_child(script_buf_to_node("witness_script", script)); } - if output.proprietary.len() > 0 { + if !output.proprietary.is_empty() { let mut prop_node = Node::new( "proprietary", Primitive::U64(output.proprietary.len() as u64), @@ -317,3 +317,44 @@ pub fn parse_tx_bytes_internal(bytes: &[u8]) -> Result { .map(|tx| tx_to_node(&tx, Network::Bitcoin)) .map_err(|e| e.to_string()) } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_parse_psbt_bitcoin_fullsigned() -> Result<(), Box> { + use crate::format::fixtures::assert_tree_matches_fixture; + use crate::test_utils::{load_psbt_bytes, SignatureState, TxFormat}; + use wasm_utxo::Network as WasmNetwork; + + let psbt_bytes = load_psbt_bytes( + WasmNetwork::Bitcoin, + SignatureState::Fullsigned, + TxFormat::Psbt, + )?; + + let node = parse_psbt_bytes_internal(&psbt_bytes)?; + + assert_tree_matches_fixture(&node, "psbt_bitcoin_fullsigned")?; + Ok(()) + } + + #[test] + fn test_parse_tx_bitcoin_fullsigned() -> Result<(), Box> { + use crate::format::fixtures::assert_tree_matches_fixture; + use crate::test_utils::{load_tx_bytes, SignatureState, TxFormat}; + use wasm_utxo::Network as WasmNetwork; + + let tx_bytes = load_tx_bytes( + WasmNetwork::Bitcoin, + SignatureState::Fullsigned, + TxFormat::PsbtLite, + )?; + + let node = parse_tx_bytes_internal(&tx_bytes)?; + + assert_tree_matches_fixture(&node, "tx_bitcoin_fullsigned")?; + Ok(()) + } +} diff --git a/packages/wasm-utxo/cli/src/parse/node_raw.rs b/packages/wasm-utxo/cli/src/parse/node_raw.rs new file mode 100644 index 00000000..2507c414 --- /dev/null +++ b/packages/wasm-utxo/cli/src/parse/node_raw.rs @@ -0,0 +1,497 @@ +/// Low-level PSBT parser using raw key-value pairs +/// +/// This module provides parsing of PSBT (Partially Signed Bitcoin Transaction) files +/// at the raw byte level, exposing the key-value pair structure as defined in BIP-174. +/// +/// # Purpose +/// +/// Unlike the high-level parser, this shows: +/// - Raw key type IDs and their human-readable names +/// - Proprietary keys with their structured format (prefix, subtype, key_data) +/// - Unknown/unrecognized keys that standard parsers might skip +/// - Field presence indicators for debugging +/// +/// # Example +/// +/// ```ignore +/// use parse::node_raw::parse_psbt_bytes_raw; +/// +/// let psbt_bytes = /* your PSBT data */; +/// let node = parse_psbt_bytes_raw(&psbt_bytes)?; +/// // Returns a tree structure showing raw PSBT key-value pairs +/// ``` +/// +/// # References +/// +/// - [BIP-174: PSBT Format](https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki) +/// - [bitcoin::psbt::raw](https://docs.rs/bitcoin/latest/bitcoin/psbt/raw/index.html) +use bitcoin::consensus::Decodable; +use bitcoin::psbt::raw::{Key, Pair}; +use bitcoin::{Network, Transaction, VarInt}; + +pub use crate::node::{Node, Primitive}; + +/// Context for interpreting PSBT key types +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +enum PsbtMapContext { + Global, + Input, + Output, +} + +/// Check if bytes are printable ASCII +fn is_printable_ascii(bytes: &[u8]) -> bool { + bytes.iter().all(|&b| (0x20..=0x7E).contains(&b)) +} + +/// Parse proprietary key structure (0xFC type keys) +fn parse_proprietary_key(key_data: &[u8]) -> Result<(Vec, u8, Vec), String> { + if key_data.is_empty() { + return Err("Empty proprietary key data".to_string()); + } + + let mut pos = 0; + + // Decode prefix length (varint) + let (prefix_len, varint_size) = decode_varint(key_data, pos)?; + pos += varint_size; + + let prefix_len = prefix_len as usize; + if pos + prefix_len > key_data.len() { + return Err("Not enough bytes for proprietary prefix".to_string()); + } + + // Extract prefix + let prefix = key_data[pos..pos + prefix_len].to_vec(); + pos += prefix_len; + + // Extract subtype (1 byte) + if pos >= key_data.len() { + return Err("Not enough bytes for proprietary subtype".to_string()); + } + let subtype = key_data[pos]; + pos += 1; + + // Remaining bytes are additional key data + let remaining_key = key_data[pos..].to_vec(); + + Ok((prefix, subtype, remaining_key)) +} + +/// Parse a raw PSBT key into a node +fn key_to_node(key: &Key, context: PsbtMapContext) -> Node { + let mut key_node = Node::new("key", Primitive::None); + + // First byte is the key type + if !key.key.is_empty() { + key_node.add_child(Node::new("type_id", Primitive::U8(key.type_value))); + key_node.add_child(Node::new( + "type_name", + Primitive::String(key_type_name(key.type_value, context)), + )); + } + + // Rest is the key data + if key.key.len() > 1 { + let key_data = &key.key[1..]; + + // Special handling for proprietary keys (0xFC) + if key.type_value == 0xFC { + match parse_proprietary_key(key_data) { + Ok((prefix, subtype, remaining_key)) => { + // Add prefix - show as ASCII string if printable + if is_printable_ascii(&prefix) { + key_node.add_child(Node::new( + "prefix", + Primitive::String(String::from_utf8_lossy(&prefix).to_string()), + )); + } else { + key_node.add_child(Node::new("prefix", Primitive::Buffer(prefix))); + } + + // Add subtype + key_node.add_child(Node::new("subtype", Primitive::U8(subtype))); + + // Add remaining key data if any + if !remaining_key.is_empty() { + key_node.add_child(Node::new("key_data", Primitive::Buffer(remaining_key))); + } + } + Err(_) => { + // Fallback: show raw key_data if parsing fails + key_node.add_child(Node::new("key_data", Primitive::Buffer(key_data.to_vec()))); + } + } + } else { + // Non-proprietary keys: just show key_data as buffer + key_node.add_child(Node::new("key_data", Primitive::Buffer(key_data.to_vec()))); + } + } + + key_node +} + +/// Parse a raw PSBT key-value pair into a node +fn pair_to_node(pair: &Pair, index: usize, context: PsbtMapContext) -> Node { + let mut pair_node = Node::new(format!("pair_{}", index), Primitive::None); + pair_node.add_child(key_to_node(&pair.key, context)); + pair_node.add_child(Node::new("value", Primitive::Buffer(pair.value.clone()))); + pair_node +} + +/// Get human-readable name for PSBT key type based on context +fn key_type_name(type_id: u8, context: PsbtMapContext) -> String { + match context { + PsbtMapContext::Global => match type_id { + 0x00 => "PSBT_GLOBAL_UNSIGNED_TX".to_string(), + 0x01 => "PSBT_GLOBAL_XPUB".to_string(), + 0x02 => "PSBT_GLOBAL_TX_VERSION".to_string(), + 0x03 => "PSBT_GLOBAL_FALLBACK_LOCKTIME".to_string(), + 0x04 => "PSBT_GLOBAL_INPUT_COUNT".to_string(), + 0x05 => "PSBT_GLOBAL_OUTPUT_COUNT".to_string(), + 0x06 => "PSBT_GLOBAL_TX_MODIFIABLE".to_string(), + 0x07 => "PSBT_GLOBAL_VERSION".to_string(), + 0xFC => "PSBT_GLOBAL_PROPRIETARY".to_string(), + _ => format!("UNKNOWN_TYPE_0x{:02X}", type_id), + }, + PsbtMapContext::Input => match type_id { + 0x00 => "PSBT_IN_NON_WITNESS_UTXO".to_string(), + 0x01 => "PSBT_IN_WITNESS_UTXO".to_string(), + 0x02 => "PSBT_IN_PARTIAL_SIG".to_string(), + 0x03 => "PSBT_IN_SIGHASH_TYPE".to_string(), + 0x04 => "PSBT_IN_REDEEM_SCRIPT".to_string(), + 0x05 => "PSBT_IN_WITNESS_SCRIPT".to_string(), + 0x06 => "PSBT_IN_BIP32_DERIVATION".to_string(), + 0x07 => "PSBT_IN_FINAL_SCRIPTSIG".to_string(), + 0x08 => "PSBT_IN_FINAL_SCRIPTWITNESS".to_string(), + 0x09 => "PSBT_IN_POR_COMMITMENT".to_string(), + 0x0a => "PSBT_IN_RIPEMD160".to_string(), + 0x0b => "PSBT_IN_SHA256".to_string(), + 0x0c => "PSBT_IN_HASH160".to_string(), + 0x0d => "PSBT_IN_HASH256".to_string(), + 0x0e => "PSBT_IN_PREVIOUS_TXID".to_string(), + 0x0f => "PSBT_IN_OUTPUT_INDEX".to_string(), + 0x10 => "PSBT_IN_SEQUENCE".to_string(), + 0x11 => "PSBT_IN_REQUIRED_TIME_LOCKTIME".to_string(), + 0x12 => "PSBT_IN_REQUIRED_HEIGHT_LOCKTIME".to_string(), + 0x13 => "PSBT_IN_TAP_KEY_SIG".to_string(), + 0x14 => "PSBT_IN_TAP_SCRIPT_SIG".to_string(), + 0x15 => "PSBT_IN_TAP_LEAF_SCRIPT".to_string(), + 0x16 => "PSBT_IN_TAP_BIP32_DERIVATION".to_string(), + 0x17 => "PSBT_IN_TAP_INTERNAL_KEY".to_string(), + 0x18 => "PSBT_IN_TAP_MERKLE_ROOT".to_string(), + 0x19 => "PSBT_IN_MUSIG2_PARTICIPANT_PUBKEYS".to_string(), + 0x1a => "PSBT_IN_MUSIG2_PUB_NONCE".to_string(), + 0x1b => "PSBT_IN_MUSIG2_PARTIAL_SIG".to_string(), + 0xFC => "PSBT_IN_PROPRIETARY".to_string(), + _ => format!("UNKNOWN_TYPE_0x{:02X}", type_id), + }, + PsbtMapContext::Output => match type_id { + 0x00 => "PSBT_OUT_REDEEM_SCRIPT".to_string(), + 0x01 => "PSBT_OUT_WITNESS_SCRIPT".to_string(), + 0x02 => "PSBT_OUT_BIP32_DERIVATION".to_string(), + 0x03 => "PSBT_OUT_AMOUNT".to_string(), + 0x04 => "PSBT_OUT_SCRIPT".to_string(), + 0x05 => "PSBT_OUT_TAP_INTERNAL_KEY".to_string(), + 0x06 => "PSBT_OUT_TAP_TREE".to_string(), + 0x07 => "PSBT_OUT_TAP_BIP32_DERIVATION".to_string(), + 0xFC => "PSBT_OUT_PROPRIETARY".to_string(), + _ => format!("UNKNOWN_TYPE_0x{:02X}", type_id), + }, + } +} + +/// Decode a varint from bytes using bitcoin crate, returns (value, bytes_consumed) +fn decode_varint(bytes: &[u8], pos: usize) -> Result<(u64, usize), String> { + if pos >= bytes.len() { + return Err("Not enough bytes for varint".to_string()); + } + + let mut cursor = &bytes[pos..]; + let varint = VarInt::consensus_decode(&mut cursor) + .map_err(|e| format!("Failed to decode varint: {}", e))?; + + // Calculate bytes consumed by comparing slice positions + let bytes_consumed = bytes.len() - pos - cursor.len(); + + Ok((varint.0, bytes_consumed)) +} + +/// Manually decode a key-value pair from bytes +/// +/// Note: The bitcoin crate has `Pair::decode()` and `Key::decode()` methods, but they are +/// marked as `pub(crate)` and not exposed in the public API. We must implement our own +/// decoder to parse raw PSBT bytes at this low level. We do reuse the bitcoin crate's +/// `VarInt` decoder where possible. +fn decode_pair(bytes: &[u8], pos: usize) -> Result<(Pair, usize), String> { + let mut current_pos = pos; + + // Decode key length (varint) + let (key_len, varint_size) = decode_varint(bytes, current_pos)?; + current_pos += varint_size; + + if key_len == 0 { + return Err("Zero-length key (map separator)".to_string()); + } + + // Key is: type_value (1 byte) + key_data + if current_pos >= bytes.len() { + return Err("Not enough bytes for key type".to_string()); + } + + let type_value = bytes[current_pos]; + current_pos += 1; + + let key_data_len = (key_len - 1) as usize; + if current_pos + key_data_len > bytes.len() { + return Err(format!( + "Not enough bytes for key data: need {}, have {}", + key_data_len, + bytes.len() - current_pos + )); + } + + let mut key_bytes = vec![type_value]; + key_bytes.extend_from_slice(&bytes[current_pos..current_pos + key_data_len]); + current_pos += key_data_len; + + let key = Key { + type_value, + key: key_bytes, + }; + + // Decode value length (varint) + let (value_len, varint_size) = decode_varint(bytes, current_pos)?; + current_pos += varint_size; + + let value_len = value_len as usize; + if current_pos + value_len > bytes.len() { + return Err(format!( + "Not enough bytes for value: need {}, have {}", + value_len, + bytes.len() - current_pos + )); + } + + let value = bytes[current_pos..current_pos + value_len].to_vec(); + current_pos += value_len; + + let pair = Pair { key, value }; + Ok((pair, current_pos - pos)) +} + +/// Extract transaction input/output counts from global map +fn extract_tx_counts(global_pairs: &[Pair]) -> Result<(usize, usize), String> { + // Find the unsigned transaction (type 0x00) + for pair in global_pairs { + if pair.key.type_value == 0x00 { + // Parse the transaction + let tx = Transaction::consensus_decode(&mut &pair.value[..]) + .map_err(|e| format!("Failed to decode unsigned transaction: {}", e))?; + return Ok((tx.input.len(), tx.output.len())); + } + } + Err("No unsigned transaction found in global map".to_string()) +} + +/// Decode a single map (set of key-value pairs terminated by 0x00) +fn decode_map( + bytes: &[u8], + start_pos: usize, + map_name: &str, + context: PsbtMapContext, +) -> Result<(Node, Vec, usize), String> { + let mut map_node = Node::new(map_name, Primitive::None); + let mut pairs = Vec::new(); + let mut pos = start_pos; + + loop { + // Check if we hit the separator (0x00) + if pos >= bytes.len() { + break; + } + + if bytes[pos] == 0x00 { + pos += 1; // Skip the separator + break; + } + + // Try to decode a pair + match decode_pair(bytes, pos) { + Ok((pair, consumed)) => { + pairs.push(pair); + pos += consumed; + } + Err(e) => { + // Check if this is a zero-length key (separator) + if e.contains("Zero-length") { + pos += 1; // Skip the 0x00 + break; + } + return Err(format!("Failed to decode pair at position {}: {}", pos, e)); + } + } + } + + // Add pair count first + let pair_count = pairs.len(); + map_node.add_child(Node::new("pair_count", Primitive::U64(pair_count as u64))); + + // Process all pairs + for (idx, pair) in pairs.iter().enumerate() { + map_node.add_child(pair_to_node(pair, idx, context)); + } + + Ok((map_node, pairs, pos)) +} + +/// Parse PSBT showing raw key-value structure from bytes +pub fn psbt_to_raw_node(bytes: &[u8], _network: Network) -> Result { + let mut psbt_node = Node::new("psbt_raw", Primitive::None); + + // 1. Check magic bytes: "psbt" + 0xff + if bytes.len() < 5 { + return Err("PSBT too short to contain magic bytes".to_string()); + } + + let magic = &bytes[0..5]; + if magic != b"psbt\xff" { + return Err(format!("Invalid PSBT magic bytes: {:02x?}", magic)); + } + + psbt_node.add_child(Node::new( + "magic", + Primitive::String(format!("{:02x?}", magic)), + )); + + let mut pos = 5; // Start after magic bytes + + // 2. Decode global map + let (global_map, global_pairs, new_pos) = + decode_map(bytes, pos, "global_map", PsbtMapContext::Global)?; + psbt_node.add_child(global_map); + pos = new_pos; + + // 3. Extract transaction input/output counts from unsigned tx + let (expected_input_count, expected_output_count) = extract_tx_counts(&global_pairs)?; + + // 4. Decode input maps + let mut input_maps_node = Node::new("input_maps", Primitive::None); + + for input_idx in 0..expected_input_count { + let (input_map, _, new_pos) = decode_map( + bytes, + pos, + &format!("input_{}", input_idx), + PsbtMapContext::Input, + )?; + input_maps_node.add_child(input_map); + pos = new_pos; + } + + input_maps_node.value = Primitive::U64(expected_input_count as u64); + psbt_node.add_child(input_maps_node); + + // 5. Decode output maps + let mut output_maps_node = Node::new("output_maps", Primitive::None); + + for output_idx in 0..expected_output_count { + let (output_map, _, new_pos) = decode_map( + bytes, + pos, + &format!("output_{}", output_idx), + PsbtMapContext::Output, + )?; + output_maps_node.add_child(output_map); + pos = new_pos; + } + + output_maps_node.value = Primitive::U64(expected_output_count as u64); + psbt_node.add_child(output_maps_node); + + // Check if we consumed all bytes + let remaining = bytes.len() - pos; + if remaining > 0 { + psbt_node.add_child(Node::new( + "remaining_bytes", + Primitive::U64(remaining as u64), + )); + } + + Ok(psbt_node) +} + +pub fn parse_psbt_bytes_raw(bytes: &[u8]) -> Result { + psbt_to_raw_node(bytes, Network::Bitcoin) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_key_type_names() { + assert_eq!( + key_type_name(0x00, PsbtMapContext::Global), + "PSBT_GLOBAL_UNSIGNED_TX" + ); + assert_eq!( + key_type_name(0xFC, PsbtMapContext::Global), + "PSBT_GLOBAL_PROPRIETARY" + ); + assert!(key_type_name(0xFF, PsbtMapContext::Global).starts_with("UNKNOWN_TYPE")); + + // Test input context + assert_eq!( + key_type_name(0x00, PsbtMapContext::Input), + "PSBT_IN_NON_WITNESS_UTXO" + ); + assert_eq!( + key_type_name(0x01, PsbtMapContext::Input), + "PSBT_IN_WITNESS_UTXO" + ); + + // Test output context + assert_eq!( + key_type_name(0x00, PsbtMapContext::Output), + "PSBT_OUT_REDEEM_SCRIPT" + ); + assert_eq!( + key_type_name(0x03, PsbtMapContext::Output), + "PSBT_OUT_AMOUNT" + ); + } + + #[test] + fn test_key_to_node() { + let key = Key { + type_value: 0x01, + key: vec![0x01, 0x02, 0x03], + }; + let node = key_to_node(&key, PsbtMapContext::Global); + assert_eq!(node.label, "key"); + assert!(!node.children.is_empty()); + } + + #[test] + fn test_magic_bytes() { + let magic = b"psbt\xff"; + assert_eq!(magic.len(), 5); + assert_eq!(magic[4], 0xff); + } + + #[test] + fn test_parse_psbt_bitcoin_fullsigned() -> Result<(), Box> { + use crate::format::fixtures::assert_tree_matches_fixture; + use crate::test_utils::{load_psbt_bytes, SignatureState, TxFormat}; + use wasm_utxo::Network; + + let psbt_bytes = + load_psbt_bytes(Network::Bitcoin, SignatureState::Fullsigned, TxFormat::Psbt)?; + + let node = parse_psbt_bytes_raw(&psbt_bytes)?; + + assert_tree_matches_fixture(&node, "psbt_raw_bitcoin_fullsigned")?; + Ok(()) + } +} diff --git a/packages/wasm-utxo/cli/src/psbt.rs b/packages/wasm-utxo/cli/src/psbt.rs deleted file mode 100644 index bff5b37b..00000000 --- a/packages/wasm-utxo/cli/src/psbt.rs +++ /dev/null @@ -1,76 +0,0 @@ -use anyhow::{Context, Result}; -use base64::Engine; -use clap::Subcommand; -use std::fs; -use std::io::{self, Read}; -use std::path::PathBuf; - -use crate::format::{render_tree_with_scheme, ColorScheme}; -use crate::parse_node::parse_psbt_bytes_internal; - -fn decode_input(raw_bytes: &[u8]) -> Result> { - // Try to interpret as text first (for base64/hex encoded input) - if let Ok(text) = std::str::from_utf8(raw_bytes) { - let trimmed = text.trim(); - - // Try base64 first (more common for PSBTs) - if let Ok(decoded) = base64::engine::general_purpose::STANDARD.decode(trimmed) { - return Ok(decoded); - } - - // Try hex - if let Ok(decoded) = hex::decode(trimmed) { - return Ok(decoded); - } - } - - // Fall back to raw bytes - Ok(raw_bytes.to_vec()) -} - -#[derive(Subcommand)] -pub enum PsbtCommand { - /// Parse a PSBT file and display its contents - Parse { - /// Path to the PSBT file (use '-' to read from stdin) - path: PathBuf, - /// Disable colored output - #[arg(long)] - no_color: bool, - }, -} - -pub fn handle_command(command: PsbtCommand) -> Result<()> { - match command { - PsbtCommand::Parse { path, no_color } => { - let raw_bytes = if path.to_str() == Some("-") { - // Read from stdin - let mut buffer = Vec::new(); - io::stdin() - .read_to_end(&mut buffer) - .context("Failed to read from stdin")?; - buffer - } else { - // Read from file - fs::read(&path) - .with_context(|| format!("Failed to read PSBT file: {}", path.display()))? - }; - - // Decode input (auto-detect base64, hex, or raw bytes) - let bytes = decode_input(&raw_bytes)?; - - let node = parse_psbt_bytes_internal(&bytes) - .map_err(|e| anyhow::anyhow!("Failed to parse PSBT: {}", e))?; - - let color_scheme = if no_color { - ColorScheme::no_color() - } else { - ColorScheme::default() - }; - - render_tree_with_scheme(&node, &color_scheme)?; - - Ok(()) - } - } -} diff --git a/packages/wasm-utxo/cli/src/psbt/mod.rs b/packages/wasm-utxo/cli/src/psbt/mod.rs new file mode 100644 index 00000000..e8be7fd0 --- /dev/null +++ b/packages/wasm-utxo/cli/src/psbt/mod.rs @@ -0,0 +1,29 @@ +use anyhow::Result; +use clap::Subcommand; + +mod parse; + +#[derive(Subcommand)] +pub enum PsbtCommand { + /// Parse a PSBT file and display its contents + Parse { + /// Path to the PSBT file (use '-' to read from stdin) + path: std::path::PathBuf, + /// Disable colored output + #[arg(long)] + no_color: bool, + /// Show raw key-value pairs instead of parsed structure + #[arg(long)] + raw: bool, + }, +} + +pub fn handle_command(command: PsbtCommand) -> Result<()> { + match command { + PsbtCommand::Parse { + path, + no_color, + raw, + } => parse::handle_parse_command(path, no_color, raw), + } +} diff --git a/packages/wasm-utxo/cli/src/psbt/parse.rs b/packages/wasm-utxo/cli/src/psbt/parse.rs new file mode 100644 index 00000000..ea2e01db --- /dev/null +++ b/packages/wasm-utxo/cli/src/psbt/parse.rs @@ -0,0 +1,32 @@ +use anyhow::Result; +use std::path::PathBuf; + +use crate::format::{render_tree_with_scheme, ColorScheme}; +use crate::input::{decode_input, read_input_bytes}; +use crate::parse::{parse_psbt_bytes_internal, parse_psbt_bytes_raw}; + +pub fn handle_parse_command(path: PathBuf, no_color: bool, raw: bool) -> Result<()> { + // Read from file or stdin + let raw_bytes = read_input_bytes(&path, "PSBT")?; + + // Decode input (auto-detect hex, base64, or raw bytes) + let bytes = decode_input(&raw_bytes)?; + + let node = if raw { + parse_psbt_bytes_raw(&bytes) + .map_err(|e| anyhow::anyhow!("Failed to parse PSBT (raw): {}", e))? + } else { + parse_psbt_bytes_internal(&bytes) + .map_err(|e| anyhow::anyhow!("Failed to parse PSBT: {}", e))? + }; + + let color_scheme = if no_color { + ColorScheme::no_color() + } else { + ColorScheme::default() + }; + + render_tree_with_scheme(&node, &color_scheme)?; + + Ok(()) +} diff --git a/packages/wasm-utxo/cli/src/test_utils.rs b/packages/wasm-utxo/cli/src/test_utils.rs new file mode 100644 index 00000000..89a835ab --- /dev/null +++ b/packages/wasm-utxo/cli/src/test_utils.rs @@ -0,0 +1,139 @@ +//! Test utilities for CLI tests +//! +//! This module provides lightweight utilities for loading test fixtures. + +use base64::{engine::general_purpose, Engine as _}; +use serde::Deserialize; +use wasm_utxo::Network; + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum SignatureState { + Unsigned, + Halfsigned, + Fullsigned, +} + +impl SignatureState { + pub fn as_str(&self) -> &'static str { + match self { + SignatureState::Unsigned => "unsigned", + SignatureState::Halfsigned => "halfsigned", + SignatureState::Fullsigned => "fullsigned", + } + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum TxFormat { + Psbt, + PsbtLite, +} + +impl TxFormat { + pub fn as_str(&self) -> &'static str { + match self { + TxFormat::Psbt => "psbt", + TxFormat::PsbtLite => "psbt-lite", + } + } +} + +#[derive(Deserialize)] +struct PsbtFixtureBase64 { + #[serde(rename = "psbtBase64")] + psbt_base64: String, +} + +#[derive(Deserialize)] +struct TxFixture { + #[serde(rename = "extractedTransaction")] + extracted_transaction: String, +} + +/// Load PSBT bytes from a fixture file +/// +/// # Arguments +/// * `network` - The network type +/// * `signature_state` - The signature state of the PSBT +/// * `tx_format` - The transaction format (Psbt or PsbtLite) +/// +/// # Example +/// ```rust,no_run +/// use cli::test_utils::*; +/// use wasm_utxo::Network; +/// +/// let psbt_bytes = load_psbt_bytes( +/// Network::Bitcoin, +/// SignatureState::Fullsigned, +/// TxFormat::PsbtLite +/// ).expect("Failed to load fixture"); +/// ``` +pub fn load_psbt_bytes( + network: Network, + signature_state: SignatureState, + tx_format: TxFormat, +) -> Result, Box> { + let filename = format!( + "{}.{}.{}.json", + tx_format.as_str(), + network.to_utxolib_name(), + signature_state.as_str() + ); + let path = format!( + "{}/test/fixtures/fixed-script/{}", + env!("CARGO_MANIFEST_DIR"), + filename + ); + + let contents = std::fs::read_to_string(&path) + .unwrap_or_else(|_| panic!("Failed to load fixture: {}", path)); + + let fixture: PsbtFixtureBase64 = serde_json::from_str(&contents)?; + + let psbt_bytes = general_purpose::STANDARD.decode(&fixture.psbt_base64)?; + Ok(psbt_bytes) +} + +/// Load transaction bytes from a fixture file's extractedTransaction field +/// +/// # Arguments +/// * `network` - The network type +/// * `signature_state` - The signature state of the transaction +/// * `tx_format` - The transaction format (Psbt or PsbtLite) +/// +/// # Example +/// ```rust,no_run +/// use cli::test_utils::*; +/// use wasm_utxo::Network; +/// +/// let tx_bytes = load_tx_bytes( +/// Network::Bitcoin, +/// SignatureState::Fullsigned, +/// TxFormat::PsbtLite +/// ).expect("Failed to load fixture"); +/// ``` +pub fn load_tx_bytes( + network: Network, + signature_state: SignatureState, + tx_format: TxFormat, +) -> Result, Box> { + let filename = format!( + "{}.{}.{}.json", + tx_format.as_str(), + network.to_utxolib_name(), + signature_state.as_str() + ); + let path = format!( + "{}/test/fixtures/fixed-script/{}", + env!("CARGO_MANIFEST_DIR"), + filename + ); + + let contents = std::fs::read_to_string(&path) + .unwrap_or_else(|_| panic!("Failed to load fixture: {}", path)); + + let fixture: TxFixture = serde_json::from_str(&contents)?; + + let tx_bytes = hex::decode(&fixture.extracted_transaction)?; + Ok(tx_bytes) +} diff --git a/packages/wasm-utxo/cli/src/tx/mod.rs b/packages/wasm-utxo/cli/src/tx/mod.rs new file mode 100644 index 00000000..0ae0c7f0 --- /dev/null +++ b/packages/wasm-utxo/cli/src/tx/mod.rs @@ -0,0 +1,22 @@ +use anyhow::Result; +use clap::Subcommand; + +mod parse; + +#[derive(Subcommand)] +pub enum TxCommand { + /// Parse a transaction file and display its contents + Parse { + /// Path to the transaction file (use '-' to read from stdin) + path: std::path::PathBuf, + /// Disable colored output + #[arg(long)] + no_color: bool, + }, +} + +pub fn handle_command(command: TxCommand) -> Result<()> { + match command { + TxCommand::Parse { path, no_color } => parse::handle_parse_command(path, no_color), + } +} diff --git a/packages/wasm-utxo/cli/src/tx/parse.rs b/packages/wasm-utxo/cli/src/tx/parse.rs new file mode 100644 index 00000000..767bba47 --- /dev/null +++ b/packages/wasm-utxo/cli/src/tx/parse.rs @@ -0,0 +1,27 @@ +use anyhow::Result; +use std::path::PathBuf; + +use crate::format::{render_tree_with_scheme, ColorScheme}; +use crate::input::{decode_input, read_input_bytes}; +use crate::parse::parse_tx_bytes_internal; + +pub fn handle_parse_command(path: PathBuf, no_color: bool) -> Result<()> { + // Read from file or stdin + let raw_bytes = read_input_bytes(&path, "transaction")?; + + // Decode input (auto-detect hex, base64, or raw bytes) + let bytes = decode_input(&raw_bytes)?; + + let node = parse_tx_bytes_internal(&bytes) + .map_err(|e| anyhow::anyhow!("Failed to parse transaction: {}", e))?; + + let color_scheme = if no_color { + ColorScheme::no_color() + } else { + ColorScheme::default() + }; + + render_tree_with_scheme(&node, &color_scheme)?; + + Ok(()) +} diff --git a/packages/wasm-utxo/cli/tests/fixtures/complex_tree.txt b/packages/wasm-utxo/cli/test/fixtures/complex_tree.txt similarity index 100% rename from packages/wasm-utxo/cli/tests/fixtures/complex_tree.txt rename to packages/wasm-utxo/cli/test/fixtures/complex_tree.txt diff --git a/packages/wasm-utxo/cli/test/fixtures/fixed-script b/packages/wasm-utxo/cli/test/fixtures/fixed-script new file mode 120000 index 00000000..0ebfaea3 --- /dev/null +++ b/packages/wasm-utxo/cli/test/fixtures/fixed-script @@ -0,0 +1 @@ +../../../test/fixtures/fixed-script/ \ No newline at end of file diff --git a/packages/wasm-utxo/cli/tests/fixtures/large_buffer.txt b/packages/wasm-utxo/cli/test/fixtures/large_buffer.txt similarity index 100% rename from packages/wasm-utxo/cli/tests/fixtures/large_buffer.txt rename to packages/wasm-utxo/cli/test/fixtures/large_buffer.txt diff --git a/packages/wasm-utxo/cli/tests/fixtures/numeric_types.txt b/packages/wasm-utxo/cli/test/fixtures/numeric_types.txt similarity index 100% rename from packages/wasm-utxo/cli/tests/fixtures/numeric_types.txt rename to packages/wasm-utxo/cli/test/fixtures/numeric_types.txt diff --git a/packages/wasm-utxo/cli/test/fixtures/psbt_bitcoin_fullsigned.txt b/packages/wasm-utxo/cli/test/fixtures/psbt_bitcoin_fullsigned.txt new file mode 100644 index 00000000..244c4993 --- /dev/null +++ b/packages/wasm-utxo/cli/test/fixtures/psbt_bitcoin_fullsigned.txt @@ -0,0 +1,269 @@ +psbt: None +├─ tx: None +│ ├─ version: 1i32 +│ ├─ lock_time: 0u32 +│ ├─ txid: 819e1ce50e5f92d52f3d6cfbb4084355392777d8b23b0bce674674577a940608 (32 bytes) +│ ├─ ntxid: 819e1ce50e5f92d52f3d6cfbb4084355392777d8b23b0bce674674577a940608 (32 bytes) +│ ├─ wtxid: 819e1ce50e5f92d52f3d6cfbb4084355392777d8b23b0bce674674577a940608 (32 bytes) +│ ├─ inputs: 7u64 +│ │ ├─ input_0: None +│ │ │ ├─ prev_txid: d99efae199fc4d54e5825a8e3368a395e9eb329915cfb5d88dc311507d184836 (32 bytes) +│ │ │ ├─ prev_vout: 0u32 +│ │ │ ├─ sequence: 4294967295u32 +│ │ │ └─ script_sig: (0 bytes) +│ │ ├─ input_1: None +│ │ │ ├─ prev_txid: 1ec9729a1b25373a30f0fe6e0879b31136a54f2f8c98618c46862748a08c5e78 (32 bytes) +│ │ │ ├─ prev_vout: 1u32 +│ │ │ ├─ sequence: 4294967295u32 +│ │ │ └─ script_sig: (0 bytes) +│ │ ├─ input_2: None +│ │ │ ├─ prev_txid: bb0dfbeba59bba69e3ce07a54346f804c543fa46d828ed539d11231adbaa8b7b (32 bytes) +│ │ │ ├─ prev_vout: 2u32 +│ │ │ ├─ sequence: 4294967295u32 +│ │ │ └─ script_sig: (0 bytes) +│ │ ├─ input_3: None +│ │ │ ├─ prev_txid: a662a5ffebf58bf3e65e53456c67c029cc154a2409740d8cd37fdee7559c5efd (32 bytes) +│ │ │ ├─ prev_vout: 3u32 +│ │ │ ├─ sequence: 4294967295u32 +│ │ │ └─ script_sig: (0 bytes) +│ │ ├─ input_4: None +│ │ │ ├─ prev_txid: d394375cee23b3b9951488c0403529157a85b058edc0351546d9eb4807e8a1d3 (32 bytes) +│ │ │ ├─ prev_vout: 4u32 +│ │ │ ├─ sequence: 4294967295u32 +│ │ │ └─ script_sig: (0 bytes) +│ │ ├─ input_5: None +│ │ │ ├─ prev_txid: 0d2f7f3486edaefc6ab92c21f7caf90085c4de4adac491106fd8a0e4f563dea3 (32 bytes) +│ │ │ ├─ prev_vout: 5u32 +│ │ │ ├─ sequence: 4294967295u32 +│ │ │ └─ script_sig: (0 bytes) +│ │ └─ input_6: None +│ │ ├─ prev_txid: 97441d99a8d66f124ab3c9de26b87bd00aeb1547051c842a88165c1b089ee902 (32 bytes) +│ │ ├─ prev_vout: 6u32 +│ │ ├─ sequence: 4294967295u32 +│ │ └─ script_sig: (0 bytes) +│ └─ outputs: 5u64 +│ ├─ output_0: None +│ │ ├─ value: 900u64 +│ │ ├─ script_pubkey: a914d909474404c124a3d04c3fbff61faa49cf43c58b87 (23 bytes) +│ │ └─ address: 3MUbfqvBeD7g1R3b9g8ZQxDwjR7SjQWciv +│ ├─ output_1: None +│ │ ├─ value: 900u64 +│ │ ├─ script_pubkey: a914054127121d37f32266cd967c485404976a67adf087 (23 bytes) +│ │ └─ address: 32AoMPMpT2ErEqupk6CJvrEMrj6TzmZu8V +│ ├─ output_2: None +│ │ ├─ value: 900u64 +│ │ ├─ script_pubkey: 0020ba48e3f9874463943f90192a45f1ae895b779362a7629af7ad6a9d7a835e3d4f (34 bytes) +│ │ └─ address: bc1qhfyw87v8g33eg0usry4ytudw39dh0ymz5a3f4aadd2wh4q67848sqay5xu +│ ├─ output_3: None +│ │ ├─ value: 900u64 +│ │ ├─ script_pubkey: 5120b27227f5cadc056afea4b02b4b97b9a0151786234c26ad588dccf134e78931c6 (34 bytes) +│ │ └─ address: bc1pkfez0aw2mszk4l4ykq45h9ae5q230p3rfsn26kydencnfeufx8rq23ty2z +│ └─ output_4: None +│ ├─ value: 900u64 +│ ├─ script_pubkey: 51204f73b5561399eb397b5ab413e090cc0c48ff703a61afe47cf7d47a23d43b978b (34 bytes) +│ └─ address: bc1pfaem24snn84nj766ksf7pyxvp3y07up6vxh7gl8h63az84pmj79sehcc5d +├─ xpubs: 3u64 +│ ├─ xpub: None +│ │ ├─ xpub: xpub661MyMwAqRbcF8FoYWukS8eTn2gVEojzwf5DYETpB8uqC8t5sqDCEFnuJ39DaPjLRerBDK9QqSMvSYpT4WSugCVbUK5HEevSKAu1wUkVWsS +│ │ ├─ fingerprint: cc18ae08 (4 bytes) +│ │ └─ path: +│ ├─ xpub: None +│ │ ├─ xpub: xpub661MyMwAqRbcGZfgedgcQiBJpkHoZ37k6uotUVLoC6Px4Y46Yrdmy1CUogcJMoAsosY381gPjhGe9jFx1uYAcxy2gTHh9YFP32tUWycqHnV +│ │ ├─ fingerprint: f2ef0389 (4 bytes) +│ │ └─ path: +│ └─ xpub: None +│ ├─ xpub: xpub661MyMwAqRbcFdScyinA4JpCViqkKsd37MQ6fwuZQQ4shdaGRRX9a8bWvR9QC1AFqKongweJJfyrm7uCoWmCw7UixwGZkZnCT2mchFr7cQb +│ ├─ fingerprint: f65cd869 (4 bytes) +│ └─ path: +├─ version: 0u32 +├─ inputs: 7u64 +│ ├─ input_0: None +│ │ ├─ non_witness_utxo: d99efae199fc4d54e5825a8e3368a395e9eb329915cfb5d88dc311507d184836 (32 bytes) +│ │ ├─ redeem_script: 522103f6f40764bd5d63f200a2778883acf75e96f15095c998263c087270d0c97e7e7f21035ffb7abc70159e0469f4b989a6d5e1785a2904169ff050b2f468fe5d3d5dbbf22103e1524d7f6fc57ab3eacbb659b787106780a475d1db483952c2310b7e9a38975b53ae (105 bytes) +│ │ │ └─ asm: OP_PUSHNUM_2 OP_PUSHBYTES_33 03f6f40764bd5d63f200a2778883acf75e96f15095c998263c087270d0c97e7e7f OP_PUSHBYTES_33 035ffb7abc70159e0469f4b989a6d5e1785a2904169ff050b2f468fe5d3d5dbbf2 OP_PUSHBYTES_33 03e1524d7f6fc57ab3eacbb659b787106780a475d1db483952c2310b7e9a38975b OP_PUSHNUM_3 OP_CHECKMULTISIG +│ │ ├─ signatures: 2u64 +│ │ │ ├─ 0: None +│ │ │ │ ├─ pubkey: 03e1524d7f6fc57ab3eacbb659b787106780a475d1db483952c2310b7e9a38975b (33 bytes) +│ │ │ │ └─ signature: 3045022100dd31a25d0ebea90e67910168ef7c2b383ca26192cd5c8709f02980b7ca90472802203795c65ee0f073b80644d0c8ffa1d428457ae2af3df5b5d8117949781d10c46201 (72 bytes) +│ │ │ └─ 1: None +│ │ │ ├─ pubkey: 03f6f40764bd5d63f200a2778883acf75e96f15095c998263c087270d0c97e7e7f (33 bytes) +│ │ │ └─ signature: 304402201e79545c011e34b1b872b4b057e66262d86881da6a7f853e7e57a9a4d12c6dc102201a538b2175c7b7161c76da18394220f354ae2729fcc1c902b74c59cd79e0153101 (71 bytes) +│ │ ├─ sighash_type: 1u32 +│ │ ├─ sighash_type: SIGHASH_ALL +│ │ ├─ bip32_derivation: None +│ │ │ ├─ pubkey: 035ffb7abc70159e0469f4b989a6d5e1785a2904169ff050b2f468fe5d3d5dbbf2 (33 bytes) +│ │ │ ├─ fingerprint: cc18ae08 (4 bytes) +│ │ │ └─ path: 0/0/1/0 +│ │ ├─ bip32_derivation: None +│ │ │ ├─ pubkey: 03e1524d7f6fc57ab3eacbb659b787106780a475d1db483952c2310b7e9a38975b (33 bytes) +│ │ │ ├─ fingerprint: f65cd869 (4 bytes) +│ │ │ └─ path: 0/0/1/0 +│ │ └─ bip32_derivation: None +│ │ ├─ pubkey: 03f6f40764bd5d63f200a2778883acf75e96f15095c998263c087270d0c97e7e7f (33 bytes) +│ │ ├─ fingerprint: f2ef0389 (4 bytes) +│ │ └─ path: 0/0/1/0 +│ ├─ input_1: None +│ │ ├─ witness_utxo: None +│ │ │ ├─ value: 1000u64 +│ │ │ ├─ script_pubkey: a9140e26b25d0ceae6f9cff3edaccaa0d1a70da7600f87 (23 bytes) +│ │ │ └─ address: 32yqjvdZcjamjJGMraHRmZ9KJ5e5TenoSg +│ │ ├─ redeem_script: 002046d4800a1393330196085399ed4a1700b4c2fd38c52188c3a3a91f721f3c9600 (34 bytes) +│ │ │ └─ asm: OP_0 OP_PUSHBYTES_32 46d4800a1393330196085399ed4a1700b4c2fd38c52188c3a3a91f721f3c9600 +│ │ ├─ witness_script: 522102a585f3fab49b5ef95346d932221a221bd55ec191f15533e0f270b3582574f0352102c4f7866cfd5996bc1068a96313ca15e9ccb5e984583a07340dddae7af014605b2102234531bc9119a36a7946e95aeb74915dd087c7b44f517b8eeeb73f89a0ff1a9953ae (105 bytes) +│ │ │ └─ asm: OP_PUSHNUM_2 OP_PUSHBYTES_33 02a585f3fab49b5ef95346d932221a221bd55ec191f15533e0f270b3582574f035 OP_PUSHBYTES_33 02c4f7866cfd5996bc1068a96313ca15e9ccb5e984583a07340dddae7af014605b OP_PUSHBYTES_33 02234531bc9119a36a7946e95aeb74915dd087c7b44f517b8eeeb73f89a0ff1a99 OP_PUSHNUM_3 OP_CHECKMULTISIG +│ │ ├─ signatures: 2u64 +│ │ │ ├─ 0: None +│ │ │ │ ├─ pubkey: 02234531bc9119a36a7946e95aeb74915dd087c7b44f517b8eeeb73f89a0ff1a99 (33 bytes) +│ │ │ │ └─ signature: 3045022100df41fbcbf3c7f77182627bcb7cd17973b8ca58c16b81de98e94c0293dcf33ac202206017171914fdfbc80f933ab3b5aae4e3d36e968757e6c0788ffbeaaebc68e21e01 (72 bytes) +│ │ │ └─ 1: None +│ │ │ ├─ pubkey: 02a585f3fab49b5ef95346d932221a221bd55ec191f15533e0f270b3582574f035 (33 bytes) +│ │ │ └─ signature: 304402205f760c27e7598a9e80a2adaf1d925c67d2e6c24aec773e5cce56d234159ab1e502201ce97d5659681ab881e10acc9c8021587f843a15336c3a8b6fb2efc053928b8501 (71 bytes) +│ │ ├─ sighash_type: 1u32 +│ │ ├─ sighash_type: SIGHASH_ALL +│ │ ├─ bip32_derivation: None +│ │ │ ├─ pubkey: 02234531bc9119a36a7946e95aeb74915dd087c7b44f517b8eeeb73f89a0ff1a99 (33 bytes) +│ │ │ ├─ fingerprint: f65cd869 (4 bytes) +│ │ │ └─ path: 0/0/11/1 +│ │ ├─ bip32_derivation: None +│ │ │ ├─ pubkey: 02a585f3fab49b5ef95346d932221a221bd55ec191f15533e0f270b3582574f035 (33 bytes) +│ │ │ ├─ fingerprint: f2ef0389 (4 bytes) +│ │ │ └─ path: 0/0/11/1 +│ │ └─ bip32_derivation: None +│ │ ├─ pubkey: 02c4f7866cfd5996bc1068a96313ca15e9ccb5e984583a07340dddae7af014605b (33 bytes) +│ │ ├─ fingerprint: cc18ae08 (4 bytes) +│ │ └─ path: 0/0/11/1 +│ ├─ input_2: None +│ │ ├─ witness_utxo: None +│ │ │ ├─ value: 1000u64 +│ │ │ ├─ script_pubkey: 0020db0427f1822b4777670e6673c28af02f6da1d5afe71a71f5c9064470b229fafd (34 bytes) +│ │ │ └─ address: bc1qmvzz0uvz9drhwecwveeu9zhs9ak6r4d0uud8rawfqez8pv3flt7suk3jde +│ │ ├─ witness_script: 522103519e572ab468560d1f8d0f87699d098308e166905f5dcae4390f060faa8f1ce32103a05bc26391221d685e18daaff36a1e95c34f99451253c16cd42650db278a79112102e80a08885c353676b820cdc290e6d81a0ac95a03e8abbf4bb7aeebfb70feb41853ae (105 bytes) +│ │ │ └─ asm: OP_PUSHNUM_2 OP_PUSHBYTES_33 03519e572ab468560d1f8d0f87699d098308e166905f5dcae4390f060faa8f1ce3 OP_PUSHBYTES_33 03a05bc26391221d685e18daaff36a1e95c34f99451253c16cd42650db278a7911 OP_PUSHBYTES_33 02e80a08885c353676b820cdc290e6d81a0ac95a03e8abbf4bb7aeebfb70feb418 OP_PUSHNUM_3 OP_CHECKMULTISIG +│ │ ├─ signatures: 2u64 +│ │ │ ├─ 0: None +│ │ │ │ ├─ pubkey: 02e80a08885c353676b820cdc290e6d81a0ac95a03e8abbf4bb7aeebfb70feb418 (33 bytes) +│ │ │ │ └─ signature: 304402206441089c8c71a4926b49a5ab12bfaa86c4b64abbc519b3d217d68fe71bc43bee02203e17d0752c0b411e9477c22c2f4556a62da39e60095c6e0774bf42aa8f491b4d01 (71 bytes) +│ │ │ └─ 1: None +│ │ │ ├─ pubkey: 03519e572ab468560d1f8d0f87699d098308e166905f5dcae4390f060faa8f1ce3 (33 bytes) +│ │ │ └─ signature: 3045022100d3b03fb77553144e14171c7b1b517a3bf33df87370b65e337f0a50844562261e0220585bc0913b56ad968161d343f321d77f5f94ff3cf62545932f1509239a15a38e01 (72 bytes) +│ │ ├─ sighash_type: 1u32 +│ │ ├─ sighash_type: SIGHASH_ALL +│ │ ├─ bip32_derivation: None +│ │ │ ├─ pubkey: 02e80a08885c353676b820cdc290e6d81a0ac95a03e8abbf4bb7aeebfb70feb418 (33 bytes) +│ │ │ ├─ fingerprint: f65cd869 (4 bytes) +│ │ │ └─ path: 0/0/21/2 +│ │ ├─ bip32_derivation: None +│ │ │ ├─ pubkey: 03519e572ab468560d1f8d0f87699d098308e166905f5dcae4390f060faa8f1ce3 (33 bytes) +│ │ │ ├─ fingerprint: f2ef0389 (4 bytes) +│ │ │ └─ path: 0/0/21/2 +│ │ └─ bip32_derivation: None +│ │ ├─ pubkey: 03a05bc26391221d685e18daaff36a1e95c34f99451253c16cd42650db278a7911 (33 bytes) +│ │ ├─ fingerprint: cc18ae08 (4 bytes) +│ │ └─ path: 0/0/21/2 +│ ├─ input_3: None +│ │ ├─ witness_utxo: None +│ │ │ ├─ value: 1000u64 +│ │ │ ├─ script_pubkey: 5120394b94d061d7b778fed8a204ce05ed0b44954ec1622f934f84114e1173f33027 (34 bytes) +│ │ │ └─ address: bc1p899ef5rp67mh3lkc5gzvup0dpdzf2nkpvghexnuyz98pzulnxqnsc3luf9 +│ │ ├─ sighash_type: 0u32 +│ │ └─ sighash_type: SIGHASH_DEFAULT +│ ├─ input_4: None +│ │ ├─ witness_utxo: None +│ │ │ ├─ value: 1000u64 +│ │ │ ├─ script_pubkey: 512029bbfaf4385b10dc2bbe7ab4d50e89cebe8f507968727b19689e2638083cc55b (34 bytes) +│ │ │ └─ address: bc1p9xal4apctvgdc2a7026d2r5fe6lg75redpe8kxtgncnrszpuc4dsq5wu3k +│ │ ├─ sighash_type: 0u32 +│ │ └─ sighash_type: SIGHASH_DEFAULT +│ ├─ input_5: None +│ │ ├─ witness_utxo: None +│ │ │ ├─ value: 1000u64 +│ │ │ ├─ script_pubkey: 512015c5815026f6a54b10194fc6980f1866a02d9ec128533c7997cdb4289bf3ef16 (34 bytes) +│ │ │ └─ address: bc1pzhzcz5px76j5kyqeflrfsrccv6szm8kp9pfnc7vhek6z3xlnautqpa2twz +│ │ ├─ sighash_type: 0u32 +│ │ ├─ sighash_type: SIGHASH_DEFAULT +│ │ └─ proprietary: 5u64 +│ │ ├─ key: None +│ │ │ ├─ prefix: BITGO +│ │ │ ├─ subtype: 1u8 +│ │ │ ├─ key_data: 15c5815026f6a54b10194fc6980f1866a02d9ec128533c7997cdb4289bf3ef16eb5ad29a85aed24de2880e774caaf624f9cb1be09c67ed4aefbb9b7bc12ddf1a (64 bytes) +│ │ │ └─ value: 021d978a17486ff9e47c82990269e531fc63981419d4ce73ee8bd2c99661c53953020fdea69e40a3adef3cdc7fa6f3af02f4c9d9e3254503c96a6a2b4aa66e778171 (66 bytes) +│ │ ├─ key: None +│ │ │ ├─ prefix: BITGO +│ │ │ ├─ subtype: 2u8 +│ │ │ ├─ key_data: 020fdea69e40a3adef3cdc7fa6f3af02f4c9d9e3254503c96a6a2b4aa66e77817115c5815026f6a54b10194fc6980f1866a02d9ec128533c7997cdb4289bf3ef16 (65 bytes) +│ │ │ └─ value: 02826949740dff45d408b1f19d94c720f53411e02c525b28ab3c593b6b530fe0370374b8a0ffcaaaee6b772dac5f7c23ef33670b32ec77c6d41efb3c36df2165a094 (66 bytes) +│ │ ├─ key: None +│ │ │ ├─ prefix: BITGO +│ │ │ ├─ subtype: 2u8 +│ │ │ ├─ key_data: 021d978a17486ff9e47c82990269e531fc63981419d4ce73ee8bd2c99661c5395315c5815026f6a54b10194fc6980f1866a02d9ec128533c7997cdb4289bf3ef16 (65 bytes) +│ │ │ └─ value: 03a4aaf46f3a0bc39a73855fa875b2f2f04bdb06235afbaedf857b593dddc63cb402cdb7f1a93ec526282198d834423371757e8f43932d03b9f43c3f7378300ae508 (66 bytes) +│ │ ├─ key: None +│ │ │ ├─ prefix: BITGO +│ │ │ ├─ subtype: 3u8 +│ │ │ ├─ key_data: 020fdea69e40a3adef3cdc7fa6f3af02f4c9d9e3254503c96a6a2b4aa66e77817115c5815026f6a54b10194fc6980f1866a02d9ec128533c7997cdb4289bf3ef16 (65 bytes) +│ │ │ └─ value: fbdc39c3b8ffca4e6caf3298fa1a4be546b99163c2f21bd374d2254ec5b3c0f4 (32 bytes) +│ │ └─ key: None +│ │ ├─ prefix: BITGO +│ │ ├─ subtype: 3u8 +│ │ ├─ key_data: 021d978a17486ff9e47c82990269e531fc63981419d4ce73ee8bd2c99661c5395315c5815026f6a54b10194fc6980f1866a02d9ec128533c7997cdb4289bf3ef16 (65 bytes) +│ │ └─ value: 1cd8a0c0598b0d88f889fdf9a3140f8f088e2187803a2faaee3f13c0163eb76c (32 bytes) +│ └─ input_6: None +│ ├─ non_witness_utxo: 97441d99a8d66f124ab3c9de26b87bd00aeb1547051c842a88165c1b089ee902 (32 bytes) +│ ├─ redeem_script: 210336ef228ffe9b8efffba052c32d334660dd1f8366cf8fe44ae5aa672b6b629095ac (35 bytes) +│ │ └─ asm: OP_PUSHBYTES_33 0336ef228ffe9b8efffba052c32d334660dd1f8366cf8fe44ae5aa672b6b629095 OP_CHECKSIG +│ ├─ signatures: 1u64 +│ │ └─ 0: None +│ │ ├─ pubkey: 0336ef228ffe9b8efffba052c32d334660dd1f8366cf8fe44ae5aa672b6b629095 (33 bytes) +│ │ └─ signature: 3045022100d2a7abb6c0563c3000e37412a9b97f6352d17e40960456fe830d264f0474f8b6022038d5cdbe88a319de5d7b7db8f57d0a92524beb242729b46a617adb530f2fa0d001 (72 bytes) +│ ├─ sighash_type: 1u32 +│ └─ sighash_type: SIGHASH_ALL +└─ outputs: 5u64 + ├─ 0: None + │ ├─ redeem_script: 522102cc4d0fa411cac244486f8eb2c08e035ff7410f460a359ca7f8810991bd3b42092102d72fd0d0d90293434ad5fca160f278e03c614497aa4e425cf454e2c1330f96ab210344d884136df550202865ffbc6218c7f9c88fe6ce39c945798190badb38a752f153ae (105 bytes) + │ │ └─ asm: OP_PUSHNUM_2 OP_PUSHBYTES_33 02cc4d0fa411cac244486f8eb2c08e035ff7410f460a359ca7f8810991bd3b4209 OP_PUSHBYTES_33 02d72fd0d0d90293434ad5fca160f278e03c614497aa4e425cf454e2c1330f96ab OP_PUSHBYTES_33 0344d884136df550202865ffbc6218c7f9c88fe6ce39c945798190badb38a752f1 OP_PUSHNUM_3 OP_CHECKMULTISIG + │ ├─ bip32_derivation: None + │ │ ├─ pubkey: 02cc4d0fa411cac244486f8eb2c08e035ff7410f460a359ca7f8810991bd3b4209 (33 bytes) + │ │ ├─ fingerprint: f2ef0389 (4 bytes) + │ │ └─ path: 0/0/0/0 + │ ├─ bip32_derivation: None + │ │ ├─ pubkey: 02d72fd0d0d90293434ad5fca160f278e03c614497aa4e425cf454e2c1330f96ab (33 bytes) + │ │ ├─ fingerprint: cc18ae08 (4 bytes) + │ │ └─ path: 0/0/0/0 + │ └─ bip32_derivation: None + │ ├─ pubkey: 0344d884136df550202865ffbc6218c7f9c88fe6ce39c945798190badb38a752f1 (33 bytes) + │ ├─ fingerprint: f65cd869 (4 bytes) + │ └─ path: 0/0/0/0 + ├─ 1: None + │ ├─ redeem_script: 0020292b052351a3c6f80d51bae642cc8821182893dbeedabc8f5d0e9677476026c1 (34 bytes) + │ │ └─ asm: OP_0 OP_PUSHBYTES_32 292b052351a3c6f80d51bae642cc8821182893dbeedabc8f5d0e9677476026c1 + │ ├─ witness_script: 5221032e11f98552685fe907f31f9e7260c906e8de700f0c3c9f2f1410623dcdfd19c02103545757ce35cf1edfb13b9e2c4a2f9ce00ab8c36bee12bca2337ce583fd28aec82102a3cfb6665fe44f7520b6a1b4de1a4d46643b385eb1fd1e0ab70efb965429755453ae (105 bytes) + │ │ └─ asm: OP_PUSHNUM_2 OP_PUSHBYTES_33 032e11f98552685fe907f31f9e7260c906e8de700f0c3c9f2f1410623dcdfd19c0 OP_PUSHBYTES_33 03545757ce35cf1edfb13b9e2c4a2f9ce00ab8c36bee12bca2337ce583fd28aec8 OP_PUSHBYTES_33 02a3cfb6665fe44f7520b6a1b4de1a4d46643b385eb1fd1e0ab70efb9654297554 OP_PUSHNUM_3 OP_CHECKMULTISIG + │ ├─ bip32_derivation: None + │ │ ├─ pubkey: 02a3cfb6665fe44f7520b6a1b4de1a4d46643b385eb1fd1e0ab70efb9654297554 (33 bytes) + │ │ ├─ fingerprint: f65cd869 (4 bytes) + │ │ └─ path: 0/0/10/1 + │ ├─ bip32_derivation: None + │ │ ├─ pubkey: 032e11f98552685fe907f31f9e7260c906e8de700f0c3c9f2f1410623dcdfd19c0 (33 bytes) + │ │ ├─ fingerprint: f2ef0389 (4 bytes) + │ │ └─ path: 0/0/10/1 + │ └─ bip32_derivation: None + │ ├─ pubkey: 03545757ce35cf1edfb13b9e2c4a2f9ce00ab8c36bee12bca2337ce583fd28aec8 (33 bytes) + │ ├─ fingerprint: cc18ae08 (4 bytes) + │ └─ path: 0/0/10/1 + ├─ 2: None + │ ├─ witness_script: 522102d6d1140bd2c0f914cb30c992aa2fcd283f471a9281ceec9ec6c5bc448e6869002103b855a8758eda6863648445a9d3cfb95388aca174621ad98f099a1c4f9326fec7210295f7b527d2ea537a4d42830410abf4340731bf9b20e54972001933b9aa23536c53ae (105 bytes) + │ │ └─ asm: OP_PUSHNUM_2 OP_PUSHBYTES_33 02d6d1140bd2c0f914cb30c992aa2fcd283f471a9281ceec9ec6c5bc448e686900 OP_PUSHBYTES_33 03b855a8758eda6863648445a9d3cfb95388aca174621ad98f099a1c4f9326fec7 OP_PUSHBYTES_33 0295f7b527d2ea537a4d42830410abf4340731bf9b20e54972001933b9aa23536c OP_PUSHNUM_3 OP_CHECKMULTISIG + │ ├─ bip32_derivation: None + │ │ ├─ pubkey: 0295f7b527d2ea537a4d42830410abf4340731bf9b20e54972001933b9aa23536c (33 bytes) + │ │ ├─ fingerprint: f65cd869 (4 bytes) + │ │ └─ path: 0/0/20/2 + │ ├─ bip32_derivation: None + │ │ ├─ pubkey: 02d6d1140bd2c0f914cb30c992aa2fcd283f471a9281ceec9ec6c5bc448e686900 (33 bytes) + │ │ ├─ fingerprint: f2ef0389 (4 bytes) + │ │ └─ path: 0/0/20/2 + │ └─ bip32_derivation: None + │ ├─ pubkey: 03b855a8758eda6863648445a9d3cfb95388aca174621ad98f099a1c4f9326fec7 (33 bytes) + │ ├─ fingerprint: cc18ae08 (4 bytes) + │ └─ path: 0/0/20/2 + ├─ 3: None + └─ 4: None diff --git a/packages/wasm-utxo/cli/test/fixtures/psbt_raw_bitcoin_fullsigned.txt b/packages/wasm-utxo/cli/test/fixtures/psbt_raw_bitcoin_fullsigned.txt new file mode 100644 index 00000000..6de908e9 --- /dev/null +++ b/packages/wasm-utxo/cli/test/fixtures/psbt_raw_bitcoin_fullsigned.txt @@ -0,0 +1,496 @@ +psbt_raw: None +├─ magic: [70, 73, 62, 74, ff] +├─ global_map: None +│ ├─ pair_count: 4u64 +│ ├─ pair_0: None +│ │ ├─ key: None +│ │ │ ├─ type_id: 0u8 +│ │ │ └─ type_name: PSBT_GLOBAL_UNSIGNED_TX +│ │ └─ value: 0100000007d99efae199fc4d54e5825a8e3368a395e9eb329915cfb5d88dc311507d1848360000000000ffffffff1ec9729a1b25373a30f0fe6e0879b31136a54f2f8c98618c46862748a08c5e780100000000ffffffffbb0dfbeba59bba69e3ce07a54346f804c543fa46d828ed539d11231adbaa8b7b0200000000ffffffffa662a5ffebf58bf3e65e53456c67c029cc154a2409740d8cd37fdee7559c5efd0300000000ffffffffd394375cee23b3b9951488c0403529157a85b058edc0351546d9eb4807e8a1d30400000000ffffffff0d2f7f3486edaefc6ab92c21f7caf90085c4de4adac491106fd8a0e4f563dea30500000000ffffffff97441d99a8... (490 bytes) +│ ├─ pair_1: None +│ │ ├─ key: None +│ │ │ ├─ type_id: 1u8 +│ │ │ ├─ type_name: PSBT_GLOBAL_XPUB +│ │ │ └─ key_data: 0488b21e0000000000000000003a922e29f0c8eb0db2a60484cbdcb631f6b107c9caae3ffdcf3e7d2ec1f6bcd00312148715f361dab685a669d42431e5d6d3f973404dab9c9fd1b950b279ad7634 (78 bytes) +│ │ └─ value: cc18ae08 (4 bytes) +│ ├─ pair_2: None +│ │ ├─ key: None +│ │ │ ├─ type_id: 1u8 +│ │ │ ├─ type_name: PSBT_GLOBAL_XPUB +│ │ │ └─ key_data: 0488b21e0000000000000000006d1d656d3ddd91c194c04565a3603702a21016ced14a265f38982d6275e67b6403d3bac2313a7c6b21cbb11b14b0d10341f922c0a403a8bd8c87f0dc820f35af6e (78 bytes) +│ │ └─ value: f65cd869 (4 bytes) +│ └─ pair_3: None +│ ├─ key: None +│ │ ├─ type_id: 1u8 +│ │ ├─ type_name: PSBT_GLOBAL_XPUB +│ │ └─ key_data: 0488b21e000000000000000000cb04fd63ab34d90fe6466b880e2a02ccf8a863374312991af8911b1aaab443340336ef228ffe9b8efffba052c32d334660dd1f8366cf8fe44ae5aa672b6b629095 (78 bytes) +│ └─ value: f2ef0389 (4 bytes) +├─ input_maps: 7u64 +│ ├─ input_0: None +│ │ ├─ pair_count: 8u64 +│ │ ├─ pair_0: None +│ │ │ ├─ key: None +│ │ │ │ ├─ type_id: 0u8 +│ │ │ │ └─ type_name: PSBT_IN_NON_WITNESS_UTXO +│ │ │ └─ value: 01000000010101010101010101010101010101010101010101010101010101010101010101000000006b4830450221008d7a270e793fd336fca10b66129c64c00815dd9d3c4546b12d699ab33520073002207d6c5dd46f5c9c65c08fd295e9b4e7db453779928c765128039634b08ed467a1012103bd0c34b2373e387575cddb103ec03916c31044f2508e261fe3597a2680ecbd1fffffffff01e80300000000000017a914567cd7b44f9f3a07c3138f37bf984b60fbbaf2438700000000 (190 bytes) +│ │ ├─ pair_1: None +│ │ │ ├─ key: None +│ │ │ │ ├─ type_id: 2u8 +│ │ │ │ ├─ type_name: PSBT_IN_PARTIAL_SIG +│ │ │ │ └─ key_data: 03e1524d7f6fc57ab3eacbb659b787106780a475d1db483952c2310b7e9a38975b (33 bytes) +│ │ │ └─ value: 3045022100dd31a25d0ebea90e67910168ef7c2b383ca26192cd5c8709f02980b7ca90472802203795c65ee0f073b80644d0c8ffa1d428457ae2af3df5b5d8117949781d10c46201 (72 bytes) +│ │ ├─ pair_2: None +│ │ │ ├─ key: None +│ │ │ │ ├─ type_id: 2u8 +│ │ │ │ ├─ type_name: PSBT_IN_PARTIAL_SIG +│ │ │ │ └─ key_data: 03f6f40764bd5d63f200a2778883acf75e96f15095c998263c087270d0c97e7e7f (33 bytes) +│ │ │ └─ value: 304402201e79545c011e34b1b872b4b057e66262d86881da6a7f853e7e57a9a4d12c6dc102201a538b2175c7b7161c76da18394220f354ae2729fcc1c902b74c59cd79e0153101 (71 bytes) +│ │ ├─ pair_3: None +│ │ │ ├─ key: None +│ │ │ │ ├─ type_id: 3u8 +│ │ │ │ └─ type_name: PSBT_IN_SIGHASH_TYPE +│ │ │ └─ value: 01000000 (4 bytes) +│ │ ├─ pair_4: None +│ │ │ ├─ key: None +│ │ │ │ ├─ type_id: 4u8 +│ │ │ │ └─ type_name: PSBT_IN_REDEEM_SCRIPT +│ │ │ └─ value: 522103f6f40764bd5d63f200a2778883acf75e96f15095c998263c087270d0c97e7e7f21035ffb7abc70159e0469f4b989a6d5e1785a2904169ff050b2f468fe5d3d5dbbf22103e1524d7f6fc57ab3eacbb659b787106780a475d1db483952c2310b7e9a38975b53ae (105 bytes) +│ │ ├─ pair_5: None +│ │ │ ├─ key: None +│ │ │ │ ├─ type_id: 6u8 +│ │ │ │ ├─ type_name: PSBT_IN_BIP32_DERIVATION +│ │ │ │ └─ key_data: 035ffb7abc70159e0469f4b989a6d5e1785a2904169ff050b2f468fe5d3d5dbbf2 (33 bytes) +│ │ │ └─ value: cc18ae0800000000000000000100000000000000 (20 bytes) +│ │ ├─ pair_6: None +│ │ │ ├─ key: None +│ │ │ │ ├─ type_id: 6u8 +│ │ │ │ ├─ type_name: PSBT_IN_BIP32_DERIVATION +│ │ │ │ └─ key_data: 03e1524d7f6fc57ab3eacbb659b787106780a475d1db483952c2310b7e9a38975b (33 bytes) +│ │ │ └─ value: f65cd86900000000000000000100000000000000 (20 bytes) +│ │ └─ pair_7: None +│ │ ├─ key: None +│ │ │ ├─ type_id: 6u8 +│ │ │ ├─ type_name: PSBT_IN_BIP32_DERIVATION +│ │ │ └─ key_data: 03f6f40764bd5d63f200a2778883acf75e96f15095c998263c087270d0c97e7e7f (33 bytes) +│ │ └─ value: f2ef038900000000000000000100000000000000 (20 bytes) +│ ├─ input_1: None +│ │ ├─ pair_count: 9u64 +│ │ ├─ pair_0: None +│ │ │ ├─ key: None +│ │ │ │ ├─ type_id: 1u8 +│ │ │ │ └─ type_name: PSBT_IN_WITNESS_UTXO +│ │ │ └─ value: e80300000000000017a9140e26b25d0ceae6f9cff3edaccaa0d1a70da7600f87 (32 bytes) +│ │ ├─ pair_1: None +│ │ │ ├─ key: None +│ │ │ │ ├─ type_id: 2u8 +│ │ │ │ ├─ type_name: PSBT_IN_PARTIAL_SIG +│ │ │ │ └─ key_data: 02234531bc9119a36a7946e95aeb74915dd087c7b44f517b8eeeb73f89a0ff1a99 (33 bytes) +│ │ │ └─ value: 3045022100df41fbcbf3c7f77182627bcb7cd17973b8ca58c16b81de98e94c0293dcf33ac202206017171914fdfbc80f933ab3b5aae4e3d36e968757e6c0788ffbeaaebc68e21e01 (72 bytes) +│ │ ├─ pair_2: None +│ │ │ ├─ key: None +│ │ │ │ ├─ type_id: 2u8 +│ │ │ │ ├─ type_name: PSBT_IN_PARTIAL_SIG +│ │ │ │ └─ key_data: 02a585f3fab49b5ef95346d932221a221bd55ec191f15533e0f270b3582574f035 (33 bytes) +│ │ │ └─ value: 304402205f760c27e7598a9e80a2adaf1d925c67d2e6c24aec773e5cce56d234159ab1e502201ce97d5659681ab881e10acc9c8021587f843a15336c3a8b6fb2efc053928b8501 (71 bytes) +│ │ ├─ pair_3: None +│ │ │ ├─ key: None +│ │ │ │ ├─ type_id: 3u8 +│ │ │ │ └─ type_name: PSBT_IN_SIGHASH_TYPE +│ │ │ └─ value: 01000000 (4 bytes) +│ │ ├─ pair_4: None +│ │ │ ├─ key: None +│ │ │ │ ├─ type_id: 4u8 +│ │ │ │ └─ type_name: PSBT_IN_REDEEM_SCRIPT +│ │ │ └─ value: 002046d4800a1393330196085399ed4a1700b4c2fd38c52188c3a3a91f721f3c9600 (34 bytes) +│ │ ├─ pair_5: None +│ │ │ ├─ key: None +│ │ │ │ ├─ type_id: 5u8 +│ │ │ │ └─ type_name: PSBT_IN_WITNESS_SCRIPT +│ │ │ └─ value: 522102a585f3fab49b5ef95346d932221a221bd55ec191f15533e0f270b3582574f0352102c4f7866cfd5996bc1068a96313ca15e9ccb5e984583a07340dddae7af014605b2102234531bc9119a36a7946e95aeb74915dd087c7b44f517b8eeeb73f89a0ff1a9953ae (105 bytes) +│ │ ├─ pair_6: None +│ │ │ ├─ key: None +│ │ │ │ ├─ type_id: 6u8 +│ │ │ │ ├─ type_name: PSBT_IN_BIP32_DERIVATION +│ │ │ │ └─ key_data: 02234531bc9119a36a7946e95aeb74915dd087c7b44f517b8eeeb73f89a0ff1a99 (33 bytes) +│ │ │ └─ value: f65cd86900000000000000000b00000001000000 (20 bytes) +│ │ ├─ pair_7: None +│ │ │ ├─ key: None +│ │ │ │ ├─ type_id: 6u8 +│ │ │ │ ├─ type_name: PSBT_IN_BIP32_DERIVATION +│ │ │ │ └─ key_data: 02a585f3fab49b5ef95346d932221a221bd55ec191f15533e0f270b3582574f035 (33 bytes) +│ │ │ └─ value: f2ef038900000000000000000b00000001000000 (20 bytes) +│ │ └─ pair_8: None +│ │ ├─ key: None +│ │ │ ├─ type_id: 6u8 +│ │ │ ├─ type_name: PSBT_IN_BIP32_DERIVATION +│ │ │ └─ key_data: 02c4f7866cfd5996bc1068a96313ca15e9ccb5e984583a07340dddae7af014605b (33 bytes) +│ │ └─ value: cc18ae0800000000000000000b00000001000000 (20 bytes) +│ ├─ input_2: None +│ │ ├─ pair_count: 8u64 +│ │ ├─ pair_0: None +│ │ │ ├─ key: None +│ │ │ │ ├─ type_id: 1u8 +│ │ │ │ └─ type_name: PSBT_IN_WITNESS_UTXO +│ │ │ └─ value: e803000000000000220020db0427f1822b4777670e6673c28af02f6da1d5afe71a71f5c9064470b229fafd (43 bytes) +│ │ ├─ pair_1: None +│ │ │ ├─ key: None +│ │ │ │ ├─ type_id: 2u8 +│ │ │ │ ├─ type_name: PSBT_IN_PARTIAL_SIG +│ │ │ │ └─ key_data: 02e80a08885c353676b820cdc290e6d81a0ac95a03e8abbf4bb7aeebfb70feb418 (33 bytes) +│ │ │ └─ value: 304402206441089c8c71a4926b49a5ab12bfaa86c4b64abbc519b3d217d68fe71bc43bee02203e17d0752c0b411e9477c22c2f4556a62da39e60095c6e0774bf42aa8f491b4d01 (71 bytes) +│ │ ├─ pair_2: None +│ │ │ ├─ key: None +│ │ │ │ ├─ type_id: 2u8 +│ │ │ │ ├─ type_name: PSBT_IN_PARTIAL_SIG +│ │ │ │ └─ key_data: 03519e572ab468560d1f8d0f87699d098308e166905f5dcae4390f060faa8f1ce3 (33 bytes) +│ │ │ └─ value: 3045022100d3b03fb77553144e14171c7b1b517a3bf33df87370b65e337f0a50844562261e0220585bc0913b56ad968161d343f321d77f5f94ff3cf62545932f1509239a15a38e01 (72 bytes) +│ │ ├─ pair_3: None +│ │ │ ├─ key: None +│ │ │ │ ├─ type_id: 3u8 +│ │ │ │ └─ type_name: PSBT_IN_SIGHASH_TYPE +│ │ │ └─ value: 01000000 (4 bytes) +│ │ ├─ pair_4: None +│ │ │ ├─ key: None +│ │ │ │ ├─ type_id: 5u8 +│ │ │ │ └─ type_name: PSBT_IN_WITNESS_SCRIPT +│ │ │ └─ value: 522103519e572ab468560d1f8d0f87699d098308e166905f5dcae4390f060faa8f1ce32103a05bc26391221d685e18daaff36a1e95c34f99451253c16cd42650db278a79112102e80a08885c353676b820cdc290e6d81a0ac95a03e8abbf4bb7aeebfb70feb41853ae (105 bytes) +│ │ ├─ pair_5: None +│ │ │ ├─ key: None +│ │ │ │ ├─ type_id: 6u8 +│ │ │ │ ├─ type_name: PSBT_IN_BIP32_DERIVATION +│ │ │ │ └─ key_data: 02e80a08885c353676b820cdc290e6d81a0ac95a03e8abbf4bb7aeebfb70feb418 (33 bytes) +│ │ │ └─ value: f65cd86900000000000000001500000002000000 (20 bytes) +│ │ ├─ pair_6: None +│ │ │ ├─ key: None +│ │ │ │ ├─ type_id: 6u8 +│ │ │ │ ├─ type_name: PSBT_IN_BIP32_DERIVATION +│ │ │ │ └─ key_data: 03519e572ab468560d1f8d0f87699d098308e166905f5dcae4390f060faa8f1ce3 (33 bytes) +│ │ │ └─ value: f2ef038900000000000000001500000002000000 (20 bytes) +│ │ └─ pair_7: None +│ │ ├─ key: None +│ │ │ ├─ type_id: 6u8 +│ │ │ ├─ type_name: PSBT_IN_BIP32_DERIVATION +│ │ │ └─ key_data: 03a05bc26391221d685e18daaff36a1e95c34f99451253c16cd42650db278a7911 (33 bytes) +│ │ └─ value: cc18ae0800000000000000001500000002000000 (20 bytes) +│ ├─ input_3: None +│ │ ├─ pair_count: 7u64 +│ │ ├─ pair_0: None +│ │ │ ├─ key: None +│ │ │ │ ├─ type_id: 1u8 +│ │ │ │ └─ type_name: PSBT_IN_WITNESS_UTXO +│ │ │ └─ value: e803000000000000225120394b94d061d7b778fed8a204ce05ed0b44954ec1622f934f84114e1173f33027 (43 bytes) +│ │ ├─ pair_1: None +│ │ │ ├─ key: None +│ │ │ │ ├─ type_id: 3u8 +│ │ │ │ └─ type_name: PSBT_IN_SIGHASH_TYPE +│ │ │ └─ value: 00000000 (4 bytes) +│ │ ├─ pair_2: None +│ │ │ ├─ key: None +│ │ │ │ ├─ type_id: 20u8 +│ │ │ │ ├─ type_name: PSBT_IN_TAP_SCRIPT_SIG +│ │ │ │ └─ key_data: 7373d723ce0a87f8fdd66843be12dae9d51939f68188d5ad96920bef5f51f49683d7f98e9ef0f7336a06f4a0115183a9f996cbac1228e9aa7638f447f0249f30 (64 bytes) +│ │ │ └─ value: 83b1bb7c6ce5868c8a723c4d350591894809b1335586f60cbfccc6dd4e28b8630a74637b1b242e5a389540db94f23bcbedee9c783830cb2afaff1f2763dbdb7b (64 bytes) +│ │ ├─ pair_3: None +│ │ │ ├─ key: None +│ │ │ │ ├─ type_id: 20u8 +│ │ │ │ ├─ type_name: PSBT_IN_TAP_SCRIPT_SIG +│ │ │ │ └─ key_data: aa88ca194fda43486504b86ac9b71f10fc41de7b1713874839427f74e78c2d5a83d7f98e9ef0f7336a06f4a0115183a9f996cbac1228e9aa7638f447f0249f30 (64 bytes) +│ │ │ └─ value: e7dab0d277ce7c41933136b44dcabef400f1d0e622a2255f9867d807bc8e0008cfd30766d36d736c8df7aa32917de59d0832b481c499f0917876134532306d45 (64 bytes) +│ │ ├─ pair_4: None +│ │ │ ├─ key: None +│ │ │ │ ├─ type_id: 21u8 +│ │ │ │ ├─ type_name: PSBT_IN_TAP_LEAF_SCRIPT +│ │ │ │ └─ key_data: c0bc17ea2bbf6ff46bd5c0c3780be2a63880eb7bb782b39ed86f29b99f4882994e1b178b1b55d3c6aac7b039e3422dfdb9c9d75d4d6fc908e9743e88b651e48d83 (65 bytes) +│ │ │ └─ value: 207373d723ce0a87f8fdd66843be12dae9d51939f68188d5ad96920bef5f51f496ad20aa88ca194fda43486504b86ac9b71f10fc41de7b1713874839427f74e78c2d5aacc0 (69 bytes) +│ │ ├─ pair_5: None +│ │ │ ├─ key: None +│ │ │ │ ├─ type_id: 22u8 +│ │ │ │ ├─ type_name: PSBT_IN_TAP_BIP32_DERIVATION +│ │ │ │ └─ key_data: 7373d723ce0a87f8fdd66843be12dae9d51939f68188d5ad96920bef5f51f496 (32 bytes) +│ │ │ └─ value: 0183d7f98e9ef0f7336a06f4a0115183a9f996cbac1228e9aa7638f447f0249f30f2ef038900000000000000001f00000003000000 (53 bytes) +│ │ └─ pair_6: None +│ │ ├─ key: None +│ │ │ ├─ type_id: 22u8 +│ │ │ ├─ type_name: PSBT_IN_TAP_BIP32_DERIVATION +│ │ │ └─ key_data: aa88ca194fda43486504b86ac9b71f10fc41de7b1713874839427f74e78c2d5a (32 bytes) +│ │ └─ value: 0183d7f98e9ef0f7336a06f4a0115183a9f996cbac1228e9aa7638f447f0249f30f65cd86900000000000000001f00000003000000 (53 bytes) +│ ├─ input_4: None +│ │ ├─ pair_count: 7u64 +│ │ ├─ pair_0: None +│ │ │ ├─ key: None +│ │ │ │ ├─ type_id: 1u8 +│ │ │ │ └─ type_name: PSBT_IN_WITNESS_UTXO +│ │ │ └─ value: e80300000000000022512029bbfaf4385b10dc2bbe7ab4d50e89cebe8f507968727b19689e2638083cc55b (43 bytes) +│ │ ├─ pair_1: None +│ │ │ ├─ key: None +│ │ │ │ ├─ type_id: 3u8 +│ │ │ │ └─ type_name: PSBT_IN_SIGHASH_TYPE +│ │ │ └─ value: 00000000 (4 bytes) +│ │ ├─ pair_2: None +│ │ │ ├─ key: None +│ │ │ │ ├─ type_id: 20u8 +│ │ │ │ ├─ type_name: PSBT_IN_TAP_SCRIPT_SIG +│ │ │ │ └─ key_data: 035c9d632db2ddb8f90cf3ccfc931822bcb1f24562b23ae041abf12e54bca64d429069c8320ff5f1c8ac2a0b1047ff1450b8c0d325e1d12f1c52684d91a3b9fb (64 bytes) +│ │ │ └─ value: 4d8e50128b5c61dd449b352a6d6f3d611e163b0794c8c2d057d25401957bb07a70420e336e18f6b255d5b869570c087091c30c1a33f0cac0a40d90d0514c69a4 (64 bytes) +│ │ ├─ pair_3: None +│ │ │ ├─ key: None +│ │ │ │ ├─ type_id: 20u8 +│ │ │ │ ├─ type_name: PSBT_IN_TAP_SCRIPT_SIG +│ │ │ │ └─ key_data: 643151ab03f3a97bb86d3592f12f8d25a8026d89cd47342fc1b49c5e2e63478b429069c8320ff5f1c8ac2a0b1047ff1450b8c0d325e1d12f1c52684d91a3b9fb (64 bytes) +│ │ │ └─ value: 0a1e013f6d57fb8b248b2b19b08b34c1a3cd5ff6de4acdf19dd4ce0e02d42154856dd569f4668f2abaccbb50ce81a9d2f53efdfb627c2cb14cf92c4189a35da7 (64 bytes) +│ │ ├─ pair_4: None +│ │ │ ├─ key: None +│ │ │ │ ├─ type_id: 21u8 +│ │ │ │ ├─ type_name: PSBT_IN_TAP_LEAF_SCRIPT +│ │ │ │ └─ key_data: c1a107a403f7a207e7b1f552d3fd3f55f64ae40e149d0d26f4868ad7faec949eb7637e37cac6e5f22347ab68e876b559117d9597ee7b37fb983c2ab9e51023c976 (65 bytes) +│ │ │ └─ value: 20643151ab03f3a97bb86d3592f12f8d25a8026d89cd47342fc1b49c5e2e63478bad20035c9d632db2ddb8f90cf3ccfc931822bcb1f24562b23ae041abf12e54bca64dacc0 (69 bytes) +│ │ ├─ pair_5: None +│ │ │ ├─ key: None +│ │ │ │ ├─ type_id: 22u8 +│ │ │ │ ├─ type_name: PSBT_IN_TAP_BIP32_DERIVATION +│ │ │ │ └─ key_data: 035c9d632db2ddb8f90cf3ccfc931822bcb1f24562b23ae041abf12e54bca64d (32 bytes) +│ │ │ └─ value: 01429069c8320ff5f1c8ac2a0b1047ff1450b8c0d325e1d12f1c52684d91a3b9fbcc18ae0800000000000000002900000004000000 (53 bytes) +│ │ └─ pair_6: None +│ │ ├─ key: None +│ │ │ ├─ type_id: 22u8 +│ │ │ ├─ type_name: PSBT_IN_TAP_BIP32_DERIVATION +│ │ │ └─ key_data: 643151ab03f3a97bb86d3592f12f8d25a8026d89cd47342fc1b49c5e2e63478b (32 bytes) +│ │ └─ value: 01429069c8320ff5f1c8ac2a0b1047ff1450b8c0d325e1d12f1c52684d91a3b9fbf2ef038900000000000000002900000004000000 (53 bytes) +│ ├─ input_5: None +│ │ ├─ pair_count: 11u64 +│ │ ├─ pair_0: None +│ │ │ ├─ key: None +│ │ │ │ ├─ type_id: 1u8 +│ │ │ │ └─ type_name: PSBT_IN_WITNESS_UTXO +│ │ │ └─ value: e80300000000000022512015c5815026f6a54b10194fc6980f1866a02d9ec128533c7997cdb4289bf3ef16 (43 bytes) +│ │ ├─ pair_1: None +│ │ │ ├─ key: None +│ │ │ │ ├─ type_id: 3u8 +│ │ │ │ └─ type_name: PSBT_IN_SIGHASH_TYPE +│ │ │ └─ value: 00000000 (4 bytes) +│ │ ├─ pair_2: None +│ │ │ ├─ key: None +│ │ │ │ ├─ type_id: 22u8 +│ │ │ │ ├─ type_name: PSBT_IN_TAP_BIP32_DERIVATION +│ │ │ │ └─ key_data: 0fdea69e40a3adef3cdc7fa6f3af02f4c9d9e3254503c96a6a2b4aa66e778171 (32 bytes) +│ │ │ └─ value: 00f65cd86900000000000000002900000005000000 (21 bytes) +│ │ ├─ pair_3: None +│ │ │ ├─ key: None +│ │ │ │ ├─ type_id: 22u8 +│ │ │ │ ├─ type_name: PSBT_IN_TAP_BIP32_DERIVATION +│ │ │ │ └─ key_data: 1d978a17486ff9e47c82990269e531fc63981419d4ce73ee8bd2c99661c53953 (32 bytes) +│ │ │ └─ value: 00f2ef038900000000000000002900000005000000 (21 bytes) +│ │ ├─ pair_4: None +│ │ │ ├─ key: None +│ │ │ │ ├─ type_id: 23u8 +│ │ │ │ └─ type_name: PSBT_IN_TAP_INTERNAL_KEY +│ │ │ └─ value: eb5ad29a85aed24de2880e774caaf624f9cb1be09c67ed4aefbb9b7bc12ddf1a (32 bytes) +│ │ ├─ pair_5: None +│ │ │ ├─ key: None +│ │ │ │ ├─ type_id: 24u8 +│ │ │ │ └─ type_name: PSBT_IN_TAP_MERKLE_ROOT +│ │ │ └─ value: b2a497ea4d0b52f5011ae135d0bbe0d9ebd777bb28e733cbcc13134b73106a1a (32 bytes) +│ │ ├─ pair_6: None +│ │ │ ├─ key: None +│ │ │ │ ├─ type_id: 252u8 +│ │ │ │ ├─ type_name: PSBT_IN_PROPRIETARY +│ │ │ │ ├─ prefix: BITGO +│ │ │ │ ├─ subtype: 1u8 +│ │ │ │ └─ key_data: 15c5815026f6a54b10194fc6980f1866a02d9ec128533c7997cdb4289bf3ef16eb5ad29a85aed24de2880e774caaf624f9cb1be09c67ed4aefbb9b7bc12ddf1a (64 bytes) +│ │ │ └─ value: 021d978a17486ff9e47c82990269e531fc63981419d4ce73ee8bd2c99661c53953020fdea69e40a3adef3cdc7fa6f3af02f4c9d9e3254503c96a6a2b4aa66e778171 (66 bytes) +│ │ ├─ pair_7: None +│ │ │ ├─ key: None +│ │ │ │ ├─ type_id: 252u8 +│ │ │ │ ├─ type_name: PSBT_IN_PROPRIETARY +│ │ │ │ ├─ prefix: BITGO +│ │ │ │ ├─ subtype: 2u8 +│ │ │ │ └─ key_data: 020fdea69e40a3adef3cdc7fa6f3af02f4c9d9e3254503c96a6a2b4aa66e77817115c5815026f6a54b10194fc6980f1866a02d9ec128533c7997cdb4289bf3ef16 (65 bytes) +│ │ │ └─ value: 02826949740dff45d408b1f19d94c720f53411e02c525b28ab3c593b6b530fe0370374b8a0ffcaaaee6b772dac5f7c23ef33670b32ec77c6d41efb3c36df2165a094 (66 bytes) +│ │ ├─ pair_8: None +│ │ │ ├─ key: None +│ │ │ │ ├─ type_id: 252u8 +│ │ │ │ ├─ type_name: PSBT_IN_PROPRIETARY +│ │ │ │ ├─ prefix: BITGO +│ │ │ │ ├─ subtype: 2u8 +│ │ │ │ └─ key_data: 021d978a17486ff9e47c82990269e531fc63981419d4ce73ee8bd2c99661c5395315c5815026f6a54b10194fc6980f1866a02d9ec128533c7997cdb4289bf3ef16 (65 bytes) +│ │ │ └─ value: 03a4aaf46f3a0bc39a73855fa875b2f2f04bdb06235afbaedf857b593dddc63cb402cdb7f1a93ec526282198d834423371757e8f43932d03b9f43c3f7378300ae508 (66 bytes) +│ │ ├─ pair_9: None +│ │ │ ├─ key: None +│ │ │ │ ├─ type_id: 252u8 +│ │ │ │ ├─ type_name: PSBT_IN_PROPRIETARY +│ │ │ │ ├─ prefix: BITGO +│ │ │ │ ├─ subtype: 3u8 +│ │ │ │ └─ key_data: 020fdea69e40a3adef3cdc7fa6f3af02f4c9d9e3254503c96a6a2b4aa66e77817115c5815026f6a54b10194fc6980f1866a02d9ec128533c7997cdb4289bf3ef16 (65 bytes) +│ │ │ └─ value: fbdc39c3b8ffca4e6caf3298fa1a4be546b99163c2f21bd374d2254ec5b3c0f4 (32 bytes) +│ │ └─ pair_10: None +│ │ ├─ key: None +│ │ │ ├─ type_id: 252u8 +│ │ │ ├─ type_name: PSBT_IN_PROPRIETARY +│ │ │ ├─ prefix: BITGO +│ │ │ ├─ subtype: 3u8 +│ │ │ └─ key_data: 021d978a17486ff9e47c82990269e531fc63981419d4ce73ee8bd2c99661c5395315c5815026f6a54b10194fc6980f1866a02d9ec128533c7997cdb4289bf3ef16 (65 bytes) +│ │ └─ value: 1cd8a0c0598b0d88f889fdf9a3140f8f088e2187803a2faaee3f13c0163eb76c (32 bytes) +│ └─ input_6: None +│ ├─ pair_count: 4u64 +│ ├─ pair_0: None +│ │ ├─ key: None +│ │ │ ├─ type_id: 0u8 +│ │ │ └─ type_name: PSBT_IN_NON_WITNESS_UTXO +│ │ └─ value: 01000000010101010101010101010101010101010101010101010101010101010101010101000000006a47304402202a91bae6d5c543ab51ccd0409f54469b539dd2e569f90949b8be637eabd3902802206d38f3d87b598275bef6d910e4614e4452573320ca3ddea150e4901aa3781f7c012103bd0c34b2373e387575cddb103ec03916c31044f2508e261fe3597a2680ecbd1fffffffff07e8030000000000001976a914883ad8d1affdf8a73cbdaf7237b5c5ab9ec2c32688ace8030000000000001976a914883ad8d1affdf8a73cbdaf7237b5c5ab9ec2c32688ace8030000000000001976a914883ad8d1affdf8a73cbdaf7237b5c5ab9ec2c32688ace8... (393 bytes) +│ ├─ pair_1: None +│ │ ├─ key: None +│ │ │ ├─ type_id: 2u8 +│ │ │ ├─ type_name: PSBT_IN_PARTIAL_SIG +│ │ │ └─ key_data: 0336ef228ffe9b8efffba052c32d334660dd1f8366cf8fe44ae5aa672b6b629095 (33 bytes) +│ │ └─ value: 3045022100d2a7abb6c0563c3000e37412a9b97f6352d17e40960456fe830d264f0474f8b6022038d5cdbe88a319de5d7b7db8f57d0a92524beb242729b46a617adb530f2fa0d001 (72 bytes) +│ ├─ pair_2: None +│ │ ├─ key: None +│ │ │ ├─ type_id: 3u8 +│ │ │ └─ type_name: PSBT_IN_SIGHASH_TYPE +│ │ └─ value: 01000000 (4 bytes) +│ └─ pair_3: None +│ ├─ key: None +│ │ ├─ type_id: 4u8 +│ │ └─ type_name: PSBT_IN_REDEEM_SCRIPT +│ └─ value: 210336ef228ffe9b8efffba052c32d334660dd1f8366cf8fe44ae5aa672b6b629095ac (35 bytes) +└─ output_maps: 5u64 + ├─ output_0: None + │ ├─ pair_count: 4u64 + │ ├─ pair_0: None + │ │ ├─ key: None + │ │ │ ├─ type_id: 0u8 + │ │ │ └─ type_name: PSBT_OUT_REDEEM_SCRIPT + │ │ └─ value: 522102cc4d0fa411cac244486f8eb2c08e035ff7410f460a359ca7f8810991bd3b42092102d72fd0d0d90293434ad5fca160f278e03c614497aa4e425cf454e2c1330f96ab210344d884136df550202865ffbc6218c7f9c88fe6ce39c945798190badb38a752f153ae (105 bytes) + │ ├─ pair_1: None + │ │ ├─ key: None + │ │ │ ├─ type_id: 2u8 + │ │ │ ├─ type_name: PSBT_OUT_BIP32_DERIVATION + │ │ │ └─ key_data: 02cc4d0fa411cac244486f8eb2c08e035ff7410f460a359ca7f8810991bd3b4209 (33 bytes) + │ │ └─ value: f2ef038900000000000000000000000000000000 (20 bytes) + │ ├─ pair_2: None + │ │ ├─ key: None + │ │ │ ├─ type_id: 2u8 + │ │ │ ├─ type_name: PSBT_OUT_BIP32_DERIVATION + │ │ │ └─ key_data: 02d72fd0d0d90293434ad5fca160f278e03c614497aa4e425cf454e2c1330f96ab (33 bytes) + │ │ └─ value: cc18ae0800000000000000000000000000000000 (20 bytes) + │ └─ pair_3: None + │ ├─ key: None + │ │ ├─ type_id: 2u8 + │ │ ├─ type_name: PSBT_OUT_BIP32_DERIVATION + │ │ └─ key_data: 0344d884136df550202865ffbc6218c7f9c88fe6ce39c945798190badb38a752f1 (33 bytes) + │ └─ value: f65cd86900000000000000000000000000000000 (20 bytes) + ├─ output_1: None + │ ├─ pair_count: 5u64 + │ ├─ pair_0: None + │ │ ├─ key: None + │ │ │ ├─ type_id: 0u8 + │ │ │ └─ type_name: PSBT_OUT_REDEEM_SCRIPT + │ │ └─ value: 0020292b052351a3c6f80d51bae642cc8821182893dbeedabc8f5d0e9677476026c1 (34 bytes) + │ ├─ pair_1: None + │ │ ├─ key: None + │ │ │ ├─ type_id: 1u8 + │ │ │ └─ type_name: PSBT_OUT_WITNESS_SCRIPT + │ │ └─ value: 5221032e11f98552685fe907f31f9e7260c906e8de700f0c3c9f2f1410623dcdfd19c02103545757ce35cf1edfb13b9e2c4a2f9ce00ab8c36bee12bca2337ce583fd28aec82102a3cfb6665fe44f7520b6a1b4de1a4d46643b385eb1fd1e0ab70efb965429755453ae (105 bytes) + │ ├─ pair_2: None + │ │ ├─ key: None + │ │ │ ├─ type_id: 2u8 + │ │ │ ├─ type_name: PSBT_OUT_BIP32_DERIVATION + │ │ │ └─ key_data: 02a3cfb6665fe44f7520b6a1b4de1a4d46643b385eb1fd1e0ab70efb9654297554 (33 bytes) + │ │ └─ value: f65cd86900000000000000000a00000001000000 (20 bytes) + │ ├─ pair_3: None + │ │ ├─ key: None + │ │ │ ├─ type_id: 2u8 + │ │ │ ├─ type_name: PSBT_OUT_BIP32_DERIVATION + │ │ │ └─ key_data: 032e11f98552685fe907f31f9e7260c906e8de700f0c3c9f2f1410623dcdfd19c0 (33 bytes) + │ │ └─ value: f2ef038900000000000000000a00000001000000 (20 bytes) + │ └─ pair_4: None + │ ├─ key: None + │ │ ├─ type_id: 2u8 + │ │ ├─ type_name: PSBT_OUT_BIP32_DERIVATION + │ │ └─ key_data: 03545757ce35cf1edfb13b9e2c4a2f9ce00ab8c36bee12bca2337ce583fd28aec8 (33 bytes) + │ └─ value: cc18ae0800000000000000000a00000001000000 (20 bytes) + ├─ output_2: None + │ ├─ pair_count: 4u64 + │ ├─ pair_0: None + │ │ ├─ key: None + │ │ │ ├─ type_id: 1u8 + │ │ │ └─ type_name: PSBT_OUT_WITNESS_SCRIPT + │ │ └─ value: 522102d6d1140bd2c0f914cb30c992aa2fcd283f471a9281ceec9ec6c5bc448e6869002103b855a8758eda6863648445a9d3cfb95388aca174621ad98f099a1c4f9326fec7210295f7b527d2ea537a4d42830410abf4340731bf9b20e54972001933b9aa23536c53ae (105 bytes) + │ ├─ pair_1: None + │ │ ├─ key: None + │ │ │ ├─ type_id: 2u8 + │ │ │ ├─ type_name: PSBT_OUT_BIP32_DERIVATION + │ │ │ └─ key_data: 0295f7b527d2ea537a4d42830410abf4340731bf9b20e54972001933b9aa23536c (33 bytes) + │ │ └─ value: f65cd86900000000000000001400000002000000 (20 bytes) + │ ├─ pair_2: None + │ │ ├─ key: None + │ │ │ ├─ type_id: 2u8 + │ │ │ ├─ type_name: PSBT_OUT_BIP32_DERIVATION + │ │ │ └─ key_data: 02d6d1140bd2c0f914cb30c992aa2fcd283f471a9281ceec9ec6c5bc448e686900 (33 bytes) + │ │ └─ value: f2ef038900000000000000001400000002000000 (20 bytes) + │ └─ pair_3: None + │ ├─ key: None + │ │ ├─ type_id: 2u8 + │ │ ├─ type_name: PSBT_OUT_BIP32_DERIVATION + │ │ └─ key_data: 03b855a8758eda6863648445a9d3cfb95388aca174621ad98f099a1c4f9326fec7 (33 bytes) + │ └─ value: cc18ae0800000000000000001400000002000000 (20 bytes) + ├─ output_3: None + │ ├─ pair_count: 5u64 + │ ├─ pair_0: None + │ │ ├─ key: None + │ │ │ ├─ type_id: 5u8 + │ │ │ └─ type_name: PSBT_OUT_TAP_INTERNAL_KEY + │ │ └─ value: 8ea58016ecabe3cf8490ec65d779141571fb9e5c12eac905d180f0e102943394 (32 bytes) + │ ├─ pair_1: None + │ │ ├─ key: None + │ │ │ ├─ type_id: 6u8 + │ │ │ └─ type_name: PSBT_OUT_TAP_TREE + │ │ └─ value: 01c0442099e43655c2cf3d950362bb6a3a446380e80b7a1f70e52884eb576b1356dc6e40ad20a86d7fe67f6994113143cc16344cb1e997b8cc8e1dee23651b97c79c09af9addac02c0442099e43655c2cf3d950362bb6a3a446380e80b7a1f70e52884eb576b1356dc6e40ad203a093530ea159d73c8ff93099ee0a9bb9e9aa39e0b2b84642d47b4f80d487cbbac02c044203a093530ea159d73c8ff93099ee0a9bb9e9aa39e0b2b84642d47b4f80d487cbbad20a86d7fe67f6994113143cc16344cb1e997b8cc8e1dee23651b97c79c09af9addac (213 bytes) + │ ├─ pair_2: None + │ │ ├─ key: None + │ │ │ ├─ type_id: 7u8 + │ │ │ ├─ type_name: PSBT_OUT_TAP_BIP32_DERIVATION + │ │ │ └─ key_data: 3a093530ea159d73c8ff93099ee0a9bb9e9aa39e0b2b84642d47b4f80d487cbb (32 bytes) + │ │ └─ value: 02cf9605caec3824347bd70ad56e776095fa63f3bc6804d0430cecffe4e253d8cebc0e3b7d952ad956bb7759de2173582c7500d8f29fe4c1ade6711b39d793581acc18ae0800000000000000001e00000003000000 (85 bytes) + │ ├─ pair_3: None + │ │ ├─ key: None + │ │ │ ├─ type_id: 7u8 + │ │ │ ├─ type_name: PSBT_OUT_TAP_BIP32_DERIVATION + │ │ │ └─ key_data: 99e43655c2cf3d950362bb6a3a446380e80b7a1f70e52884eb576b1356dc6e40 (32 bytes) + │ │ └─ value: 028d6609b2543534810e1219c57c1ba1fb1cc2b1a742726c0aa7f37d03d023401acf9605caec3824347bd70ad56e776095fa63f3bc6804d0430cecffe4e253d8cef2ef038900000000000000001e00000003000000 (85 bytes) + │ └─ pair_4: None + │ ├─ key: None + │ │ ├─ type_id: 7u8 + │ │ ├─ type_name: PSBT_OUT_TAP_BIP32_DERIVATION + │ │ └─ key_data: a86d7fe67f6994113143cc16344cb1e997b8cc8e1dee23651b97c79c09af9add (32 bytes) + │ └─ value: 028d6609b2543534810e1219c57c1ba1fb1cc2b1a742726c0aa7f37d03d023401abc0e3b7d952ad956bb7759de2173582c7500d8f29fe4c1ade6711b39d793581af65cd86900000000000000001e00000003000000 (85 bytes) + └─ output_4: None + ├─ pair_count: 5u64 + ├─ pair_0: None + │ ├─ key: None + │ │ ├─ type_id: 5u8 + │ │ └─ type_name: PSBT_OUT_TAP_INTERNAL_KEY + │ └─ value: 31b5af14121c7a997e1f58dc7178f8b2589e330fe5a9dc8c16549f90cbbe9ec5 (32 bytes) + ├─ pair_1: None + │ ├─ key: None + │ │ ├─ type_id: 6u8 + │ │ └─ type_name: PSBT_OUT_TAP_TREE + │ └─ value: 01c044204e8d0e8341fe95733afca3dbf1852de77695e287959797c6d8159fbfb02b48b6ad20c160c27afcc4888c593f18dee2d7985657508c03705ab6f0f635d352cbaf6499ac01c04420c160c27afcc4888c593f18dee2d7985657508c03705ab6f0f635d352cbaf6499ad20683608908c8bfe95e38f099068a170140332129eeb03480b1e4806d4f4f43c2cac (142 bytes) + ├─ pair_2: None + │ ├─ key: None + │ │ ├─ type_id: 7u8 + │ │ ├─ type_name: PSBT_OUT_TAP_BIP32_DERIVATION + │ │ └─ key_data: 4e8d0e8341fe95733afca3dbf1852de77695e287959797c6d8159fbfb02b48b6 (32 bytes) + │ └─ value: 010f39500a54520faeefe84e5a4f9595943523307ef253a7ddc713189a6f5a32f0f2ef038900000000000000002800000004000000 (53 bytes) + ├─ pair_3: None + │ ├─ key: None + │ │ ├─ type_id: 7u8 + │ │ ├─ type_name: PSBT_OUT_TAP_BIP32_DERIVATION + │ │ └─ key_data: 683608908c8bfe95e38f099068a170140332129eeb03480b1e4806d4f4f43c2c (32 bytes) + │ └─ value: 01d7a356fb77b18e43bc861580e45c0044c0857e31b1bde76083d9080c33d3ffcff65cd86900000000000000002800000004000000 (53 bytes) + └─ pair_4: None + ├─ key: None + │ ├─ type_id: 7u8 + │ ├─ type_name: PSBT_OUT_TAP_BIP32_DERIVATION + │ └─ key_data: c160c27afcc4888c593f18dee2d7985657508c03705ab6f0f635d352cbaf6499 (32 bytes) + └─ value: 020f39500a54520faeefe84e5a4f9595943523307ef253a7ddc713189a6f5a32f0d7a356fb77b18e43bc861580e45c0044c0857e31b1bde76083d9080c33d3ffcfcc18ae0800000000000000002800000004000000 (85 bytes) diff --git a/packages/wasm-utxo/cli/tests/fixtures/simple_tree.txt b/packages/wasm-utxo/cli/test/fixtures/simple_tree.txt similarity index 100% rename from packages/wasm-utxo/cli/tests/fixtures/simple_tree.txt rename to packages/wasm-utxo/cli/test/fixtures/simple_tree.txt diff --git a/packages/wasm-utxo/cli/tests/fixtures/small_buffer.txt b/packages/wasm-utxo/cli/test/fixtures/small_buffer.txt similarity index 100% rename from packages/wasm-utxo/cli/tests/fixtures/small_buffer.txt rename to packages/wasm-utxo/cli/test/fixtures/small_buffer.txt diff --git a/packages/wasm-utxo/cli/test/fixtures/tx_bitcoin_fullsigned.txt b/packages/wasm-utxo/cli/test/fixtures/tx_bitcoin_fullsigned.txt new file mode 100644 index 00000000..fef64a34 --- /dev/null +++ b/packages/wasm-utxo/cli/test/fixtures/tx_bitcoin_fullsigned.txt @@ -0,0 +1,85 @@ +tx: None +├─ version: 1i32 +├─ lock_time: 0u32 +├─ txid: a341d563b6d62d3c078017ae60a72fae551f7381634871b2764422e9d4968061 (32 bytes) +├─ ntxid: 819e1ce50e5f92d52f3d6cfbb4084355392777d8b23b0bce674674577a940608 (32 bytes) +├─ wtxid: bfb14a40525fa2a173ce7fc0fb4f7fd7d89b07f5b0ea0073e77487de3c0b2d97 (32 bytes) +├─ inputs: 7u64 +│ ├─ input_0: None +│ │ ├─ prev_txid: d99efae199fc4d54e5825a8e3368a395e9eb329915cfb5d88dc311507d184836 (32 bytes) +│ │ ├─ prev_vout: 0u32 +│ │ ├─ sequence: 4294967295u32 +│ │ └─ script_sig: 0047304402201e79545c011e34b1b872b4b057e66262d86881da6a7f853e7e57a9a4d12c6dc102201a538b2175c7b7161c76da18394220f354ae2729fcc1c902b74c59cd79e0153101483045022100dd31a25d0ebea90e67910168ef7c2b383ca26192cd5c8709f02980b7ca90472802203795c65ee0f073b80644d0c8ffa1d428457ae2af3df5b5d8117949781d10c462014c69522103f6f40764bd5d63f200a2778883acf75e96f15095c998263c087270d0c97e7e7f21035ffb7abc70159e0469f4b989a6d5e1785a2904169ff050b2f468fe5d3d5dbbf22103e1524d7f6fc57ab3eacbb659b787106780a475d1db483952c2310b7e9a38975b53ae (253 bytes) +│ ├─ input_1: None +│ │ ├─ prev_txid: 1ec9729a1b25373a30f0fe6e0879b31136a54f2f8c98618c46862748a08c5e78 (32 bytes) +│ │ ├─ prev_vout: 1u32 +│ │ ├─ sequence: 4294967295u32 +│ │ ├─ script_sig: 22002046d4800a1393330196085399ed4a1700b4c2fd38c52188c3a3a91f721f3c9600 (35 bytes) +│ │ └─ witness: 4u64 +│ │ ├─ item_0: (0 bytes) +│ │ ├─ item_1: 304402205f760c27e7598a9e80a2adaf1d925c67d2e6c24aec773e5cce56d234159ab1e502201ce97d5659681ab881e10acc9c8021587f843a15336c3a8b6fb2efc053928b8501 (71 bytes) +│ │ ├─ item_2: 3045022100df41fbcbf3c7f77182627bcb7cd17973b8ca58c16b81de98e94c0293dcf33ac202206017171914fdfbc80f933ab3b5aae4e3d36e968757e6c0788ffbeaaebc68e21e01 (72 bytes) +│ │ └─ item_3: 522102a585f3fab49b5ef95346d932221a221bd55ec191f15533e0f270b3582574f0352102c4f7866cfd5996bc1068a96313ca15e9ccb5e984583a07340dddae7af014605b2102234531bc9119a36a7946e95aeb74915dd087c7b44f517b8eeeb73f89a0ff1a9953ae (105 bytes) +│ ├─ input_2: None +│ │ ├─ prev_txid: bb0dfbeba59bba69e3ce07a54346f804c543fa46d828ed539d11231adbaa8b7b (32 bytes) +│ │ ├─ prev_vout: 2u32 +│ │ ├─ sequence: 4294967295u32 +│ │ ├─ script_sig: (0 bytes) +│ │ └─ witness: 4u64 +│ │ ├─ item_0: (0 bytes) +│ │ ├─ item_1: 3045022100d3b03fb77553144e14171c7b1b517a3bf33df87370b65e337f0a50844562261e0220585bc0913b56ad968161d343f321d77f5f94ff3cf62545932f1509239a15a38e01 (72 bytes) +│ │ ├─ item_2: 304402206441089c8c71a4926b49a5ab12bfaa86c4b64abbc519b3d217d68fe71bc43bee02203e17d0752c0b411e9477c22c2f4556a62da39e60095c6e0774bf42aa8f491b4d01 (71 bytes) +│ │ └─ item_3: 522103519e572ab468560d1f8d0f87699d098308e166905f5dcae4390f060faa8f1ce32103a05bc26391221d685e18daaff36a1e95c34f99451253c16cd42650db278a79112102e80a08885c353676b820cdc290e6d81a0ac95a03e8abbf4bb7aeebfb70feb41853ae (105 bytes) +│ ├─ input_3: None +│ │ ├─ prev_txid: a662a5ffebf58bf3e65e53456c67c029cc154a2409740d8cd37fdee7559c5efd (32 bytes) +│ │ ├─ prev_vout: 3u32 +│ │ ├─ sequence: 4294967295u32 +│ │ ├─ script_sig: (0 bytes) +│ │ └─ witness: 4u64 +│ │ ├─ item_0: e7dab0d277ce7c41933136b44dcabef400f1d0e622a2255f9867d807bc8e0008cfd30766d36d736c8df7aa32917de59d0832b481c499f0917876134532306d45 (64 bytes) +│ │ ├─ item_1: 83b1bb7c6ce5868c8a723c4d350591894809b1335586f60cbfccc6dd4e28b8630a74637b1b242e5a389540db94f23bcbedee9c783830cb2afaff1f2763dbdb7b (64 bytes) +│ │ ├─ item_2: 207373d723ce0a87f8fdd66843be12dae9d51939f68188d5ad96920bef5f51f496ad20aa88ca194fda43486504b86ac9b71f10fc41de7b1713874839427f74e78c2d5aac (68 bytes) +│ │ └─ item_3: c0bc17ea2bbf6ff46bd5c0c3780be2a63880eb7bb782b39ed86f29b99f4882994e1b178b1b55d3c6aac7b039e3422dfdb9c9d75d4d6fc908e9743e88b651e48d83 (65 bytes) +│ ├─ input_4: None +│ │ ├─ prev_txid: d394375cee23b3b9951488c0403529157a85b058edc0351546d9eb4807e8a1d3 (32 bytes) +│ │ ├─ prev_vout: 4u32 +│ │ ├─ sequence: 4294967295u32 +│ │ ├─ script_sig: (0 bytes) +│ │ └─ witness: 4u64 +│ │ ├─ item_0: 4d8e50128b5c61dd449b352a6d6f3d611e163b0794c8c2d057d25401957bb07a70420e336e18f6b255d5b869570c087091c30c1a33f0cac0a40d90d0514c69a4 (64 bytes) +│ │ ├─ item_1: 0a1e013f6d57fb8b248b2b19b08b34c1a3cd5ff6de4acdf19dd4ce0e02d42154856dd569f4668f2abaccbb50ce81a9d2f53efdfb627c2cb14cf92c4189a35da7 (64 bytes) +│ │ ├─ item_2: 20643151ab03f3a97bb86d3592f12f8d25a8026d89cd47342fc1b49c5e2e63478bad20035c9d632db2ddb8f90cf3ccfc931822bcb1f24562b23ae041abf12e54bca64dac (68 bytes) +│ │ └─ item_3: c1a107a403f7a207e7b1f552d3fd3f55f64ae40e149d0d26f4868ad7faec949eb7637e37cac6e5f22347ab68e876b559117d9597ee7b37fb983c2ab9e51023c976 (65 bytes) +│ ├─ input_5: None +│ │ ├─ prev_txid: 0d2f7f3486edaefc6ab92c21f7caf90085c4de4adac491106fd8a0e4f563dea3 (32 bytes) +│ │ ├─ prev_vout: 5u32 +│ │ ├─ sequence: 4294967295u32 +│ │ ├─ script_sig: (0 bytes) +│ │ └─ witness: 1u64 +│ │ └─ item_0: 2ea4aeeef7c10765ed7bdce7ac429b7395e08cf55083df38384781054b0880e244fe8a2d847a8c334431322d0eeba4e34872ef6052e2044fff7fa8763ce0c20b (64 bytes) +│ └─ input_6: None +│ ├─ prev_txid: 97441d99a8d66f124ab3c9de26b87bd00aeb1547051c842a88165c1b089ee902 (32 bytes) +│ ├─ prev_vout: 6u32 +│ ├─ sequence: 4294967295u32 +│ └─ script_sig: 483045022100d2a7abb6c0563c3000e37412a9b97f6352d17e40960456fe830d264f0474f8b6022038d5cdbe88a319de5d7b7db8f57d0a92524beb242729b46a617adb530f2fa0d00123210336ef228ffe9b8efffba052c32d334660dd1f8366cf8fe44ae5aa672b6b629095ac (109 bytes) +└─ outputs: 5u64 + ├─ output_0: None + │ ├─ value: 900u64 + │ ├─ script_pubkey: a914d909474404c124a3d04c3fbff61faa49cf43c58b87 (23 bytes) + │ └─ address: 3MUbfqvBeD7g1R3b9g8ZQxDwjR7SjQWciv + ├─ output_1: None + │ ├─ value: 900u64 + │ ├─ script_pubkey: a914054127121d37f32266cd967c485404976a67adf087 (23 bytes) + │ └─ address: 32AoMPMpT2ErEqupk6CJvrEMrj6TzmZu8V + ├─ output_2: None + │ ├─ value: 900u64 + │ ├─ script_pubkey: 0020ba48e3f9874463943f90192a45f1ae895b779362a7629af7ad6a9d7a835e3d4f (34 bytes) + │ └─ address: bc1qhfyw87v8g33eg0usry4ytudw39dh0ymz5a3f4aadd2wh4q67848sqay5xu + ├─ output_3: None + │ ├─ value: 900u64 + │ ├─ script_pubkey: 5120b27227f5cadc056afea4b02b4b97b9a0151786234c26ad588dccf134e78931c6 (34 bytes) + │ └─ address: bc1pkfez0aw2mszk4l4ykq45h9ae5q230p3rfsn26kydencnfeufx8rq23ty2z + └─ output_4: None + ├─ value: 900u64 + ├─ script_pubkey: 51204f73b5561399eb397b5ab413e090cc0c48ff703a61afe47cf7d47a23d43b978b (34 bytes) + └─ address: bc1pfaem24snn84nj766ksf7pyxvp3y07up6vxh7gl8h63az84pmj79sehcc5d