def test_refill_main_wallet(spool_regtest, rpconn): src_wallet_passowrd = uuid1().hex.encode('utf-8') src_wallet = BIP32Node.from_master_secret(src_wallet_passowrd, netcode='XTN') dest_wallet_passowrd = uuid1().hex.encode('utf-8') dest_wallet = BIP32Node.from_master_secret(dest_wallet_passowrd, netcode='XTN') src_address = src_wallet.bitcoin_address() dest_address = dest_wallet.bitcoin_address() rpconn.importaddress(src_address) rpconn.importaddress(dest_address) rpconn.sendtoaddress(src_address, 1) rpconn.generate(1) txid = spool_regtest.refill_main_wallet( ('', src_address), dest_address, 1, 1, src_wallet_passowrd, min_confirmations=1, ) rpconn.generate(1) raw_txid = rpconn.getrawtransaction(txid) raw_tx = rpconn.decoderawtransaction(raw_txid) values = (vout['value'] * 100000000 for vout in raw_tx['vout'] if vout['scriptPubKey']['addresses'].pop() == dest_address) assert spool_regtest.FEE in values assert spool_regtest.TOKEN in values assert (rpconn.getreceivedbyaddress(dest_address) * 100000000 == spool_regtest.FEE + spool_regtest.TOKEN)
def test_refill_fuel(spool_regtest, rpconn): src_wallet_passowrd = uuid1().hex.encode('utf-8') src_wallet = BIP32Node.from_master_secret(src_wallet_passowrd, netcode='XTN') dest_wallet_passowrd = uuid1().hex.encode('utf-8') dest_wallet = BIP32Node.from_master_secret(dest_wallet_passowrd, netcode='XTN') src_address = src_wallet.bitcoin_address() dest_address = dest_wallet.bitcoin_address() rpconn.importaddress(src_address) rpconn.importaddress(dest_address) rpconn.sendtoaddress(src_address, spool_regtest.FEE/100000000) rpconn.sendtoaddress(src_address, spool_regtest.FEE/100000000) rpconn.sendtoaddress( src_address, spool_regtest.TOKEN/100000000) rpconn.generate(1) txid = spool_regtest.refill( ('', src_address), dest_address, 1, 1, src_wallet_passowrd, min_confirmations=1, ) rpconn.generate(1) raw_txid = rpconn.getrawtransaction(txid) raw_tx = rpconn.decoderawtransaction(raw_txid) values = (vout['value'] * 100000000 for vout in raw_tx['vout'] if vout['scriptPubKey']['addresses'].pop() == dest_address) values = [] asm = None for vout in raw_tx['vout']: try: addr = vout['scriptPubKey']['addresses'].pop() except KeyError: asm = vout['scriptPubKey']['asm'] else: if addr == dest_address: values.append(vout['value'] * 100000000) assert spool_regtest.FEE in values assert spool_regtest.TOKEN in values assert asm.split(' ')[0] == 'OP_RETURN' assert asm.split(' ')[1] == '4153435249424553504f4f4c30314655454c' assert spool_regtest.FEE in values assert spool_regtest.TOKEN in values assert (rpconn.getreceivedbyaddress(dest_address) * 100000000 == spool_regtest.FEE + spool_regtest.TOKEN)
def generate_xpriv(self, root_seed) -> str: BIP32Node = self._network.ui._bip32node_class master_key = BIP32Node.from_master_secret(root_seed) account_key = master_key.subkey_for_path( f"44p/{self._currency_number}p/0p") account_xpriv = self._get_priv(account_key) return account_xpriv
def test_get_addresses(rpconn, piece_hashes, spool_regtest, transactions): from spool import Spool from spool.spoolex import BlockchainSpider sender_password = uuid1().hex.encode('utf-8') sender_wallet = BIP32Node.from_master_secret(sender_password, netcode='XTN') sender_address = sender_wallet.bitcoin_address() rpconn.importaddress(sender_address) rpconn.sendtoaddress(sender_address, Spool.FEE/100000000) rpconn.sendtoaddress(sender_address, Spool.TOKEN/100000000) rpconn.sendtoaddress(sender_address, Spool.TOKEN/100000000) rpconn.sendtoaddress(sender_address, Spool.TOKEN/100000000) rpconn.generate(1) receiver_address = rpconn.getnewaddress() # TODO do not rely on Spool txid = spool_regtest.transfer( ('', sender_address), receiver_address, piece_hashes, sender_password, 5, min_confirmations=1, ) decoded_raw_transfer_tx = transactions.get(txid) addresses = BlockchainSpider._get_addresses(decoded_raw_transfer_tx) assert len(addresses) == 3 assert addresses[0] == sender_address assert addresses[1] == receiver_address assert addresses[2] == piece_hashes[0]
def test_bip32(self): master = "tpubD9q6vq9zdP3gbhpjs7n2TRvT7h4PeBhxg1Kv9jEc1XAss7429VenxvQTsJaZhzTk54gnsHRpgeeNMbm1QTag4Wf1QpQ3gy221GDuUCxgfeZ" key = BIP32Node.from_hwif(master) self.assertEqual( b2x(key.sec()), "022f6b9339309e89efb41ecabae60e1d40b7809596c68c03b05deb5a694e33cd26" ) self.assertEqual( key.subkey_for_path("0").hwif(), "tpubDAtJthHcm9MJwmHp4r2UwSTmiDYZWHbQUMqySJ1koGxQpRNSaJdyL2Ab8wwtMm5DsMMk3v68299LQE6KhT8XPQWzxPLK5TbTHKtnrmjV8Gg" ) self.assertEqual( key.subkey_for_path("0/0").hwif(), "tpubDDfqpEKGqEVa5FbdLtwezc6Xgn81teTFFVA69ZfJBHp4UYmUmhqVZMmqXeJBDahvySZrPjpwMy4gKfNfrxuFHmzo1r6srB4MrsDKWbwEw3d" ) key = BIP32Node.from_master_secret( x("000102030405060708090a0b0c0d0e0f"), "XTN") self.assertEqual( key.subkey_for_path("0'/1/2'/2/1000000000").hwif(), "tpubDHNy3kAG39ThyiwwsgoKY4iRenXDRtce8qdCFJZXPMCJg5dsCUHayp84raLTpvyiNA9sXPob5rgqkKvkN8S7MMyXbnEhGJMW64Cf4vFAoaF" )
def test_create_sign_push_transaction(transactions, rpcconn): alice = BIP32Node.from_master_secret(b"alice-secret", netcode="XTN").bitcoin_address() bob = BIP32Node.from_master_secret(b"bob-secret", netcode="XTN").bitcoin_address() rpcconn.importaddress(alice) rpcconn.importaddress(bob) rpcconn.sendtoaddress(alice, 3) rpcconn.generate(1) raw_tx = transactions.create(alice, (bob, 200000000), min_confirmations=1) assert raw_tx signed_tx = transactions.sign(raw_tx, b"alice-secret") assert signed_tx bob_before = rpcconn.getreceivedbyaddress(bob) pushed_tx = transactions.push(signed_tx) assert pushed_tx rpcconn.generate(1) # pack the transaction into a block assert rpcconn.getreceivedbyaddress(bob) - bob_before == 2
def init_wallet(self, identifier, passphrase): netcode = "XTN" if self.testnet else "BTC" data = self.get_wallet(identifier) primary_seed = Mnemonic.to_seed(data['primary_mnemonic'], passphrase) primary_private_key = BIP32Node.from_master_secret(primary_seed, netcode=netcode) backup_public_key = BIP32Node.from_hwif(data['backup_public_key'][0]) checksum = self.create_checksum(primary_private_key) if checksum != data['checksum']: raise Exception("Checksum [%s] does not match expected checksum [%s], most likely due to incorrect password" % (checksum, data['checksum'])) blocktrail_public_keys = data['blocktrail_public_keys'] key_index = data['key_index'] return Wallet( client=self, identifier=identifier, primary_mnemonic=data['primary_mnemonic'], primary_private_key=primary_private_key, backup_public_key=backup_public_key, blocktrail_public_keys=blocktrail_public_keys, key_index=key_index, testnet=self.testnet )
def test_streams(self): m0 = BIP32Node.from_master_secret("foo bar baz".encode("utf8")) pm0 = m0.public_copy() self.assertEqual(m0.wallet_key(), pm0.wallet_key()) m1 = m0.subkey() pm1 = pm0.subkey() for i in range(4): m = m1.subkey(i=i) pm = pm1.subkey(i=i) self.assertEqual(m.wallet_key(), pm.wallet_key()) self.assertEqual(m.bitcoin_address(), pm.bitcoin_address()) m2 = BIP32Node.from_wallet_key(m.wallet_key(as_private=True)) m3 = m2.public_copy() self.assertEqual(m.wallet_key(as_private=True), m2.wallet_key(as_private=True)) self.assertEqual(m.wallet_key(), m3.wallet_key()) print(m.wallet_key(as_private=True)) for j in range(2): k = m.subkey(i=j) k2 = BIP32Node.from_wallet_key(k.wallet_key(as_private=True)) k3 = BIP32Node.from_wallet_key(k.wallet_key()) k4 = k.public_copy() self.assertEqual(k.wallet_key(as_private=True), k2.wallet_key(as_private=True)) self.assertEqual(k.wallet_key(), k2.wallet_key()) self.assertEqual(k.wallet_key(), k3.wallet_key()) self.assertEqual(k.wallet_key(), k4.wallet_key()) print(" %s %s" % (k.bitcoin_address(), k.wif()))
def __init__(self, pkey=None, secret=None): if secret is not None: pkey = format( BIP32Node.from_master_secret( secret.encode('utf-8')).secret_exponent(), "064x") elif pkey is None: try: pkey = format( BIP32Node.from_master_secret( urandom(4096)).secret_exponent(), '064x') except NotImplementedError as e: raise ValueError('No randomness source found: %s' % e) self.keypair = Key(secret_exponent=int(pkey, 16))
def create_bip32node(self, slug, random_bytes): bip32_node = BIP32Node.from_master_secret(random_bytes) bip32_text = bip32_node.as_text(as_private=True) c = self._exec_sql( "insert into BIP32Key (slug, as_text) values (?, ?)", slug, bip32_text) return self.bip32node_for_slug(slug)
def test_import_prv(goto_home, pick_menu_item, cap_story, need_keypress, unit_test, cap_menu, word_menu_entry, get_secrets, microsd_path, multiple_runs, reset_seed_words): unit_test('devtest/clear_seed.py') fname = 'test-%d.txt' % os.getpid() path = microsd_path(fname) from pycoin.key.BIP32Node import BIP32Node node = BIP32Node.from_master_secret(os.urandom(32)) open(path, 'wt').write(node.hwif(as_private=True)+'\n') print("Created: %s" % path) m = cap_menu() assert m[0] == 'New Wallet' pick_menu_item('Import Existing') pick_menu_item('Import XPRV') title, body = cap_story() assert 'Select file' in body need_keypress('y'); time.sleep(.01) pick_menu_item(fname) unit_test('devtest/abort_ux.py') v = get_secrets() assert v['xpub'] == node.hwif() assert v['xprv'] == node.hwif(as_private=True) reset_seed_words()
def sign_transaction(self, tx, master_password, path=''): """ Args: tx: hex transaction to sign master_password: master password for BIP32 wallets. Can be either a master_secret or a wif path (Optional[str]): optional path to the leaf address of the BIP32 wallet. This allows us to retrieve private key for the leaf address if one was used to construct the transaction. Returns: signed transaction .. note:: Only BIP32 hierarchical deterministic wallets are currently supported. """ netcode = 'XTN' if self.testnet else 'BTC' # TODO review # check if its a wif try: BIP32Node.from_text(master_password) return bitcoin.signall(tx, master_password) except (AttributeError, EncodingError): # if its not get the wif from the master secret return bitcoin.signall(tx, BIP32Node.from_master_secret(master_password, netcode=netcode).subkey_for_path(path).wif())
def sign_transaction(self, tx, master_password, path=''): """ Args: tx: hex transaction to sign master_password: master password for BIP32 wallets. Can be either a master_secret or a wif path (Optional[str]): optional path to the leaf address of the BIP32 wallet. This allows us to retrieve private key for the leaf address if one was used to construct the transaction. Returns: signed transaction .. note:: Only BIP32 hierarchical deterministic wallets are currently supported. """ netcode = 'XTN' if self.testnet else 'BTC' # TODO review # check if its a wif try: BIP32Node.from_text(master_password) return bitcoin.signall(tx, master_password) except (AttributeError, EncodingError): # if its not get the wif from the master secret return bitcoin.signall( tx, BIP32Node.from_master_secret( master_password, netcode=netcode).subkey_for_path(path).wif())
def create_key(asset, netcode="BTC"): secure_random_data = os.urandom(32) key = BIP32Node.from_master_secret(secure_random_data, netcode=netcode) return { "asset": asset, "pubkey": b2h(key.sec()), "wif": key.wif(), "address": key.address(), }
def test_refill_fuel(spool_regtest, rpconn): src_wallet_passowrd = uuid1().hex.encode('utf-8') src_wallet = BIP32Node.from_master_secret(src_wallet_passowrd, netcode='XTN') dest_wallet_passowrd = uuid1().hex.encode('utf-8') dest_wallet = BIP32Node.from_master_secret(dest_wallet_passowrd, netcode='XTN') src_address = src_wallet.bitcoin_address() dest_address = dest_wallet.bitcoin_address() rpconn.importaddress(src_address) rpconn.importaddress(dest_address) rpconn.sendtoaddress(src_address, spool_regtest.FEE / 100000000) rpconn.sendtoaddress(src_address, spool_regtest.FEE / 100000000) rpconn.sendtoaddress(src_address, spool_regtest.TOKEN / 100000000) rpconn.generate(1) txid = spool_regtest.refill( ('', src_address), dest_address, 1, 1, src_wallet_passowrd, min_confirmations=1, ) rpconn.generate(1) raw_txid = rpconn.getrawtransaction(txid) raw_tx = rpconn.decoderawtransaction(raw_txid) values = (vout['value'] * 100000000 for vout in raw_tx['vout'] if vout['scriptPubKey']['addresses'].pop() == dest_address) values = [] asm = None for vout in raw_tx['vout']: try: addr = vout['scriptPubKey']['addresses'].pop() except KeyError: asm = vout['scriptPubKey']['asm'] else: if addr == dest_address: values.append(vout['value'] * 100000000) assert spool_regtest.FEE in values assert spool_regtest.TOKEN in values assert asm.split(' ')[0] == 'OP_RETURN' assert asm.split(' ')[1] == '4153435249424553504f4f4c30314655454c' assert spool_regtest.FEE in values assert spool_regtest.TOKEN in values assert (rpconn.getreceivedbyaddress(dest_address) * 100000000 == spool_regtest.FEE + spool_regtest.TOKEN)
def create(): max_retries = 64 for _ in range(max_retries): try: return BIP32Node.from_master_secret(get_entropy(), netcode=COIN_NETWORK) except ValueError as e: continue raise e
def new_keypair(): # ku -n DASH create # wif = private key # Dash Address = public address key = BIP32Node.from_master_secret(ku.get_entropy(), 'DASH') pub = key.address(use_uncompressed=False) priv = key.wif(use_uncompressed=False) return pub, priv
def prefix_transforms_for_network(network): def _create_bip32(_): max_retries = 64 for _ in range(max_retries): try: return BIP32Node.from_master_secret(get_entropy(), netcode=network) except ValueError as e: continue # Probably a bug if we get here raise RuntimeError("can't create BIP32 key") return ( ("P:", lambda s: BIP32Node.from_master_secret(s.encode("utf8"), netcode=network)), ("H:", lambda s: BIP32Node.from_master_secret(h2b(s), netcode=network)), ("E:", lambda s: key_from_text(s)), ("create", _create_bip32), )
def test_create_sign_push_transaction(transactions, rpcconn): alice = BIP32Node.from_master_secret(b'alice-secret', netcode='XTN').bitcoin_address() bob = BIP32Node.from_master_secret(b'bob-secret', netcode='XTN').bitcoin_address() rpcconn.importaddress(alice) rpcconn.importaddress(bob) rpcconn.sendtoaddress(alice, 3) rpcconn.generate(1) raw_tx = transactions.create(alice, (bob, 200000000), min_confirmations=1) assert raw_tx signed_tx = transactions.sign(raw_tx, b'alice-secret') assert signed_tx bob_before = rpcconn.getreceivedbyaddress(bob) pushed_tx = transactions.push(signed_tx) assert pushed_tx rpcconn.generate(1) # pack the transaction into a block assert rpcconn.getreceivedbyaddress(bob) - bob_before == 2
def mnemonic_to_bip32_node(mnemonic, passphrase='', netcode='BTC'): """ mnemonic sentence to bip32 node :param mnemonic: mnemonic sentence :param passphrase: used for PBKDF2 salt('mnemonic' + passphrase) :param netcode: 'BTC' => "mainnet", 'XTN' => "testnet3" """ master_seed = Mnemonic.to_seed(mnemonic, passphrase=passphrase) return BIP32Node.from_master_secret(master_seed, netcode=netcode)
def create(self): network = "BTC" if not self.proxy.use_production: network = "XTN" entropy = "".join([chr(random.getrandbits(8)) for i in range(32)]) key = BIP32Node.from_master_secret(entropy, network) private = key.wallet_key(as_private=True).encode("utf-8") public = key.wallet_key(as_private=False).encode("utf-8") return {"xpub": public, "xprv": private}
def test_testnet(self): # WARNING: these values have not been verified independently. TODO: do so master = BIP32Node.from_master_secret(h2b("000102030405060708090a0b0c0d0e0f"), netcode='XTN') self.assertEqual( master.wallet_key(as_private=True), "tprv8ZgxMBicQKsPeDgjzdC36fs6bMjGApWDNLR9erAXMs5skhMv36j9MV5ecvfavji5kh" "qjWaWSFhN3YcCUUdiKH6isR4Pwy3U5y5egddBr16m") self.assertEqual(master.bitcoin_address(), "mkHGce7dctSxHgaWSSbmmrRWsZfzz7MxMk") self.assertEqual(master.wif(), "cVPXTF2TnozE1PenpP3x9huctiATZmp27T9Ue1d8nqLSExoPwfN5")
def _create_bip32(_): max_retries = 64 for _ in range(max_retries): try: return BIP32Node.from_master_secret(get_entropy(), netcode=network) except ValueError as e: continue # Probably a bug if we get here raise RuntimeError("can't create BIP32 key")
def _create(_): max_retries = 64 for _ in range(max_retries): try: return BIP32Node.from_master_secret(get_entropy(), netcode=args.network) except ValueError as e: continue # Probably a bug if we get here raise e
def _create_bip32(generator): max_retries = 64 for _ in range(max_retries): try: return BIP32Node.from_master_secret(secp256k1_generator, get_entropy()) except ValueError as e: continue # Probably a bug if we get here raise RuntimeError("can't create BIP32 key")
def generate_wif(netcode="BTC"): """ Generate a new wif with secure random data. Args: netcode (str): Netcode for resulting bitcoin address. Return: str: Private key encode in bitcoin wif format. """ return BIP32Node.from_master_secret(os.urandom(32), netcode=netcode).wif()
def pycoinWallet(public_key=None, public=True, testnet=settings.BTC_TESTNET, password=None): netcode = 'XTN' if testnet else 'BTC' if public: return BIP32Node.from_wallet_key(public_key) else: assert not password is None return BIP32Node.from_master_secret(password, netcode=netcode)
def mnemonic_to_bip32_hwif(mnemonic, passphrase='', netcode='BTC'): """ mnemonic sentence to bip32 private key format which starts with 'xprv' :param mnemonic: mnemonic sentence :param passphrase: used for PBKDF2 salt('mnemonic' + passphrase) :param netcode: 'BTC' => "mainnet", 'XTN' => "testnet3" """ master_seed = Mnemonic.to_seed(mnemonic, passphrase=passphrase) master = BIP32Node.from_master_secret(master_seed, netcode=netcode) return master.hwif(as_private=True)
def bip44_eth_account(mnemonic, account=0, passphrase=''): """ bip44 eth format m / 44' / 0' / {account}' account can generate related address/key pairs :param mnemonic: mnemonic sentence :param account: 0 as first account :param passphrase: used for PBKDF2 salt('mnemonic' + passphrase) """ master_seed = Mnemonic.to_seed(mnemonic, passphrase=passphrase) master = BIP32Node.from_master_secret(master_seed) return master.subkey_for_path(f'44H/60H/{account}H')
def __init__(self, w3, mnemonic, index): self.w3 = w3 master_key = BIP32Node.from_master_secret( Mnemonic("english").to_seed(mnemonic)) purpose_subtree = master_key.subkey(i=44, is_hardened=True) coin_type_subtree = purpose_subtree.subkey(i=60, is_hardened=True) account_subtree = coin_type_subtree.subkey(i=0, is_hardened=True) change_subtree = account_subtree.subkey(i=0) account = change_subtree.subkey(i=index) self.private_key = account.secret_exponent().to_bytes(32, 'big') self.address = get_address_from_private(self.private_key)
def bip44_test_external_key(mnemonic, account=0, key_idx=0, passphrase=''): """ bip44 testnet format m / 44' / 0' / {account}' / 0 / {key_idx} :param mnemonic: mnemonic sentence :param account: 0 as first account :param key_idx: 0 as first key :param passphrase: used for PBKDF2 salt('mnemonic' + passphrase) """ master_seed = Mnemonic.to_seed(mnemonic, passphrase=passphrase) master = BIP32Node.from_master_secret(master_seed, netcode='XTN') return master.subkey_for_path(f'44H/1H/{account}H/0/{key_idx}')
def sign_transaction(self, tx, master_password, path=''): # master_password can be either a master_secret or a wif netcode = 'XTN' if self.testnet else 'BTC' # check if its a wif try: BIP32Node.from_text(master_password) return pybitcointools.signall(tx, master_password) except EncodingError: # if its not get the wif from the master secret return pybitcointools.signall(tx, BIP32Node.from_master_secret(master_password, netcode=netcode).subkey_for_path(path).wif())
def _djroot_bitcoin_wallet(): from pycoin.key.BIP32Node import BIP32Node from bitcoin.models import BitcoinWallet djroot = _djroot_user() netcode = 'XTN' if settings.BTC_TESTNET else 'BTC' private_wallet = BIP32Node.from_master_secret('secret-djroot', netcode=netcode) public_key = private_wallet.wallet_key(as_private=False) djroot_wallet = BitcoinWallet.create(djroot, public_key=public_key) djroot_wallet.save() return djroot_wallet
def treegen(value, entropy=False): if entropy: # this method also takes a netcode parameter, but we don't care # what network pycoin thinks this node is, because we only use it # for key derivation. return BIP32Node.from_master_secret(unhexlify(value)) else: # this method will infer a network from the header bytes. We # don't care right now for the same reason as above, but we will # if Gem's API stops returning 'xpub' as the pubkey header bytes # because if pycoin doesn't recognize a header it will error. return BIP32Node.from_hwif(value)
def djroot_bitcoin_wallet(djroot_user, monkeypatch): from pycoin.key.BIP32Node import BIP32Node from bitcoin.models import BitcoinWallet netcode = 'XTN' if settings.BTC_TESTNET else 'BTC' private_wallet = BIP32Node.from_master_secret('secret-djroot', netcode=netcode) public_key = private_wallet.wallet_key(as_private=False) djroot_wallet = BitcoinWallet.create(djroot_user, public_key=public_key) djroot_wallet.save() monkeypatch.setattr('django.conf.settings.BTC_MAIN_WALLET', djroot_wallet.address) return djroot_wallet
def test_vector_1(self): master = BIP32Node.from_master_secret(h2b("000102030405060708090a0b0c0d0e0f")) self.assertEqual(master.wallet_key(as_private=True), "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi") self.assertEqual(master.bitcoin_address(), "15mKKb2eos1hWa6tisdPwwDC1a5J1y9nma") self.assertEqual(master.wif(), "L52XzL2cMkHxqxBXRyEpnPQZGUs3uKiL3R11XbAdHigRzDozKZeW") self.assertEqual(master.wallet_key(), "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8") m0p = master.subkey(is_hardened=True) self.assertEqual(m0p.wallet_key(), "xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw") self.assertEqual(m0p.wallet_key(as_private=True), "xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7") self.assertEqual(master.subkey_for_path("0p").wallet_key(), m0p.wallet_key()) pub_mp0 = master.subkey(is_hardened=True, as_private=False) self.assertEqual(pub_mp0.wallet_key(), m0p.wallet_key()) self.assertEqual(master.subkey_for_path("0p.pub").wallet_key(), pub_mp0.wallet_key()) m0p1 = m0p.subkey(i=1) self.assertEqual(m0p1.wallet_key(), "xpub6ASuArnXKPbfEwhqN6e3mwBcDTgzisQN1wXN9BJcM47sSikHjJf3UFHKkNAWbWMiGj7Wf5uMash7SyYq527Hqck2AxYysAA7xmALppuCkwQ") self.assertEqual(m0p1.wallet_key(as_private=True), "xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs") self.assertEqual(master.subkey_for_path("0p/1").wallet_key(), m0p1.wallet_key()) pub_m0p1 = m0p.subkey(i=1, as_private=False) self.assertEqual(pub_m0p1.wallet_key(), m0p1.wallet_key()) self.assertEqual(master.subkey_for_path("0p/1.pub").wallet_key(), pub_m0p1.wallet_key()) m0p1_1_2p = m0p1.subkey(i=2, is_hardened=True) self.assertEqual(m0p1_1_2p.wallet_key(), "xpub6D4BDPcP2GT577Vvch3R8wDkScZWzQzMMUm3PWbmWvVJrZwQY4VUNgqFJPMM3No2dFDFGTsxxpG5uJh7n7epu4trkrX7x7DogT5Uv6fcLW5") self.assertEqual(m0p1_1_2p.wallet_key(as_private=True), "xprv9z4pot5VBttmtdRTWfWQmoH1taj2axGVzFqSb8C9xaxKymcFzXBDptWmT7FwuEzG3ryjH4ktypQSAewRiNMjANTtpgP4mLTj34bhnZX7UiM") self.assertEqual(master.subkey_for_path("0p/1/2p").wallet_key(), m0p1_1_2p.wallet_key()) pub_m0p1_1_2p = m0p1.subkey(i=2, as_private=False, is_hardened=True) self.assertEqual(pub_m0p1_1_2p.wallet_key(), m0p1_1_2p.wallet_key()) self.assertEqual(master.subkey_for_path("0p/1/2p.pub").wallet_key(), pub_m0p1_1_2p.wallet_key()) m0p1_1_2p_2 = m0p1_1_2p.subkey(i=2) self.assertEqual(m0p1_1_2p_2.wallet_key(), "xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV") self.assertEqual(m0p1_1_2p_2.wallet_key(as_private=True), "xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334") self.assertEqual(master.subkey_for_path("0p/1/2p/2").wallet_key(), m0p1_1_2p_2.wallet_key()) pub_m0p1_1_2p_2 = m0p1_1_2p.subkey(i=2, as_private=False) self.assertEqual(pub_m0p1_1_2p_2.wallet_key(), m0p1_1_2p_2.wallet_key()) self.assertEqual(master.subkey_for_path("0p/1/2p/2.pub").wallet_key(), pub_m0p1_1_2p_2.wallet_key()) m0p1_1_2p_2_1000000000 = m0p1_1_2p_2.subkey(i=1000000000) self.assertEqual(m0p1_1_2p_2_1000000000.wallet_key(), "xpub6H1LXWLaKsWFhvm6RVpEL9P4KfRZSW7abD2ttkWP3SSQvnyA8FSVqNTEcYFgJS2UaFcxupHiYkro49S8yGasTvXEYBVPamhGW6cFJodrTHy") self.assertEqual(m0p1_1_2p_2_1000000000.wallet_key(as_private=True), "xprvA41z7zogVVwxVSgdKUHDy1SKmdb533PjDz7J6N6mV6uS3ze1ai8FHa8kmHScGpWmj4WggLyQjgPie1rFSruoUihUZREPSL39UNdE3BBDu76") self.assertEqual(master.subkey_for_path("0p/1/2p/2/1000000000").wallet_key(), m0p1_1_2p_2_1000000000.wallet_key()) pub_m0p1_1_2p_2_1000000000 = m0p1_1_2p_2.subkey(i=1000000000, as_private=False) self.assertEqual(pub_m0p1_1_2p_2_1000000000.wallet_key(), m0p1_1_2p_2_1000000000.wallet_key()) self.assertEqual(master.subkey_for_path("0p/1/2p/2/1000000000.pub").wallet_key(), pub_m0p1_1_2p_2_1000000000.wallet_key())
def test_repr(self): from pycoin.key import Key netcode = 'XTN' key = Key(secret_exponent=273, netcode=netcode) wallet = BIP32Node.from_master_secret(bytes(key.wif().encode('ascii')), netcode) address = wallet.address() pub_k = wallet.from_text(address) self.assertEqual(repr(pub_k), '<myb5gZNXePNf2E2ksrjnHRFCwyuvt7oEay>') wif = wallet.wif() priv_k = wallet.from_text(wif) self.assertEqual(repr(priv_k), 'private_for <03ad094b1dc9fdce5d3648ca359b4e210a89d049532fdd39d9ccdd8ca393ac82f4>')
def __init__(self, password, testnet=False): """ Create a BIP32 wallet. Addresses return by the wallet are of the form (path, address) :password: master secret for the wallet :testnet: testnet flag. Defaults to false :returns: instance of the Wallet """ netcode = 'XTN' if testnet else 'BTC' self.wallet = BIP32Node.from_master_secret(password, netcode=netcode) self.root_address = ('', self.wallet.address())
def __init__(self): conf = read_config_file("ew.conf") if conf['entropy']: entropy = binascii.unhexlify(conf['entropy']) else: mnemo = Mnemonic('english') entropy = mnemo.to_entropy(conf['passphrase']) print("entropy=" + entropy.hex()) master = BIP32Node.from_master_secret(entropy, 'BTC') print("master address=" + master.address()) # /m/4544288'/0'/0'/0/0 alias alias = master.subkey(i=EW_DERIVATION, is_hardened=True).subkey(i=0, is_hardened=True).subkey(i=0, is_hardened=True).subkey(i=0, is_hardened=False).subkey(i=0, is_hardened=False) self.address = alias.address() print("alias address=" + self.address) self.key = CBitcoinSecret(alias.wif())
def __init__(self, w3, mnemonic, index): self.w3 = w3 master_key = BIP32Node.from_master_secret( Mnemonic("english").to_seed(mnemonic)) purpose_subtree = master_key.subkey(i=44, is_hardened=True) coin_type_subtree = purpose_subtree.subkey(i=60, is_hardened=True) account_subtree = coin_type_subtree.subkey(i=0, is_hardened=True) change_subtree = account_subtree.subkey(i=0) account = change_subtree.subkey(i=index) self.private_key = account.secret_exponent().to_bytes(32, 'big') public_key = ecdsa.SigningKey.from_string(string=self.private_key, curve=ecdsa.SECP256k1, hashfunc=hashlib.sha256).get_verifying_key() self.address = self.w3.toChecksumAddress( "0x" + self.w3.sha3(hexstr=public_key.to_string().hex())[12:].hex())
def __init__(self, password, testnet=False): """ Initializes a BIP32 wallet. Addresses returned by the wallet are of the form ``(path, address)``. Args: password (bytes): Master secret for the wallet. The password can also be passed as a string (``str``). testnet (bool): Wwether to use the bitcoin testnet or mainnet. Defaults to ``False``. """ netcode = 'XTN' if testnet else 'BTC' if isinstance(password, str): password = password.encode() self.wallet = BIP32Node.from_master_secret(password, netcode=netcode) self.root_address = ('', self.wallet.address())
def get_new_address(wallet_num): passphrase = sha256(b"%s" % random.randint(0, 2**30)).hexdigest() wallet = BIP32Node.from_master_secret(passphrase) ret = dump_node(wallet) children = [] # Now build up some random paths # Just go five deep path = "m" for depth in range(5): child_number = random.randint(0, 0x80000000) path = "%s/%s" % (path, child_number) prime = random.choice([True, False]) if prime: path += "'" children.append( {"path": path, "child": dump_node(wallet.subkey_for_path(path[2:]))}) ret['children'] = children return ret
def test_is_public_private_bip32_valid(self): WALLET_KEYS = ["foo", "1", "2", "3", "4", "5"] # not all networks support BIP32 yet for netcode in "BTC XTN DOGE".split(): for wk in WALLET_KEYS: wallet = BIP32Node.from_master_secret(wk.encode("utf8"), netcode=netcode) text = wallet.wallet_key(as_private=True) self.assertEqual(is_private_bip32_valid(text, allowable_netcodes=NETWORK_NAMES), netcode) self.assertEqual(is_public_bip32_valid(text, allowable_netcodes=NETWORK_NAMES), None) a = text[:-1] + chr(ord(text[-1])+1) self.assertEqual(is_private_bip32_valid(a, allowable_netcodes=NETWORK_NAMES), None) self.assertEqual(is_public_bip32_valid(a, allowable_netcodes=NETWORK_NAMES), None) text = wallet.wallet_key(as_private=False) self.assertEqual(is_private_bip32_valid(text, allowable_netcodes=NETWORK_NAMES), None) self.assertEqual(is_public_bip32_valid(text, allowable_netcodes=NETWORK_NAMES), netcode) a = text[:-1] + chr(ord(text[-1])+1) self.assertEqual(is_private_bip32_valid(a, allowable_netcodes=NETWORK_NAMES), None) self.assertEqual(is_public_bip32_valid(a, allowable_netcodes=NETWORK_NAMES), None)
def test_vector_2(self): master = BIP32Node.from_master_secret(h2b("fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542")) self.assertEqual(master.wallet_key(as_private=True), "xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U") self.assertEqual(master.wallet_key(), "xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB") m0 = master.subkey() self.assertEqual(m0.wallet_key(), "xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH") self.assertEqual(m0.wallet_key(as_private=True), "xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt") pub_m0 = master.subkey(as_private=False) self.assertEqual(pub_m0.wallet_key(), m0.wallet_key()) m0_2147483647p = m0.subkey(i=2147483647, is_hardened=True) self.assertEqual(m0_2147483647p.wallet_key(), "xpub6ASAVgeehLbnwdqV6UKMHVzgqAG8Gr6riv3Fxxpj8ksbH9ebxaEyBLZ85ySDhKiLDBrQSARLq1uNRts8RuJiHjaDMBU4Zn9h8LZNnBC5y4a") self.assertEqual(m0_2147483647p.wallet_key(as_private=True), "xprv9wSp6B7kry3Vj9m1zSnLvN3xH8RdsPP1Mh7fAaR7aRLcQMKTR2vidYEeEg2mUCTAwCd6vnxVrcjfy2kRgVsFawNzmjuHc2YmYRmagcEPdU9") pub_m0_2147483647p = m0.subkey(i=2147483647, is_hardened=True, as_private=False) self.assertEqual(pub_m0_2147483647p.wallet_key(), m0_2147483647p.wallet_key()) m0_2147483647p_1 = m0_2147483647p.subkey(i=1) self.assertEqual(m0_2147483647p_1.wallet_key(), "xpub6DF8uhdarytz3FWdA8TvFSvvAh8dP3283MY7p2V4SeE2wyWmG5mg5EwVvmdMVCQcoNJxGoWaU9DCWh89LojfZ537wTfunKau47EL2dhHKon") self.assertEqual(m0_2147483647p_1.wallet_key(as_private=True), "xprv9zFnWC6h2cLgpmSA46vutJzBcfJ8yaJGg8cX1e5StJh45BBciYTRXSd25UEPVuesF9yog62tGAQtHjXajPPdbRCHuWS6T8XA2ECKADdw4Ef") pub_m0_2147483647p_1 = m0_2147483647p.subkey(i=1, as_private=False) self.assertEqual(pub_m0_2147483647p_1.wallet_key(), m0_2147483647p_1.wallet_key()) pub_m0_2147483647p_1 = pub_m0_2147483647p.subkey(i=1, as_private=False) self.assertEqual(pub_m0_2147483647p_1.wallet_key(), m0_2147483647p_1.wallet_key()) m0_2147483647p_1_2147483646p = m0_2147483647p_1.subkey(i=2147483646, is_hardened=True) self.assertEqual(m0_2147483647p_1_2147483646p.wallet_key(), "xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL") self.assertEqual(m0_2147483647p_1_2147483646p.wallet_key(as_private=True), "xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc") pub_m0_2147483647p_1_2147483646p = m0_2147483647p_1.subkey(i=2147483646, as_private=False, is_hardened=True) self.assertEqual(pub_m0_2147483647p_1_2147483646p.wallet_key(), m0_2147483647p_1_2147483646p.wallet_key()) m0_2147483647p_1_2147483646p_2 = m0_2147483647p_1_2147483646p.subkey(i=2) self.assertEqual(m0_2147483647p_1_2147483646p_2.wif(), "L3WAYNAZPxx1fr7KCz7GN9nD5qMBnNiqEJNJMU1z9MMaannAt4aK") self.assertEqual(m0_2147483647p_1_2147483646p_2.wallet_key(), "xpub6FnCn6nSzZAw5Tw7cgR9bi15UV96gLZhjDstkXXxvCLsUXBGXPdSnLFbdpq8p9HmGsApME5hQTZ3emM2rnY5agb9rXpVGyy3bdW6EEgAtqt") self.assertEqual(m0_2147483647p_1_2147483646p_2.wallet_key(as_private=True), "xprvA2nrNbFZABcdryreWet9Ea4LvTJcGsqrMzxHx98MMrotbir7yrKCEXw7nadnHM8Dq38EGfSh6dqA9QWTyefMLEcBYJUuekgW4BYPJcr9E7j") pub_m0_2147483647p_1_2147483646p_2 = m0_2147483647p_1_2147483646p.subkey(i=2, as_private=False) self.assertEqual(pub_m0_2147483647p_1_2147483646p_2.wallet_key(), m0_2147483647p_1_2147483646p_2.wallet_key()) pub_m0_2147483647p_1_2147483646p_2 = pub_m0_2147483647p_1_2147483646p.subkey(i=2, as_private=False) self.assertEqual(pub_m0_2147483647p_1_2147483646p_2.wallet_key(), m0_2147483647p_1_2147483646p_2.wallet_key()) self.assertEqual(master.subkey_for_path("0/2147483647p/1/2147483646p/2").wallet_key(), m0_2147483647p_1_2147483646p_2.wallet_key()) self.assertEqual(master.subkey_for_path("0/2147483647p/1/2147483646p/2.pub").wallet_key(), pub_m0_2147483647p_1_2147483646p_2.wallet_key())
def test_public_subkey(self): my_prv = BIP32Node.from_master_secret(b"foo") uag = my_prv.subkey(i=0, is_hardened=True, as_private=True) self.assertEqual(None, uag.subkey(i=0, as_private=False).secret_exponent()) with self.assertRaises(ValueError) as cm: my_prv.subkey(i=-1) err = cm.exception self.assertEqual(err.args, ("i can't be negative", )) for p in ( '-1', '0/-1', '0H/-1' ): with self.assertRaises(ValueError) as cm: my_prv.subkey_for_path(p) err = cm.exception self.assertEqual(err.args, ("i can't be negative", )) self.assertRaises(ValueError, list, my_prv.subkeys('-1')) self.assertRaises(ValueError, list, my_prv.subkeys('-1-0'))
def __init__(self): self.lastAddr = None self.specting_operations = {} self.just_started = True self.last_operation = 0 # we'll need an address list...... self.block_relation = {} # Dict Block (Set addresses) self.address_cache = {} # while testing... # example # { "1GzRWJo4xExrZpi8FW3uQ2aYESk8sJMoQz" : ( { ("dcsdcsd134wdccsdc",3) : (True,12983209000,34,34900934094334) # preferenceAsOld, value, confirmations,timestmp # , ("jjjdcsdwswscscsdc",5) : (True, 3209000,34,34900932094334) # } # , 0 # , 0 # ) self.master_node = BIP32Node.from_master_secret("secret phrase, in future versions it will use the trezor instead",netcode='XTN') self.address_index = 0 self.addresses = [] # redundant_info, for eficiency purporsses, the same as address_cache but with its key-values flipped, so we can efficiently choose the right utxo... self.utxo = {} self.sorted_utxo = {} self.confirmed = 0 self.unconfirmed = 0 self.private_key = {} # TODO, check confirm always stands before unconfirmed return
def decoded_raw_transfer_tx(rpconn, piece_hashes, spool_regtest, transactions): from spool import Spool sender_password = uuid1().hex.encode('utf-8') sender_wallet = BIP32Node.from_master_secret(sender_password, netcode='XTN') sender_address = sender_wallet.bitcoin_address() rpconn.importaddress(sender_address) rpconn.sendtoaddress(sender_address, Spool.FEE/100000000) rpconn.sendtoaddress(sender_address, Spool.TOKEN/100000000) rpconn.sendtoaddress(sender_address, Spool.TOKEN/100000000) rpconn.sendtoaddress(sender_address, Spool.TOKEN/100000000) rpconn.generate(1) receiver_address = rpconn.getnewaddress() # TODO do not rely on Spool txid = spool_regtest.transfer( ('', sender_address), receiver_address, piece_hashes, sender_password, 5, min_confirmations=1, ) return transactions.get(txid)
assert len(pcode) == 80 return pcode def pcode_b58(pcode): PREFIX = b'\x46' # Spec recommends b'\x23' return b2a_hashed_base58( PREFIX + pcode ) def node_to_pcode(node): sec = node.sec() return payment_code(sec[0], sec[1:], node.chain_code()) def pretty_json( obj ): return json.dumps(obj, indent=4, sort_keys=True) alice_wallet = BIP32Node.from_master_secret("Alice", netcode="XTN") alice_ident0 = alice_wallet.subkey_for_path("47'/0'/0'") alice_notif = alice_ident0.subkey_for_path("0/0") alice_pcode = pcode_b58( node_to_pcode(alice_ident0) ) bob_wallet = BIP32Node.from_master_secret("Bob", netcode="XTN") bob_ident0 = bob_wallet.subkey_for_path("47'/0'/0'") bob_notif = bob_ident0.subkey_for_path("0/0") bob_pcode = pcode_b58( node_to_pcode(bob_ident0) ) print "Alice's Payment Code (b58c):", alice_pcode print "Alice's Notification Address:", alice_notif.address(), '\n' print "Bob's Payment Code (b58c):", bob_pcode print "Bob's Notification Address:", bob_notif.address(), '\n'
def carol_hd_wallet(): return BIP32Node.from_master_secret(b'carol-secret', netcode='XTN')
def bob_hd_wallet(): return BIP32Node.from_master_secret(b'bob-secret', netcode='XTN')
def alice_hd_wallet(): return BIP32Node.from_master_secret(b'alice-secret', netcode='XTN')
def random_bip32_wallet(): return BIP32Node.from_master_secret( uuid1().hex.encode('utf-8'), netcode='XTN')