Glossary / Developer reference
Descriptor checksum
- What is a descriptor checksum?
- A descriptor checksum is the eight character code after the hash mark in an output descriptor, a BCH code that catches typing and copy errors before a wallet imports the wrong keys.
Specified in BIP-380.
The code sits at the end of a descriptor, after a single hash mark, in the same 32 character alphabet as bech32. BIP-380 guarantees that any error touching three symbols or fewer is caught in a descriptor up to 49,154 characters, and a random error goes undetected roughly once in a trillion. Without that check, one wrong character in a multisig backup leaves you watching addresses that hold nothing.
How it works
The descriptor checksum is a BCH code computed over the descriptor text rather than a hash of it, and that is what buys the error guarantees. BIP-380 fixes a 95 character input alphabet and splits it into three groups, putting the characters with no protection of their own into the first: digits, brackets, slashes, the wildcard asterisk and lowercase a to h, where hex encoded keys and derivation paths land. The spec's prose calls that three groups of 32, though its reference code runs 32, 32 and 31.
Each character contributes one symbol, its position inside its group, and after every third symbol a fourth is inserted carrying the three group numbers combined, so three characters expand to four symbols. A change that only moves a character within its group, or only changes which group it sits in, disturbs exactly one symbol. That is why a case error counts as exactly one symbol error, and why a single capitalized character is always caught.
The guarantees ladder down as the string grows. One symbol error is always detected; two or three are always detected up to 49,154 characters, four up to 507 characters, and five up to 77 characters, with the code tuned to minimize undetected five symbol errors out to 387. Bitcoin Core's descriptors.md quotes the four error bound as 501 characters rather than 507 and puts the residual risk at roughly one in a trillion. The single key descriptor in that document runs 140 characters, inside every bound; its 2-of-3 multipath example runs 439, past the five symbol window and inside the four symbol one.
Extended keys already defend themselves. BIP-380 notes that an xpub reaches outside the first group and carries a checksum mechanism of its own, so a key expression ends up covered twice.
Where you see it
BIP-380's test vectors are the shortest way to watch a descriptor checksum do its job. The valid string is raw(deadbeef)#89f8spxm, and the near misses the spec rejects include no checksum, a bare hash mark, a nine character checksum, a seven character checksum, raw(deedbeef) with the old checksum untouched, and a payload using a character outside the input alphabet.
Bitcoin Core prints the checksum on the way out and demands it on the way in. Every RPC that returns a descriptor attaches the eight characters, while only some require one on input, among them deriveaddresses and importdescriptors. For a line you typed or edited by hand, getdescriptorinfo returns the correct checksum.
The checksum stays optional for parsing, and BIP-380 permits applications to reject descriptors without one. Expect it when you move a multisig arrangement between a coordinator, a spare machine and a sheet of paper: those eight characters are the only part that confirms the rest arrived intact.
Descriptor checksum vs bech32
A bech32 checksum protects an address and a descriptor checksum protects a wallet definition, and the sizes involved explain the design difference. BIP-173 caps a bech32 string at 90 characters and spends the last six characters of the data part on the checksum, over the same 32 symbol alphabet. A descriptor carries no such cap and has to cover brackets, commas, quotes and spaces too, so BIP-380 expands the text into position symbols with an interleaved group symbol and spends eight.
Both write that result in the same alphabet, qpzry9x8gf2tvdw0s3jn54khce6mua7l, which is where the confusion starts. What fails differs. A bech32 address that fails its checksum cannot be paid to; a descriptor that fails its checksum is a wallet you cannot restore.