Skip to content
btclib-orgPublic

About

What a mnemonic of unknown scheme holds: its scheme, addresses, coins and forks

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

19 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

seed-scan

A command for somebody who holds a mnemonic and does not know what it is: which scheme it follows, which addresses it gave, which coins those addresses held, and whether a fork concerns them. It finds funds; the user's own wallet moves them.

PyPI version GitHub release development status license downloads supported Python versions implementation wheel

What is here

No release is out yet. seed-scan identify, seed-scan scan, seed-scan forks and seed-scan report are the first commands. btclib-org/.github#2203 records the design and tracks the first release. The command is to stay thin: what is general goes down to the packages it is to build on, bip39-slip39, bip32-descriptors, btclib-wallet and coin-addresses. A scheme or a coin they do not cover is to be reported as not checked, never passed over: the costly failure is a wrong "nothing found".

Identifying a mnemonic

seed-scan identify > bundle.json

It asks for the mnemonic, then for passphrases until an empty one, at hidden prompts, and for further shares where the words are one SLIP-0039 share. It writes the bundle to standard output and what it found to standard error. Where you know an address the mnemonic gave, --address followed by it has the command search for the address's path. seed_scan.bundle documents the bundle, and seed-scan identify --help the bounds of what it writes and searches.

Scanning a bundle

seed-scan scan bundle.json --server electrum.example.org:50002 \
    --node http://127.0.0.1:8545 > scan.json

It asks the Electrum server named, as host:port, which Bitcoin accounts of the bundle were used, and the Ethereum node named, by its URL, which Ethereum accounts were, and writes the scan result to standard output and what it found to standard error. Name either or both. Each learns every address it is asked about, so name your own: there is no default.

The Electrum connection is TLS, and the server's certificate is verified against the system's CA certificates, or against those of the file --cafile names, which is how a server with a self-signed certificate is reached. Before any address is asked, the server's genesis block and its block at a height Bitcoin Core pins are compared with Bitcoin's. SECURITY.md's Limitations, not vulnerabilities says which servers that refuses, and what it does not prove.

The node is an execution client's JSON-RPC, at an https URL, or an http one on a loopback address such as http://127.0.0.1:8545. --cafile is the Electrum server's alone: seed_scan.evm says what the node's certificate is verified against. An Ethereum address is used where it holds ether or has a nonce: token balances are not asked, so an address that only ever received tokens reads as unused.

A coin with no server or node named, and every coin but Bitcoin and Ethereum, is listed as not checked. seed_scan.scan documents the result, seed_scan.evm the node's requests, and seed-scan scan --help the bounds of the search.

Reading a fork of Bitcoin

seed-scan forks bundle.json --chain bitcoin-cash \
    --server bch.example.org:50002 > forks.json

Coins a key held on Bitcoin when a chain forked from it are on that chain too, at the same script, and the chain's own wallets may have used the key since. forks asks the Electrum server named, which serves the chain named, which of the bundle's accounts were used there, and writes the forks result to standard output and what it found to standard error. Bitcoin Cash is the chain it reads. How it reads an output that also carries CashTokens is in seed_scan.forks.

The server is the user's own, and its certificate is verified as Scanning a bundle says. Before any address is asked, its blocks at the chain's checkpoints are compared with the chain's, so that a server of a chain whose blocks differ there, as one of Bitcoin's, is refused. That shows which chain the server says it serves, not that the histories it answers are that chain's: the server is trusted for what it answers, as SECURITY.md's Limitations, not vulnerabilities says, and proving each history against the chain is btclib-org/seed-scan#34.

seed_scan.forks documents the result and which accounts are read, and seed-scan forks --help the bounds of the search.

Reporting what was found

seed-scan report bundle.json --scan scan.json > report.txt

It reads the bundle and the scan result made from it, offline, and writes what they say to standard output: for each reading, coin and purpose, the used accounts and each of their used addresses, with its balance and path, and what was not checked and why. Without --scan, as after a server or a node failed, every account is listed as not checked. A result made from another bundle is refused. The last line is the SHA-256 of the lines above it. seed_scan.report documents the layout.

What touches the secret

The commands are to keep to this split, so that the mnemonic stays on one machine and everything after it reads public data:

  • identify touches the secret and no network. It reads the mnemonic from a prompt, never from an argument. It tries each scheme, language and candidate passphrase, and, given an address the user knows, finds the reading and the path that give it. It writes a public bundle: the fingerprint and the account public keys, or the addresses where a coin has no extended public key.
  • scan and forks touch the network and no secret. They read the bundle and what the commands before them wrote, and the CA certificates they verify their server against, and scan its node: the system's or, for a server, those of the file the user names; nothing else. Scanning a bundle and Reading a fork of Bitcoin say which server and which node each asks. forks reads the bundle's accounts on a chain forked from Bitcoin, and takes what each held at the fork from the history the chain's server answers.
  • report touches neither. It assembles what scan found: what was searched, what was found, the limits of the search, and the digest of the report. It reads no result of forks, which is btclib-org/seed-scan#32.

The bundle holds no secret, but it is not harmless: an account public key gives every address of that account, so whoever holds the bundle can follow its history and balance, though not spend from it. The same holds of the report: it holds no secret, but it lets anyone follow the wallet's history.

The package is fully annotated and ships py.typed. Its refusals are seed_scan.exceptions's classes: a ValueError or a TypeError, under one base, SeedScanException.

from seed_scan.exceptions import (
    SeedScanException,
    SeedScanTypeError,
    SeedScanValueError,
)

assert issubclass(SeedScanValueError, (SeedScanException, ValueError))
assert issubclass(SeedScanTypeError, (SeedScanException, TypeError))

tests/readme_test.py runs every Python block of this file, so the example above is the one the suite checks.

Security

SECURITY.md says what the package does to guard the mnemonic and what it cannot, how to report a vulnerability, which versions are supported, and how a published file is traced back to the run that built it.

Contributing

Development is LLM-based: humans are welcome, as long as they are comfortable with agentic development ;-). A contribution must have been read and understood by the person who submits it. CONTRIBUTING.md has the rules.

CONTRIBUTING.md has the commands each CI job runs, verbatim. uv sync creates the environment; uv is the only tool that has to be installed. REVIEWING.md is what a pull request is answered against.

How the organization decides, and who holds which role, is its GOVERNANCE.md; what it intends to do, and what it deliberately does not, is its ROADMAP.md.

Links

Status

pre-commit.ci status lint workflow status test workflow status docs workflow status deps-latest workflow status pypi-install workflow status deps-oldest workflow status os-macos workflow status os-ubuntu workflow status os-windows workflow status links workflow status sdist-rebuild workflow status codeql workflow status OpenSSF Scorecard


The btclib organization and its projects are actively supported by DGI and CheckSig.

About

What a mnemonic of unknown scheme holds: its scheme, addresses, coins and forks

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages