Skip to main content
6 of 7
added 72 characters in body
Pieter Wuille
  • 106.9k
  • 9
  • 195
  • 311

Satoshi standardized on using double-SHA256 for 32-byte hashes, and SHA256+RIPEMD160 (each once) for 20-byte hashes, presumably because of (likely misguided) concern about certain attacks (like length extension attacks, which only apply when hashing secret data), and then used those everywhere:

  • P2PKH scriptPubKeys use SHA256+RIPEMD160 of the public key
  • P2PKH address checksums use truncated double-SHA256 of the payload
  • Transaction hashes (txids) use double-SHA256
  • Block hashes (and equivalently, proof of work) use double-SHA256
  • The transaction Merkle tree uses double-SHA256 to compute the next layer.
  • P2P network packets use truncated double-SHA256 of the payload as checksum.
  • The message being ECDSA signed to authorize transactions (sighash) is the double-SHA256 hash of a variant of the serialization of a transaction.

To the best of my knowledge, none of these use cases actually benefit at all from double hashing.

Later additions at first copied this practice, presumably because the rationale wasn't that well understood, and continuing with the same approach was easiest to convince people was safe:

  • P2SH addresses (BIP13) use truncated double-SHA256 as a checksum.
  • P2SH scriptPubKeys (BIP16) use SHA256+RIPEMD160 of the script.
  • WIF ("wallet import format") private keys also use truncated double-SHA256 as a checksum.
  • The same is true for the extended key xpub and xprv formats (BIP32). The derivation algorithm for keys there uses (single) SHA-512, however.
  • P2WPKH scriptPubKeys use SHA256+RIPEMD160 hashes of the public key (BIP141)
  • Witness transaction identifiers (wtxids) use double-SHA256 like normal txids do (BIP141).
  • The witness Merkle tree uses the same double-SHA256 based hashing as the transaction tree (BIP141).
  • The message being ECDSA signed for authorizing witness v0 scripts is the double-SHA256 hash of a different message scheme (BIP143).

In more modern additions, it is no longer used:

  • P2WSH scriptPubKeys use a single SHA256 hash of the public key (BIP141).
  • Bech32 and Bech32m address encoding (used for native P2WPKH, P2WSH, and soon, P2TR) addresses use a checksum based on error correction codes, not hashing (BIP173 and BIP350).
  • The upcoming taproot softfork will introduce P2TR scriptPubKeys, which combine public keys and scripts, in a scheme which involves multiple hashing steps, but they are all single-SHA256 (with a tag prefixed to them to guarantee uniquenesss). The same is true for the message being (Schnorr) signed, and the hash inside the signature algorithm. (BIP340, BIP341, BIP342).

In addition, various places where no cryptographically-sized hash is needed have been using other hash functions too:

  • In the (now deprecated) server-side Bloom filtering protocol, MurmurHash3 was used to determine filter positions (BIP37).
  • In client-side compact block filtering, SipHash-2-4 is used to determine filter positions (BIP158).
  • In the compact block P2P protocol extension, SipHash-2-4 is used to generate short (48-bit) transaction identifiers (BIP152).

Disclaimer: I'm a co-author of several proposals mentioned here, and may have forgotten other extensions.

Pieter Wuille
  • 106.9k
  • 9
  • 195
  • 311