Problem
Wallet fingerprint fixtures are now frozen constants that no automated check verifies.
tools/_wallet_test_vectors.py holds nine BIP32 master fingerprints that the test suite asserts against: three for BIP93 vector seeds, used by the CLI display and correction paths, and six arbitrary fixtures covering each BIP93 seed length. tools/bitcoin_core_regtest.py contains the loop that checks every entry against a real Bitcoin Core node, but no workflow invokes it. The CI matrix runs pytest, mypy, Ruff, tools/differential_correction.py --verify, the package build, and tools/verify_wheel_environment.py — the regtest harness is not among them.
Before #7, tools/differential_wallet.py ran in CI and cross-checked wallet derivation against an independent pure-Python BIP32 implementation. #7 removed that tool, tools/_wallet_reference.py, and requirements/test-wallet-dependencies.txt in order to drop the bip32/coincurve dependencies from the test path. That was the intent of the PR and is not in dispute, but it means the only remaining automated check on these values is the test suite asserting them against the same table that defines them.
The failure this permits is silent. core_fingerprint() raises for a seed with no fixture, so a missing entry is caught, but a wrong frozen value is self-consistent: the table and the assertions agree with each other and CI stays green. The same applies if a future change to BitcoinCore.fingerprint_seed or _master_xprv_from_seed alters the derivation — the tests compare against frozen bytes, not against Core.
All nine entries were verified by hand against a real node at c58b5ff and matched exactly, so the values are correct today. The gap is drift from here on.
Constraint
BitcoinCore.connect() requires version >= 320000, so the harness needs a Bitcoin Core v32 or newer binary. That is the reason it is not simply another run: line: a CI job has to obtain Core first, which is slower than the current matrix and adds a download or build step to every run.
The derivation path itself is narrower than the connect gate suggests. fingerprint_seed computes the master xprv in pure Python and then uses only getdescriptorinfo, deriveaddresses and validateaddress, all of which are stable well below v32.
Options
- Add a scheduled or
workflow_dispatch job on ubuntu only that fetches a pinned Core release and runs tools/bitcoin_core_regtest.py. Keeps the per-PR matrix fast while bounding drift to the schedule interval.
- Add a fixtures-only verification mode that checks
CORE_FINGERPRINTS without exercising the full wallet import flow, and gate it on the narrower RPC set rather than on BitcoinCore.connect's v32 requirement.
- Run the harness on pull requests that touch
tools/_wallet_test_vectors.py, src/codex32/_bip32.py or src/codex32/_bitcoin_core.py, using a path filter.
Option 1 is the smallest change that closes the drift window. Option 2 is worth pairing with it, since verifying the fingerprint table does not need a wallet import and could then run against any reasonably recent Core.
Acceptance criteria
- Some automated job verifies every
CORE_FINGERPRINTS entry against a real Bitcoin Core node.
- The job fails when a frozen fingerprint stops matching Core, rather than passing on table-versus-assertion agreement.
- The Bitcoin Core version used is pinned and recorded, so a change in that version is a deliberate edit.
- Adding a fixture without a verified fingerprint fails, rather than only failing at the point of use.
- The per-PR matrix does not become materially slower, or the check runs on a schedule or path filter instead.
Relation to #5
#5 proposes running this same harness as part of a release gate, and its description of current CI predates #7 — it lists differential wallet verification as a step that no longer exists.
The two are complementary rather than duplicate. #5 asks that a release not ship without integration qualification; this issue asks that everyday CI notice when a frozen fingerprint stops matching Core, which needs to hold between releases. Closing #5 alone would leave the fixtures unverified on the main branch until release time.
Problem
Wallet fingerprint fixtures are now frozen constants that no automated check verifies.
tools/_wallet_test_vectors.pyholds nine BIP32 master fingerprints that the test suite asserts against: three for BIP93 vector seeds, used by the CLI display and correction paths, and six arbitrary fixtures covering each BIP93 seed length.tools/bitcoin_core_regtest.pycontains the loop that checks every entry against a real Bitcoin Core node, but no workflow invokes it. The CI matrix runs pytest, mypy, Ruff,tools/differential_correction.py --verify, the package build, andtools/verify_wheel_environment.py— the regtest harness is not among them.Before #7,
tools/differential_wallet.pyran in CI and cross-checked wallet derivation against an independent pure-Python BIP32 implementation. #7 removed that tool,tools/_wallet_reference.py, andrequirements/test-wallet-dependencies.txtin order to drop thebip32/coincurvedependencies from the test path. That was the intent of the PR and is not in dispute, but it means the only remaining automated check on these values is the test suite asserting them against the same table that defines them.The failure this permits is silent.
core_fingerprint()raises for a seed with no fixture, so a missing entry is caught, but a wrong frozen value is self-consistent: the table and the assertions agree with each other and CI stays green. The same applies if a future change toBitcoinCore.fingerprint_seedor_master_xprv_from_seedalters the derivation — the tests compare against frozen bytes, not against Core.All nine entries were verified by hand against a real node at c58b5ff and matched exactly, so the values are correct today. The gap is drift from here on.
Constraint
BitcoinCore.connect()requiresversion >= 320000, so the harness needs a Bitcoin Core v32 or newer binary. That is the reason it is not simply anotherrun:line: a CI job has to obtain Core first, which is slower than the current matrix and adds a download or build step to every run.The derivation path itself is narrower than the connect gate suggests.
fingerprint_seedcomputes the master xprv in pure Python and then uses onlygetdescriptorinfo,deriveaddressesandvalidateaddress, all of which are stable well below v32.Options
workflow_dispatchjob on ubuntu only that fetches a pinned Core release and runstools/bitcoin_core_regtest.py. Keeps the per-PR matrix fast while bounding drift to the schedule interval.CORE_FINGERPRINTSwithout exercising the full wallet import flow, and gate it on the narrower RPC set rather than onBitcoinCore.connect's v32 requirement.tools/_wallet_test_vectors.py,src/codex32/_bip32.pyorsrc/codex32/_bitcoin_core.py, using a path filter.Option 1 is the smallest change that closes the drift window. Option 2 is worth pairing with it, since verifying the fingerprint table does not need a wallet import and could then run against any reasonably recent Core.
Acceptance criteria
CORE_FINGERPRINTSentry against a real Bitcoin Core node.Relation to #5
#5 proposes running this same harness as part of a release gate, and its description of current CI predates #7 — it lists differential wallet verification as a step that no longer exists.
The two are complementary rather than duplicate. #5 asks that a release not ship without integration qualification; this issue asks that everyday CI notice when a frozen fingerprint stops matching Core, which needs to hold between releases. Closing #5 alone would leave the fixtures unverified on the main branch until release time.