def main(): # generate 16 bytes of entropy and # convert to a mnemonic phrase (12 words) entropy = bytes([urandom.getrandbits(8) for i in range(16)]) mnemonic = bip39.mnemonic_from_bytes(entropy) # or just define hardcoded: mnemonic = "alien visual jealous source coral memory embark certain radar capable clip edit" print(mnemonic) # convert to seed, empty password seed = bip39.mnemonic_to_seed(mnemonic) # convert to the root key # you can define the version - x/y/zprv for desired network root = bip32.HDKey.from_seed(seed, version=NETWORKS["test"]["xprv"]) print(root.to_base58()) print("\nBIP-44 - legacy") # derive account according to bip44 bip44_xprv = root.derive("m/44h/1h/0h") print(bip44_xprv.to_base58()) # corresponding master public key: bip44_xpub = bip44_xprv.to_public() print(bip44_xpub.to_base58()) # first 5 receiving addresses for i in range(5): # .key member is a public key for HD public keys # and a private key for HD private keys pub = bip44_xpub.derive("m/0/%d" % i).key sc = script.p2pkh(pub) print(sc.address(NETWORKS["test"])) print("\nBIP-84 - native segwit") # derive account according to bip84 bip84_xprv = root.derive("m/84h/1h/0h") # you can also change version of the key to get zpub (vpub on testnet) bip84_xprv.version = NETWORKS["test"]["zprv"] print(bip84_xprv.to_base58()) # corresponding master public key: bip84_xpub = bip84_xprv.to_public() print(bip84_xpub.to_base58()) # first 5 receiving addresses for i in range(5): pub = bip84_xpub.derive("m/0/%d" % i).key sc = script.p2wpkh(pub) print(sc.address(NETWORKS["test"])) print("\nBIP-49 - nested segwit") # derive account according to bip49 bip49_xprv = root.derive("m/49h/1h/0h") # you can also change version of the key to get ypub (upub on testnet) bip49_xprv.version = NETWORKS["test"]["yprv"] print(bip49_xprv.to_base58()) # corresponding master public key: bip49_xpub = bip49_xprv.to_public() print(bip49_xpub.to_base58()) # first 5 receiving addresses for i in range(5): pub = bip49_xpub.derive("m/0/%d" % i).key # use p2sh(p2wpkh(pubkey)) to get nested segwit scriptpubkey sc = script.p2sh(script.p2wpkh(pub)) print(sc.address(NETWORKS["test"]))
def test_bip39(self): for [seed, exp_mnemonic, hex_seed, xprv] in VECTORS: act_mnemonic = mnemonic_from_bytes(unhexlify(seed)) act_xkey = HDKey.from_seed( mnemonic_to_seed(act_mnemonic, password="******")) self.assertEqual(act_mnemonic, exp_mnemonic) self.assertTrue(mnemonic_is_valid(act_mnemonic)) self.assertEqual( hexlify(mnemonic_to_bytes(act_mnemonic)).decode(), seed) self.assertEqual(act_xkey.to_base58(), xprv)
def init_keys(password): mnemonic = bip39.mnemonic_from_bytes(entropy) seed = bip39.mnemonic_to_seed(mnemonic, password) keystore.load_seed(seed) # choose testnet by default select_network("test") gc.collect() show_main() if usb_host.callback is None: usb_host.callback = host_callback
def load_wallet(self, recovery_phrase: str, password: str) -> bool: seed = mnemonic_to_seed(recovery_phrase, password) master_xpriv = HDKey.from_seed( seed, NETWORKS[self.network]["xprv"]) wallet_xpub = master_xpriv.derive(self.wallet_keypath).to_public() if wallet_xpub == self.wallet_xpub: self.master_xpriv = master_xpriv self.serial_client.write_load_wallet_success() return True return False
def save_wallet(self, recovery_phrase: str, password: str, was_recovered: bool): seed = mnemonic_to_seed(recovery_phrase, password) self.master_xpriv = HDKey.from_seed( seed, NETWORKS[self.network]["xprv"]) self.master_xpub = self.master_xpriv.to_public() wallet_xpubs = self.derive_wallet_xpubs(was_recovered) master_fingerprint = self.master_xpub.child(0).fingerprint self.serial_client.write_init_wallet_success( wallet_xpubs, master_fingerprint, len(recovery_phrase.split()) )
def __init__(self, mnemonic, password="", network=NETWORKS["test"]): seed = bip39.mnemonic_to_seed(mnemonic, password) self.network = network # our root key self.root = bip32.HDKey.from_seed(seed, version=network["xprv"]) # fingerprint self.fingerprint = self.root.child(0).fingerprint # makes sense to cache the account self.derivation = "m/84h/%dh/0h" % network[ "bip32"] # contains coin type - 0 for main, 1 for test self.account = self.root.derive(self.derivation).to_public()
def set_mnemonic(self, mnemonic=None, password=""): """Load mnemonic and password and create root key""" if mnemonic is not None: self.mnemonic = mnemonic.strip() if not bip39.mnemonic_is_valid(self.mnemonic): raise KeyStoreError("Invalid mnemonic") seed = bip39.mnemonic_to_seed(self.mnemonic, password) self.root = bip32.HDKey.from_seed(seed) self.fingerprint = self.root.child(0).fingerprint # id key to sign and encrypt wallet files # stored on untrusted external chip self.idkey = self.root.child(0x1D, hardened=True).key.serialize()
def set_mnemonic(self, mnemonic=None, password=""): if mnemonic == self.mnemonic and password != "": # probably checking mnemonic after saving self.show_loader() else: self.show_loader(title="Generating keys...") """Load mnemonic and password and create root key""" if mnemonic is not None: self.mnemonic = mnemonic.strip() if not bip39.mnemonic_is_valid(self.mnemonic): raise KeyStoreError("Invalid mnemonic") seed = bip39.mnemonic_to_seed(self.mnemonic, password) self.root = bip32.HDKey.from_seed(seed) self.fingerprint = self.root.child(0).fingerprint # id key to sign and encrypt wallet files # stored on untrusted external chip self.idkey = self.root.child(0x1D, hardened=True).key.serialize()
#################################### ################# BIP-39 ##################### phrase = bip39.mnemonic_from_bytes(entropy) print("Your recovery phrase:\n%s\n" % phrase) # uncomment this line to make invalid mnemonic: # phrase += " satoshi" # you can check if recovery phrase is valid or not: if not bip39.mnemonic_is_valid(phrase): raise ValueError("Meh... Typo in the recovery?") # convert mnemonic and password to bip-32 seed seed = bip39.mnemonic_to_seed(phrase, password="******") print("Seed:", hexlify(seed).decode()) ################# BIP-32 ##################### # we will use signet: network = NETWORKS["signet"] # create HDKey from 64-byte seed root_key = bip32.HDKey.from_seed(seed) # generate an account child key: # purpose: 84h - BIP-84 # coin type: 1h - Testnet # account: 0h - first account account = root_key.derive("m/84h/1h/0h") # convert HD private key to HD public key
import display import lvgl as lv from lvqr import QRCode from bitcoin import bip39, bip32, script from bitcoin.networks import NETWORKS display.init() mnemonic = "poverty august total basket pool print promote august piece squirrel coil sting" # seed with empty password seed = bip39.mnemonic_to_seed(mnemonic) # root key root = bip32.HDKey.from_seed(seed) class AddressNavigator(lv.obj): def __init__(self, account, *args, script_fn=script.p2wpkh, network=NETWORKS["main"], **kwargs): super().__init__(*args, **kwargs) self.account = account self.script_fn = script_fn self.network = network self._index = 0 # create title self.title = lv.label(self) self.title.set_align(lv.label.ALIGN.CENTER) self.title.align(self, lv.ALIGN.IN_TOP_MID, 0, 50) # create qr code self.qr = QRCode(self) self.qr.set_size(400)
network = NETWORKS["test"] entropy = b'\x64\xd3\xe4\xa0\xa3\x87\xe2\x80\x21\xdf\x55\xa5\x1d\x45\x4d\xcf' recovery_phrase = bip39.mnemonic_from_bytes(entropy) print("Your recovery phrase:\n%s\n" % recovery_phrase) # uncomment this line to make invalid mnemonic: # recovery_phrase += " satoshi" # you can check if recovery phrase is valid or not: if not bip39.mnemonic_is_valid(recovery_phrase): raise ValueError("Meh... Typo in the recovery?") # convert mnemonic and password to bip-32 seed seed = bip39.mnemonic_to_seed(recovery_phrase, password="******") print("Seed:", hexlify(seed).decode("ascii")) # create HDKey from 64-byte seed root_key = bip32.HDKey.from_seed(seed) # generate an account child key: # purpose: 84h - BIP-84 # coin type: 1h - Testnet # account: 0h - first account account = root_key.derive("m/84h/1h/0h") # convert HD private key to HD public key account_pub = account.to_public() # for Bitcoin Core: pure BIP-32 serialization print("\nYour xpub:", account_pub.to_base58(version=NETWORKS["test"]["xpub"])) # for Electrum and others who cares about SLIP-0132 # used for bip-84 by many wallets
def main(): # get root key from the mnemonic mnemonic = "alien visual jealous source coral memory embark certain radar capable clip edit" seed = bip39.mnemonic_to_seed(mnemonic) root = bip32.HDKey.from_seed(seed, version=NETWORKS["test"]["xprv"]) # get bip84-xpub to import to Bitcoin Core: # we will use the form [fingerprint/derivation]xpub # to import to Bitcoin Core with descriptors # first let's get the root fingerprint # we can get it from any child of the root key fingerprint = root.child(0).fingerprint hardened_derivation = "m/84h/1h/0h" # derive account according to bip84 bip84_xprv = root.derive(hardened_derivation) # corresponding master public key: bip84_xpub = bip84_xprv.to_public() print("[%s%s]%s" % (hexlify(fingerprint).decode('utf-8'), hardened_derivation[1:], bip84_xpub.to_base58())) # parse psbt transaction b64_psbt = "cHNidP8BAHICAAAAAY3LB6teEH6qJHluFYG3AQe8n0HDUcUSEuw2WIJ1ECDUAAAAAAD/////AoDDyQEAAAAAF6kU882+nVMDKGj4rKzjDB6NjyJqSBCHaPMhCgAAAAAWABQUbW8/trQg4d3PKL8WLi2kUa1BqAAAAAAAAQEfAMLrCwAAAAAWABTR6Cr4flM2A0LMGjGiaZ+fhod37SIGAhHf737H1jCUjkJ1K5DqFkaY0keihxeWBQpm1kDtVZyxGLMX7IZUAACAAQAAgAAAAIAAAAAAAAAAAAAAIgIDPtTTi27VFw59jdmWDV8b1YciQzhYGO7m8zB9CvD0brcYsxfshlQAAIABAACAAAAAgAEAAAAAAAAAAA==" # first convert it to binary raw = a2b_base64(b64_psbt) # then parse tx = psbt.PSBT.parse(raw) # print how much we are spending and where total_in = 0 for inp in tx.inputs: total_in += inp.witness_utxo.value print("Inputs:", total_in, "satoshi") change_out = 0 # value that goes back to us send_outputs = [] for i, out in enumerate(tx.outputs): # check if it is a change or not: change = False # should be one or zero for single-key addresses for pub in out.bip32_derivations: # check if it is our key if out.bip32_derivations[pub].fingerprint == fingerprint: hdkey = root.derive(out.bip32_derivations[pub].derivation) mypub = hdkey.key.get_public_key() if mypub != pub: raise ValueError("Derivation path doesn't look right") # now check if provided scriptpubkey matches sc = script.p2wpkh(mypub) if sc == tx.tx.vout[i].script_pubkey: change = True continue if change: change_out += tx.tx.vout[i].value else: send_outputs.append(tx.tx.vout[i]) print("Spending", total_in - change_out, "satoshi") fee = total_in - change_out for out in send_outputs: fee -= out.value print(out.value, "to", out.script_pubkey.address(NETWORKS["test"])) print("Fee:", fee, "satoshi") # sign the transaction tx.sign_with(root) raw = tx.serialize() # convert to base64 b64_psbt = b2a_base64(raw) # somehow b2a ends with \n... if b64_psbt[-1:] == b"\n": b64_psbt = b64_psbt[:-1] # print print("\nSigned transaction:") print(b64_psbt.decode('utf-8'))