Skip to content

Verify frozen wallet fingerprint fixtures against real Bitcoin Core in CI #9

Description

@BenWestgate

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

  1. 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.
  2. 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.
  3. 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.

Activity

  1. BenWestgate commented on Sep 25, 2026

    @BenWestgate
    OwnerAuthor

    Release monitor update (2026-09-25): the official Bitcoin Core 32.0 directory currently exposes only test.rc2/ (https://bitcoincore.org/bin/bitcoin-core-32.0/), while the public download page still lists 31.1 as the latest stable release. PR #51 therefore remains correctly pinned to 32.0rc2 for now. If a later 32.0 RC or final appears before v1 qualification, update the pinned archive/hash and rerun the Core fixture harness before release.

  2. added
    area: ciContinuous integration and workflow configuration.
    area: wallet/coreWallet integration and Bitcoin Core boundaries.
    on Sep 25, 2026
  3. BenWestgate commented on Sep 27, 2026

    @BenWestgate
    OwnerAuthor

    Release monitor refresh (2026-09-26): upstream still has only v32.0rc1 and v32.0rc2; there is no final v32.0 tag. #51 remains correctly pinned to rc2, and its path-filtered PR workflow is now green against that exact binary. Repin/re-run if a newer v32 candidate appears before release.

  4. added 6 commits that reference this issue on Sep 29, 2026
    1038dfb
    768bcba
    75d3833
    664a668
    fc82de3
    e5b957a
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: ciContinuous integration and workflow configuration.area: wallet/coreWallet integration and Bitcoin Core boundaries.enhancementNew feature or requestgate: adversarial reviewResolve, merge, or explicitly defer before the next full adversarial review.

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions