Glossary

Replay Attack

Reusing a valid transaction or signature on a different chain or context where it wasn't intended.

Key Takeaways

  • A replay attack reuses a valid transaction on a different chain or context: when a blockchain forks into two networks, transactions signed on one chain can be broadcast on the other because both chains share the same history and script rules.
  • Replay protection mechanisms prevent cross-chain theft: techniques like SIGHASH_FORKID, unique address formats, and chain-specific signature schemes ensure transactions are only valid on their intended network.
  • Lightning and layer-2 protocols have built-in protection: channel-specific keys, HTLCs, and unique commitment structures make replay attacks impractical on off-chain networks like Lightning and Spark.

What Is a Replay Attack?

A replay attack occurs when a valid transaction or data transmission is maliciously or fraudulently repeated on a network where it was not intended. In blockchain contexts, this most commonly happens after a chain fork: a single signed transaction can be valid on both the original chain and the new fork, allowing anyone to "replay" it on the second network and move funds the signer never authorized on that chain.

Think of it like a signed check that gets photocopied. The original check is valid at your bank, but the copy could be cashed at a different bank that recognizes the same signature. In crypto, the "banks" are two forked blockchains, and the "check" is a signed transaction that both chains accept because they share identical UTXO sets and validation rules up to the fork point.

Replay attacks became a major concern during high-profile forks like Bitcoin Cash (2017) and Ethereum Classic (2016). Without explicit replay protection, users moving coins on one chain risked having the same transaction executed on the other, effectively doubling or losing funds depending on the attacker's intent.

How It Works

To understand replay attacks, consider what happens when a blockchain forks. At the fork block, both chains share an identical history: the same transactions, the same UTXOs, and the same private keys control the same balances on both networks. Any transaction signed for one chain is structurally valid on the other.

The Fork Replay Scenario

  1. Chain A forks into Chain A and Chain B at block height N. All UTXOs that existed before block N exist on both chains.
  2. Alice signs a transaction on Chain A, spending a pre-fork UTXO to send 1 BTC to Bob.
  3. An attacker (or Bob himself) copies that signed transaction and broadcasts it on Chain B.
  4. Chain B validates the transaction because the UTXO exists there too, the signature is valid, and the script conditions are met.
  5. Alice has now sent 1 BTC on both chains, though she only intended to transact on Chain A.

The attack works because Bitcoin transactions are self-contained: a signed transaction includes the input references, output scripts, and signatures, but nothing that binds it to a specific chain. Both chains interpret the same bytes identically.

Transaction Structure and Vulnerability

A standard Bitcoin transaction contains inputs referencing previous UTXOs by their transaction ID and output index, plus signatures proving authorization. The signature covers a hash of the transaction data using a SIGHASH flag:

// Simplified Bitcoin transaction structure
{
  "version": 2,
  "inputs": [
    {
      "txid": "abc123...",    // References a UTXO
      "vout": 0,              // Output index
      "scriptSig": "3045..." // Signature + public key
    }
  ],
  "outputs": [
    {
      "value": 100000000,           // 1 BTC in satoshis
      "scriptPubKey": "OP_DUP ..."  // Recipient script
    }
  ]
}

Nothing in this structure identifies which chain it belongs to. If both chains have the referenced UTXO (txid abc123... at index 0), both will accept the transaction. This is the fundamental vulnerability that replay attacks exploit.

Replay Protection Mechanisms

Several techniques have been developed to prevent replay attacks across forked chains. These mechanisms modify the transaction format or signing process so that transactions on one chain are invalid on the other.

SIGHASH_FORKID

Bitcoin Cash introduced SIGHASH_FORKID as a replay protection mechanism during its 2017 fork from Bitcoin. This approach modifies the signature hash algorithm by including a fork identifier in the data being signed:

// Standard Bitcoin SIGHASH types
SIGHASH_ALL        = 0x01  // Sign all inputs and outputs
SIGHASH_NONE       = 0x02  // Sign inputs only
SIGHASH_SINGLE     = 0x03  // Sign inputs + matching output

// Bitcoin Cash added SIGHASH_FORKID
SIGHASH_FORKID     = 0x40  // OR'd with the above types
SIGHASH_ALL | SIGHASH_FORKID = 0x41

// The fork ID is mixed into the signature hash:
// sighash = SHA256(SHA256(serialize(tx, hashType | (forkId << 8))))
// Bitcoin Cash uses forkId = 0, but the FORKID flag itself
// changes the serialization format, making signatures
// invalid on the original Bitcoin chain.

Because the signature covers different data on each chain, a transaction signed with SIGHASH_FORKID on Bitcoin Cash produces an invalid signature on Bitcoin, and vice versa. This provides strong, protocol-level replay protection without requiring user action.

Different Address Formats

Some forks adopt distinct address formats to reduce accidental cross-chain transactions. Bitcoin Cash moved to CashAddr format (starting with bitcoincash:) while Bitcoin uses bech32 addresses (starting with bc1) for SegWit outputs. While address format differences help prevent user error, they are not true replay protection: the underlying scripts may still be compatible across chains.

OP_RETURN Tagging

Another approach uses OP_RETURN outputs to embed chain-specific identifiers in transactions. Nodes on one chain can reject transactions containing another chain's tag. This is less elegant than SIGHASH-based protection but can be implemented without consensus changes.

Coin Splitting

Users can manually protect themselves by "splitting" their coins after a fork. This involves creating a transaction that spends a post-fork coinbase output (which only exists on one chain) alongside pre-fork UTXOs. The resulting transaction is inherently unreplayable because the coinbase input does not exist on the other chain:

  1. Obtain a small amount of post-fork coins (from a faucet, exchange, or miner) that only exist on one chain
  2. Create a transaction that spends both the post-fork coins and your pre-fork UTXOs
  3. The combined transaction references an input that does not exist on the other chain, making it invalid there
  4. Your outputs are now "split" and safe from replay on both chains

