
Abstract. BIP-174 defines the PSBT—a binary container for an unsigned or partially signed Bitcoin transaction, containing information sufficient for autonomous signing and subsequent signature combining. This paper systematizes the primary specification of PSBT v0: the global parameter map, input and output maps, validation invariants, participant roles, combining, and finalization; its cryptanalytic significance is also discussed.
Keywords: Bitcoin, PSBT, BIP-174, ECDSA, secp256k1, UTXO, SegWit, multisig, CoinJoin, air-gapped signer, SIGHASH, cryptanalysis.
Status and purpose
BIP-174 was created on July 12, 2017, is Final , and belongs to the Applications layer of the Bitcoin standardization. Its central goal is to resolve incompatibilities between proprietary formats for exchanging unsigned transactions between wallets, hardware devices, and offline signers.
PSBT is not a network consensus format and is not broadcast as a standalone object: after finalization, a regular serialized Bitcoin transaction is extracted from it. Therefore, the security of PSBT is determined simultaneously by the correctness of the cryptographic signature, the authenticity of the provided prevout data, and the security of the user’s confirmation interface.
Normative boundary. “BIP-174” does not mean the document was written by Bitcoin Core Developers as a formal body: BIP is an open standard for Bitcoin’s workflow; the specification was authored by Ava Chow. However, Bitcoin Core and the wallet ecosystem are important reference implementations and consumers of this standard.
Container model
The binary structure of a PSBT consists of a magic sequence, one global map, then maps for each input and each output position. Each map is a sequence of key-value entries, terminated by a byte 0x00.
<psbt> := <magic> <global-map> <input-map>* <output-map>* <magic> := 0x70 0x73 0x62 0x74 0xFF # ASCII "psbt" || 0xFF <global-map> := <keypair>* 0x00 <input-map> := <keypair>* 0x00 <output-map> := <keypair>* 0x00 <keypair> := <key> <value> <key> := <keylen> <keytype> <keydata> <value> := <valuelen> <valuedata>
The keylen, keytype and fields valuelen use CompactSize; coding must be minimal. Within a single card, the complete key, that is, , is identical keytype || keydata, not just the type: this allows, for example, for multiple partial signature records with different public keys.
Parser invariants
- Check magic
70736274ff, minimal CompactSize and exact data lengths. - Reject duplicates of a full key in the same region as invalid PSBT.
- Preserve and re-serialize unknown fields if the format version is recognized.
- Stop processing an unknown PSBT version rather than “guessing” its semantics.
A historical cryptanalytic example. Serialization canonicity is not a cosmetic requirement. Bitcoin has survived classes of vulnerabilities related to different representations of a single logical object (in particular, malleability before SegWit). Strict lengths, key uniqueness, and a separator 0xFF reduce the risk of a regular transaction being mistakenly interpreted as a PSBT or of different parsers accepting conflicting data.
PSBT v0
For v0, the field PSBT_GLOBAL_VERSION may be absent or have the value 0. A single global record is required PSBT_GLOBAL_UNSIGNED_TX = 0x00, containing the unsigned transaction in legacy serialization: all scriptSig and witness must be empty.
This transaction determines the number of subsequent input and output maps and serves as the semantic object identifier during merging. In v0, the structure of the transaction itself is already “frozen” before the signature begins; the fields specific to PSBTv2 (BIP-370) do not apply to the primary v0 model.
Global map
| Type v0 | Data | Purpose and example |
|---|---|---|
0x00 UNSIGNED_TX | Serialized unsigned transaction without witness | Mandatory anchor v0. Example: The CoinJoin coordinator generates inputs, outputs, and fees, then broadcasts the same “skeleton” to all participants. |
0x01 XPUB | 78-byte BIP-32 xpub in keydata; fingerprint and path in value | Allows you to display public child keys and detect changes. Example: a 2-of-3 corporate wallet publishes the account-level xpub of three participants without revealing their private keys. |
0xFB VERSION | uint32 little-endian | If absent, it means v0. Example: The converter must store v0 unless it adds a field that requires a different version. |
0xFC PROPRIETARY | identifier, subtype, keydata and value | Manufacturer-specific metadata. Example: An HSM may store an internal policy identifier; this should not replace public standardization. |
Cryptanalytic note: An extended public key doesn’t reveal the private key, but it does reveal the derivation structure and links addresses within a single wallet. Therefore, transferring XPUB through an intermediary increases the metadata required for address clustering and should be limited to the necessary minimum.
Entrance maps
Each input map describes exactly one consumable UTXO and the signature construction materials. The signer should not obtain missing data from an untrusted external source: the normative model assumes that everything necessary is included in the PSBT.
| Group | Fields v0 | Meaning and practical example |
|---|---|---|
| Prevout | 0x00 NON_WITNESS_UTXO, 0x01 WITNESS_UTXO | The full previous transaction for legacy spending or the output (amount + scriptPubKey) for SegWit. For P2WPKH, the hardware wallet sees the amount and address script; for P2PKH, it checks the txid of the full prevtx. |
| Signature | 0x02 PARTIAL_SIG, 0x03 SIGHASH_TYPE | The partial signature record key is the public key, and the value is the DER-ECDSA signature with the sighash byte. In 2-of-3 P2WSH, three independent signers add up to three records, and the finalizer selects the required two. |
| Scripts | 0x04 REDEEM_SCRIPT, 0x05 WITNESS_SCRIPT | Confirm P2SH/P2WSH conditions. Example of an archival escrow scheme: witnessScript requires two of the three keys; substituting the script changes the spending policy, so its hash must match the locking script. |
| Derivation | 0x06 BIP32_DERIVATION | Each pubkey contains a fingerprint and a path. This allows the device to find the key and distinguish change; at the same time, the path serves as sensitive metadata. |
| Final state | 0x07 FINAL_SCRIPTSIG, 0x08 FINAL_SCRIPTWITNESS | Prepared stack data. For native P2WPKH, the finalizer creates a witness [signature, pubkey], but scriptSig is missing. |
| Hashlock | 0x0A RIPEMD160, 0x0B SHA256, 0x0C HASH160, 0x0D HASH256 | Hash-in-key — preimage-in-value pairs. An example of HTLC in Lightning: the revealed preimage allows a script branch to be satisfied and simultaneously becomes observable on the blockchain. |
| Others | 0x09 POR_COMMITMENT, 0xFC PROPRIETARY | BIP-127 Proof-of-Reserves textual commitment and private internal data. Their presence should not change the consensus semantics without an explicitly verifiable policy. |
Mandatory checks of the signatory
- To
NON_WITNESS_UTXOcalculateSHA256d(prevtx)and compare with txid prevout. - To
WITNESS_UTXOensure that redeemScript and witnessScript hash into the expected locking scripts. - Check that the requested signature
SIGHASH_TYPEis acceptable; if the existing signature does not match, finalization should fail. - Display to the user the recipients, amounts, fees, and—if derivation verification is reliable—the change-output.
For ECDSA over group order n: s = k^{-1}(z + rd) mod n, where d is the private key, k is the one-time nonce, z is the message hash, and r is the x-coordinate of kG mod n.
Cryptanalytic fact: nonce duplication. If the same nonce k is used for two signatures with the same key, then [ s₁ = k⁻¹(z₁ + r·d) mod n and] s₂ = k⁻¹(z₂ + r·d) mod n follows k = (z₁ − z₂)(s₁ − s₂)⁻¹ mod n[and d = (s₁k − z₁)r⁻¹ mod n] . This is not a flaw in PSBT as a container, but PSBT accumulates signatures and messages, so an auditor must detect duplicate values r among signatures of a single public key; historical compromises of ECDSA keys in cryptosystems have repeatedly occurred precisely due to weak entropy or nonce duplication. The deterministic RFC 6979 recommended in BIP-174 test vectors reduces the dependence on an external randomness generator, but requires correct implementation.
Exit maps
The v0 output map does not duplicate the amount and scriptPubKey: they are already in UNSIGNED_TX. Its purpose is to convey data useful to the recipient or signatory for policy recovery, derivation, and change recognition.
| Type v0 | Purpose | A real-life example |
|---|---|---|
0x00 REDEEM_SCRIPT | Redeem script for the future P2SH output | The Treasury is creating a 2-of-3 P2SH to allow participants to import policies without manual re-engineering. |
0x01 WITNESS_SCRIPT | Future P2WSH output script | Escrow with a timelock and backup key; the recipient retains the terms for subsequent spending. |
0x02 BIP32_DERIVATION | fingerprint and derivation path for pubkey | The hardware wallet recognizes change m/84'/0'/0'/1/i and does not show it as an external payment. |
0xFC PROPRIETARY | Private extension | The internal approval system adds the ticket ID; third-party software is required to transparently transfer the unknown field. |
An important difference between the versions: PSBT_OUT_AMOUNT and PSBT_OUT_SCRIPT are fields of PSBTv2, not primary v0. Mixing these models in the analyzer leads to false validation and dangerous incompatibility.
Roles and protocol
| Role | Normative function | Example |
|---|---|---|
| Creator | Creates unsigned transactions and empty cards | The CoinJoin coordinator generates a template without receiving the private keys of the participants. |
| Updater | Adds UTXO, scripts, BIP32 paths | The online wallet augments the PSBT with chain state data before transferring it to the air-gapped device. |
| Signer | Checks materials and only adds valid signatures | The hardware wallet signs its input without changing the recipient or the fee amount. |
| Combiner | Combines records of one unsigned transaction | The multisig server receives two independent signed PSBTs and combines them without knowing the private keys. |
| Input Finalizer | Builds the final scriptSig/witness and cleans up intermediate data | For 2-of-3, P2WSH places a dummy element, two signatures, and a witnessScript in the correct order into the witness. |
| Extractor | Extracts a network transaction only when all inputs are complete | After verifying the completed transaction, the wallet transmits the raw transaction to the node for broadcast. |
Unification
The Combiner is only allowed to combine PSBTs belonging to a single unsigned transaction: in v0, this is verified by matching the global field of the type 0x00. The result must contain the union of all key-value pairs; identical pairs are deduplicated, and if there are conflicting values for a single key, the implementation may choose one value or reject any known conflicts.
Combine(f_A(P), f_B(P)) = f_A(f_B(P)) = f_B(f_A(P))
This property expresses the desired commutativity and idempotency of the accumulation of independent data. A practical example is 2-of-3 multisig: Alice and Bob sign the same P locally, after which the combiner combines the two records PARTIAL_SIG; if one of the participants signs a modified skeleton, a secure combiner must recognize the difference UNSIGNED_TX and not mix the objects.
Finalization and extraction
The finalizer verifies the sufficiency of signatures for each input and generates FINAL_SCRIPTSIG (0x07) and/or FINAL_SCRIPTWITNESS (0x08). An empty scriptSig or witness is not encoded as an empty field: the corresponding entry is simply absent; after finalization, UTXOs and unknown fields are preserved, and intermediate data other than these is deleted.
# Conceptual diagram of P2WPKH finalization assert VerifyECDSA(pubkey, signature, sighash(tx, input_i, SIGHASH_ALL)) witness[i] = [signature || 0x01, pubkey] # FINAL_SCRIPTSIG is not set for native P2WPKH
The extractor verifies the completeness of each input using the final fields, transfers the scriptSig and witness to the transaction, and outputs a valid network format. It should not modify the incomplete PSBT; therefore, extraction is not a mechanism for “composing” missing evidence.
Cryptanalytic Perspective
PSBT transforms the signature attack from an informal data exchange into a set of verifiable relationships: prevtx-to-txid, script-to-hash, pubkey-to-derivation, signature-to-sighash. However, the container doesn’t replace a trusted UI: a malicious Creator can legitimately generate a PSBT with an unwanted recipient, an inflated fee, or a dangerous sighash if the signer doesn’t disclose the transaction’s purpose to the user.
- Legacy sum substitution. Full
NON_WITNESS_UTXOand txid verification prevent substitution of a different prevout; this is especially important since the legacy signature is not committed to the sum under the SegWit model. - WitnessScript/redeemScript substitution. Hash matching prevents the 2-of-3 policy from being converted into a script with a different spending branch.
- Unexpected sighash.
SIGHASH_NONEAndSIGHASH_SINGLEthey change which parts of the transaction the signature is attached to; the signer must apply an allowlist rather than accept the field without analysis. - Metadata leakage. xpub, fingerprint, BIP32 paths, and proprietary fields can deanonymize the owner and link wallets; PSBT should be transmitted as a confidential object.
- Parser discrepancies. Duplicates, non-canonical CompactSize, invalid sizes, and unknown versions should result in a failure, not a best-effort parse.
Recommendations for implementation
- Distinguish between three states: syntactically valid, cryptographically verified, user-confirmed.
- Compare unsigned transactions byte by byte before combine; additionally check consistency of known fields.
- For legacy, transmit and verify the full prevtx; for SegWit, validate the amount and scriptPubKey in the witness UTXO, and on high-trust devices, allow the full prevtx as a strengthened check.
- Do not log the entire PSBT to public logs: it may contain addresses, derivation paths, signatures, hashlock preimages, and private metadata.
- Fuzz the parser for duplicates, truncated CompactSize, invalid terminators, and key-value conflicts; BIP-174 test vectors should be part of the CI.
Conclusion
BIP-174 v0 formalized the secure “create-append-offline-sign-merge-finalize-extract” pipeline for Bitcoin. Its cryptanalytic value lies not in changing the strength of secp256k1, but in providing a verifiable context in which a signature has an unambiguous object, UTXO, and scripting policy. However, nonce errors, weak UI checks, and metadata leaks remain critical risks.
Sources
BIP-174: PSBT v0 — regulatory analysis: https://bitcrack.ru/bip-174-psbt-v0-regulatory-analysis/
- A. Chow. BIP-174: Partially Signed Bitcoin Transaction Format , status Final, created 2017-07-12. GitHub bitcoin/bips.
- Bitcoin BIP-32: Hierarchical Deterministic Wallets.
- RFC 6979: Deterministic Usage of the Digital Signature Algorithm (DSA) and Elliptic Curve Digital Signature Algorithm (ECDSA).
- Bitcoin BIP-127: Proof of Reserves; BIP-370: PSBT Version 2; BIP-141: Segregated Witness.
