Back to all stories
Blogs
Tech & Dev
Exploring PSBT in Bitcoin DeFi: Security Best Practices
12/17/2024
Exploring PSBT in Bitcoin DeFi: Security Best Practices

In recent years, Partially Signed Bitcoin Transactions (PSBT) have gained significant traction within the Bitcoin ecosystem. The rise of innovations like Ordinals and inscription-based assets has driven demand for secure, multi-party signatures and complex transactions, positioning PSBT as an indispensable tool for navigating Bitcoin’s evolving landscape

At CertiK, we are dedicated to advancing the security and integrity of PSBT usage. We have recently conducted comprehensive audits and penetration tests on popular projects like UniSat Wallet Extension, SwapSats, and Trac’s Tap Protocol, which heavily utilize PSBT for facilitating complex transaction workflows. Through our in-depth analyses, we have identified vulnerabilities related to PSBT implementation and provided actionable recommendations to enhance their security posture.

In this article, we share our extensive research and insights into PSBT, delving into its components, applications in Bitcoin DeFi, and the security risks associated with improper usage. We aim to highlight best practices for secure PSBT implementation and contribute to the ongoing efforts to strengthen Bitcoin ecosystem security.

PSBT Overview

Since its inception, the Bitcoin network has continuously evolved to address increasing demands for security, efficiency, and scalability. Among the most notable advancements during this journey is the development of Partially Signed Bitcoin Transactions (PSBT), a transformative innovation in transaction management. Defined in Bitcoin Improvement Proposal 174 (BIP 174), PSBTs standardize the workflow for creating, sharing, and signing Bitcoin transactions, especially in multi-party or multi-device contexts.

Prior to the introduction of PSBT in 2017, coordinating complex transactions that required multiple signatures or involved multiple parties was difficult and fraught with security risks. Wallet software often used proprietary formats for partially signed transactions, leading to incompatibilities between different wallets and platforms. The introduction of BIP-174 addressed these issues by proposing a universal format for PSBTs. This standardization allowed different wallet software and hardware devices to communicate seamlessly, facilitating the collaborative creation and signing of multi-party transactions.

In 2023, Ordinals—a protocol that assigns serial numbers to individual satoshis and allows users to attach extra data to them—brought renewed focus to PSBTs. Ordinals enable the creation of non-fungible tokens (NFTs) and other unique digital assets such as BRC-20 directly on the Bitcoin blockchain by inscribing data onto individual satoshis. Managing these assets requires precise control over transaction inputs and outputs, as well as the ability to handle complex scripts and signatures, which PSBTs are well-equipped to handle. As a result, PSBT technology experienced a revival last year, and has been widely applied in applications across the Bitcoin ecosystem.

Walkthrough of the PSBT Workflow

PSBTs enable the creation, sharing, and signing of Bitcoin transactions in a standardized and secure manner, especially when multiple parties are involved.

High-level steps of PSBT workflow:

  1. The initiator constructs an unsigned transaction by selecting the necessary inputs and outputs, which is then converted into PSBT format. This PSBT, which contains all required transaction details but no signatures, is securely distributed to the relevant parties.
  2. Each participant independently reviews the PSBT to verify that the inputs, outputs, amounts, and addresses align with their intentions, ensuring the accuracy and validity of the transaction details.
  3. Participants then add their partial signatures to the PSBT for the inputs they control, without exposing private keys. After signing, they may verify the partial signatures added by others to ensure their validity and accuracy. This collaborative process may require multiple iterations of signature contributions and verifications until all required signatures have been added.
  4. The PSBT is then returned to the transaction initiator or coordinator, who checks that all necessary signatures are present.
  5. Once all signatures are collected and verified, the PSBT is finalized by replacing the partial signatures and scripts with the final input scripts (scriptSig and scriptWitness), creating a fully signed transaction ready for broadcasting.
  6. The finalized transaction is then broadcasted to the Bitcoin network for confirmation and execution. Once the transaction is confirmed and included in the blockchain, the Bitcoin ledger is updated to reflect the transaction’s inputs and outputs.

The following diagram may help clarify the workflow described above:

PSBT Workflow PSBT CoinJoin Workflow

Key Differences Between PSBT and Multisignature Transactions

While both PSBTs and multisignature transactions involve multiple signatures, they serve different purposes within the Bitcoin network. Multisignature transactions require multiple private keys to authorize a transaction, enforcing a specified number of signatures before funds can be spent. PSBTs, on the other hand, allow multiple parties to collaboratively create and sign transactions, regardless of whether the transaction itself requires multiple signatures.

