def test_chain_pubkey_derivation(self): account_master_pubkeys = self.wallet.accounts["0"].get_master_pubkeys() x1_btc_pubkey = bip32_public_derivation( self.wallet.master_public_keys.get("x1/"), "", "/0") self.assertEqual( 'xpub6CfssEAJDCoTHU922RJy8oyXkdPNP8sMFxorzG9ncAbZjZRKCq5NFdRVybzvqHSPntpRDfHtGErXPbk1Y9uAJGJLZFtscVCMZP7mnRFqyQX', account_master_pubkeys[0]) x2_btc_pubkey = bip32_public_derivation( self.wallet.master_public_keys.get("x2/"), "", "/0") self.assertEqual( 'xpub6Ckpjg1oUbAUwXAChU3eWAovMZTWmdMLFskZvRbVTbd8QNM5XG1WdBDubzFAkJjMMktsRRyyzhNKPuYaGNgroYuaz8R3fCGiLWBvmbXX1F2', account_master_pubkeys[1]) # switch chains self._switch_chain("MZC") account_master_pubkeys = self.wallet.accounts["0"].get_master_pubkeys() x1_mzc_pubkey = bip32_public_derivation( self.wallet.master_public_keys.get("x2/"), "", "/13") self.assertEqual( 'xpub6CfssEAJDCoTrhLTgjvQU5PYkwT81bBvuBsnVJ1eP2XDxhNLfbVDHC8G9kxwcSpAtGFEoLqkUrz64nV59kV8fDqkFc3xjn6nUbtiwmQzrRe', account_master_pubkeys[0]) x2_mzc_pubkey = bip32_public_derivation( self.wallet.master_public_keys.get("x2/"), "", "/13") self.assertEqual( 'xpub6Ckpjg1oUbAVWUPSbpbSkNEieqQyxnFCbJG2EnR6AnZUZWuxD6WCDwVQScUaLcUHmbBEuJfM8HCw912QXNGN9FHLQzzPgvsnxMt1YTzbeys', account_master_pubkeys[1])
def test_redeem_script(self): acc = self.wallet.accounts["0"] x1_first_btc_key = bip32_public_derivation( self.wallet.master_public_keys.get("x1/"), "", "/0/0/0") x2_first_btc_key = bip32_public_derivation( self.wallet.master_public_keys.get("x2/"), "", "/0/0/0") x3_first_btc_key = bip32_public_derivation( self.wallet.master_public_keys.get("x3/"), "", "/0/0/0") x4_first_btc_key = bip32_public_derivation( self.wallet.master_public_keys.get("x4/"), "", "/0/0/0") x_pubkeys = [ x1_first_btc_key, x2_first_btc_key, x3_first_btc_key, x4_first_btc_key ] raw_pubkeys = map(lambda x: deserialize_xkey(x)[4], x_pubkeys) pubkeys = map(lambda x: x.encode('hex'), raw_pubkeys) # Compare redeem script to manually calculated one redeem_script = multisig_script(sorted(pubkeys), acc.multisig_m) self.assertEqual( '53210278a1a7de63493a8c8e0e7f4ebb13fd2a8144db25bb3bc2e5f44127a851a389332102ee780aa224c9fe54caff984205077b7cca08ced3188a3f3c639d83deda6b9a592103124429ddbed55593d0abea0d0d3d283eca4546e40017b2945f4666c561b494ba210312872f0aa80fa1a9bc7df77fa5be310f5441f7bfec798fe19209b04954dec8da54ae', redeem_script) p2sh_addr = hash_160_to_bc_address( hash_160(redeem_script.decode('hex')), self.wallet.active_chain.p2sh_version) self.assertEqual("32Ktuh5jGEAAJyNXQE7f1LUAcMXSfvdSzE", p2sh_addr)
def test_p2sh_address_creation(self): x1_first_btc_key = bip32_public_derivation(self.wallet.master_public_keys.get("x1/"), "", "/0/0/0") x2_first_btc_key = bip32_public_derivation(self.wallet.master_public_keys.get("x2/"), "", "/0/0/0") x_pubkeys = [x1_first_btc_key, x2_first_btc_key] raw_pubkeys = map( lambda x: deserialize_xkey(x)[4], x_pubkeys ) pubkeys = map( lambda x: x.encode('hex'), raw_pubkeys ) # Compare redeem script to manually calculated one redeem_script = Transaction.multisig_script(sorted(pubkeys), 2) self.assertEqual('522102ee780aa224c9fe54caff984205077b7cca08ced3188a3f3c639d83deda6b9a592103124429ddbed55593d0abea0d0d3d283eca4546e40017b2945f4666c561b494ba52ae', redeem_script) p2sh_addr = hash_160_to_bc_address( hash_160(redeem_script.decode('hex')), self.wallet.active_chain.p2sh_version ) self.assertEqual('3MqemPAHZDGLr537QBvU7i4dRFY3Xvad7X', p2sh_addr) # switch chains self._switch_chain("MZC") x1_first_mzc_key = bip32_public_derivation(self.wallet.master_public_keys.get("x1/"), "", "/13/0/0") x2_first_mzc_key = bip32_public_derivation(self.wallet.master_public_keys.get("x2/"), "", "/13/0/0") x_pubkeys = [x1_first_mzc_key, x2_first_mzc_key] raw_pubkeys = map( lambda x: deserialize_xkey(x)[4], x_pubkeys ) pubkeys = map( lambda x: x.encode('hex'), raw_pubkeys ) # Compare redeem script to manually calculated one redeem_script = Transaction.multisig_script(sorted(pubkeys), 2) self.assertEqual('5221027bdb7f5c42096580442e63235434bcc9ddf9689bbeb917705cd0edf9c6e264292102919725862f59a43274443ea11d7a8e25c15147213dcb6186c24d8629d37d6d8d52ae', redeem_script) p2sh_addr = hash_160_to_bc_address( hash_160(redeem_script.decode('hex')), self.wallet.active_chain.p2sh_version ) self.assertEqual('4jjXnsGuWLH3YgnagWH12kK7HjDtsBv8SQ', p2sh_addr)
def test_p2sh_address_creation(self): x1_first_btc_key = bip32_public_derivation(self.wallet.master_public_keys.get("x1/"), "", "/0/0/0") x2_first_btc_key = bip32_public_derivation(self.wallet.master_public_keys.get("x2/"), "", "/0/0/0") x_pubkeys = [x1_first_btc_key, x2_first_btc_key] raw_pubkeys = map( lambda x: deserialize_xkey(x)[4], x_pubkeys ) pubkeys = map( lambda x: x.encode('hex'), raw_pubkeys ) # Compare redeem script to manually calculated one redeem_script = multisig_script(sorted(pubkeys), 2) self.assertEqual('522102ee780aa224c9fe54caff984205077b7cca08ced3188a3f3c639d83deda6b9a592103124429ddbed55593d0abea0d0d3d283eca4546e40017b2945f4666c561b494ba52ae', redeem_script) p2sh_addr = hash_160_to_bc_address( hash_160(redeem_script.decode('hex')), self.wallet.active_chain.p2sh_version ) self.assertEqual('3MqemPAHZDGLr537QBvU7i4dRFY3Xvad7X', p2sh_addr) # switch chains self._switch_chain("MZC") x1_first_mzc_key = bip32_public_derivation(self.wallet.master_public_keys.get("x1/"), "", "/13/0/0") x2_first_mzc_key = bip32_public_derivation(self.wallet.master_public_keys.get("x2/"), "", "/13/0/0") x_pubkeys = [x1_first_mzc_key, x2_first_mzc_key] raw_pubkeys = map( lambda x: deserialize_xkey(x)[4], x_pubkeys ) pubkeys = map( lambda x: x.encode('hex'), raw_pubkeys ) # Compare redeem script to manually calculated one redeem_script = multisig_script(sorted(pubkeys), 2) self.assertEqual('5221027bdb7f5c42096580442e63235434bcc9ddf9689bbeb917705cd0edf9c6e264292102919725862f59a43274443ea11d7a8e25c15147213dcb6186c24d8629d37d6d8d52ae', redeem_script) p2sh_addr = hash_160_to_bc_address( hash_160(redeem_script.decode('hex')), self.wallet.active_chain.p2sh_version ) self.assertEqual('4jjXnsGuWLH3YgnagWH12kK7HjDtsBv8SQ', p2sh_addr)
def test_redeem_script(self): acc = self.wallet.accounts["0"] x1_first_btc_key = bip32_public_derivation(self.wallet.master_public_keys.get("x1/"), "", "/0/0/0") x2_first_btc_key = bip32_public_derivation(self.wallet.master_public_keys.get("x2/"), "", "/0/0/0") x3_first_btc_key = bip32_public_derivation(self.wallet.master_public_keys.get("x3/"), "", "/0/0/0") x4_first_btc_key = bip32_public_derivation(self.wallet.master_public_keys.get("x4/"), "", "/0/0/0") x_pubkeys = [x1_first_btc_key, x2_first_btc_key, x3_first_btc_key, x4_first_btc_key] raw_pubkeys = map( lambda x: deserialize_xkey(x)[4], x_pubkeys ) pubkeys = map( lambda x: x.encode('hex'), raw_pubkeys ) # Compare redeem script to manually calculated one redeem_script = multisig_script(sorted(pubkeys), acc.multisig_m) self.assertEqual('53210278a1a7de63493a8c8e0e7f4ebb13fd2a8144db25bb3bc2e5f44127a851a389332102ee780aa224c9fe54caff984205077b7cca08ced3188a3f3c639d83deda6b9a592103124429ddbed55593d0abea0d0d3d283eca4546e40017b2945f4666c561b494ba210312872f0aa80fa1a9bc7df77fa5be310f5441f7bfec798fe19209b04954dec8da54ae', redeem_script) p2sh_addr = hash_160_to_bc_address( hash_160(redeem_script.decode('hex')), self.wallet.active_chain.p2sh_version ) self.assertEqual("32Ktuh5jGEAAJyNXQE7f1LUAcMXSfvdSzE", p2sh_addr)
def test_chain_pubkey_derivation(self): account_master_pubkeys = self.wallet.accounts["0"].get_master_pubkeys() x1_btc_pubkey = bip32_public_derivation(self.wallet.master_public_keys.get("x1/"), "", "/0") self.assertEqual('xpub6CfssEAJDCoTHU922RJy8oyXkdPNP8sMFxorzG9ncAbZjZRKCq5NFdRVybzvqHSPntpRDfHtGErXPbk1Y9uAJGJLZFtscVCMZP7mnRFqyQX', account_master_pubkeys[0]) x2_btc_pubkey = bip32_public_derivation(self.wallet.master_public_keys.get("x2/"), "", "/0") self.assertEqual('xpub6Ckpjg1oUbAUwXAChU3eWAovMZTWmdMLFskZvRbVTbd8QNM5XG1WdBDubzFAkJjMMktsRRyyzhNKPuYaGNgroYuaz8R3fCGiLWBvmbXX1F2', account_master_pubkeys[1]) # switch chains self._switch_chain("MZC") account_master_pubkeys = self.wallet.accounts["0"].get_master_pubkeys() x1_mzc_pubkey = bip32_public_derivation(self.wallet.master_public_keys.get("x2/"), "", "/13") self.assertEqual('xpub6CfssEAJDCoTrhLTgjvQU5PYkwT81bBvuBsnVJ1eP2XDxhNLfbVDHC8G9kxwcSpAtGFEoLqkUrz64nV59kV8fDqkFc3xjn6nUbtiwmQzrRe', account_master_pubkeys[0]) x2_mzc_pubkey = bip32_public_derivation(self.wallet.master_public_keys.get("x2/"), "", "/13") self.assertEqual('xpub6Ckpjg1oUbAVWUPSbpbSkNEieqQyxnFCbJG2EnR6AnZUZWuxD6WCDwVQScUaLcUHmbBEuJfM8HCw912QXNGN9FHLQzzPgvsnxMt1YTzbeys', account_master_pubkeys[1])
def _do_test_bip32(self, seed, sequence): xprv, xpub = bip32_root(bfh(seed), 'standard') self.assertEqual("m/", sequence[0:2]) path = 'm' sequence = sequence[2:] for n in sequence.split('/'): child_path = path + '/' + n if n[-1] != "'": xpub2 = bip32_public_derivation(xpub, path, child_path) xprv, xpub = bip32_private_derivation(xprv, path, child_path) if n[-1] != "'": self.assertEqual(xpub, xpub2) path = child_path return xpub, xprv
def _do_test_bip32(self, seed, sequence, testnet): xprv, xpub = bip32_root(seed.decode('hex'), testnet) assert sequence[0:2] == "m/" path = 'm' sequence = sequence[2:] for n in sequence.split('/'): child_path = path + '/' + n if n[-1] != "'": xpub2 = bip32_public_derivation(xpub, path, child_path, testnet) xprv, xpub = bip32_private_derivation(xprv, path, child_path, testnet) if n[-1] != "'": assert xpub == xpub2 path = child_path return xpub, xprv
def test_transaction(self): wallet_keys = { 'xpub6GDQf5vZmrpQvD4ixNdqHmgSZ76Uo2Cg5isBupnvZpnNbhdRhgdhq9hkfCSKRE31rGfYuXNfZ5gTamFkj1GXt6k87MD1hUn28tuvLHY71Bk': 'L2FQCaHPwgS4CmAf6bKtbjVWDbcHv42c72by1zLEyLuDrUG22CwM', 'xpub6GLs33TeHkrLSTJ2uxiMLnuqxCHG9iBFCwjTwyg4EvzyxUi78U1sXxxRPUQfLGNEZRT3yYKEwR39ZbUtofEgcmTLtJdSetnFiQPEwTZRW5y': 'L1aD1WSA3UGU56sAmjfYVj1rK3fnSzWKj2wTsDTN1DpgUgPVwQCa', 'xpub6Fc64k9RTc79yD7xErF2yKSdUraGBhGWDt1FomUFVCFg52165LZvvoGL59hebJBGtauFqNL5zMeRgPGV29sfQp6XqoiiD9E53UDatBhFZuk': 'L25eCRYrDNVNrTZV1XZhmaZti3dVsZz3egm1R7LsPHRdpYuyLYKE' # 'xpub6GiSmJrVQC5q2m5cRcZvUgnGUsfeEqi3eEfUTgacnA33G8PAQnJeeMzpNAGUA9JL3goUui7BY52rVPwhmxMALkmFh5ZuwJDKrPv8ERkG3CK': 'L3jUPoR7fUwB9mwfuqqF79mHDpj5rpygQhdWntJ9ShZ9nbyRab5h' } acc = self.wallet.accounts["0"] redeem_script = '53210278a1a7de63493a8c8e0e7f4ebb13fd2a8144db25bb3bc2e5f44127a851a389332102ee780aa224c9fe54caff984205077b7cca08ced3188a3f3c639d83deda6b9a592103124429ddbed55593d0abea0d0d3d283eca4546e40017b2945f4666c561b494ba210312872f0aa80fa1a9bc7df77fa5be310f5441f7bfec798fe19209b04954dec8da54ae' coins = [{ 'address': '32SbQbBthcMzRSpCw1ifAXqWviJGH5HKUk', 'value': 600000, 'prevout_n': 0, 'prevout_hash': '1111111111111111111111111111111111111111111111111111111111111111', 'height': 100000, 'coinbase': 'True' }] txin = coins[0] x_pubkeys = map(lambda x: bip32_public_derivation(x, "", "/0/0/0"), self.wallet.master_public_keys.values()) pubkeys = map(lambda x: deserialize_xkey(x)[4].encode('hex'), x_pubkeys) s = ''.join(map(lambda x: int_to_hex(x, 2), (0, 0))) x_pubkeys = map( lambda x: 'ff' + DecodeBase58Check(x).encode('hex') + s, x_pubkeys) pubkeys, x_pubkeys = zip(*sorted(zip(pubkeys, x_pubkeys))) txin['pubkeys'] = list(pubkeys) txin['x_pubkeys'] = list(x_pubkeys) txin['signatures'] = [None] * len(pubkeys) txin['redeemScript'] = redeem_script txin['num_sig'] = acc.multisig_m outputs = [('address', '1PyXgL1qmZPuxcVi9CcguQb3v7WUvQZBud', 500000)] inputs = [] tx = Transaction(inputs, outputs) tx.add_input(txin) self.wallet.sign_transaction(tx, "secret") # ins = tx.inputs_to_sign() keypairs = {} sec = None for innard in ins: # this is easier than the commented loop below in_xpub, _ = BIP32_Account.parse_xpubkey(innard) if wallet_keys.get(in_xpub): keypairs[innard] = wallet_keys[in_xpub] # ... # in_xpub, in_seq = BIP32_Account.parse_xpubkey(innard) # sec = None # for k, vaccount in self.wallet.accounts.items(): # acc_v = vaccount.get_master_pubkeys()[0] # acc_xpub = bip32_public_derivation(acc_v, "", "/0/0") # if in_xpub == acc_xpub: # pk = vaccount.get_private_key(in_seq, self.wallet, "secret") # sec = pk[0] # if sec: # keypairs [ innard ] = sec if keypairs: tx.sign(keypairs) self.assertEqual( '0100000001111111111111111111111111111111111111111111111111111111111111111100000000fd6701004730440220774e80fda89895d8bf3ac39c38f39456d31c1e857dc1c77c000f4de6c3de15fe02207b6d13b5ba17eadeb607f3ca56f693a0b777dae668584cefec0910a8bc90869a0147304402205e80562254972f873b5b59b1cdc81e422c7a2959d8868e5a54238fbfdf6f107002200204eef593812453ae2c22334c409f9ef25523cf9619399eb2d3c249673443dc01483045022100a81e69796aa5e5ae0d8924047e3c81a8dd64dfbc791caba6728ac7820aa114da022060b85875fd58223b7c61ef45fac2567a9f76934f947e4d03d927f5b078e1fb45014c8b53210278a1a7de63493a8c8e0e7f4ebb13fd2a8144db25bb3bc2e5f44127a851a389332102ee780aa224c9fe54caff984205077b7cca08ced3188a3f3c639d83deda6b9a592103124429ddbed55593d0abea0d0d3d283eca4546e40017b2945f4666c561b494ba210312872f0aa80fa1a9bc7df77fa5be310f5441f7bfec798fe19209b04954dec8da54aeffffffff0120a10700000000001976a914fc03ab7c28d17349f084f7cadde4dafc356918d388ac00000000', str(tx)) ########### # serialized_tx = str(tx) tx2 = Transaction.deserialize(serialized_tx, active_chain=self.wallet.active_chain) self.assertEquals(4, len(tx2.inputs[0]['x_pubkeys'])) self.assertEquals(3, tx2.inputs[0]['num_sig'])
def test_transaction(self): wallet_keys = { 'xpub6GDQf5vZmrpQvD4ixNdqHmgSZ76Uo2Cg5isBupnvZpnNbhdRhgdhq9hkfCSKRE31rGfYuXNfZ5gTamFkj1GXt6k87MD1hUn28tuvLHY71Bk': 'L2FQCaHPwgS4CmAf6bKtbjVWDbcHv42c72by1zLEyLuDrUG22CwM', 'xpub6GLs33TeHkrLSTJ2uxiMLnuqxCHG9iBFCwjTwyg4EvzyxUi78U1sXxxRPUQfLGNEZRT3yYKEwR39ZbUtofEgcmTLtJdSetnFiQPEwTZRW5y': 'L1aD1WSA3UGU56sAmjfYVj1rK3fnSzWKj2wTsDTN1DpgUgPVwQCa', 'xpub6Fc64k9RTc79yD7xErF2yKSdUraGBhGWDt1FomUFVCFg52165LZvvoGL59hebJBGtauFqNL5zMeRgPGV29sfQp6XqoiiD9E53UDatBhFZuk': 'L25eCRYrDNVNrTZV1XZhmaZti3dVsZz3egm1R7LsPHRdpYuyLYKE' # 'xpub6GiSmJrVQC5q2m5cRcZvUgnGUsfeEqi3eEfUTgacnA33G8PAQnJeeMzpNAGUA9JL3goUui7BY52rVPwhmxMALkmFh5ZuwJDKrPv8ERkG3CK': 'L3jUPoR7fUwB9mwfuqqF79mHDpj5rpygQhdWntJ9ShZ9nbyRab5h' } acc = self.wallet.accounts["0"] redeem_script = '53210278a1a7de63493a8c8e0e7f4ebb13fd2a8144db25bb3bc2e5f44127a851a389332102ee780aa224c9fe54caff984205077b7cca08ced3188a3f3c639d83deda6b9a592103124429ddbed55593d0abea0d0d3d283eca4546e40017b2945f4666c561b494ba210312872f0aa80fa1a9bc7df77fa5be310f5441f7bfec798fe19209b04954dec8da54ae' coins = [ {'address': '32SbQbBthcMzRSpCw1ifAXqWviJGH5HKUk', 'value': 600000, 'prevout_n': 0, 'prevout_hash': '1111111111111111111111111111111111111111111111111111111111111111', 'height': 100000, 'coinbase': 'True' } ] txin = coins[0] x_pubkeys = map( lambda x:bip32_public_derivation(x, "", "/0/0/0"), self.wallet.master_public_keys.values() ) pubkeys = map(lambda x: deserialize_xkey(x)[4].encode('hex'), x_pubkeys) s = ''.join( map(lambda x: int_to_hex(x, 2), (0, 0))) x_pubkeys = map( lambda x: 'ff' + DecodeBase58Check(x).encode('hex') + s, x_pubkeys) pubkeys, x_pubkeys = zip( *sorted(zip(pubkeys, x_pubkeys))) txin['pubkeys'] = list(pubkeys) txin['x_pubkeys'] = list(x_pubkeys) txin['signatures'] = [None] * len(pubkeys) txin['redeemScript'] = redeem_script txin['num_sig'] = acc.multisig_m outputs = [ ('address', '1PyXgL1qmZPuxcVi9CcguQb3v7WUvQZBud', 500000) ] inputs = [] tx = Transaction(inputs, outputs) tx.add_input(txin) self.wallet.sign_transaction(tx, "secret") # ins = tx.inputs_to_sign() keypairs = {} sec = None for innard in ins: # this is easier than the commented loop below in_xpub, _ = BIP32_Account.parse_xpubkey(innard) if wallet_keys.get(in_xpub): keypairs[ innard ] = wallet_keys[in_xpub] # ... # in_xpub, in_seq = BIP32_Account.parse_xpubkey(innard) # sec = None # for k, vaccount in self.wallet.accounts.items(): # acc_v = vaccount.get_master_pubkeys()[0] # acc_xpub = bip32_public_derivation(acc_v, "", "/0/0") # if in_xpub == acc_xpub: # pk = vaccount.get_private_key(in_seq, self.wallet, "secret") # sec = pk[0] # if sec: # keypairs [ innard ] = sec if keypairs: tx.sign(keypairs) self.assertEqual('0100000001111111111111111111111111111111111111111111111111111111111111111100000000fd6701004730440220774e80fda89895d8bf3ac39c38f39456d31c1e857dc1c77c000f4de6c3de15fe02207b6d13b5ba17eadeb607f3ca56f693a0b777dae668584cefec0910a8bc90869a0147304402205e80562254972f873b5b59b1cdc81e422c7a2959d8868e5a54238fbfdf6f107002200204eef593812453ae2c22334c409f9ef25523cf9619399eb2d3c249673443dc01483045022100a81e69796aa5e5ae0d8924047e3c81a8dd64dfbc791caba6728ac7820aa114da022060b85875fd58223b7c61ef45fac2567a9f76934f947e4d03d927f5b078e1fb45014c8b53210278a1a7de63493a8c8e0e7f4ebb13fd2a8144db25bb3bc2e5f44127a851a389332102ee780aa224c9fe54caff984205077b7cca08ced3188a3f3c639d83deda6b9a592103124429ddbed55593d0abea0d0d3d283eca4546e40017b2945f4666c561b494ba210312872f0aa80fa1a9bc7df77fa5be310f5441f7bfec798fe19209b04954dec8da54aeffffffff0120a10700000000001976a914fc03ab7c28d17349f084f7cadde4dafc356918d388ac00000000', str(tx)) ########### # serialized_tx = str(tx) tx2 = Transaction.deserialize(serialized_tx, active_chain = self.wallet.active_chain) self.assertEquals(4, len( tx2.inputs[0]['x_pubkeys']) ) self.assertEquals(3, tx2.inputs[0]['num_sig'] )