WO-05 — Addresses and IDs

8 October 2026 · Branch wo-05-addresses from wo-14-grover.

Implemented

Added e46::addresses for single-owner and sorted k-of-n shared payloads and Bech32m addresses; txid, raw-only wtxid, block ID, and Rad ID derivation; and strict q-version decoding for the user-facing objects. Transaction hashes consume the exact serialized spans specified in §2g; transaction serialization is not implemented by this work order. Block ID rejects headers other than 120 bytes. Rad ID delegates to the existing WO-08 derivation. No frozen golden or other work order’s source was changed.

Owner decision 15 is resolved: wtxid is a raw 32-byte digest displayed as plain hex, never Bech32m encoded. e46wtx/te46wtx are reserved for possible future display and are unused. DECISIONS-NEEDED.md records the answer. Per owner direction, Claude’s §2a addition is now visible as an unstaged change in the shared worktree. The WO-05 staged set does not include or modify CHAIN-DESIGN.md. Separate unstaged MAPS edits and an untracked MAPS/DASHBOARD-BRIEF.md are also present in the shared worktree and were left out of this work order.

Evidence and checks

The new Python reference and frozen corpus are e46/golden/addresses_reference.py and e46/golden/wo05-golden.json. The corpus covers four single-owner keys, four k-of-n cases (including n=15 and unsorted input), transaction and witness hash boundaries, 120-byte headers, eight WO-08 Rad IDs, and all ten published §2a Bech32m examples. generate_wo05.py --check passes.

verify_wo05.py matched the C++ library to the independent Python reference on 1,649 comparisons: 1,200 deterministic fresh inputs, 379 seeded Bech32m parser mutations, curated vectors, and the published examples. The seed was 62025100805; there were zero mismatches. The decoder accepted the uniform-uppercase examples and rejected corrupt, malformed, wrong-network, wrong-version, and wrong-length inputs.

cmake --preset release                 PASS
cmake --build --preset release         PASS, -Wall -Wextra -Werror
ctest --preset release                 PASS, 19/19
cmake --preset sanitize                PASS
cmake --build --preset sanitize        PASS
ctest --preset sanitize                PASS, 19/19
ctest --preset release -R '^addresses_' PASS, 3/3 (after parser mutations)
ctest --preset sanitize -R '^addresses_' PASS, 3/3 (after parser mutations)

The fuzz preset configured and compiled addresses_fuzz.cpp, but linking the libFuzzer executable failed because this machine lacks /Library/Developer/CommandLineTools/usr/lib/clang/21/lib/darwin/libclang_rt.fuzzer_osx.a. No package or toolchain was installed. The sanitizer-backed, seeded C++ decoder mutation differential above ran instead; it does not claim a libFuzzer campaign.

No new decision remains Open. No push or merge was performed.