def test_initial_key(self): RECEIVING_ADDRESSES = [ "1LDkC1H438qSnJLHCYkQ3WTZQkSEwoYGHc", "12mENAcc8ZhZbR6hv7LGm3jV7PwbYeF8Xk", "1A3NpABFd6YHvwr1ti1r8brU3BzQuV2Nr4", "1Gn6nWAoZrpmtV9zuNbyivWvRBpcygWaQX", "1M5i5P3DhtDbnvSTfmnUbcrTVgF8GDWQW9", ] CHANGE_ADDRESSES = [ "1iiAbyBTh1J69UzD1JcrfW8JSVJ9ve9gT", "146wnqmsQNYCZ6AXRCqLkzZyGM1ZU6nr3F", "1Mwexajvia3s8AcaGUkyEg9ZZJPJeTbKTZ", ] wallet = ElectrumWallet(initial_key="00000000000000000000000000000001") for idx, address in enumerate(RECEIVING_ADDRESSES): subkey = wallet.subkey("%s/0" % idx) calculated_address = subkey.address() self.assertEqual(address, calculated_address) wif = subkey.wif() key = Key.from_text(wif) self.assertEqual(key.address(use_uncompressed=True), address) for idx, address in enumerate(CHANGE_ADDRESSES): subkey = wallet.subkey("%s/1" % idx) calculated_address = subkey.address() self.assertEqual(address, calculated_address) wif = subkey.wif() key = Key.from_text(wif) self.assertEqual(key.address(use_uncompressed=True), address)
def test_initial_key(self): RECEIVING_ADDRESSES = [ "1LDkC1H438qSnJLHCYkQ3WTZQkSEwoYGHc", "12mENAcc8ZhZbR6hv7LGm3jV7PwbYeF8Xk", "1A3NpABFd6YHvwr1ti1r8brU3BzQuV2Nr4", "1Gn6nWAoZrpmtV9zuNbyivWvRBpcygWaQX", "1M5i5P3DhtDbnvSTfmnUbcrTVgF8GDWQW9" ] CHANGE_ADDRESSES = [ "1iiAbyBTh1J69UzD1JcrfW8JSVJ9ve9gT", "146wnqmsQNYCZ6AXRCqLkzZyGM1ZU6nr3F", "1Mwexajvia3s8AcaGUkyEg9ZZJPJeTbKTZ" ] wallet = ElectrumWallet(initial_key="00000000000000000000000000000001") for idx, address in enumerate(RECEIVING_ADDRESSES): subkey = wallet.subkey("%s/0" % idx) calculated_address = subkey.address() self.assertEqual(address, calculated_address) wif = subkey.wif() key = Key.from_text(wif) self.assertEqual(key.address(use_uncompressed=True), address) for idx, address in enumerate(CHANGE_ADDRESSES): subkey = wallet.subkey("%s/1" % idx) calculated_address = subkey.address() self.assertEqual(address, calculated_address) wif = subkey.wif() key = Key.from_text(wif) self.assertEqual(key.address(use_uncompressed=True), address)
def do_test(exp_hex, wif, c_wif, public_pair_sec, c_public_pair_sec, address_b58, c_address_b58): secret_exponent = int(exp_hex, 16) sec = h2b(public_pair_sec) c_sec = h2b(c_public_pair_sec) keys_wif = [ Key(secret_exponent=secret_exponent), Key.from_text(wif), Key.from_text(c_wif), ] key_sec = Key.from_sec(sec) key_sec_c = Key.from_sec(c_sec) keys_sec = [key_sec, key_sec_c] for key in keys_wif: self.assertEqual(key.secret_exponent(), secret_exponent) self.assertEqual(key.public_copy().secret_exponent(), None) v = repr(key) if key._prefer_uncompressed: self.assertEqual(key.wif(), wif) else: self.assertEqual(key.wif(), c_wif) self.assertEqual(key.wif(use_uncompressed=True), wif) self.assertEqual(key.wif(use_uncompressed=False), c_wif) for key in keys_wif + keys_sec: if key._prefer_uncompressed: self.assertEqual(key.sec(), sec) else: self.assertEqual(key.sec(), c_sec) self.assertEqual(key.sec(use_uncompressed=True), sec) self.assertEqual(key.sec(use_uncompressed=False), c_sec) if key._prefer_uncompressed: self.assertEqual(key.address(), address_b58) else: self.assertEqual(key.address(), c_address_b58) self.assertEqual(key.address(use_uncompressed=False), c_address_b58) self.assertEqual(key.address(use_uncompressed=True), address_b58) key_pub = Key.from_text(address_b58, is_compressed=False) key_pub_c = Key.from_text(c_address_b58, is_compressed=True) self.assertEqual(key_pub.address(), address_b58) self.assertEqual(key_pub.address(use_uncompressed=True), address_b58) self.assertEqual(key_pub.address(use_uncompressed=False), None) self.assertEqual(key_pub_c.address(), c_address_b58) self.assertEqual(key_pub_c.address(use_uncompressed=True), None) self.assertEqual(key_pub_c.address(use_uncompressed=False), c_address_b58)
def test_repr(self): key = Key(secret_exponent=273, netcode='XTN') address = key.address() pub_k = Key.from_text(address) self.assertEqual(repr(pub_k), '<mhDVBkZBWLtJkpbszdjZRkH1o5RZxMwxca>') wif = key.wif() priv_k = Key.from_text(wif) self.assertEqual(repr(priv_k), 'private_for <0264e1b1969f9102977691a40431b0b672055dcf31163897d996434420e6c95dc9>')
def test_repr(self): key = Key(secret_exponent=273, netcode='XTN') address = key.address() pub_k = Key.from_text(address) self.assertEqual(repr(pub_k), '<mhDVBkZBWLtJkpbszdjZRkH1o5RZxMwxca>') wif = key.wif() priv_k = Key.from_text(wif) self.assertEqual( repr(priv_k), 'private_for <0264e1b1969f9102977691a40431b0b672055dcf31163897d996434420e6c95dc9>' )
def do_test(exp_hex, wif, c_wif, public_pair_sec, c_public_pair_sec, address_b58, c_address_b58): secret_exponent = int(exp_hex, 16) sec = h2b(public_pair_sec) c_sec = h2b(c_public_pair_sec) keys_wif = [ Key(secret_exponent=secret_exponent), Key.from_text(wif), Key.from_text(c_wif), ] key_sec = Key.from_sec(sec) key_sec_c = Key.from_sec(c_sec) keys_sec = [key_sec, key_sec_c] for key in keys_wif: self.assertEqual(key.secret_exponent(), secret_exponent) self.assertEqual(key.public_copy().secret_exponent(), None) repr(key) if key._prefer_uncompressed: self.assertEqual(key.wif(), wif) else: self.assertEqual(key.wif(), c_wif) self.assertEqual(key.wif(use_uncompressed=True), wif) self.assertEqual(key.wif(use_uncompressed=False), c_wif) for key in keys_wif + keys_sec: if key._prefer_uncompressed: self.assertEqual(key.sec(), sec) else: self.assertEqual(key.sec(), c_sec) self.assertEqual(key.sec(use_uncompressed=True), sec) self.assertEqual(key.sec(use_uncompressed=False), c_sec) if key._prefer_uncompressed: self.assertEqual(key.address(), address_b58) else: self.assertEqual(key.address(), c_address_b58) self.assertEqual(key.address(use_uncompressed=False), c_address_b58) self.assertEqual(key.address(use_uncompressed=True), address_b58) key_pub = Key.from_text(address_b58, is_compressed=False) key_pub_c = Key.from_text(c_address_b58, is_compressed=True) self.assertEqual(key_pub.address(), address_b58) self.assertEqual(key_pub.address(use_uncompressed=True), address_b58) self.assertEqual(key_pub.address(use_uncompressed=False), None) self.assertEqual(key_pub_c.address(), c_address_b58) self.assertEqual(key_pub_c.address(use_uncompressed=True), None) self.assertEqual(key_pub_c.address(use_uncompressed=False), c_address_b58)
def __init__(self, mainnet, dashrpc): self.dashrpc = dashrpc self.mainnet = mainnet self._init_state_dir(os.path.join(DASHVEND_DIR, 'state')) self.key = Key.from_text( mainnet and BIP32_MAINNET_SEED or BIP32_TESTNET_SEED) self._init_next_address()
def __init__(self, mainnet, dashrpc): self.dashrpc = dashrpc self.mainnet = mainnet self._init_state_dir(os.path.join(DASHVEND_DIR, 'state')) self.key = Key.from_text(mainnet and BIP32_MAINNET_SEED or BIP32_TESTNET_SEED) self._init_next_address()
def test_1(self): wallet = ElectrumWallet(initial_key="00000000000000000000000000000001") for idx, address in enumerate(RECEIVING_ADDRESSES): subkey = wallet.subkey("%s/0" % idx) calculated_address = subkey.address() self.assertEqual(address, calculated_address) wif = subkey.wif() key = Key.from_text(wif) self.assertEqual(key.address(use_uncompressed=True), address) for idx, address in enumerate(CHANGE_ADDRESSES): subkey = wallet.subkey("%s/1" % idx) calculated_address = subkey.address() self.assertEqual(address, calculated_address) wif = subkey.wif() key = Key.from_text(wif) self.assertEqual(key.address(use_uncompressed=True), address)
def test_sign_bitcoind_partially_signed_2_of_2(self): # Finish signing a 2 of 2 transaction, that already has one signature signed by bitcoind # This tx can be found on testnet3 blockchain # txid: 9618820d7037d2f32db798c92665231cd4599326f5bd99cb59d0b723be2a13a2 raw_script = ( "522103e33b41f5ed67a77d4c4c54b3e946bd30d15b8f66e42cb29fde059c168851165521" "02b92cb20a9fb1eb9656a74eeb7387636cf64cdf502ff50511830328c1b479986452ae" ) p2sh_lookup = build_p2sh_lookup([h2b(raw_script)]) partially_signed_raw_tx = ( "010000000196238f11a5fd3ceef4efd5a186a7e6b9217d900418e72aca917cd6a6e634" "e74100000000910047304402201b41b471d9dd93cf97eed7cfc39a5767a546f6bfbf3e" "0c91ff9ad23ab9770f1f02205ce565666271d055be1f25a7e52e34cbf659f6c70770ff" "59bd783a6fcd1be3dd0147522103e33b41f5ed67a77d4c4c54b3e946bd30d15b8f66e4" "2cb29fde059c16885116552102b92cb20a9fb1eb9656a74eeb7387636cf64cdf502ff5" "0511830328c1b479986452aeffffffff01a0bb0d00000000001976a9143b3beefd6f78" "02fa8706983a76a51467bfa36f8b88ac00000000") tx = Tx.from_hex(partially_signed_raw_tx) tx_out = TxOut(1000000, h2b("a914a10dfa21ee8c33b028b92562f6fe04e60563d3c087")) tx.set_unspents([tx_out]) key = Key.from_text( "cThRBRu2jAeshWL3sH3qbqdq9f4jDiDbd1SVz4qjTZD2xL1pdbsx") hash160_lookup = build_hash160_lookup([key.secret_exponent()]) self.assertEqual(tx.bad_signature_count(), 1) tx.sign(hash160_lookup=hash160_lookup, p2sh_lookup=p2sh_lookup) self.assertEqual(tx.bad_signature_count(), 0) self.assertEqual( tx.id(), "9618820d7037d2f32db798c92665231cd4599326f5bd99cb59d0b723be2a13a2")
def getOrCreateAddress(self, subpath_number): try: return Address.objects.get(wallet=self, subpath_number=subpath_number) except Address.DoesNotExist: pass new_address_full_path = self.path + [subpath_number] new_address_full_path_str = '/'.join([str(i) for i in new_address_full_path]) # Create raw bitcoin address and key key = Key.from_text(settings.MASTERWALLET_BIP32_KEY) subkey = key.subkeys(new_address_full_path_str).next() btc_address = subkey.address(use_uncompressed=False) btc_private_key = subkey.wif(use_uncompressed=False) # Make sure private key is stored to the database of bitcoind rpc = AuthServiceProxy('http://' + settings.BITCOIN_RPC_USERNAME + ':' + settings.BITCOIN_RPC_PASSWORD + '@' + settings.BITCOIN_RPC_IP + ':' + str(settings.BITCOIN_RPC_PORT)) try: rpc.importprivkey(btc_private_key, '', False) except: raise Exception('Unable to store Bitcoin address to Bitcoin node!') # Create new Address and return it new_address = Address(wallet=self, subpath_number=subpath_number, address=btc_address) new_address.save() return new_address
def handle(self, *args, **options): rpc = AuthServiceProxy('http://' + settings.BITCOIN_RPC_USERNAME + ':' + settings.BITCOIN_RPC_PASSWORD + '@' + settings.BITCOIN_RPC_IP + ':' + str(settings.BITCOIN_RPC_PORT)) private_keys_imported = False for address in Address.objects.all(): address_found = True try: rpc.dumpprivkey(address.address) except JSONRPCException as e: if e.code == -4: # Address is not found print 'Address ' + address.address + ' was not found. Importing it...' # Do some key magic new_address_full_path = address.wallet.path + [address.subpath_number] new_address_full_path_str = '/'.join([str(i) for i in new_address_full_path]) key = Key.from_text(settings.MASTERWALLET_BIP32_KEY) subkey = key.subkeys(new_address_full_path_str).next() # Check address and form the private key btc_address = subkey.address(use_uncompressed=False) assert btc_address == address.address btc_private_key = subkey.wif(use_uncompressed=False) # Do the importing rpc.importprivkey(btc_private_key, '', False) private_keys_imported = True if private_keys_imported: print 'Note! Private keys were added, but they were not scanned! Please restart bitcoin with -rescan option!'
def test_master_public_and_private(self): # these addresses were generated by hand using electrum with a master public key # corresponding to secret exponent 1 RECEIVING_ADDRESSES = [ "1AYPdHLna6bKFUbeXoAEVbaXUxifUwCMay", "13UeuWJba5epizAKyfCfiFKY5Kbxfdxe7B", "19f6KJUTL5AGBRvLBGiL6Zpcx53QA7zaKT", "1Cm33VuSkoUETwx5nsF1wgmGqYwJZxpZdY", "14Z6ErkETixQMUeivsYbrdoUFns2J1iSct", ] CHANGE_ADDRESSES = [ "1JVYsmjrqSy1BKvo1gYpNjX7AYea74nQYe", "1Cc7itfQaDqZK3vHYphFsySujQjBNba8mw", "15wrXvrAnyv3usGeQRohnnZ8tz9XAekbag", "1MnWCEjE5YiZpZrkP8HcXEeDqwg43RxLwu", "1Fgyp3PUx9AAg8yJe1zGXHP5dVC6i1tXbs", "12XTLd4u9jeqw4egLAUhoKLxHARCdKWkty" ] k = Key(secret_exponent=1) master_public_key = k.sec(use_uncompressed=True)[1:] wallet = ElectrumWallet(master_public_key=master_public_key) for idx, address in enumerate(RECEIVING_ADDRESSES): subkey = wallet.subkey("%s/0" % idx) calculated_address = subkey.address() self.assertEqual(address, calculated_address) for idx, address in enumerate(CHANGE_ADDRESSES): subkey = wallet.subkey("%s/1" % idx) calculated_address = subkey.address() self.assertEqual(address, calculated_address) wallet = ElectrumWallet(master_private_key=1) for idx, address in enumerate(RECEIVING_ADDRESSES): subkey = wallet.subkey("%s/0" % idx) calculated_address = subkey.address() self.assertEqual(address, calculated_address) wif = subkey.wif() key = Key.from_text(wif) self.assertEqual(key.address(use_uncompressed=True), address) for idx, address in enumerate(CHANGE_ADDRESSES): subkey = wallet.subkey("%s/1" % idx) calculated_address = subkey.address() self.assertEqual(address, calculated_address) wif = subkey.wif() key = Key.from_text(wif) self.assertEqual(key.address(use_uncompressed=True), address)
def test_master_public_and_private(self): # these addresses were generated by hand using electrum with a master public key # corresponding to secret exponent 1 RECEIVING_ADDRESSES = [ "1AYPdHLna6bKFUbeXoAEVbaXUxifUwCMay", "13UeuWJba5epizAKyfCfiFKY5Kbxfdxe7B", "19f6KJUTL5AGBRvLBGiL6Zpcx53QA7zaKT", "1Cm33VuSkoUETwx5nsF1wgmGqYwJZxpZdY", "14Z6ErkETixQMUeivsYbrdoUFns2J1iSct", ] CHANGE_ADDRESSES = [ "1JVYsmjrqSy1BKvo1gYpNjX7AYea74nQYe", "1Cc7itfQaDqZK3vHYphFsySujQjBNba8mw", "15wrXvrAnyv3usGeQRohnnZ8tz9XAekbag", "1MnWCEjE5YiZpZrkP8HcXEeDqwg43RxLwu", "1Fgyp3PUx9AAg8yJe1zGXHP5dVC6i1tXbs", "12XTLd4u9jeqw4egLAUhoKLxHARCdKWkty", ] k = Key(secret_exponent=1) master_public_key = k.sec(use_uncompressed=True)[1:] wallet = ElectrumWallet(master_public_key=master_public_key) for idx, address in enumerate(RECEIVING_ADDRESSES): subkey = wallet.subkey("%s/0" % idx) calculated_address = subkey.address() self.assertEqual(address, calculated_address) for idx, address in enumerate(CHANGE_ADDRESSES): subkey = wallet.subkey("%s/1" % idx) calculated_address = subkey.address() self.assertEqual(address, calculated_address) wallet = ElectrumWallet(master_private_key=1) for idx, address in enumerate(RECEIVING_ADDRESSES): subkey = wallet.subkey("%s/0" % idx) calculated_address = subkey.address() self.assertEqual(address, calculated_address) wif = subkey.wif() key = Key.from_text(wif) self.assertEqual(key.address(use_uncompressed=True), address) for idx, address in enumerate(CHANGE_ADDRESSES): subkey = wallet.subkey("%s/1" % idx) calculated_address = subkey.address() self.assertEqual(address, calculated_address) wif = subkey.wif() key = Key.from_text(wif) self.assertEqual(key.address(use_uncompressed=True), address)
def addr_to_script(addr): if addr[:2] == 't3': scr = 'a914' + a2b_hashed_base58(addr)[2:].encode('hex') + '87' return scr.decode('hex') assert addr[:2] == 't1' k = Key.from_text(addr) enc = '76a914' + k.hash160()[1:].encode('hex') + '88ac' return enc.decode('hex')
def pubkey_from_wif(wif): """ Get public key from given bitcoin wif. Args: wif (str): Private key encode in bitcoin wif format. Return: str: Hex encoded 33Byte compressed public key. """ return b2h(Key.from_text(wif).sec())
def address_from_wif(wif): """ Get bitcoin address from given bitcoin wif. Args: wif (str): Private key encode in bitcoin wif format. Return: str: Bitcoin address """ return Key.from_text(wif).address()
def wif_to_privkey(wif): """ Get private key from given bitcoin wif. Args: wif (str): Private key encode in bitcoin wif format. Return: str: Hex encoded 32Byte secret exponent """ return b2h(encoding.to_bytes_32(Key.from_text(wif).secret_exponent()))
def pkh_segwit_address_from_wif(wif): """ The P2SH redeemScript is always 22 bytes. It starts with a OP_0, followed by a canonical push of the keyhash (i.e. 0x0014{20-byte keyhash}) Same as any other P2SH, the scriptPubKey is OP_HASH160 hash160(redeemScript) OP_EQUAL """ my_key = Key.from_text(wif) script = ScriptPayToAddressWit(b'\0', my_key.hash160()).script() script_hex = binascii.hexlify(script).decode() return address_for_pay_to_script(script, netcode=NET_CODE), script_hex
def test_p2wpkh_native(self): from pycoin.key import Key node = Key.from_text( 'zpub6nsHdRuY92FsMKdbn9BfjBCG6X8pyhCibNP6uDvpnw2cyrVhecvHRMa3Ne8kdJZxjxgwnpbHLkcR4bfnhHy6auHPJyDTQ3kianeuVLdkCYQ' ) self.assertEqual( node.subkey(0).subkey(0).address(), 'bc1q3g5tmkmlvxryhh843v4dz026avatc0zzr6h3af') self.assertEqual( node.subkey(1).subkey(0).address(), 'bc1qdy94n2q5qcp0kg7v9yzwe6wvfkhnvyzje7nx2p')
def test_p2wpkh_native_testnet(self): from pycoin.key import Key node = Key.from_text( 'vpub5aHCMN33HjfXNzN9F3FkUVwr43DMj6FgjVbeAKgUWf9iS56RTGw5MaNdLi7jy49eZmJmP7eQYcA3m6CjWc3UduXfZr4ggipy6wfofB6xtaV' ) self.assertEqual( node.subkey(1).subkey(2).address(), 'tb1qweczj5ypy6x92e98f5leq8x3frrqdhp6yearkh') self.assertEqual( node.subkey(3).subkey(4).address(), 'tb1qpkwg0m8xtxg95gczglc4x04ccq52ns3ez74kq2')
def test_p2wpkh_in_p2sh_testnet(self): from pycoin.key import Key node = Key.from_text( 'upub5FS3DrUQtjhPtXF9ckWB6wZVpW42bVU696FJKGohDu4KGTEkkxsAQNdkqU7ihyMKPCtPauBQ8EGN4zJWasC3TrTTdFhR9XyATvjeM5AHgrR' ) self.assertEqual( node.subkey(1).subkey(2).address(), '2MuAxAoui1rKSr9Ugp2w5G5PbYjdFkuEo1x') self.assertEqual( node.subkey(3).subkey(4).address(), '2NE2981iCZBoYgBynpSDWuqF8RWMuBVxdoL')
def test_testnet(self): from pycoin.key import Key node = Key.from_text( 'tpubDEenJGgVMucDfF8qb3MdhJhiGVZ8P2DUzw8NBtNc4uWRPGqUNNmxqUR8M3c1KwN3yE3CFm8nMLQmZH47Q65RQmsSiLenXhxD42DSU1CWyiz' ) self.assertEqual( node.subkey(1).subkey(2).address(), 'mvq2eqwKs9LQdFNH6BKEhw11udKjqDjo5J') self.assertEqual( node.subkey(3).subkey(4).address(), 'mpAgWFoJM5HYCz4byuvaHBfP8taCFPVPR7')
def test_p2wpkh_in_p2sh(self): from pycoin.key import Key node = Key.from_text( 'ypub6XDth9u8DzXV1tcpDtoDKMf6kVMaVMn1juVWEesTshcX4zUVvfNgjPJLXrD9N7AdTLnbHFL64KmBn3SNaTe69iZYbYCqLCCNPZKbLz9niQ4' ) self.assertEqual( node.subkey(0).subkey(0).address(), '35ohQTdNykjkF1Mn9nAVEFjupyAtsPAK1W') self.assertEqual( node.subkey(1).subkey(0).address(), '3KaBTcviBLEJajTEMstsA2GWjYoPzPK7Y7')
def mk_notif_tx(my_pcode_node, payee_pcode_node, wallet_nodes, change_nodes, fee): amount = Decimal('0.00000600') payee_notif_node = payee_pcode_node.subkey_for_path("0/0") txio_tuple = create_tx_io(amount, payee_notif_node.address(), wallet_nodes, change_nodes, fee) first_exp = Key.from_text(txio_tuple[3][0]).secret_exponent() my_masked_pcode = node_to_masked_pcode(my_pcode_node, payee_notif_node, first_exp) op_return_script = pay_to.ScriptNulldata(my_masked_pcode) op_return_txout = TxOut(0, op_return_script.script()) txio_tuple[1].append(op_return_txout) return create_signed_tx(txio_tuple)
def spend_sh_fund(tx_ins, wif_keys, tx_outs): """ spend script hash fund the key point of an input comes from multisig address is that, its sign script is combined with several individual signs :param tx_ins: list with tuple(tx_id, idx, balance, address, redeem_script) :param wif_keys: private keys in wif format, technical should be the same order with the pubkey in redeem script, but pycoin has inner control, so here order is not mandatory :param tx_outs: balance, receiver_address :return: raw hex and tx id """ _txs_in = [] _un_spent = [] for tx_id, idx, balance, address, _ in tx_ins: # must h2b_rev NOT h2b tx_id_b = h2b_rev(tx_id) _txs_in.append(TxIn(tx_id_b, idx)) _un_spent.append( Spendable( balance, script_obj_from_address(address, netcodes=[NET_CODE]).script(), tx_id_b, idx)) _txs_out = [] for balance, receiver_address in tx_outs: _txs_out.append( TxOut( balance, script_obj_from_address(receiver_address, netcodes=[NET_CODE]).script())) version, lock_time = 1, 0 tx = Tx(version, _txs_in, _txs_out, lock_time) tx.set_unspents(_un_spent) # construct hash160_lookup[hash160] = (secret_exponent, public_pair, compressed) for each individual key hash160_lookup = build_hash160_lookup( [Key.from_text(wif_key).secret_exponent() for wif_key in wif_keys]) for i in range(0, len(tx_ins)): # you can add some conditions that if the input script is not p2sh type, not provide p2sh_lookup, # so that all kinds of inputs can work together p2sh_lookup = build_p2sh_lookup([binascii.unhexlify(tx_ins[i][-1])]) tx.sign_tx_in(hash160_lookup, i, tx.unspents[i].script, hash_type=SIGHASH_ALL, p2sh_lookup=p2sh_lookup) return tx.as_hex(), tx.id()
def parse_prefixes(item, PREFIX_TRANSFORMS): for k, f in PREFIX_TRANSFORMS: if item.startswith(k): try: return f(item[len(k):]) except Exception: pass try: return Key.from_text(item) except encoding.EncodingError: pass return None
def key_found(arg, payables, key_iters): try: key = Key.from_text(arg) # TODO: check network if key.wif() is None: payables.append((key.address(), 0)) return True key_iters.append(iter([key.wif()])) return True except Exception: pass return False
def sign(privkey, data): """ Sign data with given private key. Args: privkey (str): Hex encoded private key data (str): Hex encoded data to be signed. Return: str: Hex encoded signature in DER format. """ secret_exponent = Key.from_text(privkey_to_wif(privkey)).secret_exponent() e = util.bytestoint(h2b(data)) r, s = ecdsa_sign(G, secret_exponent, e) return b2h(ecdsa.util.sigencode_der(r, s, G.order()))
def commit(self, bitcoin_key_text, miner_fee=10000): """ Commit the entry to the Bitcoin blockchain. Args: bitcoin_key_text: the Bitcoin private key for the new transaction, in WIF format. miner_fee: the miner fee to pay in Satoshis (default: 10000 Satoshis). Returns: The transaction ID. """ bitcoin_key = Key.from_text(bitcoin_key_text) self.tx = send_op_return_tx(bitcoin_key, self.tree.root.val, miner_fee) return self.tx.id()
def test_sign_bitcoind_partially_signed_2_of_2(self): # Finish signing a 2 of 2 transaction, that already has one signature signed by bitcoind # This tx can be found on testnet3 blockchain, txid: 9618820d7037d2f32db798c92665231cd4599326f5bd99cb59d0b723be2a13a2 raw_script = "522103e33b41f5ed67a77d4c4c54b3e946bd30d15b8f66e42cb29fde059c16885116552102b92cb20a9fb1eb9656a74eeb7387636cf64cdf502ff50511830328c1b479986452ae" p2sh_lookup = build_p2sh_lookup([h2b(raw_script)]) partially_signed_raw_tx = "010000000196238f11a5fd3ceef4efd5a186a7e6b9217d900418e72aca917cd6a6e634e74100000000910047304402201b41b471d9dd93cf97eed7cfc39a5767a546f6bfbf3e0c91ff9ad23ab9770f1f02205ce565666271d055be1f25a7e52e34cbf659f6c70770ff59bd783a6fcd1be3dd0147522103e33b41f5ed67a77d4c4c54b3e946bd30d15b8f66e42cb29fde059c16885116552102b92cb20a9fb1eb9656a74eeb7387636cf64cdf502ff50511830328c1b479986452aeffffffff01a0bb0d00000000001976a9143b3beefd6f7802fa8706983a76a51467bfa36f8b88ac00000000" tx = Tx.from_hex(partially_signed_raw_tx) tx_out = TxOut(1000000, h2b("a914a10dfa21ee8c33b028b92562f6fe04e60563d3c087")) tx.set_unspents([tx_out]) key = Key.from_text("cThRBRu2jAeshWL3sH3qbqdq9f4jDiDbd1SVz4qjTZD2xL1pdbsx") hash160_lookup = build_hash160_lookup([key.secret_exponent()]) self.assertEqual(tx.bad_signature_count(), 1) tx.sign(hash160_lookup=hash160_lookup, p2sh_lookup=p2sh_lookup) self.assertEqual(tx.bad_signature_count(), 0) self.assertEqual(tx.id(), "9618820d7037d2f32db798c92665231cd4599326f5bd99cb59d0b723be2a13a2")
def get_unused_address(social_id, deriv): ''' Need to be careful about when to move up the latest_derivation listing. Figure only incrementing the database entry when blockchain activity is found is the least likely to create large gaps of empty addresses in someone's BTC Wallet. ''' pp = pprint.PrettyPrinter(indent=2) userdata = User.query.filter_by(social_id=social_id).first() # Pull BTC Address from given user data key = Key.from_text(userdata.xpub).subkey(0). \ subkey(deriv) address = key.address(use_uncompressed=False) if is_address_valid(userdata.xpub) == "BTC": return "STREAMER SUBMITTED BTCADDR INSTEAD OF XPUB, PLEASE INFORM "\ + "STREAMER OR DEVELOPER" if is_address_valid(key.address(use_uncompressed=False)) != "BTC": return "NO VALID ADDRESS, PLEASE INFORM STREAMER OR DEVELOPER" # Check for existing payment request, delete if older than 5m. payment_request = PayReq.query.filter_by(addr=address).first() if payment_request: req_timestamp = payment_request.timestamp now_timestamp = datetime.utcnow() delta_timestamp = now_timestamp - req_timestamp if delta_timestamp > timedelta(seconds=60 * 5): db.session.delete(payment_request) db.session.commit() payment_request = None pp.pprint(check_payment_on_address(address)) if not check_address_history(address): if not payment_request: return address else: print("Address has payment request...") print("Address Derivation: ", deriv) return get_unused_address(social_id, deriv + 1) else: print("Address has blockchain history, searching new address...") print("Address Derivation: ", userdata.latest_derivation) userdata.latest_derivation = userdata.latest_derivation + 1 db.session.commit() return get_unused_address(social_id, deriv + 1)
def sign_deposit(get_txs_func, payer_wif, rawtx): """ Sign deposit transaction. Args: get_txs_func (function): txid list -> matching raw transactions. payer_wif (str): Payer wif used for signing. rawtx (str): Deposit raw transaction to be signed. Return: Signed deposit raw transaction. """ tx = load_tx(get_txs_func, rawtx) key = Key.from_text(payer_wif) with xxx_capture_out(): tx.sign(build_hash160_lookup([key.secret_exponent()])) return tx.as_hex()
def generate(context, request, api_version, xpub=None, start=0, count=1): if not xpub: raise MyBitsException('Parameter `xpub` missing') start = int(start) count = int(count) if not 0 < count <= 20: raise MyBitsException('Parameter `count` must be between 1 and 20') try: mpk = Key.from_text(xpub) except EncodingError: raise MyBitsException('Invalid `xpub`') return [str(key.address()) for key in mpk.subkeys("0/{}-{}".format(start, start+count))]
def get_unused_address(social_id, deriv): ''' Need to be careful about when to move up the latest_derivation listing. Figure only incrementing the database entry when blockchain activity is found is the least likely to create large gaps of empty addresses in someone's BTC Wallet. ''' serverList = read_server_list() randomServer = grab_random_server(serverList) randomAddress = randomServer['serverAddress'] randomPort = randomServer['serverPort'] pp = pprint.PrettyPrinter(indent=2) userdata = User.query.filter_by(social_id=social_id).first() # Pull BTC Address from given user data key = Key.from_text(userdata.xpub).subkey(0). \ subkey(deriv) address = key.address(use_uncompressed=False) # Check for existing payment request, delete if older than 5m. payment_request = PayReq.query.filter_by(addr=address).first() if payment_request: req_timestamp = payment_request.timestamp now_timestamp = datetime.utcnow() delta_timestamp = now_timestamp - req_timestamp if delta_timestamp > timedelta(seconds=60 * 5): db.session.delete(payment_request) db.session.commit() payment_request = None if not check_address_history(address, randomAddress, randomPort): if not payment_request: return address else: print("Address has payment request...") print("Address Derivation: ", deriv) return get_unused_address(social_id, deriv + 1) else: print("Address has blockchain history, searching new address...") print("Address Derivation: ", userdata.latest_derivation) userdata.latest_derivation = userdata.latest_derivation + 1 db.session.commit() return get_unused_address(social_id, deriv + 1)
def sign_vote(votestr, mnprivkey): privatekey = utils.wifToPrivateKey(mnprivkey) signingkey = Bip62SigningKey.from_string(privatekey.decode('hex'), curve=ecdsa.SECP256k1) public_key = signingkey.get_verifying_key() key = Key.from_text(mnprivkey) address = key.address(use_uncompressed=True) msghash = utils.double_sha256(utils.msg_magic(votestr)) signature = signingkey.sign_digest_deterministic( msghash, hashfunc=hashlib.sha256, sigencode=ecdsa.util.sigencode_string) assert public_key.verify_digest(signature, msghash, sigdecode=ecdsa.util.sigdecode_string) for i in range(4): sig = base64.b64encode(chr(27 + i) + signature) if verify_dash_signature(generator_secp256k1, address, msghash, sig): return sig
def handle(self, *args, **options): rpc = AuthServiceProxy('http://' + settings.BITCOIN_RPC_USERNAME + ':' + settings.BITCOIN_RPC_PASSWORD + '@' + settings.BITCOIN_RPC_IP + ':' + str(settings.BITCOIN_RPC_PORT)) private_keys_imported = False for address in Address.objects.all(): address_found = True try: rpc.dumpprivkey(address.address) except JSONRPCException as e: if e.code == -4: # Address is not found print 'Address ' + address.address + ' was not found. Importing it...' # Do some key magic new_address_full_path = address.wallet.path + [ address.subpath_number ] new_address_full_path_str = '/'.join( [str(i) for i in new_address_full_path]) key = Key.from_text(settings.MASTERWALLET_BIP32_KEY) subkey = key.subkeys(new_address_full_path_str).next() # Check address and form the private key btc_address = subkey.address(use_uncompressed=False) assert btc_address == address.address btc_private_key = subkey.wif(use_uncompressed=False) # Do the importing rpc.importprivkey(btc_private_key, '', False) private_keys_imported = True if private_keys_imported: print 'Note! Private keys were added, but they were not scanned! Please restart bitcoin with -rescan option!'
def answer(private_key, expected_address): private_key_digits = [] for d in private_key: private_key_digits.append(BASE58_LOOKUP[d]) #print(private_key) #print(private_key_digits) prefix = private_key_digits[0] suffix = private_key_digits[1:] test_suffix = tuple(suffix) if not private_key_suffix_is_valid(test_suffix): test_suffix = find_winner(tuple(suffix)) print('WINNER!') private_key = b2a_base58(suffix_to_bytes(test_suffix)) print(private_key) return Key.from_text(private_key).address()
def register_page(request, refererUUID): getBtcPrice() price = sysvar.objects.get(pk=1) btcPrice = price.btcPrice counter = price.counter email_taken = False username_taken = False if request.user.is_authenticated(): return render(request, 'home.html') registration_form = RegistrationForm() if request.method == 'POST': form = RegistrationForm(request.POST) if form.is_valid(): datas = {} if User.objects.filter( username=form.cleaned_data['username']).exists(): username_taken = True return render( request, 'register_page.html', { 'form': registration_form, 'username_taken': username_taken, 'btcPrice': btcPrice }) elif User.objects.filter( email=form.cleaned_data['email']).exists(): email_taken = True return render( request, 'register_page.html', { 'form': registration_form, 'email_taken': email_taken, 'btcPrice': btcPrice }) datas['username'] = form.cleaned_data['username'] datas['email'] = form.cleaned_data['email'] datas['password1'] = form.cleaned_data['password1'] datas['referer'] = refererUUID #We will generate a random activation key s = 'xprv9s21ZrQH143K2Lap6SnULZfdEi4ivcbottMVoY7MaupCQhVLfARkygyW9N7PKsBSPd2gTQXZr1R4iqkLCQ3TUxvs9NvwYRScCVGV8Aos7ad' mykey = Key.from_text(s) mysub = mykey.subkey(counter) address = Key.address(mysub) wif = Key.wif(mysub) datas['deposit_add'] = address datas['wif'] = wif price.counter = price.counter + 1 price.save() salt = hashlib.sha1(str( random.random()).encode('utf-8')).hexdigest()[:5] usernamesalt = datas['email'] if isinstance(usernamesalt, str): usernamesalt = str.encode(usernamesalt) if isinstance(salt, str): salt = str.encode(salt) print(salt) print(usernamesalt) datas['activation_key'] = hashlib.sha1(salt + usernamesalt).hexdigest() datas[ 'email_path'] = "/home/connell-gough/django/bl4btc/btc/static/ActivationEmail.txt" datas['email_subject'] = "activate your account" form.sendEmail(datas) #Send validation email form.save(datas) #Save the user and his profile request.session['registered'] = True #For display purposes return render(request, 'register_page.html', { 'email_sent': True, 'btcPrice': btcPrice }) else: registration_form = form #Display form with error messages (incorrect fields, etc) return render( request, 'register_page.html', { 'form': registration_form, 'btcPrice': btcPrice, 'refererUUID': refererUUID })
def main(): parser = argparse.ArgumentParser( description="Manipulate bitcoin (or alt coin) transactions.", epilog=EPILOG) parser.add_argument('-t', "--transaction-version", type=int, help='Transaction version, either 1 (default) or 3 (not yet supported).') parser.add_argument('-l', "--lock-time", type=parse_locktime, help='Lock time; either a block' 'index, or a date/time (example: "2014-01-01T15:00:00"') parser.add_argument('-n', "--network", default="BTC", help='Define network code (M=Bitcoin mainnet, T=Bitcoin testnet).') parser.add_argument('-a', "--augment", action='store_true', help='augment tx by adding any missing spendable metadata by fetching' ' inputs from cache and/or web services') parser.add_argument("-i", "--fetch-spendables", metavar="address", action="append", help='Add all unspent spendables for the given bitcoin address. This information' ' is fetched from web services.') parser.add_argument('-f', "--private-key-file", metavar="path-to-private-keys", action="append", help='file containing WIF or BIP0032 private keys. If file name ends with .gpg, ' '"gpg -d" will be invoked automatically. File is read one line at a time, and if ' 'the file contains only one WIF per line, it will also be scanned for a bitcoin ' 'address, and any addresses found will be assumed to be public keys for the given' ' private key.', type=argparse.FileType('r')) parser.add_argument('-g', "--gpg-argument", help='argument to pass to gpg (besides -d).', default='') parser.add_argument("--remove-tx-in", metavar="tx_in_index_to_delete", action="append", type=int, help='remove a tx_in') parser.add_argument("--remove-tx-out", metavar="tx_out_index_to_delete", action="append", type=int, help='remove a tx_out') parser.add_argument('-F', "--fee", help='fee, in satoshis, to pay on transaction, or ' '"standard" to auto-calculate. This is only useful if the "split pool" ' 'is used; otherwise, the fee is automatically set to the unclaimed funds.', default="standard", metavar="transaction-fee", type=parse_fee) parser.add_argument('-C', "--cache", help='force the resultant transaction into the transaction cache.' ' Mostly for testing.', action='store_true'), parser.add_argument('-u', "--show-unspents", action='store_true', help='show TxOut items for this transaction in Spendable form.') parser.add_argument('-b', "--bitcoind-url", help='URL to bitcoind instance to validate against (http://user:pass@host:port).') parser.add_argument('-o', "--output-file", metavar="path-to-output-file", type=argparse.FileType('wb'), help='file to write transaction to. This supresses most other output.') parser.add_argument("argument", nargs="+", help='generic argument: can be a hex transaction id ' '(exactly 64 characters) to be fetched from cache or a web service;' ' a transaction as a hex string; a path name to a transaction to be loaded;' ' a spendable 4-tuple of the form tx_id/tx_out_idx/script_hex/satoshi_count ' 'to be added to TxIn list; an address/satoshi_count to be added to the TxOut ' 'list; an address to be added to the TxOut list and placed in the "split' ' pool".') args = parser.parse_args() # defaults txs = [] spendables = [] payables = [] key_iters = [] TX_ID_RE = re.compile(r"^[0-9a-fA-F]{64}$") # there are a few warnings we might optionally print out, but only if # they are relevant. We don't want to print them out multiple times, so we # collect them here and print them at the end if they ever kick in. warning_tx_cache = None warning_get_tx = None warning_spendables = None if args.private_key_file: wif_re = re.compile(r"[1-9a-km-zA-LMNP-Z]{51,111}") # address_re = re.compile(r"[1-9a-kmnp-zA-KMNP-Z]{27-31}") for f in args.private_key_file: if f.name.endswith(".gpg"): gpg_args = ["gpg", "-d"] if args.gpg_argument: gpg_args.extend(args.gpg_argument.split()) gpg_args.append(f.name) popen = subprocess.Popen(gpg_args, stdout=subprocess.PIPE) f = popen.stdout for line in f.readlines(): # decode if isinstance(line, bytes): line = line.decode("utf8") # look for WIFs possible_keys = wif_re.findall(line) def make_key(x): try: return Key.from_text(x) except Exception: return None keys = [make_key(x) for x in possible_keys] for key in keys: if key: key_iters.append((k.wif() for k in key.subkeys(""))) # if len(keys) == 1 and key.hierarchical_wallet() is None: # # we have exactly 1 WIF. Let's look for an address # potential_addresses = address_re.findall(line) # we create the tx_db lazily tx_db = None for arg in args.argument: # hex transaction id if TX_ID_RE.match(arg): if tx_db is None: warning_tx_cache = message_about_tx_cache_env() warning_get_tx = message_about_get_tx_env() tx_db = get_tx_db() tx = tx_db.get(h2b_rev(arg)) if not tx: for m in [warning_tx_cache, warning_get_tx, warning_spendables]: if m: print("warning: %s" % m, file=sys.stderr) parser.error("can't find Tx with id %s" % arg) txs.append(tx) continue # hex transaction data try: tx = Tx.tx_from_hex(arg) txs.append(tx) continue except Exception: pass try: key = Key.from_text(arg) # TODO: check network if key.wif() is None: payables.append((key.address(), 0)) continue # TODO: support paths to subkeys key_iters.append((k.wif() for k in key.subkeys(""))) continue except Exception: pass if os.path.exists(arg): try: with open(arg, "rb") as f: if f.name.endswith("hex"): f = io.BytesIO(codecs.getreader("hex_codec")(f).read()) tx = Tx.parse(f) txs.append(tx) try: tx.parse_unspents(f) except Exception as ex: pass continue except Exception: pass parts = arg.split("/") if len(parts) == 4: # spendable try: spendables.append(Spendable.from_text(arg)) continue except Exception: pass # TODO: fix allowable_prefixes allowable_prefixes = b'\0' if len(parts) == 2 and encoding.is_valid_bitcoin_address( parts[0], allowable_prefixes=allowable_prefixes): try: payables.append(parts) continue except ValueError: pass parser.error("can't parse %s" % arg) if args.fetch_spendables: warning_spendables = message_about_spendables_for_address_env() for address in args.fetch_spendables: spendables.extend(spendables_for_address(address)) for tx in txs: if tx.missing_unspents() and args.augment: if tx_db is None: warning_tx_cache = message_about_tx_cache_env() warning_get_tx = message_about_get_tx_env() tx_db = get_tx_db() tx.unspents_from_db(tx_db, ignore_missing=True) txs_in = [] txs_out = [] unspents = [] # we use a clever trick here to keep each tx_in corresponding with its tx_out for tx in txs: smaller = min(len(tx.txs_in), len(tx.txs_out)) txs_in.extend(tx.txs_in[:smaller]) txs_out.extend(tx.txs_out[:smaller]) unspents.extend(tx.unspents[:smaller]) for tx in txs: smaller = min(len(tx.txs_in), len(tx.txs_out)) txs_in.extend(tx.txs_in[smaller:]) txs_out.extend(tx.txs_out[smaller:]) unspents.extend(tx.unspents[smaller:]) for spendable in spendables: txs_in.append(spendable.tx_in()) unspents.append(spendable) for address, coin_value in payables: script = standard_tx_out_script(address) txs_out.append(TxOut(coin_value, script)) lock_time = args.lock_time version = args.transaction_version # if no lock_time is explicitly set, inherit from the first tx or use default if lock_time is None: if txs: lock_time = txs[0].lock_time else: lock_time = DEFAULT_LOCK_TIME # if no version is explicitly set, inherit from the first tx or use default if version is None: if txs: version = txs[0].version else: version = DEFAULT_VERSION if args.remove_tx_in: s = set(args.remove_tx_in) txs_in = [tx_in for idx, tx_in in enumerate(txs_in) if idx not in s] if args.remove_tx_out: s = set(args.remove_tx_out) txs_out = [tx_out for idx, tx_out in enumerate(txs_out) if idx not in s] tx = Tx(txs_in=txs_in, txs_out=txs_out, lock_time=lock_time, version=version, unspents=unspents) fee = args.fee try: distribute_from_split_pool(tx, fee) except ValueError as ex: print("warning: %s" % ex.args[0], file=sys.stderr) unsigned_before = tx.bad_signature_count() if unsigned_before > 0 and key_iters: def wif_iter(iters): while len(iters) > 0: for idx, iter in enumerate(iters): try: wif = next(iter) yield wif except StopIteration: iters = iters[:idx] + iters[idx+1:] break print("signing...", file=sys.stderr) sign_tx(tx, wif_iter(key_iters)) unsigned_after = tx.bad_signature_count() if unsigned_after > 0 and key_iters: print("warning: %d TxIn items still unsigned" % unsigned_after, file=sys.stderr) if len(tx.txs_in) == 0: print("warning: transaction has no inputs", file=sys.stderr) if len(tx.txs_out) == 0: print("warning: transaction has no outputs", file=sys.stderr) include_unspents = (unsigned_after > 0) tx_as_hex = tx.as_hex(include_unspents=include_unspents) if args.output_file: f = args.output_file if f.name.endswith(".hex"): f.write(tx_as_hex.encode("utf8")) else: tx.stream(f) if include_unspents: tx.stream_unspents(f) f.close() elif args.show_unspents: for spendable in tx.tx_outs_as_spendable(): print(spendable.as_text()) else: if not tx.missing_unspents(): check_fees(tx) dump_tx(tx, args.network) if include_unspents: print("including unspents in hex dump since transaction not fully signed") print(tx_as_hex) if args.cache: if tx_db is None: warning_tx_cache = message_about_tx_cache_env() warning_get_tx = message_about_get_tx_env() tx_db = get_tx_db() tx_db.put(tx) if args.bitcoind_url: if tx_db is None: warning_tx_cache = message_about_tx_cache_env() warning_get_tx = message_about_get_tx_env() tx_db = get_tx_db() validate_bitcoind(tx, tx_db, args.bitcoind_url) if tx.missing_unspents(): print("\n** can't validate transaction as source transactions missing", file=sys.stderr) else: try: if tx_db is None: warning_tx_cache = message_about_tx_cache_env() warning_get_tx = message_about_get_tx_env() tx_db = get_tx_db() tx.validate_unspents(tx_db) print('all incoming transaction values validated') except BadSpendableError as ex: print("\n**** ERROR: FEES INCORRECTLY STATED: %s" % ex.args[0], file=sys.stderr) except Exception as ex: print("\n*** can't validate source transactions as untampered: %s" % ex.args[0], file=sys.stderr) # print warnings for m in [warning_tx_cache, warning_get_tx, warning_spendables]: if m: print("warning: %s" % m, file=sys.stderr)
print("enter the " + str(which) + " address=> ", end="") address = input() is_valid = is_address_valid(address) if is_valid: return address print("invalid address, please try again") src_address = get_address("source") spendables = spendables_for_address(src_address) print(spendables) while 1: print("enter the WIF for %s=> " % src_address, end="") wif = input() is_valid = is_wif_valid(wif) if is_valid: break print("invalid wif, please try again") key = Key.from_text(wif) if src_address not in (key.address(use_uncompressed=False), key.address(use_uncompressed=True)): print("** WIF doesn't correspond to %s" % src_address) print("The secret exponent is %d" % key.secret_exponent()) dst_address = get_address("destination") tx = create_signed_tx(spendables, payables=[dst_address], wifs=[wif]) print("here is the signed output transaction") print(tx.as_hex())
def change_prefix(address, new_prefix): return hash160_sec_to_bitcoin_address(Key.from_text(address).hash160(), address_prefix=new_prefix)
def addr_to_testnet(addr): return Key(hash160=Key.from_text(addr).hash160(), netcode='XTN').address()
def parse_context(args, parser): # defaults txs = [] spendables = [] payables = [] key_iters = [] TX_ID_RE = re.compile(r"^[0-9a-fA-F]{64}$") # there are a few warnings we might optionally print out, but only if # they are relevant. We don't want to print them out multiple times, so we # collect them here and print them at the end if they ever kick in. warning_tx_cache = None warning_tx_for_tx_hash = None warning_spendables = None if args.private_key_file: wif_re = re.compile(r"[1-9a-km-zA-LMNP-Z]{51,111}") # address_re = re.compile(r"[1-9a-kmnp-zA-KMNP-Z]{27-31}") for f in args.private_key_file: if f.name.endswith(".gpg"): gpg_args = ["gpg", "-d"] if args.gpg_argument: gpg_args.extend(args.gpg_argument.split()) gpg_args.append(f.name) popen = subprocess.Popen(gpg_args, stdout=subprocess.PIPE) f = popen.stdout for line in f.readlines(): # decode if isinstance(line, bytes): line = line.decode("utf8") # look for WIFs possible_keys = wif_re.findall(line) def make_key(x): try: return Key.from_text(x) except Exception: return None keys = [make_key(x) for x in possible_keys] for key in keys: if key: key_iters.append((k.wif() for k in key.subkeys(""))) # if len(keys) == 1 and key.hierarchical_wallet() is None: # # we have exactly 1 WIF. Let's look for an address # potential_addresses = address_re.findall(line) # update p2sh_lookup p2sh_lookup = {} if args.pay_to_script: for p2s in args.pay_to_script: try: script = h2b(p2s) p2sh_lookup[hash160(script)] = script except Exception: print("warning: error parsing pay-to-script value %s" % p2s) if args.pay_to_script_file: hex_re = re.compile(r"[0-9a-fA-F]+") for f in args.pay_to_script_file: count = 0 for l in f: try: m = hex_re.search(l) if m: p2s = m.group(0) script = h2b(p2s) p2sh_lookup[hash160(script)] = script count += 1 except Exception: print("warning: error parsing pay-to-script file %s" % f.name) if count == 0: print("warning: no scripts found in %s" % f.name) # we create the tx_db lazily tx_db = None for arg in args.argument: # hex transaction id if TX_ID_RE.match(arg): if tx_db is None: warning_tx_cache = message_about_tx_cache_env() warning_tx_for_tx_hash = message_about_tx_for_tx_hash_env(args.network) tx_db = get_tx_db(args.network) tx = tx_db.get(h2b_rev(arg)) if not tx: for m in [warning_tx_cache, warning_tx_for_tx_hash, warning_spendables]: if m: print("warning: %s" % m, file=sys.stderr) parser.error("can't find Tx with id %s" % arg) txs.append(tx) continue # hex transaction data try: tx = Tx.from_hex(arg) txs.append(tx) continue except Exception: pass is_valid = is_address_valid(arg, allowable_netcodes=[args.network]) if is_valid: payables.append((arg, 0)) continue try: key = Key.from_text(arg) # TODO: check network if key.wif() is None: payables.append((key.address(), 0)) continue # TODO: support paths to subkeys key_iters.append((k.wif() for k in key.subkeys(""))) continue except Exception: pass if os.path.exists(arg): try: with open(arg, "rb") as f: if f.name.endswith("hex"): f = io.BytesIO(codecs.getreader("hex_codec")(f).read()) tx = Tx.parse(f) txs.append(tx) try: tx.parse_unspents(f) except Exception as ex: pass continue except Exception: pass parts = arg.split("/") if len(parts) == 4: # spendable try: spendables.append(Spendable.from_text(arg)) continue except Exception: pass if len(parts) == 2 and is_address_valid(parts[0], allowable_netcodes=[args.network]): try: payables.append(parts) continue except ValueError: pass parser.error("can't parse %s" % arg) if args.fetch_spendables: warning_spendables = message_about_spendables_for_address_env(args.network) for address in args.fetch_spendables: spendables.extend(spendables_for_address(address)) for tx in txs: if tx.missing_unspents() and args.augment: if tx_db is None: warning_tx_cache = message_about_tx_cache_env() warning_tx_for_tx_hash = message_about_tx_for_tx_hash_env(args.network) tx_db = get_tx_db(args.network) tx.unspents_from_db(tx_db, ignore_missing=True) return (txs, spendables, payables, key_iters, p2sh_lookup, tx_db, warning_tx_cache, warning_tx_for_tx_hash, warning_spendables)
def main(): networks = "MTLD" parser = argparse.ArgumentParser( description='Crypto coin utility ku ("key utility") to show' ' information about Bitcoin or other cryptocoin data structures.', epilog='Known networks codes:\n ' \ + ', '.join(['%s (%s)'%(i, full_network_name_for_netcode(i)) for i in NETWORK_NAMES]) ) parser.add_argument('-w', "--wallet", help='show just Bitcoin wallet key', action='store_true') parser.add_argument('-W', "--wif", help='show just Bitcoin WIF', action='store_true') parser.add_argument('-a', "--address", help='show just Bitcoin address', action='store_true') parser.add_argument( '-u', "--uncompressed", help='show output in uncompressed form', action='store_true') parser.add_argument( '-P', "--public", help='only show public version of wallet keys', action='store_true') parser.add_argument('-j', "--json", help='output as JSON', action='store_true') parser.add_argument('-s', "--subkey", help='subkey path (example: 0H/2/15-20)') parser.add_argument('-n', "--network", help='specify network (default: BTC = Bitcoin)', default='BTC', choices=NETWORK_NAMES) parser.add_argument("--override-network", help='override detected network type', default=None, choices=NETWORK_NAMES) parser.add_argument( 'item', nargs="+", help='a BIP0032 wallet key string;' ' a WIF;' ' a bitcoin address;' ' an SEC (ie. a 66 hex chars starting with 02, 03 or a 130 hex chars starting with 04);' ' the literal string "create" to create a new wallet key using strong entropy sources;' ' P:wallet passphrase (NOT RECOMMENDED);' ' H:wallet passphrase in hex (NOT RECOMMENDED);' ' secret_exponent (in decimal or hex);' ' x,y where x,y form a public pair (y is a number or one of the strings "even" or "odd");' ' hash160 (as 40 hex characters)') args = parser.parse_args() if args.override_network: # force network arg to match override, but also will override decoded data below. args.network = args.override_network 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 PREFIX_TRANSFORMS = ( ("P:", lambda s: BIP32Node.from_master_secret(s.encode("utf8"), netcode=args.network)), ("H:", lambda s: BIP32Node.from_master_secret(h2b(s), netcode=args.network)), ("create", _create), ) for item in args.item: key = None for k, f in PREFIX_TRANSFORMS: if item.startswith(k): try: key = f(item[len(k):]) break except Exception: pass else: try: key = Key.from_text(item) except encoding.EncodingError: pass if key is None: secret_exponent = parse_as_secret_exponent(item) if secret_exponent: key = Key(secret_exponent=secret_exponent, netcode=args.network) if SEC_RE.match(item): key = Key.from_sec(h2b(item)) if key is None: public_pair = parse_as_public_pair(item) if public_pair: key = Key(public_pair=public_pair, netcode=args.network) if HASH160_RE.match(item): key = Key(hash160=h2b(item), netcode=args.network) if key is None: print("can't parse %s" % item, file=sys.stderr) continue if args.override_network: # Override the network value, so we can take the same xpubkey and view what # the values would be on each other network type. # XXX public interface for this is needed... key._netcode = args.override_network for key in key.subkeys(args.subkey or ""): if args.public: key = key.public_copy() output_dict, output_order = create_output(item, key) if args.json: print(json.dumps(output_dict, indent=3, sort_keys=True)) elif args.wallet: print(output_dict["wallet_key"]) elif args.wif: print(output_dict["wif_uncompressed" if args.uncompressed else "wif"]) elif args.address: print(output_dict["address" + ("_uncompressed" if args.uncompressed else "")]) else: dump_output(output_dict, output_order)
def wallet(testnet, hwif): hwif = unicode_str(hwif) netcode = 'XTN' if testnet else 'BTC' if not validate.is_private_bip32_valid(hwif, allowable_netcodes=[netcode]): raise exceptions.InvalidHWIF(hwif) return Key.from_text(hwif)
def make_key(x): try: return Key.from_text(x) except Exception: return None
def main(): parser = argparse.ArgumentParser( description="DigitalOracle HD multisig command line utility", formatter_class=argparse.RawDescriptionHelpFormatter, ) parser.add_argument("-e", "--email", help="e-mail for create") parser.add_argument("-p", "--phone", help="phone number for create - in the format +14155551212") parser.add_argument("-n", "--network", default="BTC", choices=NETWORK_NAMES) parser.add_argument("-i", "--inputpath", nargs="+", help="HD subkey path for each input (example: 0/2/15)") parser.add_argument( "-c", "--changepath", nargs="+", help="HD subkey path for each change output (example: 0/2/15) or a dash for non-change outputs", ) parser.add_argument("-s", "--spendid", help="an additional hex string to disambiguate spends to the same address") parser.add_argument( "-u", "--baseurl", help="the API endpoint, defaults to the sandbox - https://s.digitaloracle.co/" ) parser.add_argument( "-v", "--verbose", default=0, action="count", help="Verbosity, use more -v flags for more verbosity" ) parser.add_argument("command", help="""a command""") parser.add_argument("item", nargs="+", help="""a key""") parser.epilog = textwrap.dedent( """ Items: * P:wallet_passphrase - a secret for deriving an HD hierarchy with private keys * xpub - an account extended public key for deriving an HD hierarchy with public keys only * FILE.bin - unsigned transaction binary * FILE.hex - unsigned transaction hex Commands: * dump - dump the public subkeys * create - create Oracle account based on the supplied leading key with with any additional keys * address - get the deposit address for a subkey path * sign - sign a transaction, tx.bin or tx.hex must be supplied. Only one subkey path is supported. Notes: * --subkey is applicable for the address and sign actions, but not the create action """ ) args = parser.parse_args() keys = [] txs = [] for item in args.item: key = None tx = None if item.startswith("P:"): s = item[2:] key = BIP32Node.from_master_secret(s.encode("utf8"), netcode=args.network) keys.append(key) else: try: key = Key.from_text(item) keys.append(key) except encoding.EncodingError: pass if key is None: if os.path.exists(item): try: with open(item, "rb") as f: if f.name.endswith("hex"): f = io.BytesIO(codecs.getreader("hex_codec")(f).read()) tx = Tx.parse(f) txs.append(tx) try: tx.parse_unspents(f) except Exception as ex: pass continue except Exception as ex: print("could not parse %s %s" % (item, ex), file=sys.stderr) pass if tx is None and key is None: print("could not understand item %s" % (item,)) account = MultisigAccount(keys, complete=False) oracle = Oracle(account, tx_db=get_tx_db(), base_url=args.baseurl) oracle.verbose = args.verbose if args.command == "dump": sub_keys = [key.subkey_for_path(path or "") for key, path in izip_longest(keys, args.inputpath)] for key in sub_keys: print(key.wallet_key(as_private=False)) elif args.command == "create": calls = [] if args.email: calls.append("email") if args.phone: calls.append("phone") parameters = {"levels": [{"asset": "BTC", "period": 60, "value": 0.001}, {"delay": 0, "calls": calls}]} oracle.create(parameters, email=args.email, phone=args.phone) elif args.command == "address": oracle.get() path = args.inputpath[0] if args.inputpath else "" payto = account.payto_for_path(path) if args.verbose > 0: sub_keys = [key.subkey_for_path(path) for key in account.keys] print("* account keys") print(account.keys) print("* child keys") for key in sub_keys: print(key.wallet_key(as_private=False)) print("* address") print(payto.address(netcode=args.network)) elif args.command == "sign": oracle.get() scripts = [account.script_for_path(path) for path in args.inputpath] change_paths = [None if path == "-" else path for path in (args.changepath or [])] for tx in txs: print(tx.id()) print(b2h(stream_to_bytes(tx.stream))) sub_keys = [keys[0].subkey_for_path(path) for path in args.inputpath] # sign locally local_sign(tx, scripts, sub_keys) # have Oracle sign result = oracle.sign_with_paths(tx, args.inputpath, change_paths, spend_id=args.spendid) print("Result:") print(result) if "transaction" in result: print("Hex serialized transaction:") print(b2h(stream_to_bytes(result["transaction"].stream))) else: print("unknown command %s" % (args.command,), file=sys.stderr)
def main(): networks = "MTLD" parser = argparse.ArgumentParser( description='Crypto coin utility ku ("key utility") to show' ' information about Bitcoin or other cryptocoin data structures.') parser.add_argument('-w', "--wallet", help='show just Bitcoin wallet key', action='store_true') parser.add_argument('-W', "--wif", help='show just Bitcoin WIF', action='store_true') parser.add_argument('-a', "--address", help='show just Bitcoin address', action='store_true') parser.add_argument( '-u', "--uncompressed", help='show output in uncompressed form', action='store_true') parser.add_argument( '-P', "--public", help='only show public version of wallet keys', action='store_true') parser.add_argument('-j', "--json", help='output as JSON', action='store_true') parser.add_argument('-s', "--subkey", help='subkey path (example: 0H/2/15-20)') parser.add_argument('-n', "--network", help='specify network (one of %s)' % networks, default='M') parser.add_argument( 'item', nargs="+", help='a BIP0032 wallet key string;' ' a WIF;' ' a bitcoin address;' ' an SEC (ie. a 66 hex chars starting with 02, 03 or a 130 hex chars starting with 04);' ' the literal string "create" to create a new wallet key using strong entropy sources;' ' P:wallet passphrase (NOT RECOMMENDED);' ' H:wallet passphrase in hex (NOT RECOMMENDED);' ' secret_exponent (in decimal or hex);' ' x,y where x,y form a public pair (y is a number or one of the strings "even" or "odd");' ' hash160 (as 40 hex characters)') args = parser.parse_args() PREFIX_TRANSFORMS = ( ("P:", lambda s: Key(hierarchical_wallet=Wallet.from_master_secret(s.encode("utf8"), netcode=args.network))), ("H:", lambda s: Key(hierarchical_wallet=Wallet.from_master_secret(h2b(s), netcode=args.network))), ("create", lambda s: Key(hierarchical_wallet=Wallet.from_master_secret(get_entropy(), netcode=args.network))), ) for item in args.item: key = None for k, f in PREFIX_TRANSFORMS: if item.startswith(k): try: key = f(item[len(k):]) break except Exception: pass else: try: key = Key.from_text(item) except encoding.EncodingError: pass if key is None: secret_exponent = parse_as_secret_exponent(item) if secret_exponent: key = Key(secret_exponent=secret_exponent, netcode=args.network) if SEC_RE.match(item): key = Key.from_sec(h2b(item)) if key is None: public_pair = parse_as_public_pair(item) if public_pair: key = Key(public_pair=public_pair, netcode=args.network) if HASH160_RE.match(item): key = Key(hash160=h2b(item), netcode=args.network) if key is None: print("can't parse %s" % item, file=sys.stderr) continue for key in key.subkeys(args.subkey or ""): if args.public: key = key.public_copy() output_dict, output_order = create_output(item, key) if args.json: print(json.dumps(output_dict, indent=3)) elif args.wallet: print(output_dict["wallet_key"]) elif args.wif: print(output_dict["wif_uncompressed" if args.uncompressed else "wif"]) elif args.address: print(output_dict[ "bitcoin_address_uncompressed" if args.uncompressed else "bitcoin_address"]) else: dump_output(output_dict, output_order)
def key(testnet, wif): netcode = 'XTN' if testnet else 'BTC' if not validate.is_wif_valid(wif, allowable_netcodes=[netcode]): raise exceptions.InvalidWif(address) return Key.from_text(wif)
<<<<<<< Updated upstream # Also cryptocorp's key is supplyed ======= private_wallets = json.load(open((chain_file + ".mseks.json"), "r")) # The next is because I will use only one key private_wallets.remove(private_wallets[1]) >>>>>>> Stashed changes chainPaths = ["0/0/7","0/0/7","0/0/7"] print("Chain paths:") pp.pprint(chainPaths) print("") # masterbip32nodes = [Key.from_text(i) for i in public_wallets] sub_bip32_nodes = [BIP32Node.subkey_for_path(Key.from_text(public_wallets[i]), chainPaths[i]) for i in range(len(chainPaths))] print("Sub BIP32 wallets:") for i in sub_bip32_nodes: print(i) print("") script_encoded = ScriptMultisig(n=2, sec_keys=[key.sec() for key in sub_bip32_nodes]).script() script = b2h(script_encoded) print("Script:") print(script) print("") address = address_for_pay_to_script(script_encoded) # 3Bi36w9RZHmibi1ip7ud9dvtpDt59ij7GC
def generate_address_from_xpub(xpub, index=0, is_hardened=False): key = Key.from_text(xpub) return str(key.subkey(index, is_hardened).address())
# 2) usb serial number of unit (base32 encoding of 128-bit number: 26 chars) # 3) a random number picked by device (device nonce: 256 bits) # should_be = sha256(sha256(data + CHIP_SERIAL + OD_NONCE).digest()).digest() if should_be != SECRET_EXPONENT: print("\nFAILED: You probably didn't record exactly the bytes written to this drive.") raise SystemExit print("STEP1: Secret exponent is hash of things we expected (good).") # Optional: verify the secret exponent is the basis of the private key try: import pycoin except ImportError: print("\nNeed pycoin installed for complete check: 'pip install pycoin'\n") raise SystemExit # pull out secret key from provided secret key from pycoin.key import Key k = Key.from_text(PRIVKEY) expect = pycoin.encoding.to_bytes_32(k.secret_exponent()) if expect == should_be and k.address() == ADDRESS: print("\nSUCCESS: Private key uses secret exponent we expected. Perfect.") else: print("\nFAILED: Something went wrong along the way. Is this the right private key?") # EOF