You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
96 lines
4.0 KiB
96 lines
4.0 KiB
import pytest |
|
import copy |
|
import jmbitcoin as btc |
|
|
|
""" Awkward test module name `test_btc_snicker` is to avoid |
|
conflicts with snicker tests in jmclient. |
|
""" |
|
|
|
@pytest.mark.parametrize( |
|
"our_input_val, their_input_val, network_fee, script_type, net_transfer", [ |
|
(24000000, 20000000, 2000, "p2wpkh", 100), |
|
(124000000, 20000000, 800, "p2wpkh", -100), |
|
(24000000, 20000000, 2000, "p2sh-p2wpkh", 100), |
|
(124000000, 20000000, 800, "p2sh-p2wpkh", -100), |
|
]) |
|
def test_is_snicker_tx(our_input_val, their_input_val, network_fee, |
|
script_type, net_transfer): |
|
our_input = (bytes([1])*32, 0) |
|
their_input = (bytes([2])*32, 1) |
|
assert our_input_val - their_input_val - network_fee > 0 |
|
total_input_amount = our_input_val + their_input_val |
|
total_output_amount = total_input_amount - network_fee |
|
receiver_output_amount = their_input_val + net_transfer |
|
proposer_output_amount = total_output_amount - receiver_output_amount |
|
|
|
# all keys are just made up; only the script type will be checked |
|
privs = [bytes([i])*32 + bytes([1]) for i in range(1,4)] |
|
pubs = [btc.privkey_to_pubkey(x) for x in privs] |
|
|
|
if script_type == "p2wpkh": |
|
spks = [btc.pubkey_to_p2wpkh_script(x) for x in pubs] |
|
elif script_type == "p2sh-p2wpkh": |
|
spks = [btc.pubkey_to_p2sh_p2wpkh_script(x) for x in pubs] |
|
else: |
|
assert False |
|
tweaked_addr, our_addr, change_addr = [str( |
|
btc.CCoinAddress.from_scriptPubKey(x)) for x in spks] |
|
# now we must construct the three outputs with correct output amounts. |
|
outputs = [{"address": tweaked_addr, "value": receiver_output_amount}] |
|
outputs.append({"address": our_addr, "value": receiver_output_amount}) |
|
outputs.append({"address": change_addr, |
|
"value": total_output_amount - 2 * receiver_output_amount}) |
|
assert all([x["value"] > 0 for x in outputs]) |
|
|
|
# make_shuffled_tx mutates ordering (yuck), work with copies only: |
|
outputs1 = copy.deepcopy(outputs) |
|
# version and locktime as currently specified in the BIP |
|
# for 0/1 version SNICKER. (Note the locktime is partly because |
|
# of expected delays). |
|
tx = btc.make_shuffled_tx([our_input, their_input], outputs1, |
|
version=2, locktime=0) |
|
assert btc.is_snicker_tx(tx) |
|
|
|
# construct variants which will be invalid. |
|
|
|
# mixed script types in outputs |
|
wrong_tweaked_spk = btc.pubkey_to_p2pkh_script(pubs[1]) |
|
wrong_tweaked_addr = str(btc.CCoinAddress.from_scriptPubKey( |
|
wrong_tweaked_spk)) |
|
outputs2 = copy.deepcopy(outputs) |
|
outputs2[0] = {"address": wrong_tweaked_addr, |
|
"value": receiver_output_amount} |
|
tx2 = btc.make_shuffled_tx([our_input, their_input], outputs2, |
|
version=2, locktime=0) |
|
assert not btc.is_snicker_tx(tx2) |
|
|
|
# nonequal output amounts |
|
outputs3 = copy.deepcopy(outputs) |
|
outputs3[1] = {"address": our_addr, "value": receiver_output_amount - 1} |
|
tx3 = btc.make_shuffled_tx([our_input, their_input], outputs3, |
|
version=2, locktime=0) |
|
assert not btc.is_snicker_tx(tx3) |
|
|
|
# too few outputs |
|
outputs4 = copy.deepcopy(outputs) |
|
outputs4 = outputs4[:2] |
|
tx4 = btc.make_shuffled_tx([our_input, their_input], outputs4, |
|
version=2, locktime=0) |
|
assert not btc.is_snicker_tx(tx4) |
|
|
|
# too many outputs |
|
outputs5 = copy.deepcopy(outputs) |
|
outputs5.append({"address": change_addr, "value": 200000}) |
|
tx5 = btc.make_shuffled_tx([our_input, their_input], outputs5, |
|
version=2, locktime=0) |
|
assert not btc.is_snicker_tx(tx5) |
|
|
|
# wrong nVersion |
|
tx6 = btc.make_shuffled_tx([our_input, their_input], outputs, |
|
version=1, locktime=0) |
|
assert not btc.is_snicker_tx(tx6) |
|
|
|
# wrong nLockTime |
|
tx7 = btc.make_shuffled_tx([our_input, their_input], outputs, |
|
version=2, locktime=1) |
|
assert not btc.is_snicker_tx(tx7)
|
|
|