Multisig Chart Table: Comparison between PSBT and Multisignature Transactions

PSBT Components

Understanding the structure of a PSBT is essential for utilizing it effectively, and ensuring transaction security. Below is a breakdown of its key components.

1. Inputs

Inputs in a PSBT reference the unspent transaction outputs (UTXOs) that are being used to fund the transaction.

  • Previous Transaction Hash and Index: Each input references a specific UTXO being spent, identified by txid, the hash of the previous transaction and vout, the index of the output in the referenced transaction.

Sample input:

Sample Input

  • Sequence Number: Indicates the input’s sequence for relative timelocks, commonly used in advanced scripting scenarios.
  • Non-Witness UTXO: The complete previous transaction data is included in this component. Required for spending non-SegWit outputs to verify the input against the entire transaction.
  • Witness UTXO: For SegWit transaction, contains only the output being spent. It is more efficient compared to the Non-Witness UTXO, but provides less detailed information.
  • Optional Components:
    • P2WSH (Pay-to-Witness-Script-Hash): Contains the witness script for spending SegWit outputs.
    • P2SH (Pay-to-Script-Hash): Includes the redeem script for spending P2SH outputs.
    • Sighash: Defines the signature hash type, specifying how much of the transaction is signed.

2. Outputs

Outputs define where the funds are being sent, which are in the form of UTXO. They are often used for sending change or refund.

  • ScriptPubKey: The locking script that specifies the conditions for spending the output.
  • Amount: Denominated in satoshis, indicating the value of the output.

3. Transaction Metadata

  • Version: Specifies the transaction format version; after BIP-0370, PSBT version 2 became the standard.
  • Locktime: Indicates the earliest time or block height at which the transaction can be included in a block.

4. Signatures

  • Partial Signatures: Each signer adds their signature corresponding to their private key.
  • Public Key Identification: Associates the signature with the correct public key for verification.

5. Finalization Data

  • ScriptSig and Witness Data: Final scripts that satisfy the conditions specified in the ScriptPubKey.

PSBT Tooling

A variety of tools and libraries support the creation, manipulation, and signing of PSBTs, facilitating their adoption across different platforms.

Bitcoin Core Commands

Bitcoin Core, the reference implementation of the Bitcoin protocol, provides several commands for working with PSBTs.

  • converttopsbt: Converts a raw transaction to a PSBT format.
  • createpsbt: Generates a PSBT from provided inputs and outputs without accessing the wallet.
  • walletcreatefundedpsbt: Creates a PSBT using the wallet's UTXOs to fund the transaction, automatically selecting inputs and calculating fees.
  • decodepsbt: Returns a JSON object representing the serialized, base64-encoded PSBT

Third-Party Libraries and Tools

Library and Tools

PSBT Use Cases in the Bitcoin Ecosystem

The rise of protocols like Ordinals, Runes, and BRC-20 tokens has significantly expanded Bitcoin's functionality by enabling tokenized assets and NFTs directly on the Bitcoin blockchain. PSBTs play a crucial role in these developments by allowing precise control over transaction inputs and outputs, which is essential for securely managing and transferring these unique digital assets. PSBTs have also helped improve wallet signing processes, particularly with the integration of hardware wallets and secure signing devices.

The growing interest in Bitcoin DeFi has also accelerated the usage of PSBTs. Developers are leveraging PSBTs to build decentralized exchanges, atomic swap protocols, and collaborative transaction platforms that operate securely and efficiently. By standardizing the process of creating, sharing, and signing transactions involving multiple parties, PSBTs facilitate complex financial operations that were previously difficult to implement securely on the Bitcoin network.

1. Order-Book Based Exchange in Ordinal Marketplace

PSBT is used by ordinal marketplaces to facilitate trading Ordinal NFTs. An order transaction utilizing PSBT solutions can be created by a buyer or seller. The creator sends the PSBT file to other participants. After the PSBT file is signed by all participants, it can be finalized and broadcasted to the Bitcoin network.

Why is PSBT Essential in Ordinal Marketplaces?

Ordinals are unique digital assets inscribed on individual satoshis, requiring precise control over transaction inputs and outputs to preserve their integrity. PSBT enables multiple parties, such as buyers and sellers, to collaboratively construct and sign transactions without exposing private keys or compromising security.

