def test_finish(key_priv, pkh_B, action_A, action_B, total_sats, input_sats, out_sats, change_sats): rps.set_data_part(player_A_data + pkh_B + scryptlib.utils.get_push_int(action_B)[1:]) context = scryptlib.utils.create_dummy_input_context() context.utxo.script_pubkey = rps.locking_script context.utxo.value = total_sats change_out = TxOutput(change_sats, P2PKH_Address(pkh_A, Bitcoin).to_script()) context.tx.outputs.append(change_out) if out_sats > 0: pay_out = TxOutput(out_sats, P2PKH_Address(pkh_B, Bitcoin).to_script()) context.tx.outputs.append(pay_out) preimage = scryptlib.utils.get_preimage_from_input_context( context, sighash_flag) input_idx = 0 utxo_satoshis = context.utxo.value sighash = context.tx.signature_hash(input_idx, utxo_satoshis, rps.locking_script, sighash_flag) sig = key_priv.sign(sighash, hasher=None) sig = sig + pack_byte(sighash_flag) return rps.finish(SigHashPreimage(preimage), action_A, Sig(sig), PubKey(key_pub_A), change_sats).verify(context)
def regtest_topup_account(receive_address: P2PKH_Address, amount: int = 25) -> Optional[str]: matured_balance = regtest_get_mined_balance() while matured_balance < amount: nblocks = 1 if matured_balance == 0: nblocks = 200 result = node_rpc_call("generatetoaddress", nblocks, Net.REGTEST_P2PKH_ADDRESS) if result.status_code == 200: logger.debug(f"generated {nblocks}: {result.json()['result']}") matured_balance = regtest_get_mined_balance() # Note: for bare multi-sig support may need to craft rawtxs manually via bitcoind's # 'signrawtransaction' jsonrpc method - AustEcon payload = json.dumps({ "jsonrpc": "2.0", "method": "sendtoaddress", "params": [receive_address.to_string(), amount], "id": 0 }) result = requests.post("http://*****:*****@127.0.0.1:18332", data=payload) if result.status_code != 200: raise requests.exceptions.HTTPError(result.text) txid = result.json()['result'] logger.info( "topped up wallet with %s coins to receive address='%s'. txid=%s", amount, receive_address.to_string(), txid) return txid
def test_verify_withdraw(): withdraw_sats = 2000000 fee = 3000 input_sats = 10000000 output_sats = input_sats - withdraw_sats - fee mature_time = 1627122529 faucet.set_data_part(scryptlib.utils.get_push_int(mature_time)) context = scryptlib.utils.create_dummy_input_context() context.utxo.script_pubkey = faucet.locking_script context.utxo.value = input_sats new_locking_script = faucet.code_part << Script( scryptlib.utils.get_push_int(mature_time + 300)) tx_out_0 = TxOutput(value=output_sats, script_pubkey=new_locking_script) context.tx.outputs.append(tx_out_0) tx_out_1 = TxOutput(value=withdraw_sats, script_pubkey=P2PKH_Address(pkh, Bitcoin).to_script()) context.tx.outputs.append(tx_out_1) context.tx.inputs[0].sequence = 0xfffffffe context.tx.locktime = mature_time + 300 preimage = scryptlib.utils.get_preimage_from_input_context(context) verify_result = faucet.withdraw(SigHashPreimage(preimage), Ripemd160(pkh)).verify(context) assert verify_result == True # Wrong mature time context.tx.outputs = [] new_locking_script = faucet.code_part << Script( scryptlib.utils.get_push_int(mature_time + 299)) tx_out_0 = TxOutput(value=output_sats, script_pubkey=new_locking_script) context.tx.outputs.append(tx_out_0) tx_out_1 = TxOutput(value=withdraw_sats, script_pubkey=P2PKH_Address(pkh, Bitcoin).to_script()) context.tx.outputs.append(tx_out_1) context.tx.locktime = mature_time + 299 preimage = scryptlib.utils.get_preimage_from_input_context(context) with pytest.raises(bitcoinx.VerifyFailed): faucet.withdraw(SigHashPreimage(preimage), Ripemd160(pkh)).verify(context)
def test_verify_with_change(): deposit_sats = 100000 input_sats = 100000 output_sats = deposit_sats + input_sats change_sats = 547 faucet.set_data_part(scryptlib.utils.get_push_int(1602553516)) context = scryptlib.utils.create_dummy_input_context() context.utxo.script_pubkey = faucet.locking_script context.utxo.value = input_sats tx_out_0 = TxOutput(value=output_sats, script_pubkey=faucet.locking_script) context.tx.outputs.append(tx_out_0) tx_out_1 = TxOutput(value=change_sats, script_pubkey=P2PKH_Address(pkh, Bitcoin).to_script()) context.tx.outputs.append(tx_out_1) sighash_flag = SigHash(SigHash.ALL | SigHash.FORKID) preimage = scryptlib.utils.get_preimage_from_input_context( context, sighash_flag) verify_result = faucet.deposit(SigHashPreimage(preimage), deposit_sats, Ripemd160(pkh), change_sats).verify(context) assert verify_result == True with pytest.raises(bitcoinx.VerifyFailed): faucet.deposit(SigHashPreimage(preimage), deposit_sats, Ripemd160(pkh), change_sats + 1).verify(context)
def sale(n_bought, pkh, pub_key): context = scryptlib.utils.create_dummy_input_context() context.utxo.script_pubkey = ats.locking_script context.utxo.value = input_sats new_data_part = ats.data_part << pub_key.to_bytes( ) + scryptlib.utils.get_push_int(n_bought)[1:] new_locking_script = Script(ats.code_part.to_bytes() + new_data_part.to_bytes()) change_sats = input_sats - n_bought * SATS_PER_TOKEN out_sats = input_sats + n_bought * SATS_PER_TOKEN # Counter output tx_out = TxOutput(value=out_sats, script_pubkey=new_locking_script) context.tx.outputs.append(tx_out) # Change output change_out = TxOutput( change_sats, P2PKH_Address(pub_key.hash160(), Bitcoin).to_script()) context.tx.outputs.append(change_out) preimage = scryptlib.utils.get_preimage_from_input_context( context, sighash_flag) verify_result = ats.buy(SigHashPreimage(preimage), Ripemd160(pkh), change_sats, Bytes(pub_key.to_bytes()), n_bought).verify(context) assert verify_result == True return new_data_part
def test_verify_scenario_2(): context = scryptlib.utils.create_dummy_input_context() context.utxo.script_pubkey = escrow.locking_script context.utxo.value = input_sats change_out = TxOutput(int(input_sats - fee), P2PKH_Address(pkh_A, Bitcoin).to_script()) context.tx.outputs.append(change_out) sighash_flag = SigHash(SigHash.ALL | SigHash.FORKID) sighash = context.tx.signature_hash(0, input_sats, escrow.locking_script, sighash_flag) sig_A = key_priv_A.sign(sighash, hasher=None) sig_A = sig_A + pack_byte(sighash_flag) sig_E = key_priv_E.sign(sighash, hasher=None) sig_E = sig_E + pack_byte(sighash_flag) preimage = scryptlib.utils.get_preimage_from_input_context( context, sighash_flag) verify_result = escrow.unlock(SigHashPreimage(preimage), PubKey(key_pub_A), Sig(sig_A), PubKey(key_pub_E), Sig(sig_E), Bytes(secret0)).verify(context) assert verify_result == True # Wrong secret with pytest.raises(bitcoinx.VerifyFailed): verify_result = escrow.unlock(SigHashPreimage(preimage), PubKey(key_pub_A), Sig(sig_A), PubKey(key_pub_E), Sig(sig_E), Bytes(secret1)).verify(context)
def test_verify_wrong_out_amount(): pkh_0_out_wrong = TxOutput(in_sats - miner_fee + 123, P2PKH_Address(pkh_0, Bitcoin).to_script()) context = create_input_context(in_sats, acs.locking_script, pkh_0_out_wrong) preimage = scryptlib.utils.get_preimage_from_input_context( context, sighash_flag) verify_result = acs.unlock(SigHashPreimage(preimage)).verify(context) assert verify_result == False
def regtest_topup_account(receive_address: P2PKH_Address, max_amount: int=25) -> str: matured_balance = regtest_get_mined_balance() # Sweep up to 25 coins to wallet receive address amount = min(max_amount, matured_balance) if not amount > 0: logger.error("Insufficient funds in regtest slush fund to topup wallet. Mine " "more blocks") # Note: for bare multi-sig support may need to craft rawtxs manually via bitcoind's # 'signrawtransaction' jsonrpc method - AustEcon payload = json.dumps({"jsonrpc": "2.0", "method": "sendtoaddress", "params": [receive_address.to_string(), amount], "id": 0}) result = requests.post("http://*****:*****@127.0.0.1:18332", data=payload) result.raise_for_status() txid = result.json()['result'] logger.info("topped up wallet with %s coins to receive address='%s'. txid=%s", amount, receive_address.to_string(), txid) return txid
def test_verify_wrong_addr(): key_priv = PrivateKey.from_arbitrary_bytes(b'123test') key_pub = key_priv.public_key pkh = key_pub.hash160() pkh_0_out_wrong = TxOutput(in_sats - miner_fee, P2PKH_Address(pkh, Bitcoin).to_script()) context = create_input_context(in_sats, acs.locking_script, pkh_0_out_wrong) preimage = scryptlib.utils.get_preimage_from_input_context( context, sighash_flag) verify_result = acs.unlock(SigHashPreimage(preimage)).verify(context) assert verify_result == False
def initialize_counter(counter_obj, counter_initial_val, funding_txid, funding_out_idx, \ unlock_key_priv, miner_fee, contract_out_sats, change_addr): counter_obj.set_data_part( scryptlib.utils.get_push_int(counter_initial_val)) # Funding TX funding_tx_hash = hex_str_to_hash(funding_txid) unlock_key_pub = unlock_key_priv.public_key r = requests.get('https://api.whatsonchain.com/v1/bsv/main/tx/{}'.format( funding_txid)).json() funding_locking_script = Script.from_hex( r['vout'][funding_out_idx]['scriptPubKey']['hex']) unlocked_satoshis = int(r['vout'][funding_out_idx]['value'] * 10**8) n_sequence = 0xffffffff tx_input = TxInput(funding_tx_hash, funding_out_idx, None, n_sequence) # Output with counter script code contract_out = TxOutput(contract_out_sats, counter_obj.locking_script) # Change output tx_output_script = P2PKH_Address.from_string(change_addr, Bitcoin).to_script() change_out = TxOutput(unlocked_satoshis - miner_fee - contract_out_sats, tx_output_script) tx = Tx(2, [tx_input], [contract_out, change_out], 0x00000000) # Create signature for input sighash_flag = SigHash(SigHash.ALL | SigHash.FORKID) sighash = tx.signature_hash(0, unlocked_satoshis, funding_locking_script, sighash_flag) sig = unlock_key_priv.sign(sighash, hasher=None) sig = sig + pack_byte(sighash_flag) # Set script for input unlock_script = Script() << sig << unlock_key_pub.to_bytes() tx.inputs[0].script_sig = unlock_script broadcast_tx(tx)
def test_follow(pkh_B, action, init_sats, input_sats, out_sats, change_sats): rps.set_data_part(player_A_data + b'\x00' * pub_key_hashlen + scryptlib.utils.get_push_int(action_INIT)[1:]) context = scryptlib.utils.create_dummy_input_context() context.utxo.script_pubkey = rps.locking_script context.utxo.value = init_sats new_data_part = player_A_data + pkh_B + scryptlib.utils.get_push_int( action)[1:] new_locking_script = Script(rps.code_part.to_bytes() + new_data_part) tx_out = TxOutput(value=out_sats, script_pubkey=new_locking_script) context.tx.outputs.append(tx_out) change_out = TxOutput(change_sats, P2PKH_Address(pkh_B, Bitcoin).to_script()) context.tx.outputs.append(change_out) preimage = scryptlib.utils.get_preimage_from_input_context( context, sighash_flag) return rps.follow(SigHashPreimage(preimage), action, Ripemd160(pkh_B), change_sats).verify(context)
def _generate_address(): pkh_bytes = os.urandom(20) return P2PKH_Address(pkh_bytes, Bitcoin)
import json import os import pytest import time import unittest from bitcoinx import P2PKH_Address, Bitcoin from electrumsv import paymentrequest PKH_HEX = "8b2b1e60ccf6c206f1fde862897cd61be5f2a021" PKH_ADDRESS = P2PKH_Address(bytes.fromhex(PKH_HEX), Bitcoin) P2PKH_SCRIPT = PKH_ADDRESS.to_script() TRANSACTION_HEX = ("0100000002f25568d10d46181bc65b01b735f8cccdb91e4e7d172c5efb984b839d1c"+ "912084000000002401ff2102faf7f10ccad1bc40e697e6b90b1d7c9daf92fdf47a4cf726f1c0422e473"+ "0fe85fefffffff146000000000000f25568d10d46181bc65b01b735f8cccdb91e4e7d172c5efb984b83"+ "9d1c912084010000006b483045022100fa8ebdc7cefc407fd1b560fb2e2e5e96e900e94634d96df4fd2"+ "84126048746a2022028d91ca132a1a386a67df69a2c5ba216218870c256c163d729f1575f7a8824f541"+ "21030c4ee92cd3c174e9aabcdec56ddc6b6d09a7767b563055a10e5406ec48f477eafeffffff01de9e0"+ "100000000001976a914428f0dbcc74fc3a999bbaf8bf4600531e155e66b88ac75c50800") def _generate_address(): pkh_bytes = os.urandom(20) return P2PKH_Address(pkh_bytes, Bitcoin) class TestOutput(unittest.TestCase):
miner_fee = 546 key_priv_0 = PrivateKey.from_arbitrary_bytes(b'test123') key_pub_0 = key_priv_0.public_key pkh_0 = key_pub_0.hash160() contract = './test/res/acs.scrypt' compiler_result = scryptlib.utils.compile_contract(contract) desc = compiler_result.to_desc() AnyoneCanSpend = scryptlib.contract.build_contract_class(desc) acs = AnyoneCanSpend(Ripemd160(pkh_0)) pkh_0_out = TxOutput(in_sats - miner_fee, P2PKH_Address(pkh_0, Bitcoin).to_script()) context = create_input_context(in_sats, acs.locking_script, pkh_0_out) sighash_flag = SigHash(SigHash.ANYONE_CAN_PAY | SigHash.ALL | SigHash.FORKID) preimage = scryptlib.utils.get_preimage_from_input_context( context, sighash_flag) def test_verify_correct(): verify_result = acs.unlock(SigHashPreimage(preimage)).verify(context) assert verify_result == True def test_verify_wrong_addr(): key_priv = PrivateKey.from_arbitrary_bytes(b'123test') key_pub = key_priv.public_key
counter.set_data_part(scryptlib.utils.get_push_int(COUNTER_INITIAL_VAL)) context = scryptlib.utils.create_dummy_input_context() context.utxo.script_pubkey = counter.locking_script subsequent_counter_val_bytes = scryptlib.utils.get_push_int( COUNTER_INITIAL_VAL + 1) new_locking_script = counter.code_part << Script(subsequent_counter_val_bytes) # Counter output tx_out = TxOutput(value=out_sats, script_pubkey=new_locking_script) context.tx.outputs.append(tx_out) # Change output pkh_0_out = TxOutput(change_sats, P2PKH_Address(pkh_0, Bitcoin).to_script()) context.tx.outputs.append(pkh_0_out) sighash_flag = SigHash(SigHash.ANYONE_CAN_PAY | SigHash.ALL | SigHash.FORKID) preimage = scryptlib.utils.get_preimage_from_input_context( context, sighash_flag) def test_verify_correct(): verify_result = counter.increment(SigHashPreimage(preimage), out_sats, Ripemd160(pkh_0), change_sats).verify(context) assert verify_result == True def test_verify_wrong_sats():