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))
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 = msw1.transaction_sign(t) t2 = msw2.transaction_import(t.raw()) t2 = msw2.transaction_sign(t2) self.assertEqual(msw2.transaction_send(t2), 'succesfull_test_sendrawtransaction')
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, transaction_fee=50000) t = msw1.transaction_sign(t) t2 = msw2.transaction_import(t.raw()) t2 = msw2.transaction_sign(t2) self.assertTrue(t2.verify())
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_multisig_bitcoinlib_testnet_transaction_send(self): if os.path.isfile(DATABASEFILE_UNITTESTS): os.remove(DATABASEFILE_UNITTESTS) key_list = [ 'Pdke4WfXvALPdbrKEfBU9z9BNuRNbv1gRr66BEiZHKcRXDSZQ3gV', 'PhUTR4ZkZu9Xkzn3ee3xMU1TxbNx6ENJvUjX4wBaZDyTCMrn1zuE', 'PdnZFcwpxUSAcFE6MHB78weVAguwzSTUMBqswkqie7Uxfxsd77Zs' ] # Create wallet and generate key wl = HDWallet.create_multisig('multisig_test_simple', key_list, sigs_required=2, network='bitcoinlib_test', databasefile=DATABASEFILE_UNITTESTS) wl.new_key() # Sign, verify and send transaction wl.utxos_update( ) # In bitcoinlib_test network this generates new UTXO's t = wl.transaction_create([('21DBmFUMQMP7A6KeENXgZQ4wJdSCeGc2zFo', 100000)]) t = wl.transaction_sign(t) self.assertTrue(t.verify()) self.assertEqual(wl.transaction_send(t), 'succesfull_test_sendrawtransaction')
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 = wlt.transaction_sign(t) 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.raw()) t = wallet_dict[wallet_id].transaction_sign(t) n_signs += 1 return t
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_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)
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)
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, SIGS_REQUIRED, sort_keys=True, network=NETWORK) wallet3o5.new_key() print("\n\nA multisig wallet with 1 key has been created on this system") else: wallet3o5 = HDWallet(WALLET_NAME) print("\nUpdating UTXO's...") wallet3o5.utxos_update() wallet3o5.info() utxos = wallet3o5.utxos() # Creating transactions just like in a normal wallet, then send raw transaction to other cosigners. They # can sign the transaction with there on key and pass it on to the next signer or broadcast it to the network.
% cosigner[0]) print("Passphrase: %s" % words) print("Password: %s" % ('*' * len(password))) print("Share this public key below with other cosigner") print("Public key: %s" % public_account.wif_public()) if cosigner[3] == 'private': key_list.append(hdkey) key_list_thispc.append(hdkey) else: key_list.append(public_account) key_list_thispc.append(public_account.public()) thispc_wallet = HDWallet.create_multisig(WALLET_NAME, key_list_thispc, SIGNATURES_REQUIRED, sort_keys=True, network=NETWORK) thispc_wallet.new_key() print("\n\nA multisig wallet has been created on this system") thispc_wallet.info() print("\n---> Please create a wallet on your Other PC like this:") print("from bitcoinlib.wallets import HDWallet") print("from bitcoinlib.keys import HDKey") print("") print("key_list = [") print(" '%s'," % key_list[0].account_multisig_key().wif_public()) print(" '%s'," % key_list[1].wif()) print(" HDKey('%s', key_type='single')" % key_list[2].wif_public())
% cosigner[0]) print("Passphrase: %s" % words) print("Password: %s" % ('*' * len(password))) print("Share this public key below with other cosigner") print("Public key: %s" % public_account.wif_public()) if cosigner[3] == 'private': key_list.append(hdkey) key_list_thispc.append(hdkey) else: key_list.append(public_account) key_list_thispc.append(public_account.public()) thispc_wallet = HDWallet.create_multisig(WALLET_NAME, key_list_thispc, SIGNATURES_REQUIRED, sort_keys=True, witness_type=WITNESS_TYPE, network=NETWORK) thispc_wallet.new_key() print("\n\nA multisig wallet has been created on this system") thispc_wallet.info() print("\n---> Please create a wallet on your Other PC like this:") print("from bitcoinlib.wallets import HDWallet") print("from bitcoinlib.keys import HDKey") print("") print("key_list = [") print(" '%s'," % key_list[0].account_multisig_key().wif_public()) print(" '%s'," % key_list[1].wif()) print(" HDKey('%s', key_type='single', witness_type='%s')" %