Other options, like raw transactions or custom protocols, are not suitable because they lack necessary features and security guarantees. Raw transactions do not support partial signing, which means there is always a single transaction creator responsible for constructing the entire transaction. This approach requires users to manually validate transactions, increasing the risk of errors and security vulnerabilities. For custom protocols, users might be forced to use specific wallets provided by the marketplace. This requirement can limit accessibility because users cannot use their preferred wallets. It also reduces interoperability, as these marketplace-specific wallets may not be compatible with other platforms or services. Besides, some marketplaces might employ centralized escrow services to facilitate trades, introducing counterparty risk, as users must trust the escrow agent to handle funds appropriately.

The following is a typical PSBT workflow for marketplaces trading, illustrated with an example based on msigner, where a selling order can be created through the following steps:

  1. The seller signs a PSBT using the SIGHASH_SINGLE | ANYONECANPAY.

PSBT Inputs:

PSBT Inputs

PSBT Outputs:

PSBT Outputs

  1. The buyer signs a full PSBT using the SIGHASH_DEFAULT with all the information available to the buyer. The buyer should select payment UTXO and prevent spending UTXO that contains inscription.

Inputs:

Inputs

Outputs:

Outputs 1

Outputs 2

  1. The exchange, which performs the combiner role in the PSBT workflow, performs the following:
  • Verifies seller signature
  • Verifies buyer signature
  • Merges seller and buyer signatures
  • Finalizes and run mempool acceptance test
  • Broadcasts the transaction

2. Collaborative Transactions

PSBTs simplify the workflow in multisig setups by standardizing the signing process. They enable multiple parties to contribute inputs and agree on outputs.

  • Join funding: Join funding is a process where multiple participants come together to pool their resources for collective payment. This can be particularly useful for shared investments, joint purchases, or group donations. The mechanism behind this trustless collaborative effort is enabled through the use of PSBTs. Users create a PSBT with inputs from the UTXOs of all parties involved. Each participant then reviews the transaction to ensure that it aligns with their intentions. Once satisfied, they sign the transaction with their private keys. The PSBT can only be finalized and become a valid transaction ready for broadcast once all participants have signed it.
  • Shared UTXO Management: Shared UTXO management refers to the collaborative control and management of UTXOs by multiple parties, commonly used in business or organizational contexts. PSBTs facilitate this by allowing funds to be managed with multiple approvals, enhancing security and oversight.

3. Hash Time-Locked Contracts (HTLCs) and Cross Chain Swaps

PSBTs are crucial for enabling atomic swaps and trustless exchanges between different blockchains. By constructing transactions that are only valid under specific conditions, PSBTs facilitate cross-chain swaps without intermediaries. In this process, Hash Time-Locked Contracts (HTLCs) are often used alongside PSBTs to enforce atomicity in the exchange. HTLCs employ cryptographic hash functions and time-based conditions to guarantee a fair transaction. If the required conditions are not satisfied within a predetermined timeframe, the transaction is automatically canceled. This mechanism ensures that both parties either complete the exchange or revert to their original state without any loss. Integrating PSBTs with HTLCs allows users to perform secure cross-chain swaps between Bitcoin and other blockchains, enabling asset exchanges without relying on centralized platforms or trusted third parties.

4. Transaction Batching and Fee Optimization

PSBTs’ unique capabilities enable each input and output in a batched transaction to be signed separately. The use of PSBTs in transaction batching helps reduce transaction fees. By combining multiple transactions into one, users not only save on fees, but also help alleviate congestion on the Bitcoin network.

5. Offline Signing and Hardware Wallets Integration

PSBTs provide a safer and more efficient workflow for offline signing by standardizing how incomplete transactions are represented. Before PSBT, users had to manually handle raw transaction data and perform input and output validations themselves. In multi-party transactions, one participant had to assemble the complete transaction before others could verify it. This approach relied on a trusted third party or required users to carefully verify the transaction. With PSBT, each party can independently add their own inputs and outputs and verify all components without needing an internet connection. This keeps the signing and verification processes offline, which is a significant security benefit for hardware wallets. The standardized PSBT format also ensures compatibility across various hardware wallets, allowing them to interpret and sign transactions seamlessly—even on air-gapped devices.

Security Concerns and Common Misuses

Despite the advantages offered by PSBTs, they may not be a familiar topic for newcomers eager to launch innovative Bitcoin DeFi solutions. Improper usage can lead to significant security vulnerabilities, resulting in breaches and financial losses.

In the following section, we present case studies of real-world incidents involving PSBT misuse. These examples aim to provide developers with essential insights into safeguarding assets and ensuring the integrity of transactions within the Bitcoin DeFi ecosystem.

1. Improper Use of Sighash Flags

