def test_wallet_multisig_2of2_with_single_key(self): if os.path.isfile(DATABASEFILE_UNITTESTS): os.remove(DATABASEFILE_UNITTESTS) keys = [ HDKey(network='bitcoinlib_test'), HDKey(network='bitcoinlib_test', key_type='single') ] key_list = [keys[0], keys[1].public()] wl = HDWallet.create_multisig('multisig_expk2', key_list, sigs_required=2, network='bitcoinlib_test', databasefile=DATABASEFILE_UNITTESTS) wl.new_key() wl.new_key() wl.new_key_change() wl.utxos_update() self.assertEqual(wl.keys()[0].name, 'Multisig Key 8/7') self.assertEqual(wl.keys()[1].name, 'Multisig Key 10/7') self.assertEqual(wl.keys()[2].name, 'Multisig Key 12/7') t = wl.transaction_create( [(HDKey(network='bitcoinlib_test').key.address(), 6400000)], min_confirms=0) t = wl.transaction_sign(t, keys[1]) self.assertEqual(wl.transaction_send(t), 'succesfull_test_sendrawtransaction')
def test_wallet_key_import_and_sign_multisig(self): if os.path.isfile(DATABASEFILE_UNITTESTS): os.remove(DATABASEFILE_UNITTESTS) network = 'bitcoinlib_test' words = 'square innocent drama' seed = Mnemonic().to_seed(words, 'password') hdkey = HDKey.from_seed(seed, network=network) hdkey.key_type = 'single' key_list = [ HDKey(network=network).account_multisig_key().public(), HDKey(network=network), hdkey.public() ] wallet = HDWallet.create_multisig('Multisig-2-of-3-example', key_list, 2, sort_keys=True, network=network, databasefile=DATABASEFILE_UNITTESTS) wallet.new_key() wallet.utxos_update() wallet.import_key(hdkey) wt = wallet.send_to('n2eMqTT929pb1RDNuqEnxdaLau1rxy3efi', 10000000) self.assertIsNone(wt.error)
def test_wallet_multisig_sign_with_external_single_key(self): if os.path.isfile(DATABASEFILE_UNITTESTS): os.remove(DATABASEFILE_UNITTESTS) NETWORK = 'bitcoinlib_test' words = 'square innocent drama' seed = Mnemonic().to_seed(words, 'password') hdkey = HDKey.from_seed(seed, network=NETWORK) hdkey.key_type = 'single' key_list = [ HDKey(network=NETWORK).account_multisig_key().public(), HDKey(network=NETWORK), hdkey.public() ] wallet = HDWallet.create_multisig('Multisig-2-of-3-example', key_list, 2, network=NETWORK, databasefile=DATABASEFILE_UNITTESTS) wallet.new_key() wallet.utxos_update() res = wallet.send_to('n2eMqTT929pb1RDNuqEnxdaLau1rxy3efi', 10000000) t = res['transaction'].raw_hex() t2 = wallet.transaction_import(t) self.assertFalse(t2.verify()) t2 = wallet.transaction_sign(t2, hdkey) self.assertTrue(t2.verify())
def test_transactions_multisig_signature_redeemscript_mixup(self): pk1 = HDKey( 'tprv8ZgxMBicQKsPen95zTdorkDGPi4jHy9xBf4TdVxrB1wTJgSKCZbHpWhmaTGoRXHj2dJRcJQhRkV22Mz3uhg9nThjGLA' 'JKzrPuZXPmFUgQ42') pk2 = HDKey( 'tprv8ZgxMBicQKsPdhv4GxyNcfNK1Wka7QEnQ2c8DNdRL5z3hzf7ufUYNW14fgArjFvLtyg5xmPrkpx6oGBo2dquPf5inH6' 'Jg6h2D89nsQdY8Ga') redeemscript = b'522103b008ee001282efb523f68d494896f3072903e03b3fb91d16713c56bf79693a382102d43dcc8a5db03172ba' \ b'95c345bb2d478654853f311dc4b1cbd313e5a327f0e3ba52ae' # Create 2-of-2 multisig transaction with 1 input and 1 output t = Transaction(network='testnet') t.add_input( 'a2c226037d73022ea35af9609c717d98785906ff8b71818cd4095a12872795e7', 1, [pk1.key.public_byte, pk2.key.public_byte], script_type='p2sh_multisig', sigs_required=2) t.add_output(900000, '2NEgmZU64NjiZsxPULekrFcqdS7YwvYh24r') # Sign with private key and verify t.sign(pk1.private_byte) t.sign(pk2.private_byte) self.assertTrue(t.verify()) # Now deserialize and check if redeemscript is still the same dt = transaction_deserialize(t.raw_hex(), network='testnet') self.assertEqual(binascii.hexlify(dt[0][0].redeemscript), redeemscript)
def test_transactions_sign_multiple_inputs(self): # Two private keys with 1 UTXO on the blockchain each wif1 = 'xprvA3PZhxgsb5cogy52pm8eJf21gW2epoetxdCZxpmBWddViHmB7wgR4apQVxRHmyngapZ14pBzWSCP6sztWn8EaMmnwZaj' \ 'fs7oS6rZDYdnrwh' wif2 = 'xprvA3PZhxgsb5cojKHWdGGFBNut51QbAe5arWb7s7cJ9cT6zThQJFvYKKZDcmFirWJVVHgRYzqLc9XnuDMrP3Qwy8sK8Zu5' \ 'MisgvXVtGdwDhrH' # Create inputs with a UTXO with 2 unspent outputs which corresponds to this private keys utxo_hash = '0177ac29fa8b2960051321c730c6f15017503aa5b9c1dd2d61e7286e366fbaba' pk1 = HDKey(wif1) pk2 = HDKey(wif2) input1 = Input(prev_hash=utxo_hash, output_index=0, keys=pk1.public_byte, tid=0) input2 = Input(prev_hash=utxo_hash, output_index=1, keys=pk2.public_byte, tid=1) # Create a transaction with 2 inputs, and add 2 outputs below osm_address = '1J3pt9koWJZTo2jarg98RL89iJqff9Kobp' change_address = '1Ht9iDJ3FjwweQNuj451QVL6RAP5qxadFb' output1 = Output(amount=900000, address=osm_address) output2 = Output(amount=150000, address=change_address) t = Transaction(inputs=[input1, input2], outputs=[output1, output2]) # Sign the inputs and verify # See txid 1ec28c925df0079ead9976d38165909ccb3580a428ce069ee13e63879df0c2fc t.sign(pk1.private_byte, 0) t.sign(pk2.private_byte, 1) self.assertTrue(t.verify())
def test_wallet_multisig_reopen_wallet(self): def _open_all_wallets(): wl1 = wallet_create_or_open_multisig( 'multisigmulticur1_tst', sigs_required=2, network=network, databasefile=DATABASEFILE_UNITTESTS, key_list=[pk1, pk2.account_multisig_key().wif_public(), pk3.account_multisig_key().wif_public()]) wl2 = wallet_create_or_open_multisig( 'multisigmulticur2_tst', sigs_required=2, network=network, databasefile=DATABASEFILE_UNITTESTS, key_list=[pk1.account_multisig_key().wif_public(), pk2, pk3.account_multisig_key().wif_public()]) wl3 = wallet_create_or_open_multisig( 'multisigmulticur3_tst', sigs_required=2, network=network, databasefile=DATABASEFILE_UNITTESTS, key_list=[pk1.account_multisig_key().wif_public(), pk2.account_multisig_key().wif_public(), pk3]) return wl1, wl2, wl3 if os.path.isfile(DATABASEFILE_UNITTESTS): os.remove(DATABASEFILE_UNITTESTS) network = 'litecoin' phrase1 = 'shop cloth bench traffic vintage security hour engage omit almost episode fragile' phrase2 = 'exclude twice mention orchard grit ignore display shine cheap exercise same apart' phrase3 = 'citizen obscure tribe index little welcome deer wine exile possible pizza adjust' pk1 = HDKey.from_passphrase(phrase1, network=network) pk2 = HDKey.from_passphrase(phrase2, network=network) pk3 = HDKey.from_passphrase(phrase3, network=network) wallets = _open_all_wallets() for wlt in wallets: self.assertEqual(wlt.get_key().address, '354bZpUpeaUEwsRn5Le5BymTvqPHf9jZkS') del wallets wallets2 = _open_all_wallets() for wlt in wallets2: self.assertEqual(wlt.get_key().address, '354bZpUpeaUEwsRn5Le5BymTvqPHf9jZkS') wlt._session.close_all()
def test_wallet_multisig_2of2_with_single_key(self): if os.path.isfile(DATABASEFILE_UNITTESTS): os.remove(DATABASEFILE_UNITTESTS) keys = [ HDKey(network='bitcoinlib_test'), HDKey(network='bitcoinlib_test', key_type='single') ] key_list = [keys[0], keys[1].public()] wl = HDWallet.create_multisig('multisig_expk2', key_list, sigs_required=2, network='bitcoinlib_test', databasefile=DATABASEFILE_UNITTESTS, sort_keys=False) wl.new_key() wl.new_key() wl.new_key_change() wl.utxos_update() key_names = [k.name for k in wl.keys(is_active=False)] self.assertListEqual(key_names, ['Multisig Key 8/7', 'Multisig Key 10/7', 'Multisig Key 12/7']) t = wl.transaction_create([(HDKey(network='bitcoinlib_test').key.address(), 6400000)], min_confirms=0) t.sign(keys[1]) t.send() self.assertIsNone(t.error) key_names_active = [k.name for k in wl.keys(is_active=False)] self.assertEqual(key_names_active, ['Multisig Key 8/7', 'Multisig Key 10/7', 'Multisig Key 12/7', 'Multisig Key 14/7'])
def test_wallet_multisig_2of2(self): """ Create 2 cosigner wallets with 1 own private key a public key from other cosigner Then create and sign transaction if first wallet, import and sign it in second wallet and verify created transaction. """ if os.path.isfile(DATABASEFILE_UNITTESTS): os.remove(DATABASEFILE_UNITTESTS) keys = [ HDKey('YXscyqNJ5YK411nwB4wzazXjJn9L9iLAR1zEMFcpLipDA25rZregBGgwXmprsvQLeQAsuTvemtbCWR1AHaPv2qmvkartoiFUU6' 'qu1uafT2FETtXT', network='bitcoinlib_test'), HDKey('YXscyqNJ5YK411nwB4EyGbNZo9eQSUWb64vAFKHt7E2LYnbmoNz8Gyjs6xc7iYAudcnkgf127NPnaanuUgyRngAiwYBcXKGsSJ' 'wadGhxByT2MnLd', network='bitcoinlib_test')] msw1 = HDWallet.create_multisig('msw1', [keys[0], keys[1].subkey_for_path("m/45'/9999999'/0'").wif_public()], network='bitcoinlib_test', sort_keys=False, sigs_required=2, databasefile=DATABASEFILE_UNITTESTS) msw2 = HDWallet.create_multisig('msw2', [keys[0].subkey_for_path("m/45'/9999999'/0'").wif_public(), keys[1]], network='bitcoinlib_test', sort_keys=False, sigs_required=2, databasefile=DATABASEFILE_UNITTESTS) msw1.new_key() msw2.new_key() msw1.utxos_update() msw2.utxos_update() utxos = msw1.utxos() output_arr = [('21KnydRNSmqAf8Py74mMiwRXYHGxW27zyDu', utxos[0]['value'] - 50000)] input_arr = [(utxos[0]['tx_hash'], utxos[0]['output_n'], utxos[0]['key_id'], utxos[0]['value'])] t = msw1.transaction_create(output_arr, input_arr, fee=50000) t.sign() t2 = msw2.transaction_import(t) t2.sign() self.assertTrue(t2.verify())
def test_wallet_import_private_for_known_public(self): hdkey = HDKey( 'xprv9s21ZrQH143K2noEZoqGHnaDDLjrnFpis8jm7NWDhkWuNNCqMupGSy7PMYtGL9jvdTY7Nx3GZ6UZ9C52nebwbYXK73imaPUK24' 'dZJtGZhGd') with HDWallet.create('public-private', hdkey.account_key().public(), databasefile=DATABASEFILE_UNITTESTS) \ as wlt: wlt.import_key(hdkey) self.assertListEqual([k.path for k in wlt.keys()], ["m/44'/0'/0'", 'm', "m/44'", "m/44'/0'"]) self.assertEqual(wlt.new_account().address, '16m3JAtQjHbmEZd8uYTyKebvrxh2RsFHB') self.assertEqual(wlt.new_key().address, '1P8BTrsBn8DKGQq7nSWPiEiUDgiG8sW1kf')
def _multisig_test(sigs_required, number_of_sigs, sort_keys, network): # Create Keys key_dict = {} for key_id in range(number_of_sigs): key_dict[key_id] = HDKey(network=network) random_output_address = HDKey(network=network).key.address() # Create wallets with 1 private key each wallet_dict = {} wallet_keys = {} for wallet_id in range(number_of_sigs): wallet_name = 'multisig-%d' % wallet_id key_list = [] for key_id in key_dict: if key_id == wallet_id: key_list.append(key_dict[key_id]) else: key_list.append(key_dict[key_id].subkey_for_path( "m/45'/%d'/0'" % Network(network).bip44_cointype).wif_public()) wallet_dict[wallet_id] = HDWallet.create_multisig( wallet_name, key_list, sigs_required=sigs_required, network=network, sort_keys=sort_keys, databasefile=DATABASEFILE_UNITTESTS) wallet_keys[wallet_id] = wallet_dict[wallet_id].new_key() wallet_dict[wallet_id].utxos_update() # Create transaction in one random wallet wallet_ids = [i for i in range(0, number_of_sigs)] shuffle(wallet_ids) transaction_fee = 50000 wallet_id = wallet_ids.pop() wlt = wallet_dict[wallet_id] utxos = wlt.utxos() output_arr = [(random_output_address, utxos[0]['value'] - transaction_fee)] input_arr = [(utxos[0]['tx_hash'], utxos[0]['output_n'], utxos[0]['key_id'], utxos[0]['value'])] t = wlt.transaction_create(output_arr, input_arr, transaction_fee=transaction_fee) t.sign() n_signs = 1 # Sign transaction with other wallets until required number of signatures is reached while wallet_ids and n_signs < sigs_required: wallet_id = wallet_ids.pop() t = wallet_dict[wallet_id].transaction_import(t) t.sign() n_signs += 1 return t
def test_wallet_multisig_2of2_different_database(self): """ Same unittest as before (test_wallet_multisig_sign_2_different_wallets) but now with 2 separate databases to check for database inteference. """ if os.path.isfile(DATABASEFILE_UNITTESTS): os.remove(DATABASEFILE_UNITTESTS) if os.path.isfile(DATABASEFILE_UNITTESTS_2): os.remove(DATABASEFILE_UNITTESTS_2) keys = [ HDKey( 'YXscyqNJ5YK411nwB4wzazXjJn9L9iLAR1zEMFcpLipDA25rZregBGgwXmprsvQLeQAsuTvemtbCWR1AHaPv2qmvkartoiFUU6' 'qu1uafT2FETtXT', network='bitcoinlib_test'), HDKey( 'YXscyqNJ5YK411nwB4EyGbNZo9eQSUWb64vAFKHt7E2LYnbmoNz8Gyjs6xc7iYAudcnkgf127NPnaanuUgyRngAiwYBcXKGsSJ' 'wadGhxByT2MnLd', network='bitcoinlib_test') ] msw1 = HDWallet.create_multisig('msw1', [ keys[0], keys[1].subkey_for_path("m/45'/9999999'/0'").wif_public() ], network='bitcoinlib_test', sort_keys=False, sigs_required=2, databasefile=DATABASEFILE_UNITTESTS) msw2 = HDWallet.create_multisig('msw2', [ keys[0].subkey_for_path("m/45'/9999999'/0'").wif_public(), keys[1] ], network='bitcoinlib_test', sort_keys=False, sigs_required=2, databasefile=DATABASEFILE_UNITTESTS_2) msw1.new_key() msw2.new_key() msw1.utxos_update() msw2.utxos_update() utxos = msw1.utxos() output_arr = [('21KnydRNSmqAf8Py74mMiwRXYHGxW27zyDu', utxos[0]['value'] - 50000)] input_arr = [(utxos[0]['tx_hash'], utxos[0]['output_n'], utxos[0]['key_id'], utxos[0]['value'])] t = msw1.transaction_create(output_arr, input_arr, transaction_fee=50000) t.sign() t2 = msw2.transaction_import(t) t2.sign() t2.send() self.assertIsNone(t2.error)
def create_wallet(wallet_name, args, databasefile): if args.network is None: args.network = DEFAULT_NETWORK print("\nCREATE wallet '%s' (%s network)" % (wallet_name, args.network)) if args.create_multisig: if not isinstance(args.create_multisig, list) or len(args.create_multisig) < 2: clw_exit("Please enter multisig creation parameter in the following format: " "<number-of-signatures> <number-of-signatures-required> " "<key-0> <key-1> [<key-2> ... <key-n>]") try: sigs_total = int(args.create_multisig[0]) except ValueError: clw_exit("Number of total signatures (first argument) must be a numeric value. %s" % args.create_multisig[0]) try: sigs_required = int(args.create_multisig[1]) except ValueError: clw_exit("Number of signatures required (second argument) must be a numeric value. %s" % args.create_multisig[1]) key_list = args.create_multisig[2:] keys_missing = sigs_total - len(key_list) assert(keys_missing >= 0) if keys_missing: print("Not all keys provided, creating %d additional keys" % keys_missing) for _ in range(keys_missing): passphrase = get_passphrase(args) passphrase = ' '.join(passphrase) seed = binascii.hexlify(Mnemonic().to_seed(passphrase)) key_list.append(HDKey().from_seed(seed, network=args.network)) return HDWallet.create_multisig(name=wallet_name, keys=key_list, sigs_required=sigs_required, network=args.network, databasefile=databasefile, sort_keys=True, witness_type=args.witness_type) elif args.create_from_key: return HDWallet.create(name=wallet_name, network=args.network, keys=args.create_from_key, databasefile=databasefile, witness_type=args.witness_type) else: passphrase = args.passphrase if passphrase is None: passphrase = get_passphrase(args) elif not passphrase: passphrase = input("Enter Passphrase: ") if not isinstance(passphrase, list): passphrase = passphrase.split(' ') elif len(passphrase) == 1: passphrase = passphrase[0].split(' ') if len(passphrase) < 12: clw_exit("Please specify passphrase with 12 words or more") passphrase = ' '.join(passphrase) seed = binascii.hexlify(Mnemonic().to_seed(passphrase)) hdkey = HDKey().from_seed(seed, network=args.network) return HDWallet.create(name=wallet_name, network=args.network, keys=hdkey, witness_type=args.witness_type, databasefile=databasefile)
def create_wallet(wallet_name, args, databasefile): print("\nCREATE wallet '%s' (%s network)" % (wallet_name, args.network)) if args.create_multisig: if not isinstance(args.create_multisig, list) or len(args.create_multisig) < 3: clw_exit( "Please enter multisig creation parameter in the following format: " "<number-of-signatures-required> <key-0> <key-1> [<key-2> ... <key-n>]" ) try: sigs_required = int(args.create_multisig[0]) except ValueError: clw_exit( "Number of signatures required (first argument) must be a numeric value. %s" % args.create_multisig[0]) key_list = args.create_multisig[1:] return HDWallet.create_multisig(name=wallet_name, key_list=key_list, sigs_required=sigs_required, network=args.network, databasefile=databasefile) else: passphrase = args.passphrase if passphrase is None: inp_passphrase = Mnemonic('english').generate( args.passphrase_strength) print("\nYour mnemonic private key sentence is: %s" % inp_passphrase) print( "\nPlease write down on paper and backup. With this key you can restore your wallet and all keys" ) passphrase = inp_passphrase.split(' ') inp = input( "\nType 'yes' if you understood and wrote down your key: ") if inp not in ['yes', 'Yes', 'YES']: clw_exit("Exiting...") elif not passphrase: passphrase = input("Enter Passphrase: ") if not isinstance(passphrase, list): passphrase = passphrase.split(' ') elif len(passphrase) == 1: passphrase = passphrase[0].split(' ') if len(passphrase) < 12: clw_exit("Please specify passphrase with 12 words or more") passphrase = ' '.join(passphrase) seed = binascii.hexlify(Mnemonic().to_seed(passphrase)) hdkey = HDKey().from_seed(seed, network=args.network) return HDWallet.create(name=wallet_name, network=args.network, key=hdkey.wif(), databasefile=databasefile)
def test_wallet_multisig_network_mixups(self): if os.path.isfile(DATABASEFILE_UNITTESTS): os.remove(DATABASEFILE_UNITTESTS) network = 'litecoin_testnet' phrase1 = 'shop cloth bench traffic vintage security hour engage omit almost episode fragile' phrase2 = 'exclude twice mention orchard grit ignore display shine cheap exercise same apart' phrase3 = 'citizen obscure tribe index little welcome deer wine exile possible pizza adjust' pk2 = HDKey.from_passphrase(phrase2, network=network) pk3 = HDKey.from_passphrase(phrase3, network=network) wlt = wallet_create_or_open_multisig( 'multisig_network_mixups', sigs_required=2, network=network, databasefile=DATABASEFILE_UNITTESTS, key_list=[phrase1, pk2.account_multisig_key().wif_public(), pk3.account_multisig_key().wif_public()]) self.assertEqual(wlt.get_key().address, 'QeBprfDJNadgqJV4R5d7e9i6duVK8HFgAN') self.assertEqual(wlt.get_key().network.network_name, network)
def create_wallet(wallet_name, args, databasefile): if args.network is None: args.network = DEFAULT_NETWORK print("\nCREATE wallet '%s' (%s network)" % (wallet_name, args.network)) if args.create_multisig: if not isinstance(args.create_multisig, list) or len(args.create_multisig) < 3: clw_exit( "Please enter multisig creation parameter in the following format: " "<number-of-signatures-required> <key-0> <key-1> [<key-2> ... <key-n>]" ) try: sigs_required = int(args.create_multisig[0]) except ValueError: clw_exit( "Number of signatures required (first argument) must be a numeric value. %s" % args.create_multisig[0]) key_list = args.create_multisig[1:] return HDWallet.create_multisig(name=wallet_name, key_list=key_list, sigs_required=sigs_required, network=args.network, databasefile=databasefile, sort_keys=True) elif args.create_from_key: return HDWallet.create(name=wallet_name, network=args.network, key=args.create_from_key, databasefile=databasefile) else: passphrase = args.passphrase if passphrase is None: passphrase = get_passphrase(args) elif not passphrase: passphrase = input("Enter Passphrase: ") if not isinstance(passphrase, list): passphrase = passphrase.split(' ') elif len(passphrase) == 1: passphrase = passphrase[0].split(' ') if len(passphrase) < 12: clw_exit("Please specify passphrase with 12 words or more") passphrase = ' '.join(passphrase) seed = binascii.hexlify(Mnemonic().to_seed(passphrase)) hdkey = HDKey().from_seed(seed, network=args.network) return HDWallet.create(name=wallet_name, network=args.network, key=hdkey.wif(), databasefile=databasefile)
def __init__(self, *args, **kwargs): self.project_name = os.environ.get('PROJECT_NAME') self.deployment_name = os.environ.get('DEPLOYMENT_NAME') # Initialize bitcoin wallet xpub_wif = os.environ.get('HDKEY_XPUB_WIF', None) if xpub_wif is None: raise NoXPUBFoud try: xpub = HDKey(xpub_wif) self.wallet = Wallet.create("Wallet", keys=xpub, network='bitcoin', witness_type='segwit') except Exception as e: raise e # Initialize Ubiops Client ubiops_api_token = os.environ.get('UBIOPS_API_TOKEN', None) internal_ubiops_api_host = os.environ.get('INT_API_URL') ubiops_conf = ubiops.Configuration( host=internal_ubiops_api_host, api_key={'Authorization': 'Token {}'.format(ubiops_api_token)}, ) client = ubiops.ApiClient(ubiops_conf) self.ubiops_api = ubiops.api.CoreApi(client) environment_variables = self.ubiops_api.deployment_environment_variables_list(self.project_name, self.deployment_name) self.last_used_path_index = os.environ.get('LAST_USED_PATH_INDEX', '0/0') self.last_used_path_index_env = None for env in environment_variables: if env.name == 'LAST_USED_PATH_INDEX': self.last_used_path_index_env = env print("Wallet initialized successfuly.")
def key(network, key): network_name = network_code_translation[network] try: k = HDKey(key, network=network_name) except Exception as e: flash(_('Invalid key: %s' % e), category='error') return redirect(url_for('main.index')) if k.is_private: flash(_( 'Never post your private key online. Only use this for test keys or in an offline environment!' ), category='error') return render_template('explorer/key.html', title=_('Key'), subtitle=k.wif(), key=k, network=network)
def setUp(self): self.pk1 = HDKey( 'tprv8ZgxMBicQKsPen95zTdorkDGPi4jHy9xBf4TdVxrB1wTJgSKCZbHpWhmaTGoRXHj2dJRcJQhRkV22Mz3uh' 'g9nThjGLAJKzrPuZXPmFUgQ42') self.pk2 = HDKey( 'tprv8ZgxMBicQKsPdhv4GxyNcfNK1Wka7QEnQ2c8DNdRL5z3hzf7ufUYNW14fgArjFvLtyg5xmPrkpx6oGBo2' 'dquPf5inH6Jg6h2D89nsQdY8Ga') self.pk3 = HDKey( 'tprv8ZgxMBicQKsPedw6MqKGBhVtpDTMpGqdUUrkurgvpAZxoEpn2SVJbUtArig6cnpxenVWs42FRB3wp5Lim' 'CAVsjLKHmAK1hB1fYJ8aUyzQeH') self.pk4 = HDKey( 'tprv8ZgxMBicQKsPefyc4C5BZwKRtBoNS8WA1to31B6QCxrrXY83FnWVALo3YKNuuisqbN9FUM245nZnXEQbf' 'uEemfBXy7CLD6abaXx24PotyQY') self.pk5 = HDKey( 'tprv8ZgxMBicQKsPdbyo59MRWqjXq3tTCS4PgJuFzJZvp8dBZz5HpQBw994LDS7ig8rsJcZwq6r3LghBeb82L' 'iYu6rL35dm3XiMMJjNoY8d6pqN') self.utxo_tbtcleft = 740000 self.utxo_prev_tx = 'f601e39f6b99b64fc2e98beb706ec7f14d114db7e61722c0313b0048df49453e' self.utxo_output_n = 1
def _check_list(self, language, vectors): mnemo = Mnemonic(language) for v in vectors: if v[0]: phrase = mnemo.to_mnemonic(v[0]) else: phrase = v[1] seed = change_base(mnemo.to_seed(phrase, v[4]), 256, 16) print("Test %s => %s" % (v[0], phrase)) self.assertEqual(v[1], phrase) self.assertEqual(v[2], seed) k = HDKey.from_seed(seed) self.assertEqual(k.extended_wif(), v[3])
def _check_list(self, language, vectors): mnemo = Mnemonic(language) for v in vectors: if v[0]: phrase = mnemo.to_mnemonic(v[0], check_on_curve=False) else: phrase = v[1] seed = change_base(mnemo.to_seed(phrase, v[4], validate=False), 256, 16) # print("Test %s => %s" % (v[0], phrase)) self.assertEqual(v[1], phrase) self.assertEqual(v[2], seed) k = HDKey.from_seed(seed) self.assertEqual(k.wif(is_private=True), v[3])
def _check_list(self, language, vectors): mnemo = Mnemonic(language) for v in vectors: if v[0]: phrase = mnemo.to_mnemonic(v[0]) else: phrase = v[1] seed = change_base(mnemo.to_seed(phrase, v[4]), 256, 16) print("Test %s => %s" % (v[0], phrase)) self.assertEqual(v[1], phrase) self.assertEqual(v[2], seed) k = HDKey.from_seed(seed) self.assertEqual(k.wif(), v[3])
def test_wallet_offline_create_transaction(self): hdkey_wif = 'tprv8ZgxMBicQKsPf5exCdeBgnYjJt2LxDcQbv6u9HHymY3qh6EoTy8SGwou5xyvExL3iWfBsZWp3YUyo9gRmxQxrBS2FwGk' \ 'qjcDhTcyVLhrXXZ' hdkey = HDKey(hdkey_wif) wlt = wallet_create_or_open('offline-create-transaction', key=hdkey, network='testnet', databasefile=DATABASEFILE_UNITTESTS) wlt.get_key() utxos = [{ 'address': 'n2S9Czehjvdmpwd2YqekxuUC1Tz5ZdK3YN', 'script': '', 'confirmations': 10, 'output_n': 1, 'tx_hash': '9df91f89a3eb4259ce04af66ad4caf3c9a297feea5e0b3bc506898b6728c5003', 'value': 8970937 }] wlt.utxos_update(utxos=utxos) t = wlt.transaction_create([('n2S9Czehjvdmpwd2YqekxuUC1Tz5ZdK3YN', 100)], fee=5000) t.sign() self.assertTrue(t.verify()) del wlt
def test_wallet_multisig_create_2_cosigner_wallets(self): if os.path.isfile(DATABASEFILE_UNITTESTS): os.remove(DATABASEFILE_UNITTESTS) pk_wif1 = 'tprv8ZgxMBicQKsPdvHCP6VxtFgowj2k7nBJnuRiVWE4DReDFojkLjyqdT8mtR6XJK9dRBcaa3RwvqiKFjsEQVhKfQmHZCCY' \ 'f4jRTWvJuVuK67n' pk_wif2 = 'tprv8ZgxMBicQKsPdkJVWDkqQQAMVYB2usfVs3VS2tBEsFAzjC84M3TaLMkHyJWjydnJH835KHvksS92ecuwwWFEdLAAccwZ' \ 'KjhcA63NUyvDixB' pk1 = HDKey(pk_wif1, network='testnet') pk2 = HDKey(pk_wif2, network='testnet') wl1 = HDWallet.create_multisig('multisig_test_wallet1', [pk_wif1, pk2.subkey_for_path("m/45'/1'/0'").wif_public()], sigs_required=2, network='testnet', databasefile=DATABASEFILE_UNITTESTS) wl2 = HDWallet.create_multisig('multisig_test_wallet2', [pk1.subkey_for_path("m/45'/1'/0'").wif_public(), pk_wif2], sigs_required=2, network='testnet', databasefile=DATABASEFILE_UNITTESTS) wl1_key = wl1.new_key() wl2_key = wl2.new_key() self.assertEqual(wl1_key.address, wl2_key.address)
from bitcoinlib.config.config import BCL_DATABASE_DIR from bitcoinlib.keys import HDKey from bitcoinlib.wallets import HDWallet test_databasefile = os.path.join(BCL_DATABASE_DIR, 'bitcoinlib.test.sqlite') test_database = 'sqlite:///' + test_databasefile if os.path.isfile(test_databasefile): os.remove(test_databasefile) # # Create a multi-signature wallet using Bitcoinlib testnet and then create a transaction # # Create 3 wallets with one private keys each, and 2 public keys corresponding with other wallets NETWORK = 'bitcoinlib_test' pk1 = HDKey(network=NETWORK) pk2 = HDKey(network=NETWORK) pk3 = HDKey(network=NETWORK) klist = [pk1, pk2.public_master_multisig(), pk3.public_master_multisig()] wl1 = HDWallet.create('multisig_2of3_cosigner1', sigs_required=2, keys=klist, network=NETWORK, db_uri=test_database) klist = [pk1.public_master_multisig(), pk2, pk3.public_master_multisig()] wl2 = HDWallet.create('multisig_2of3_cosigner2', sigs_required=2, keys=klist, network=NETWORK, db_uri=test_database) klist = [pk1.public_master_multisig(), pk2.public_master_multisig(), pk3]
# * P2WPKH - Pay-to-wallet-public-key-hash, Native SegWit single key # * P2WSH - Pay-to-wallet-script-hash, Native SegWit multisig/script # * P2SH-P2WPKH - P2WPKH nested in a P2SH script # * P2SH-P2WSH - P2WSH nested in P2SH script # # If you deposit at least 0.001 TBTC test bitcoins to the first wallet, several transactions will be created for every # kind of segwit wallet # from bitcoinlib.wallets import wallet_create_or_open, wallet_create_or_open_multisig from bitcoinlib.keys import HDKey from time import sleep wif = 'tprv8ZgxMBicQKsPdpenF8SX1WMsr6eaS3rZgqhqVu1LJ3wkAp1NhREnFrsvzK4A7ERrHhxqjzZpoESRjwpgrrhjC1cWALzZRxoycCNz8jBNWre' wif2 = 'tprv8ZgxMBicQKsPdktmSG4hGs6kq3dmTMmiDtLZwaipsCYxqbhtqWH69kNGZvNufnemLTCP3gbypLf1koKfAEujo5cnWPKBg3YbpZa63J9Cqtj' cowif2 = HDKey(wif2).account_multisig_key() # # CREATE WALLETS # # Segwit P2SH-P2WPKH Wallet w1 = wallet_create_or_open('segwit_testnet_p2sh_p2wpkh', key=wif, witness_type='p2sh-segwit', network='testnet') w1_key = w1.get_key() # Segwit Native P2WPKH Wallet w2 = wallet_create_or_open('segwit_testnet_p2wpkh', key=wif,
def from_key(name, wallet_id, session, key='', account_id=0, network='bitcoin', change=0, purpose=44, parent_id=0, path='m'): k = HDKey(import_key=key, network=network) keyexists = session.query(DbKey).filter(DbKey.key_wif == k.extended_wif()).all() if keyexists: raise WalletError("Key %s already exists" % k.extended_wif()) if k.depth() != len(path.split('/'))-1: if path == 'm' and k.depth() == 3: # Create path when importing new account-key networkcode = networks.NETWORKS[network]['bip44_cointype'] path = "m/%d'/%s'/%d'" % (purpose, networkcode, account_id) else: raise WalletError("Key depth of %d does not match path lenght of %d" % (k.depth(), len(path.split('/')) - 1)) wk = session.query(DbKey).filter(or_(DbKey.key == str(k.private()), DbKey.key_wif == k.extended_wif(), DbKey.address == k.public().address())).first() if wk: return HDWalletKey(wk.id, session) nk = DbKey(name=name, wallet_id=wallet_id, key=str(k.private()), purpose=purpose, account_id=account_id, depth=k.depth(), change=change, address_index=k.child_index(), key_wif=k.extended_wif(), address=k.public().address(), parent_id=parent_id, is_private=True, path=path, key_type=k.key_type) session.add(nk) session.commit() return HDWalletKey(nk.id, session)
print("Hex %s" % pk) print("Checksum bin %s" % Mnemonic().checksum(pk)) print("Mnemonic %s" % words) print("Seed for HD Key %s" % to_hexstring(Mnemonic().to_seed(words, 'test'))) print("Back to Entropy %s" % to_hexstring(Mnemonic().to_entropy(words))) # Generate a random Mnemonic HD Key print("\nGenerate a random Mnemonic HD Key") entsize = 128 words = Mnemonic('english').generate(entsize) print("Your Mnemonic is %s" % words) print(" (An avarage of %d tries is needed to brute-force this password)" % ((2**entsize) // 2)) seed = Mnemonic().to_seed(words) hdk = HDKey().from_seed(seed) print("Seed for HD Key %s" % to_hexstring(seed)) print("HD Key WIF is %s" % hdk.wif()) # Generate a key from a Mnemonic sentence print("\nGenerate a key from a Mnemonic sentence") words = "type fossil omit food supply enlist move perfect direct grape clean diamond" print("Your Mnemonic is %s" % words) seed = Mnemonic().to_seed(words) hdk = HDKey().from_seed(seed) print("Seed for HD Key %s" % to_hexstring(seed)) print("HD Key WIF is %s" % hdk.wif()) # Let's talk Spanish print("\nGenerate a key from a Spanish Mnemonic sentence") words = "laguna afirmar talón resto peldaño deuda guerra dorado catorce avance oasis barniz"
network='testnet') w1_key = w1.get_key() # Segwit Native P2WPKH Wallet w2 = wallet_create_or_open('segwit_testnet_p2wpkh', keys=wif, witness_type='segwit', network='testnet') w2_key = w2.get_key() # Segwit Native P2WSH Wallet w3 = wallet_create_or_open( 'segwit_testnet_p2wsh', keys=[ wif, HDKey(wif2).public_master_multisig(witness_type='segwit').public() ], witness_type='segwit', network='testnet') w3_key = w3.get_key() # Segwit P2SH-P2WSH Wallet w4 = wallet_create_or_open('segwit_testnet_p2sh_p2wsh', keys=[ wif, HDKey(wif2).public_master_multisig( witness_type='p2sh-segwit').public() ], witness_type='p2sh-segwit', network='testnet') w4_key = w4.get_key()
k = Key('5KN7MzqK5wt2TP1fQCYyHBtDrXdJuXbUzm4A9rKAteGu3Qi5CVR') print("Private key %s" % k.wif()) print("Encrypted pk %s " % k.bip38_encrypt('TestingOneTwoThree')) print("Is Compressed %s\n" % k.compressed) print("\n=== Import and Decrypt BIP38 Key ===") k = Key('6PRVWUbkzzsbcVac2qwfssoUJAN1Xhrg6bNk8J7Nzm5H7kxEbn2Nh2ZoGg', passphrase='TestingOneTwoThree') print("Private key %s" % k.wif()) print("Is Compressed %s\n" % k.compressed) # # Hierarchical Deterministic Key Class and Child Key Derivation Examples # print("\n=== Generate random HD Key on testnet ===") hdk = HDKey(network='testnet') print("Random BIP32 HD Key on testnet %s" % hdk.wif()) print("\n=== Import HD Key from seed ===") k = HDKey.from_seed('000102030405060708090a0b0c0d0e0f') print("HD Key WIF for seed 000102030405060708090a0b0c0d0e0f: %s" % k.wif()) print("Key type is : %s" % k.key_type) print("\n=== Generate random Litecoin key ===") lk = HDKey(network='litecoin') lk.info() print("\n=== Generate random Dash key ===") lk = HDKey(network='dash') lk.info()
'tpubD6NzVbkrYhZ4XfKVKY9LUfXh4t3ZHMDw9Q2SUUDTCCXrzFGfLm6v5n4frZWNfc5fwkbc33C3FwvbwbxgrDGKNSL2WcLAhPcZXijrQvLvyYA' }, ] if not wallet_exists(WALLET_NAME): # This wallets key list, use tools/mnemonic_key_create.py to create your own. # cosigners_private = [] key_list = [] for cosigner in cosigners: if not cosigner['key']: raise ValueError( "Please create private keys with mnemonic_key_create.py and add to COSIGNERS definitions" ) hdkey = HDKey(cosigner['key'], key_type=cosigner['key_type']) if hdkey.is_private: cosigners_private.append(cosigner['name']) cosigner['hdkey'] = hdkey key_list.append(hdkey) # YOU SHOULD ENABLE THIS CHECK FOR REAL WALLETS # if len(cosigners_private) > 1: # raise ValueError("It is strongly advised to use not more then 1 private key per wallet.") if len(key_list) != SIGS_N: raise ValueError( "Number of cosigners (%d) is different then expected. SIG_N=%d" % (len(key_list), SIGS_N)) wallet3o5 = HDWallet.create_multisig(WALLET_NAME, key_list,
def main(): print("Command Line Wallet for BitcoinLib\n") # --- Parse commandline arguments --- args = parse_args() databasefile = DEFAULT_DATABASE if args.database: databasefile = os.path.join(BCL_DATABASE_DIR, args.database) if args.generate_key: passphrase = get_passphrase(args) passphrase = ' '.join(passphrase) seed = binascii.hexlify(Mnemonic().to_seed(passphrase)) hdkey = HDKey.from_seed(seed, network=args.network) print( "Private master key, to create multisig wallet on this machine: %s" % hdkey.wif()) print( "Public account key, to share with other cosigner multisig wallets: %s" % hdkey.public_master(witness_type=args.witness_type, multisig=True)) print("Network: %s" % hdkey.network.name) clw_exit() # List wallets, then exit if args.list_wallets: print("BitcoinLib wallets:") for w in wallets_list(databasefile=databasefile): if 'parent_id' in w and w['parent_id']: continue print("[%d] %s (%s) %s" % (w['id'], w['name'], w['network'], w['owner'])) clw_exit() # Delete specified wallet, then exit if args.wallet_remove: if not wallet_exists(args.wallet_name, databasefile=databasefile): clw_exit("Wallet '%s' not found" % args.wallet_name) inp = input( "\nWallet '%s' with all keys and will be removed, without private key it cannot be restored." "\nPlease retype exact name of wallet to proceed: " % args.wallet_name) if inp == args.wallet_name: if wallet_delete(args.wallet_name, force=True, databasefile=databasefile): clw_exit("\nWallet %s has been removed" % args.wallet_name) else: clw_exit("\nError when deleting wallet") else: clw_exit("\nSpecified wallet name incorrect") wlt = None if args.wallet_name and not args.wallet_name.isdigit( ) and not wallet_exists(args.wallet_name, databasefile=databasefile): if not args.create_from_key and input( "Wallet %s does not exist, create new wallet [yN]? " % args.wallet_name).lower() != 'y': clw_exit('Aborted') wlt = create_wallet(args.wallet_name, args, databasefile) args.wallet_info = True else: try: wlt = HDWallet(args.wallet_name, databasefile=databasefile) if args.passphrase is not None: print( "WARNING: Using passphrase option for existing wallet ignored" ) if args.create_from_key is not None: print( "WARNING: Using create_from_key option for existing wallet ignored" ) except WalletError as e: clw_exit("Error: %s" % e.msg) if wlt is None: clw_exit("Could not open wallet %s" % args.wallet_name) if args.import_private: if wlt.import_key(args.import_private): clw_exit("Private key imported") else: clw_exit("Failed to import key") if args.wallet_recreate: wallet_empty(args.wallet_name) print("Removed transactions and generated keys from this wallet") if args.update_utxos: wlt.utxos_update() if args.update_transactions: wlt.scan(scan_gap_limit=5) if args.export_private: if wlt.scheme == 'multisig': for w in wlt.cosigner: if w.main_key and w.main_key.is_private: print(w.main_key.wif) elif not wlt.main_key or not wlt.main_key.is_private: print("No private key available for this wallet") else: print(wlt.main_key.wif) clw_exit() if args.network is None: args.network = wlt.network.name tx_import = None if args.import_tx_file: try: fn = args.import_tx_file f = open(fn, "r") except FileNotFoundError: clw_exit("File %s not found" % args.import_tx_file) try: tx_import = ast.literal_eval(f.read()) except (ValueError, SyntaxError): tx_import = f.read() if args.import_tx: try: tx_import = ast.literal_eval(args.import_tx) except (ValueError, SyntaxError): tx_import = args.import_tx if tx_import: if isinstance(tx_import, dict): wt = wlt.transaction_import(tx_import) else: wt = wlt.transaction_import_raw(tx_import, network=args.network) wt.sign() if args.push: res = wt.send() if res: print("Transaction pushed to network. Transaction ID: %s" % wt.hash) else: print("Error creating transaction: %s" % wt.error) wt.info() print("Signed transaction:") print_transaction(wt) clw_exit() if args.receive: keys = wlt.get_key(network=args.network, number_of_keys=args.receive) if args.receive != 1: keys += wlt.get_key_change(network=args.network, number_of_keys=args.receive) keys = [keys] if not isinstance(keys, list) else keys print("Receive address(es):") for key in keys: addr = key.address print(addr) if QRCODES_AVAILABLE and args.receive == 1: qrcode = pyqrcode.create(addr) print(qrcode.terminal()) if not QRCODES_AVAILABLE and args.receive == 1: print( "Install qr code module to show QR codes: pip install pyqrcode" ) clw_exit() if args.create_transaction == []: clw_exit("Missing arguments for --create-transaction/-t option") if args.create_transaction: if args.fee_per_kb: clw_exit("Fee-per-kb option not allowed with --create-transaction") try: wt = create_transaction(wlt, args.create_transaction, args) except WalletError as e: clw_exit("Cannot create transaction: %s" % e.msg) wt.sign() print("Transaction created") wt.info() if args.push: wt.send() if wt.pushed: print("Transaction pushed to network. Transaction ID: %s" % wt.hash) else: print("Error creating transaction: %s" % wt.error) else: print( "\nTransaction created but not send yet. Transaction dictionary for export: " ) print_transaction(wt) clw_exit() if args.sweep: if args.fee: clw_exit("Fee option not allowed with --sweep") offline = True print("Sweep wallet. Send all funds to %s" % args.sweep) if args.push: offline = False wt = wlt.sweep(args.sweep, offline=offline, network=args.network, fee_per_kb=args.fee_per_kb) if not wt: clw_exit( "Error occurred when sweeping wallet: %s. Are UTXO's available and updated?" % wt) wt.info() if args.push: if wt.pushed: print("Transaction pushed to network. Transaction ID: %s" % wt.hash) elif not wt: print("Cannot sweep wallet, are UTXO's updated and available?") else: print("Error sweeping wallet: %s" % wt.error) else: print( "\nTransaction created but not send yet. Transaction dictionary for export: " ) print_transaction(wt) clw_exit() # print("Updating wallet") if args.network == 'bitcoinlib_test': wlt.utxos_update() print("Wallet info for %s" % wlt.name) wlt.info()
def test_wallet_multisig_sorted_keys(self): if os.path.isfile(DATABASEFILE_UNITTESTS): os.remove(DATABASEFILE_UNITTESTS) key1 = HDKey() key2 = HDKey() key3 = HDKey() w1 = HDWallet.create_multisig('w1', [ key1, key2.account_multisig_key().public(), key3.account_multisig_key().public() ], sigs_required=2, sort_keys=True, databasefile=DATABASEFILE_UNITTESTS) w2 = HDWallet.create_multisig('w2', [ key1.account_multisig_key().public(), key2, key3.account_multisig_key().public() ], sigs_required=2, sort_keys=True, databasefile=DATABASEFILE_UNITTESTS) w3 = HDWallet.create_multisig('w3', [ key1.account_multisig_key().public(), key2.account_multisig_key().public(), key3 ], sigs_required=2, sort_keys=True, databasefile=DATABASEFILE_UNITTESTS) for _ in range(10): address1 = w1.new_key().address address2 = w2.new_key().address address3 = w3.new_key().address self.assertTrue((address1 == address2 == address3), 'Different addressed generated: %s %s %s' % (address1, address2, address3))