Folders and files
| Name | Name | Last commit date | ||
|---|---|---|---|---|
Repository files navigation
YuBTC - put your money in your head.
Donations
=========
If YuBTC was useful, tips are welcome:
1KCp7GLkZpTBVCwrMfaAaWqyTWRAXYDpKq
A console BTC client. Downloads nothing, stores nothing on disk: private keys
are derived from a seed on each invocation.
Commands:
newseed Generate a new seed.
address Show the native (P2PKH) address.
balance Show the balance.
send Send BTC to an address.
dumpprivkey Show the private key in WIF format.
pushtx Broadcast a pre-signed raw transaction from stdin.
Network providers
=================
By default every command that talks to the network hits
blockchain.info. Switch providers with `--provider NAME`:
$ yubtc balance --provider blockstream
$ yubtc balance --provider mempool.space
Registered providers:
blockchain.info blockchain.info's public API (default)
blockstream blockstream.info's Esplora API
mempool.space mempool.space's Esplora API
The blockstream and mempool.space backends share the same JSON schema
(Esplora); only the base URL differs. Confirmations are computed
locally from each UTXO's block height and the chain tip, so a slow
provider can't break the gap scan.
An unknown `--provider` name is rejected by click before any network
work runs -- no silent fallback to the default.
Key derivation
==============
yuBTC supports two key derivation paths, gated on whether a passphrase
is set:
* **No passphrase** (the default): the legacy path. For each nonce the
32-byte secret is `sha256(keccak256(blake2b256(nonce ‖ seed)))`. Each
nonce is independent -- reusing a seed with the same passphrase at a
different nonce gives a different address, but two different seeds at
the same nonce are also independent. The wallet is compatible with
the original yubtc behaviour: an old wallet with no passphrase opens
to the same addresses as it always did.
* **With passphrase**: BIP-39 + BIP-32 + BIP-44. The mnemonic is
NFKD-normalised, stretched through PBKDF2-HMAC-SHA512 (2048 iter,
salt `b'mnemonic' + passphrase`, 64 bytes) to produce the BIP-39
seed. The BIP-32 master is derived from that seed, and the final
32-byte key is the leaf at the **main path**:
m/44'/0'/0'/0/<nonce>
(`purpose / coin_type / account / chain / address_index`).
Same mnemonic + passphrase + nonce yields the same address in Trezor,
Ledger, Electrum, etc. The wallet walks only the receiving chain
(`chain = 0`) and uses the next unused index of the same chain for
cashback -- a single-account, single-chain tree, in line with the
wallet's no-storage rescan-on-every-run model. A full BIP-44 walk
would be O(N×M) per scan with no upside for this use case.
Private key formats
===================
`dumpprivkey` returns a **WIF (Wallet Import Format)** string --
compressed, mainnet, base58check-encoded. Concretely, the bytes are:
0x80 || <32-byte secret> || 0x01
The trailing `0x01` is the compressed-pubkey flag; the prefix `0x80`
is the mainnet private-key prefix. The whole 34-byte payload is then
base58check-encoded so a typo in the WIF is detected by checksum, not
by silently signing for the wrong key.
Only compressed WIF is supported on import (`privwif2privkey`); an
uncompressed WIF (33-byte body, no trailing `0x01`) raises
`'uncompressed wif not supported'` rather than silently downgrading.
Inside the wallet the privkey is held as a 32-byte secret. yubtc does
not store anything, so the WIF is the only thing to keep between
sessions -- paste it into another BIP-39-aware wallet to recover.
Usage from a checkout (no installation needed):
$ pip install -r requirements.txt
$ ./yubtc newseed
The ./yubtc launcher runs the code straight from src/, so only the third-party
dependencies have to be installed, not YuBTC itself. Run the tests the same way:
$ pip install 'pytest>=7.0'
$ pytest
Alternatively, install it as a real package to get a yubtc command on PATH:
$ pip install .
Examples:
$ yubtc newseed
place fabric recall try between menu brush there around oil wing busy summer brush record
Address: 14bUA6ioEkUVCx8cU2zvjpK4KBVHxvEnt3
$ yubtc dumpprivkey
seed:
Address: 14bUA6ioEkUVCx8cU2zvjpK4KBVHxvEnt3
L25VQR3RxMNhAVgehEqGjMWXvNHDc4bdmPraiwoEoNQr4UVviz2n
$ yubtc balance
seed:
14bUA6ioEkUVCx8cU2zvjpK4KBVHxvEnt3: 0.99998552 BTC
$ yubtc send -c 0 -f 0.00001234 14bUA6ioEkUVCx8cU2zvjpK4KBVHxvEnt3 ALL
seed:
Address: 14bUA6ioEkUVCx8cU2zvjpK4KBVHxvEnt3
send 0.99997318 BTC to 14bUA6ioEkUVCx8cU2zvjpK4KBVHxvEnt3 (cashback=0.00000000, fee=0.00001234, txsize=192)? n