The sighash flag dictates the immutability of certain parts of a transaction once it's signed. Using the sighash flag incorrectly can leave a transaction vulnerable to alterations by hackers. Below is an explanation of different sighash flags and their implications.

  • SIGHASH_ALL (0x01): Signs all inputs and outputs; provides the highest security by preventing modifications.
  • SIGHASH_NONE (0x02): Signs all inputs but none of the outputs; allows outputs to be changed.
  • SIGHASH_SINGLE (0x03): Signs all inputs and only one corresponding output; risky if outputs are reordered.
  • SIGHASH_ANYONECANPAY (0x80): Modifies the above flags to only sign the current input; other inputs can be added.

Real-World Example of Sighash Flag Misuse: Atomicals Market Incident

On November 15, 2023, Atomicals Market experienced a “zero-yuan purchase” incident. Sellers placed an order to sell $ATOM on the market, but it was purchased by a hacker at zero cost. The Atomicals Protocol revealed that the root cause was the usage of the SIGHASH_NONE | ANYONECANPAY sighash by Atomicals Market, leading to the theft of user funds.

The SIGHASH_NONE | ANYONECANPAY flag specifies that only the signer's input is signed and other inputs can be added, while leaving the outputs changeable. This could potentially be exploited by a hacker to alter the destination of the funds after the input has been signed. It's important for users and developers to understand and correctly implement sighash flags to avoid misuses and asset loss.

The seller’s order should be signed with SIGHASH_SINGLE | ANYONECANPAY instead.

Flag

The SIGHASH_NONE | ANYONECANPAY flag indicates that the seller’s input is signed, leaving the transaction output mutable. If the hacker manages to obtain the seller’s signature and rebuild the transaction with the output value set to zero, signing and broadcasting the transaction will result in the seller’s token being sold with no payment.

Steps

Other Potential Attack Vectors

  • Output Modification: If outputs are not properly signed, attackers can alter them to redirect funds to themselves or change payment amounts. An example of this would be if a multisig wallet implementation incorrectly used SIGHASH_SINGLE without ensuring that the output index matched the input index. This oversight would allow attackers to manipulate outputs after partial signing.
  • Replay Attacks: An attacker could resubmit a valid PSBT in a different context or at a different time, exploiting improper sighash usage or lack of transaction uniqueness.

Best Practices for Secure SigHash Flag Usage

  • Default to SIGHASH_ALL: Ensures that all transaction details are immutable after signing.
  • Avoid Complex Sighash Combinations: Unless necessary and fully understood, avoid using flags like SIGHASH_ANYONECANPAY in combination with other sighash flags.
  • Thorough Verification: Before signing, verify all transaction details, including inputs, outputs, and scripts.

2. Poor UTXO Selection

Effective UTXO selection is critical for both the security and efficiency of PSBT transactions. Poor UTXO selection can expose users to privacy risks, unnecessarily increase transaction fees, and potentially lead to transaction failure.

When constructing a transaction, the wallet selects UTXOs to fund the transaction outputs and fees. The strategy used in selecting these UTXOs can have significant implications:

  • Privacy Concerns: Combining UTXOs from different addresses can link those addresses together, reducing user anonymity.
  • Fee Optimization: Selecting smaller UTXOs may require including more inputs, increasing the transaction size and fees.
  • Dust Inputs: Including very small UTXOs (dust) can bloat the transaction size without adding significant value, leading to inefficient transactions.

Best Practices for UTXO Selection

To mitigate risks associated with poor UTXO selection, the following best practices should be adopted:

  • Optimize UTXO Management: Prefer using larger UTXOs to minimize the number of inputs, reducing transaction size and fees. Incorporate algorithms that automatically balance privacy and fee efficiency.
  • Dust Threshold Awareness: Ensure change outputs are above the dust threshold to keep them usable in future transactions.

3. Accidental Asset Burn

Proper handling of ordinals and other tokenized assets is essential to prevent accidental losses or burning. Ordinals, Runes, ARC-20 tokens, and similar protocols enable the representation of non-fungible tokens (NFTs) and other digital assets directly on the Bitcoin blockchain by associating data with individual satoshis. Mismanagement of these assets in PSBT handling can lead to irreversible loss.

