def test_create_sighash_txs(setup_tx_creation): #non-standard hash codes: for sighash in [ bitcoin.SIGHASH_ANYONECANPAY + bitcoin.SIGHASH_SINGLE, bitcoin.SIGHASH_NONE, bitcoin.SIGHASH_SINGLE ]: wallet = make_wallets(1, [[2, 0, 0, 0, 1]], 3)[0]['wallet'] sync_wallet(wallet) amount = 350000000 ins_full = wallet.select_utxos(0, amount) print "using hashcode: " + str(sighash) txid = make_sign_and_push(ins_full, wallet, amount, hashcode=sighash) assert txid #Create an invalid sighash single (too many inputs) extra = wallet.select_utxos(4, 100000000) #just a few more inputs ins_full.update(extra) with pytest.raises(Exception) as e_info: txid = make_sign_and_push(ins_full, wallet, amount, hashcode=bitcoin.SIGHASH_SINGLE) #trigger insufficient funds with pytest.raises(Exception) as e_info: fake_utxos = wallet.select_utxos(4, 1000000000)
def test_spend_p2sh_utxos(setup_tx_creation): #make a multisig address from 3 privs privs = [chr(x) * 32 + '\x01' for x in range(1, 4)] pubs = [btc.privkey_to_pubkey(binascii.hexlify(priv)) for priv in privs] script = btc.mk_multisig_script(pubs, 2) msig_addr = btc.scriptaddr(script, magicbyte=196) #pay into it wallet = make_wallets(1, [[2, 0, 0, 0, 1]], 3)[0]['wallet'] jm_single().bc_interface.sync_wallet(wallet) amount = 350000000 ins_full = wallet.select_utxos(0, amount) txid = make_sign_and_push(ins_full, wallet, amount, output_addr=msig_addr) assert txid #wait for mining time.sleep(4) #spend out; the input can be constructed from the txid of previous msig_in = txid + ":0" ins = [msig_in] #random output address and change addr output_addr = wallet.get_new_addr(1, 1) amount2 = amount - 50000 outs = [{'value': amount2, 'address': output_addr}] tx = btc.mktx(ins, outs) sigs = [] for priv in privs[:2]: sigs.append(btc.multisign(tx, 0, script, binascii.hexlify(priv))) tx = btc.apply_multisignatures(tx, 0, script, sigs) txid = jm_single().bc_interface.pushtx(tx) assert txid
def test_spend_p2wpkh(setup_tx_creation): #make 3 p2wpkh outputs from 3 privs privs = [struct.pack(b'B', x) * 32 + b'\x01' for x in range(1, 4)] pubs = [bitcoin.privkey_to_pubkey(priv) for priv in privs] scriptPubKeys = [bitcoin.pubkey_to_p2wpkh_script(pub) for pub in pubs] addresses = [str(bitcoin.CCoinAddress.from_scriptPubKey( spk)) for spk in scriptPubKeys] #pay into it wallet_service = make_wallets(1, [[3, 0, 0, 0, 0]], 3)[0]['wallet'] wallet_service.sync_wallet(fast=True) amount = 35000000 p2wpkh_ins = [] for i, addr in enumerate(addresses): ins_full = wallet_service.select_utxos(0, amount) txid = make_sign_and_push(ins_full, wallet_service, amount, output_addr=addr) assert txid p2wpkh_ins.append((txid, 0)) txhex = jm_single().bc_interface.get_transaction(txid) #wait for mining jm_single().bc_interface.tick_forward_chain(1) #random output address output_addr = wallet_service.get_internal_addr(1) amount2 = amount*3 - 50000 outs = [{'value': amount2, 'address': output_addr}] tx = bitcoin.mktx(p2wpkh_ins, outs) for i, priv in enumerate(privs): # sign each of 3 inputs; note that bitcoin.sign # automatically validates each signature it creates. sig, msg = bitcoin.sign(tx, i, priv, amount=amount, native="p2wpkh") if not sig: assert False, msg txid = jm_single().bc_interface.pushtx(tx.serialize()) assert txid
def test_spend_p2wsh(setup_tx_creation): #make 2 x 2 of 2multisig outputs; will need 4 privs privs = [struct.pack(b'B', x) * 32 + b'\x01' for x in range(1, 5)] privs = [binascii.hexlify(priv).decode('ascii') for priv in privs] pubs = [bitcoin.privkey_to_pubkey(priv) for priv in privs] redeemScripts = [ bitcoin.mk_multisig_script(pubs[i:i + 2], 2) for i in [0, 2] ] scriptPubKeys = [ bitcoin.pubkeys_to_p2wsh_script(pubs[i:i + 2]) for i in [0, 2] ] addresses = [ bitcoin.pubkeys_to_p2wsh_address(pubs[i:i + 2]) for i in [0, 2] ] #pay into it wallet_service = make_wallets(1, [[3, 0, 0, 0, 0]], 3)[0]['wallet'] wallet_service.sync_wallet(fast=True) amount = 35000000 p2wsh_ins = [] for addr in addresses: ins_full = wallet_service.select_utxos(0, amount) txid = make_sign_and_push(ins_full, wallet_service, amount, output_addr=addr) assert txid p2wsh_ins.append(txid + ":0") #wait for mining time.sleep(1) #random output address and change addr output_addr = wallet_service.get_internal_addr(1) amount2 = amount * 2 - 50000 outs = [{'value': amount2, 'address': output_addr}] tx = bitcoin.mktx(p2wsh_ins, outs) sigs = [] for i in range(2): sigs = [] for priv in privs[i * 2:i * 2 + 2]: # sign input j with each of 2 keys sig = bitcoin.multisign(tx, i, redeemScripts[i], priv, amount=amount) sigs.append(sig) # check that verify_tx_input correctly validates; assert bitcoin.verify_tx_input(tx, i, scriptPubKeys[i], sig, bitcoin.privkey_to_pubkey(priv), scriptCode=redeemScripts[i], amount=amount) tx = bitcoin.apply_p2wsh_multisignatures(tx, i, redeemScripts[i], sigs) txid = jm_single().bc_interface.pushtx(tx) assert txid
def test_spend_p2wpkh(setup_tx_creation): #make 3 p2wpkh outputs from 3 privs privs = [struct.pack(b'B', x) * 32 + b'\x01' for x in range(1, 4)] pubs = [ bitcoin.privkey_to_pubkey(binascii.hexlify(priv).decode('ascii')) for priv in privs ] scriptPubKeys = [bitcoin.pubkey_to_p2wpkh_script(pub) for pub in pubs] addresses = [bitcoin.pubkey_to_p2wpkh_address(pub) for pub in pubs] #pay into it wallet_service = make_wallets(1, [[3, 0, 0, 0, 0]], 3)[0]['wallet'] wallet_service.sync_wallet(fast=True) amount = 35000000 p2wpkh_ins = [] for addr in addresses: ins_full = wallet_service.select_utxos(0, amount) txid = make_sign_and_push(ins_full, wallet_service, amount, output_addr=addr) assert txid p2wpkh_ins.append(txid + ":0") #wait for mining time.sleep(1) #random output address output_addr = wallet_service.get_internal_addr(1) amount2 = amount * 3 - 50000 outs = [{'value': amount2, 'address': output_addr}] tx = bitcoin.mktx(p2wpkh_ins, outs) sigs = [] for i, priv in enumerate(privs): # sign each of 3 inputs tx = bitcoin.p2wpkh_sign(tx, i, binascii.hexlify(priv), amount, native=True) # check that verify_tx_input correctly validates; # to do this, we need to extract the signature and get the scriptCode # of this pubkey scriptCode = bitcoin.pubkey_to_p2pkh_script(pubs[i]) witness = bitcoin.deserialize(tx)['ins'][i]['txinwitness'] assert len(witness) == 2 assert witness[1] == pubs[i] sig = witness[0] assert bitcoin.verify_tx_input(tx, i, scriptPubKeys[i], sig, pubs[i], scriptCode=scriptCode, amount=amount) txid = jm_single().bc_interface.pushtx(tx) assert txid
def do_tx(wallet, amount): ins_full = wallet.select_utxos(0, amount) cj_addr = wallet.get_internal_addr(1) change_addr = wallet.get_internal_addr(0) wallet.update_cache_index() txid = make_sign_and_push(ins_full, wallet, amount, output_addr=cj_addr, change_addr=change_addr, estimate_fee=True) assert txid time.sleep(2) #blocks jm_single().bc_interface.sync_unspent(wallet)
def test_absurd_fees(setup_tx_creation): """Test triggering of ValueError exception if the transaction fees calculated from the blockchain interface exceed the limit set in the config. """ jm_single().bc_interface.absurd_fees = True #pay into it wallet = make_wallets(1, [[2, 0, 0, 0, 1]], 3)[0]['wallet'] jm_single().bc_interface.sync_wallet(wallet) amount = 350000000 ins_full = wallet.select_utxos(0, amount) with pytest.raises(ValueError) as e_info: txid = make_sign_and_push(ins_full, wallet, amount, estimate_fee=True)
def test_create_sighash_txs(setup_tx_creation): #non-standard hash codes: for sighash in [bitcoin.SIGHASH_ANYONECANPAY + bitcoin.SIGHASH_SINGLE, bitcoin.SIGHASH_NONE, bitcoin.SIGHASH_SINGLE]: wallet_service = make_wallets(1, [[2, 0, 0, 0, 1]], 3)[0]['wallet'] wallet_service.sync_wallet(fast=True) amount = 350000000 ins_full = wallet_service.select_utxos(0, amount) txid = make_sign_and_push(ins_full, wallet_service, amount, hashcode=sighash) assert txid #trigger insufficient funds with pytest.raises(Exception) as e_info: fake_utxos = wallet_service.select_utxos(4, 1000000000)
def do_tx(wallet_service, amount): ins_full = wallet_service.select_utxos(0, amount) cj_addr = wallet_service.get_internal_addr(1) change_addr = wallet_service.get_internal_addr(0) wallet_service.save_wallet() txid = make_sign_and_push(ins_full, wallet_service, amount, output_addr=cj_addr, change_addr=change_addr, estimate_fee=True) assert txid time.sleep(2) #blocks wallet_service.sync_unspent() return txid
def test_create_sighash_txs(setup_tx_creation): #non-standard hash codes: for sighash in [btc.SIGHASH_ANYONECANPAY + btc.SIGHASH_SINGLE, btc.SIGHASH_NONE, btc.SIGHASH_SINGLE]: wallet = make_wallets(1, [[2, 0, 0, 0, 1]], 3)[0]['wallet'] jm_single().bc_interface.sync_wallet(wallet) amount = 350000000 ins_full = wallet.select_utxos(0, amount) print "using hashcode: " + str(sighash) txid = make_sign_and_push(ins_full, wallet, amount, hashcode=sighash) assert txid #Create an invalid sighash single (too many inputs) extra = wallet.select_utxos(4, 100000000) #just a few more inputs ins_full.update(extra) with pytest.raises(Exception) as e_info: txid = make_sign_and_push(ins_full, wallet, amount, hashcode=btc.SIGHASH_SINGLE) #trigger insufficient funds with pytest.raises(Exception) as e_info: fake_utxos = wallet.select_utxos(4, 1000000000)
def test_create_p2sh_output_tx(setup_tx_creation, nw, wallet_structures, mean_amt, sdev_amt, amount, pubs, k): wallets = make_wallets(nw, wallet_structures, mean_amt, sdev_amt) for w in wallets.values(): sync_wallet(w['wallet'], fast=True) for k, w in enumerate(wallets.values()): wallet = w['wallet'] ins_full = wallet.select_utxos(0, amount) script = bitcoin.mk_multisig_script(pubs, k) output_addr = bitcoin.script_to_address(script, vbyte=196) txid = make_sign_and_push(ins_full, wallet, amount, output_addr=output_addr) assert txid
def test_create_p2sh_output_tx(setup_tx_creation, nw, wallet_structures, mean_amt, sdev_amt, amount, pubs, k): wallets = make_wallets(nw, wallet_structures, mean_amt, sdev_amt) for w in wallets.values(): w['wallet'].sync_wallet(fast=True) for k, w in enumerate(wallets.values()): wallet_service = w['wallet'] ins_full = wallet_service.select_utxos(0, amount) script = bitcoin.mk_multisig_script(pubs, k) output_addr = bitcoin.p2sh_scriptaddr(bitcoin.safe_from_hex(script), magicbyte=196) txid = make_sign_and_push(ins_full, wallet_service, amount, output_addr=output_addr) assert txid
def test_spend_freeze_script(setup_tx_creation): ensure_bip65_activated() wallet_service = make_wallets(1, [[3, 0, 0, 0, 0]], 3)[0]['wallet'] wallet_service.sync_wallet(fast=True) mediantime = jm_single().bc_interface.rpc("getblockchaininfo", [])["mediantime"] timeoffset_success_tests = [(2, False), (-60 * 60 * 24 * 30, True), (60 * 60 * 24 * 30, False)] for timeoffset, required_success in timeoffset_success_tests: #generate keypair priv = b"\xaa" * 32 + b"\x01" pub = bitcoin.privkey_to_pubkey(priv) addr_locktime = mediantime + timeoffset redeem_script = bitcoin.mk_freeze_script(pub, addr_locktime) script_pub_key = bitcoin.redeem_script_to_p2wsh_script(redeem_script) # cannot convert to address within wallet service, as not known # to wallet; use engine directly: addr = wallet_service._ENGINE.script_to_address(script_pub_key) #fund frozen funds address amount = 100000000 funding_ins_full = wallet_service.select_utxos(0, amount) funding_txid = make_sign_and_push(funding_ins_full, wallet_service, amount, output_addr=addr) assert funding_txid #spend frozen funds frozen_in = (funding_txid, 0) output_addr = wallet_service.get_internal_addr(1) miner_fee = 5000 outs = [{'value': amount - miner_fee, 'address': output_addr}] tx = bitcoin.mktx([frozen_in], outs, locktime=addr_locktime + 1) i = 0 sig, success = bitcoin.sign(tx, i, priv, amount=amount, native=redeem_script) assert success push_success = jm_single().bc_interface.pushtx(tx.serialize()) assert push_success == required_success
def test_create_p2sh_output_tx(setup_tx_creation, nw, wallet_structures, mean_amt, sdev_amt, amount, pubs, k): wallets = make_wallets(nw, wallet_structures, mean_amt, sdev_amt) for w in wallets.values(): jm_single().bc_interface.sync_wallet(w['wallet']) for k, w in enumerate(wallets.values()): wallet = w['wallet'] ins_full = wallet.select_utxos(0, amount) script = btc.mk_multisig_script(pubs, k) #try the alternative argument passing pubs.append(k) script2 = btc.mk_multisig_script(*pubs) assert script2 == script output_addr = btc.scriptaddr(script, magicbyte=196) txid = make_sign_and_push(ins_full, wallet, amount, output_addr=output_addr) assert txid
def test_spend_freeze_script(setup_tx_creation): ensure_bip65_activated() wallet_service = make_wallets(1, [[3, 0, 0, 0, 0]], 3)[0]['wallet'] wallet_service.sync_wallet(fast=True) mediantime = jm_single().bc_interface.rpc("getblockchaininfo", [])["mediantime"] timeoffset_success_tests = [(2, False), (-60*60*24*30, True), (60*60*24*30, False)] for timeoffset, required_success in timeoffset_success_tests: #generate keypair priv = "aa"*32 + "01" pub = unhexlify(bitcoin.privkey_to_pubkey(priv)) addr_locktime = mediantime + timeoffset redeem_script = bitcoin.mk_freeze_script(pub, addr_locktime) script_pub_key = bitcoin.redeem_script_to_p2wsh_script(redeem_script) regtest_vbyte = 100 addr = bitcoin.script_to_address(script_pub_key, vbyte=regtest_vbyte) #fund frozen funds address amount = 100000000 funding_ins_full = wallet_service.select_utxos(0, amount) funding_txid = make_sign_and_push(funding_ins_full, wallet_service, amount, output_addr=addr) assert funding_txid #spend frozen funds frozen_in = funding_txid + ":0" output_addr = wallet_service.get_internal_addr(1) miner_fee = 5000 outs = [{'value': amount - miner_fee, 'address': output_addr}] tx = bitcoin.mktx([frozen_in], outs, locktime=addr_locktime+1) i = 0 sig = bitcoin.get_p2sh_signature(tx, i, redeem_script, priv, amount) assert bitcoin.verify_tx_input(tx, i, script_pub_key, sig, pub, scriptCode=redeem_script, amount=amount) tx = bitcoin.apply_freeze_signature(tx, i, redeem_script, sig) push_success = jm_single().bc_interface.pushtx(tx) assert push_success == required_success