Lightning Network Protection

The Lightning Network is inherently resistant to replay attacks due to its channel-based architecture. Several design choices make replaying Lightning transactions impractical or meaningless.

Channel-Specific Keys and Commitments

Each Lightning channel uses unique per-channel keys derived during the funding process. Commitment transactions reference the specific funding output (a 2-of-2 multisig UTXO) that exists only on one chain. Even after a fork, the funding transaction's txid differs on each chain once any channel operation occurs post-fork, breaking the replay path.

Additionally, each commitment transaction includes a revocation key mechanism tied to the channel's state number. Replaying an old commitment transaction on any chain triggers the justice transaction penalty, allowing the counterparty to claim all channel funds. This makes replay not just ineffective but actively punished.

HTLC Hash Binding

HTLCs used for Lightning payments are bound to specific payment hashes and preimages. Replaying an HTLC on a different chain would require the same preimage, but the routing paths, channel states, and timelocks differ across chains. An attacker cannot profitably replay a payment because settling it requires knowledge of the preimage, which is only revealed through the intended payment route.

Smart Contract Replay Vulnerabilities

Replay attacks extend beyond simple value transfers. On platforms supporting smart contracts, additional attack surfaces emerge:

Signature Replay in Contracts

Smart contracts that verify signatures for authorization (such as multisig wallets or meta-transaction relayers) can be vulnerable to signature replay. If a contract accepts a signed message authorizing an action but does not track which signatures have been used, an attacker can submit the same signature multiple times:

// Vulnerable: no nonce or replay protection
function withdraw(uint amount, bytes signature) {
    require(verify(owner, hash(amount), signature));
    transfer(msg.sender, amount);
}

// Protected: includes nonce to prevent replay
mapping(uint => bool) usedNonces;

function withdraw(uint amount, uint nonce, bytes signature) {
    require(!usedNonces[nonce]);
    require(verify(owner, hash(amount, nonce), signature));
    usedNonces[nonce] = true;
    transfer(msg.sender, amount);
}

The protected version includes a nonce in the signed data and tracks which nonces have been consumed. This prevents the same signature from being accepted twice.

Cross-Chain Contract Replay

When a smart contract platform forks, deployed contracts exist on both chains with identical code and state. Transactions interacting with these contracts (function calls, token transfers) can be replayed just like simple transfers. EIP-155 addressed this for Ethereum by including the chain ID in the transaction signature hash, similar in concept to SIGHASH_FORKID:

// EIP-155 signature includes chain ID
// Pre-EIP-155: sign(hash(nonce, gasPrice, gas, to, value, data))
// Post-EIP-155: sign(hash(nonce, gasPrice, gas, to, value, data,
//                         chainId, 0, 0))

Sidechain and Layer-2 Considerations

Sidechains and layer-2 protocols must consider replay protection in their bridge and peg mechanisms. When assets move between a parent chain and a sidechain, the locking and unlocking transactions must be bound to specific chains to prevent an attacker from replaying a withdrawal proof on the wrong network.

Modern layer-2 designs like Spark address this through cryptographic binding between on-chain and off-chain states. Spark uses Schnorr-based threshold signatures with operator sets that are unique to the Spark network, making transaction data non-replayable on Bitcoin's base layer. The cooperative and unilateral exit mechanisms are tied to specific on-chain UTXOs, preventing cross-context replay. For a deeper comparison of layer-2 approaches and their security models, see the Bitcoin layer-2 comparison.

Use Cases and Relevance

  • Fork protection: during contentious forks like Bitcoin/Bitcoin Cash or Ethereum/Ethereum Classic, replay protection determines whether users can safely transact on one chain without affecting the other
  • Exchange security: exchanges must implement replay-aware deposit processing after forks, crediting deposits on the correct chain and rejecting replayed transactions
  • Wallet software: HD wallets and signing devices need chain-aware signing to prevent users from accidentally creating replayable transactions using shared derivation paths
  • Smart contract auditing: contracts handling signatures or cross-chain messages must be audited for replay vulnerabilities, which remain one of the most common smart contract bugs
  • Protocol design: new protocols and sidechains must incorporate replay protection from the start, as retrofitting it after launch is significantly harder

Risks and Considerations

Unprotected Forks

Not all forks implement replay protection. Some intentionally omit it, expecting users to split coins manually. This places the burden on users who may not understand the risk, leading to accidental fund loss. Before transacting after any fork, verify whether the new chain includes protocol-level replay protection.

Incomplete Protection

Address format changes alone do not constitute replay protection. A user who manually constructs a transaction using raw scripts can bypass address-level differences. True replay protection must operate at the signature or transaction serialization level to be effective.

Legacy Transaction Formats

Some replay protection mechanisms only apply to new transaction formats. Legacy transactions created with older software may remain replayable even on chains that support protection for newer formats. Users should ensure their wallet software produces transactions using the chain's recommended format, such as SegWit or Taproot outputs on Bitcoin.

Time-Sensitive Exposure

The replay window is most dangerous immediately after a fork, when both chains share identical UTXO sets. As post-fork transactions create chain-specific UTXOs, the attack surface naturally shrinks. However, dormant pre-fork UTXOs remain vulnerable indefinitely until they are spent on both chains or split using a chain-specific input.

This glossary entry is for informational purposes only and does not constitute financial or investment advice. Always do your own research before using any protocol or technology.