Best Practices for Preventing Burning of Ordinal-Based Assets

  • UTXO Management: Avoid Mixing Ordinals with Regular UTXOs. Keep ordinal-containing UTXOs separate from regular funds. Use separate code logic for each individual Ordinal asset.
  • Handle Dust Thresholds Carefully: Below the minimum output value (typically 546 satoshis for standard P2PKH outputs), outputs are considered uneconomical to spend and may be rejected by the network. Developers should ensure that outputs containing ordinals are above the dust threshold to remain valid and spendable. If an ordinal is included in an output below the dust threshold, it may become effectively "burnt," as it cannot be spent or may be ignored by nodes.
  • Explicit Output Definitions: Ensure that ordinals are assigned to specific outputs and not included in change outputs inadvertently.

UTXO Management Strategies for User

  • Dedicated Wallets for Different Ordinal Assets: Use separate wallets for ordinal assets to prevent mixing with regular transactions. By isolating ordinals in dedicated wallets, you can reduce the risk of accidentally mixing them with regular UTXOs.
  • Labeling and Tracking: Maintain detailed records of UTXOs containing ordinals, including transaction IDs, addresses, and associated metadata.
  • Verification Before Signing: Before signing a PSBT, double-check all transaction outputs to confirm that ordinals are directed correctly.

PSBT Security Checklist

To systematically identify potential security issues in PSBT implementations during audits, we have developed a comprehensive security checklist based on our past experience auditing PSBT projects. This checklist also serves as a practical guide for developers, providing essential insights and best practices for securely utilizing PSBT in Bitcoin DeFi projects.

1. PSBT Input

  • Filter Out Dust UTXOs: Exclude UTXOs below the dust threshold to avoid unspendable outputs and prevent accidental burning of assets. This is especially important for ordinals and tokenized assets.
  • Total UTXO Value Match: Verify that the sum of input values covers the total of the outputs and transaction fees to prevent underfunded transactions that could fail or be rejected by the network.
  • Avoid Mixing Ordinals with Regular UTXOs: Keep UTXOs containing ordinals or tokenized assets separate from regular UTXOs to prevent accidental transfers or losses.
  • Include tapInternalKey for Taproot Wallets: Incorporate the tapInternalKey when dealing with Taproot addresses to ensure proper spending conditions and enhance privacy features provided by Taproot.
  • Contextual UTXO Strategy: Select UTXOs based on the specific context, prioritizing factors such as privacy, fee optimization, and the avoidance of unnecessarily linking addresses.
  • Check Transaction Version: Employ transaction version 2 when utilizing features like OP_CHECKSEQUENCEVERIFY and other advanced scripting capabilities that require it.

2. PSBT Output

  • Refund Excess Satoshis: Implement change outputs to return surplus funds to the sender, ensuring no value is inadvertently left unclaimed.
  • Change Amount Above Dust Threshold: Ensure that change outputs are above the dust threshold to keep them valid and spendable, preventing the creation of unspendable "dust" outputs.

3. Fee Management

  • Accurate Fee Estimation: Utilize real-time network data/API, and consider transaction size and complexity to calculate accurate fees, ensuring timely confirmation without overpaying.
  • Mempool Acceptance Check: Verify that the finalized transaction meets the network's acceptance criteria, such as standardness rules and minimum fee requirements.

4. PSBT Signature

  • Default to SIGHASH_ALL: Use SIGHASH_ALL by default to provide the highest level of transaction integrity by signing all inputs and outputs, preventing unauthorized modifications.
  • Caution with Sighash Changes: Fully understand the security implications before deviating from the default sighash flags. Avoid complex combinations like SIGHASH_ANYONECANPAY unless absolutely necessary and correctly implemented.
  • Verify Partial Signatures: Confirm that each partial signature correctly signs the corresponding input. Identify and address any duplicate or conflicting signatures for the same input.

5. Finalize the PSBT Correctly

  • Complete All Fields: Verify that all required PSBT fields are populated, including inputs, outputs, and global transaction data before finalization.
  • No Missing Information: Check that no required data (e.g., redeem scripts, witness scripts) is missing from the PSBT.
  • Lock the PSBT: Once all signatures are merged and validated, finalize the PSBT to prevent further modifications.

Final Words

Partially Signed Bitcoin Transactions (PSBT) have been widely used in the Bitcoin ecosystem to enable secure, complex, and collaborative transaction workflows essential for DeFi applications. However, improper usage of PSBTs can introduce serious security vulnerabilities, including transaction malleability and accidental loss of assets.

At CertiK, we leverage our deep technical expertise in PSBT security to help projects tackle the intricate challenges of secure PSBT implementation. Through audits and the development of comprehensive best practices, we equip developers and organizations with the critical knowledge to utilize PSBTs securely and efficiently.

For an in-depth audit of your protocol code or to consult with our team of experienced auditors and security experts, please get in touch with us at CertiK.com.