TECHNICAL_DOC // KEYS / CHECKSUM
CHECKSUM
A checksum is a short value derived from data used to detect transcription
or transmission errors. Bitcoin uses two different checksum schemes: a 4-byte
SHA256d truncation for Base58Check (legacy addresses, WIF, extended keys)
and a 30-bit BCH polynomial code for Bech32/Bech32m (SegWit addresses).
Both prevent funds from being sent to mistyped addresses.
CHECKSUM_PURPOSE
WHY BITCOIN ADDRESSES INCLUDE CHECKSUMS
A Bitcoin address is one-shot: there is no
"undo" once a transaction confirms.
Without a checksum:
Typo → tx broadcasts to invalid hash
→ funds locked permanently to provably-unspendable script
→ effectively burned
With a checksum:
Wallet decodes address, recomputes checksum
Mismatch → wallet rejects address before signing
→ typo caught at input time
Bitcoin uses two checksum families:
Base58Check (legacy):
4-byte truncation of SHA256(SHA256(payload))
~32 bits of error-detection power
Bech32 / Bech32m (SegWit):
30-bit BCH polynomial code
Mathematically guarantees detection of:
- any single error (100%)
- up to 4 errors (100%)
- any number of errors (1 - 2⁻³⁰ ≈ 99.9999999%)
BASE58CHECK CHECKSUM
Base58Check Verification Procedure
DECODE
When parsing a "1...", "3...", "5...", "K...", "L...", or "xpub..." string, the wallet recomputes the checksum and rejects the input if it does not match.
Input: Base58 string (e.g. "1A1zP1eP5QGefi2D...")
Step 1: Base58 decode → bytes
decoded = base58_decode(input) (25 bytes for P2PKH)
Step 2: Split
payload = decoded[:-4] (e.g. version + hash160)
expected = decoded[-4:] (last 4 bytes)
Step 3: Recompute
computed = SHA256(SHA256(payload))[0:4]
Step 4: Compare
if computed != expected:
raise InvalidChecksum
else:
accept payload
Bech32 BCH Verification
DECODE
Bech32 uses polynomial arithmetic over GF(32). The polymod of the entire decoded string (HRP + data + checksum) must equal a fixed constant.
Input: lowercase string with HRP, "1", and 5-bit chars
Step 1: Split at last "1"
hrp = "bc" (or "tb")
data_chars = "qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4"
Step 2: Convert chars to 5-bit values via alphabet
Step 3: Build full input
values = expand_hrp(hrp) + data_5bit_values
Step 4: Compute polymod
result = bech32_polymod(values)
Step 5: Verify constant
Bech32 (witness v0): result must equal 1
Bech32m (witness v1): result must equal 0x2bc830a3
Mismatch → invalid address.
Mixed case input → invalid (always lowercase).
TERMINOLOGY_INDEX
SHA256d
SHA256 applied twice. Bitcoin's standard hash. First 4 bytes used as Base58Check checksum.
BCH Code
Bose–Chaudhuri–Hocquenghem cyclic error-correcting code. Used in Bech32/Bech32m for guaranteed error detection.
Polymod
Polynomial modulo operation over GF(32) used to compute the Bech32 checksum.
Hamming Distance
Minimum number of character changes that produce a valid result. Bech32: ≥5. Higher → stronger detection.