bip_hd: a minimal, easy-to-use BIP-32/BIP-44 implementation
- this is a work in progress, only a few coins are currently supported
Testing:
$ test/unit_tests.py -v bip_hd
Examples:
$ PYTHONPATH=. examples/bip_hd.py
This commit is contained in:
parent
a8253a692b
commit
ea1e8d1228
9 changed files with 2363 additions and 2 deletions
88
examples/bip_hd.py
Executable file
88
examples/bip_hd.py
Executable file
|
|
@ -0,0 +1,88 @@
|
|||
#!/usr/bin/env python3
|
||||
#
|
||||
# mmgen = Multi-Mode GENerator, a command-line cryptocurrency wallet
|
||||
# Copyright (C)2013-2024 The MMGen Project <mmgen@tuta.io>
|
||||
# Licensed under the GNU General Public License, Version 3:
|
||||
# https://www.gnu.org/licenses
|
||||
# Public project repositories:
|
||||
# https://github.com/mmgen/mmgen-wallet
|
||||
# https://gitlab.com/mmgen/mmgen-wallet
|
||||
|
||||
"""
|
||||
examples/bip_hd.py: Usage examples for the MMGen BIP-32/-44 hierarchical/deterministic library
|
||||
"""
|
||||
|
||||
from mmgen.cfg import Config
|
||||
from mmgen.util import fmt
|
||||
from mmgen.bip39 import bip39
|
||||
from mmgen.bip_hd import MasterNode,BipHDNode
|
||||
|
||||
cfg = Config()
|
||||
|
||||
bip39_mnemonic = 'cat swing flag economy stadium alone churn speed unique patch report train'
|
||||
|
||||
seed = bip39().generate_seed(bip39_mnemonic.split())
|
||||
|
||||
m = MasterNode(cfg, seed)
|
||||
|
||||
# Derive sample path:
|
||||
|
||||
# to_chain() derives default chain for coin/addr_type pair:
|
||||
dfl_pub_chain = m.to_chain(idx=0, coin='ltc', addr_type='bech32')
|
||||
dfl_chg_chain = m.to_chain(idx=1, coin='ltc', addr_type='bech32')
|
||||
|
||||
print(f'Default path (LTC, bech32):\n')
|
||||
print(f' public chain xpub:\n {dfl_pub_chain.xpub}\n')
|
||||
print(f' internal chain xpub:\n {dfl_chg_chain.xpub}\n')
|
||||
print(f' public chain addr 0:\n {dfl_pub_chain.derive_public(0).address}\n')
|
||||
print(f' public chain addr 1:\n {dfl_pub_chain.derive_public(1).address}\n')
|
||||
|
||||
# Derive sample path using path string:
|
||||
|
||||
dfl_pub_chain_from_path = BipHDNode.from_path(
|
||||
base_cfg = cfg,
|
||||
seed = seed,
|
||||
# purpose=84 (bech32 [BIP-84]), coin_type=2 (LTC mainnet [SLIP-44]), account=0, chain=0 (public)
|
||||
# as per BIP-44, ‘purpose’, ‘coin_type’ and ‘account’ are hardened, while ‘chain’ is not
|
||||
path_str = "m/84'/2'/0'/0",
|
||||
coin = 'ltc',
|
||||
addr_type = 'bech32')
|
||||
|
||||
assert dfl_pub_chain_from_path.xpub == dfl_pub_chain.xpub
|
||||
|
||||
# Derive sample path step-by-step:
|
||||
|
||||
# Configure master node with coin/addr_type pair:
|
||||
master = m.init_cfg(coin='ltc', addr_type='bech32')
|
||||
|
||||
# ‘idx’ and ‘hardened’ args may be omitted at depths where defaults exist:
|
||||
purpose = master.derive_private() # ‘idx’ is auto-computed from addr_type (BIP-44/49/84)
|
||||
coin_type = purpose.derive_private() # ‘idx’ is auto-computed from coin/network (SLIP-44)
|
||||
account = coin_type.derive_private(idx=0)
|
||||
pub_chain = account.derive_public(idx=0)
|
||||
|
||||
assert pub_chain.xpub == dfl_pub_chain.xpub
|
||||
|
||||
# Initialize node from xpub:
|
||||
pub_chain_from_xpub = BipHDNode.from_extended_key(cfg, 'ltc', pub_chain.xpub)
|
||||
|
||||
assert pub_chain_from_xpub.xpub == pub_chain.xpub
|
||||
|
||||
# To derive arbitrary BIP-32 paths, ignoring BIP-44, specify ‘no_path_checks’
|
||||
nonstd_path = BipHDNode.from_path(
|
||||
base_cfg = cfg,
|
||||
seed = seed,
|
||||
path_str = "m/111'/222/333/444",
|
||||
coin = 'eth',
|
||||
addr_type = 'E',
|
||||
no_path_checks = True)
|
||||
|
||||
print(f'Non-standard path (ETH):\n')
|
||||
print(f' xpub:\n {nonstd_path.xpub}\n')
|
||||
print(f' WIF key:\n {nonstd_path.privkey.wif}\n')
|
||||
print(f' address:\n {nonstd_path.address}\n')
|
||||
|
||||
# Display parsed xpub:
|
||||
parsed_xpub = nonstd_path.key_extended(public=True)
|
||||
print('Default path parsed xpub:\n')
|
||||
print(fmt(str(parsed_xpub), indent=' '))
|
||||
Loading…
Add table
Add a link
Reference in a new issue