diff --git a/bitcoin/secp256k1_transaction.py b/bitcoin/secp256k1_transaction.py index 6658f622..c601e4d1 100644 --- a/bitcoin/secp256k1_transaction.py +++ b/bitcoin/secp256k1_transaction.py @@ -42,7 +42,6 @@ def json_changebase(obj, changer): # Transaction serialization and deserialization - def deserialize(tx): if isinstance(tx, str) and re.match('^[0-9a-fA-F]*$', tx): #tx = bytes(bytearray.fromhex(tx)) @@ -53,6 +52,7 @@ def deserialize(tx): # so that it is call-by-reference pos = [0] + #TODO: these are disgustingly ignorant of overrun errors! def read_as_int(bytez): pos[0] += bytez return decode(tx[pos[0] - bytez:pos[0]][::-1], 256) @@ -73,8 +73,22 @@ def read_var_string(): size = read_var_int() return read_bytes(size) + def read_flag_byte(val): + flag = read_bytes(1) + if from_byte_to_int(flag)==val: + return True + else: + pos[0] -= 1 + return False + obj = {"ins": [], "outs": []} obj["version"] = read_as_int(4) + segwit = False + if read_flag_byte(0): segwit = True + if segwit: + if not read_flag_byte(1): #BIP141 is currently "MUST" ==1 + raise Exception("Invalid segwit transaction format") + ins = read_var_int() for i in range(ins): obj["ins"].append({ @@ -82,6 +96,7 @@ def read_var_string(): "hash": read_bytes(32)[::-1], "index": read_as_int(4) }, + #TODO this will probably crap out on null for segwit "script": read_var_string(), "sequence": read_as_int(4) }) @@ -91,13 +106,29 @@ def read_var_string(): "value": read_as_int(8), "script": read_var_string() }) + #segwit flag is only set if at least one txinwitness exists, + #in other words it would have to be at least partially signed; + #and, if it is, the witness section must be properly created + #including "00" for any input that either does not YET or will not + #have a witness attached. + if segwit: + #read witness data + #there must be one witness object for each txin + #technically, we could parse the contents of the witness + #into objects, but we'll just replicate the behaviour of the + #rpc decoderawtx, and attach a "txinwitness" for each in, with + #the items in the witness space separated + for i in range(ins): + num_items = read_var_int() + items = [] + for ni in range(num_items): + items.append(read_var_string()) + obj["ins"][i]["txinwitness"] = items + obj["locktime"] = read_as_int(4) return obj - def serialize(txobj): - #if isinstance(txobj, bytes): - # txobj = bytes_to_hex_string(txobj) o = [] if json_is_base(txobj, 16): json_changedbase = json_changebase(txobj, @@ -105,6 +136,13 @@ def serialize(txobj): hexlified = safe_hexlify(serialize(json_changedbase)) return hexlified o.append(encode(txobj["version"], 256, 4)[::-1]) + segwit = False + if any("txinwitness" in x.keys() for x in txobj["ins"]): + segwit = True + if segwit: + #append marker and flag + o.append('\x00') + o.append('\x01') o.append(num_to_var_int(len(txobj["ins"]))) for inp in txobj["ins"]: o.append(inp["outpoint"]["hash"][::-1]) @@ -116,6 +154,17 @@ def serialize(txobj): for out in txobj["outs"]: o.append(encode(out["value"], 256, 8)[::-1]) o.append(num_to_var_int(len(out["script"])) + out["script"]) + if segwit: + #number of witnesses is not explicitly encoded; + #it's implied by txin length + for inp in txobj["ins"]: + if "txinwitness" not in inp.keys(): + o.append('\x00') + continue + items = inp["txinwitness"] + o.append(num_to_var_int(len(items))) + for item in items: + o.append(num_to_var_int(len(item)) + item) o.append(encode(txobj["locktime"], 256, 4)[::-1]) return ''.join(o) if is_python2 else reduce(lambda x, y: x + y, o, bytes()) @@ -127,6 +176,45 @@ def serialize(txobj): SIGHASH_SINGLE = 3 SIGHASH_ANYONECANPAY = 0x80 +def segwit_signature_form(txobj, i, script, amount, hashcode=SIGHASH_ALL): + """Given a deserialized transaction txobj, an input index i, + which spends from a witness, + a script for redemption and an amount in satoshis, prepare + the version of the transaction to be hashed and signed. + """ + #if isinstance(txobj, string_or_bytes_types): + # return serialize(segwit_signature_form(deserialize(txobj), i, script, + # amount, hashcode)) + script = binascii.unhexlify(script) + nVersion = encode(txobj["version"], 256, 4)[::-1] + #create hashPrevouts preimage + pi = "" + for inp in txobj["ins"]: + pi += binascii.unhexlify(inp["outpoint"]["hash"])[::-1] + pi += encode(inp["outpoint"]["index"], 256, 4)[::-1] + hashPrevouts = bin_dbl_sha256(pi) + #create hashSequence preimage + pi = "" + for inp in txobj["ins"]: + pi += encode(inp["sequence"], 256, 4)[::-1] + hashSequence = bin_dbl_sha256(pi) + #add this input's outpoint + thisOut = binascii.unhexlify(txobj["ins"][i]["outpoint"]["hash"])[::-1] + thisOut += encode(txobj["ins"][i]["outpoint"]["index"], 256, 4)[::-1] + scriptCode = num_to_var_int(len(script)) + script + amt = encode(amount, 256, 8)[::-1] + thisSeq = encode(txobj["ins"][i]["sequence"], 256, 4)[::-1] + #create hashOutputs preimage + pi = "" + for out in txobj["outs"]: + pi += encode(out["value"], 256, 8)[::-1] + pi += (num_to_var_int(len(binascii.unhexlify(out["script"]))) + \ + binascii.unhexlify(out["script"])) + hashOutputs = bin_dbl_sha256(pi) + nLockTime = encode(txobj["locktime"], 256, 4)[::-1] + return nVersion + hashPrevouts + hashSequence + thisOut + scriptCode + amt + \ + thisSeq + hashOutputs + nLockTime + def signature_form(tx, i, script, hashcode=SIGHASH_ALL): i, hashcode = int(i), int(hashcode) if isinstance(tx, string_or_bytes_types): @@ -134,6 +222,10 @@ def signature_form(tx, i, script, hashcode=SIGHASH_ALL): newtx = copy.deepcopy(tx) for inp in newtx["ins"]: inp["script"] = "" + #Any witness must not be included in the + #serialization for the template for non-segwit signings. + if "txinwitness" in inp.keys(): + del inp["txinwitness"] newtx["ins"][i]["script"] = script if hashcode & 0x1f == SIGHASH_NONE: newtx["outs"] = [] @@ -153,13 +245,29 @@ def signature_form(tx, i, script, hashcode=SIGHASH_ALL): inp["sequence"] = 0 if hashcode & SIGHASH_ANYONECANPAY: newtx["ins"] = [newtx["ins"][i]] - else: - pass return newtx +def segwit_txid(tx, hashcode=None): + #An easy way to construct the old-style hash (which is the real txid, + #the one without witness or marker/flag, is to remove all txinwitness + #entries from the deserialized form of the full tx, then reserialize, + #because serialize uses that as a flag to decide which serialization + #style to apply. + dtx = deserialize(tx) + for vin in dtx["ins"]: + if "txinwitness" in vin: + del vin["txinwitness"] + reserialized_tx = serialize(dtx) + return txhash(reserialized_tx, hashcode) + def txhash(tx, hashcode=None): if isinstance(tx, str) and re.match('^[0-9a-fA-F]*$', tx): tx = changebase(tx, 16, 256) + if from_byte_to_int(tx[4]) == 0: + if not from_byte_to_int(tx[5]) == 1: + #This is invalid, but a raise is a DOS vector in some contexts. + return None + return segwit_txid(tx, hashcode) if hashcode: return dbl_sha256(from_string_to_bytes(tx) + encode( int(hashcode), 256, 4)[::-1]) @@ -219,13 +327,9 @@ def script_to_address(script, vbyte=0): script) == 25: return bin_to_b58check(script[3:-2], vbyte) # pubkey hash addresses else: - if vbyte in [111, 196]: - # Testnet - scripthash_byte = 196 - else: - scripthash_byte = 5 - # BIP0016 scripthash addresses - return bin_to_b58check(script[2:-1], scripthash_byte) + # BIP0016 scripthash addresses: requires explicit vbyte set + if vbyte == 0: raise Exception("Invalid version byte for P2SH") + return bin_to_b58check(script[2:-1], vbyte) def p2sh_scriptaddr(script, magicbyte=5): @@ -270,7 +374,7 @@ def serialize_script_unit(unit): if unit < 16: return from_int_to_byte(unit + 80) else: - return bytes([unit]) + return from_int_to_byte(unit) elif unit is None: return b'\x00' else: @@ -287,13 +391,24 @@ def serialize_script_unit(unit): if is_python2: def serialize_script(script): + #bugfix: if *every* item in the script is of type int, + #for example a script of OP_TRUE, or None, + #then the previous version would always report json_is_base as True, + #resulting in an infinite loop (look who's demented now). + #There is no easy solution without being less flexible; + #here we default to returning a hex serialization in cases where + #there are no strings to use as flags. + if all([(isinstance(x, int) or x is None) for x in script]): + #no indication given whether output should be hex or binary, so..? + return binascii.hexlify(''.join(map(serialize_script_unit, script))) if json_is_base(script, 16): return binascii.hexlify(serialize_script(json_changebase( - script, lambda x: binascii.unhexlify(x)))) + script, lambda x: binascii.unhexlify(x)))) return ''.join(map(serialize_script_unit, script)) else: def serialize_script(script): + #TODO Python 3 bugfix as above needed if json_is_base(script, 16): return safe_hexlify(serialize_script(json_changebase( script, lambda x: binascii.unhexlify(x)))) @@ -315,7 +430,7 @@ def mk_multisig_script(*args): # [pubs],k or pub1,pub2...pub[n],k # Signing and verifying -def verify_tx_input(tx, i, script, sig, pub): +def verify_tx_input(tx, i, script, sig, pub, witness=None, amount=None): if re.match('^[0-9a-fA-F]*$', tx): tx = binascii.unhexlify(tx) if re.match('^[0-9a-fA-F]*$', script): @@ -324,18 +439,30 @@ def verify_tx_input(tx, i, script, sig, pub): sig = safe_hexlify(sig) if not re.match('^[0-9a-fA-F]*$', pub): pub = safe_hexlify(pub) + if witness: + if not re.match('^[0-9a-fA-F*$', witness): + witness = safe_hexlify(witness) hashcode = decode(sig[-2:], 16) - modtx = signature_form(tx, int(i), script, hashcode) + if witness and amount: + #TODO assumes p2sh wrapped segwit input; OK for JM wallets + scriptCode = "76a914"+hash160(binascii.unhexlify(pub))+"88ac" + modtx = segwit_signature_form(deserialize(binascii.hexlify(tx)), int(i), + scriptCode, amount, hashcode) + else: + modtx = signature_form(tx, int(i), script, hashcode) return ecdsa_tx_verify(modtx, sig, pub, hashcode) -def sign(tx, i, priv, hashcode=SIGHASH_ALL, usenonce=None): +def sign(tx, i, priv, hashcode=SIGHASH_ALL, usenonce=None, amount=None): i = int(i) if (not is_python2 and isinstance(re, bytes)) or not re.match( '^[0-9a-fA-F]*$', tx): return binascii.unhexlify(sign(safe_hexlify(tx), i, priv)) if len(priv) <= 33: priv = safe_hexlify(priv) + if amount: + return p2sh_p2wpkh_sign(tx, i, priv, amount, hashcode=hashcode, + usenonce=usenonce) pub = privkey_to_pubkey(priv, True) address = pubkey_to_address(pub) signing_tx = signature_form(tx, i, mk_pubkey_script(address), hashcode) @@ -344,6 +471,22 @@ def sign(tx, i, priv, hashcode=SIGHASH_ALL, usenonce=None): txobj["ins"][i]["script"] = serialize_script([sig, pub]) return serialize(txobj) +def p2sh_p2wpkh_sign(tx, i, priv, amount, hashcode=SIGHASH_ALL, usenonce=None): + """Given a serialized transaction, index, private key in hex, + amount in satoshis and optionally hashcode, return the serialized + transaction containing a signature and witness for this input; it's + assumed that the input is of type pay-to-witness-pubkey-hash nested in p2sh. + """ + pub = privkey_to_pubkey(priv) + script = pubkey_to_p2sh_p2wpkh_script(pub) + scriptCode = "76a914"+hash160(binascii.unhexlify(pub))+"88ac" + signing_tx = segwit_signature_form(deserialize(tx), i, scriptCode, amount, + hashcode=hashcode) + sig = ecdsa_tx_sign(signing_tx, priv, hashcode, usenonce=usenonce) + txobj = deserialize(tx) + txobj["ins"][i]["script"] = "16"+script + txobj["ins"][i]["txinwitness"] = [sig, pub] + return serialize(txobj) def signall(tx, priv): # if priv is a dictionary, assume format is diff --git a/test/test_segwit.py b/test/test_segwit.py new file mode 100644 index 00000000..b90533e5 --- /dev/null +++ b/test/test_segwit.py @@ -0,0 +1,267 @@ +#! /usr/bin/env python +from __future__ import absolute_import +'''Test segwit transactions.''' + +import sys +import os +import time +import binascii +import json +from pprint import pformat +import bitcoin as btc +import pytest +from joinmarket import load_program_config, jm_single, get_log +from decimal import Decimal +log = get_log() + + +def test_segwit_valid_txs(setup_segwit): + with open("test/tx_segwit_valid.json", "r") as f: + json_data = f.read() + valid_txs = json.loads(json_data) + for j in valid_txs: + if len(j) < 2: + continue + deserialized_tx = btc.deserialize(str(j[1])) + print pformat(deserialized_tx) + assert btc.serialize(deserialized_tx) == str(j[1]) + #TODO use bcinterface to decoderawtransaction + #and compare the json values + +@pytest.fixture(scope="module") +def setup_segwit(): + load_program_config() + + +''' +Examples of valid segwit from the json with parsing + +["Valid P2WPKH (Private key of segwit tests is +L5AQtV2HDm4xGsseLokK2VAT2EtYKcTm3c7HwqnJBFt9LdaQULsM)"], + +[[["0000000000000000000000000000000000000000000000000000000000000100", +0, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1000]], + +"01000000 +00 +01 +ins start +in num +01 +in txid +000100000000000000000000000000000000000000000000000000000000000000 +in txid out index +00000000 +sequence +ffffffff +num outs +01 +amount +e803000000000000 +script +1976a9144c9c3dfac4207d5d8cb89df5722cb3d712385e3f88ac +(number of witnesses = 1, implied by txin length) +witnesses : number 1 +item count for this witness +02 +signature length +48 +signature + hashcode 01 +3045022100cfb07164b36ba64c1b1e8c7720a56ad64d96f6ef332d3d37f9cb3c96477dc4450220 +0a464cd7a9cf94cd70f66ce4f4f0625ef650052c7afcfe29d7d7e01830ff91ed01 +pubkey length +21 +pubkey +03596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71 +locktime +00000000", "P2SH,WITNESS"], +''' +''' +P2WSH example +01000000 +00 +01 +01 +00010000000000000000000000000000000000000000000000000000000000000000 +000000 +ffffffff +01 +amount +e803000000000000 +length 25 +19 +OP_DUP OP_HASH160 +76a9 +hash length +14 +ripemd160(sha256(pubkey)) +4c9c3dfac4207d5d8cb89df5722cb3d712385e3f +OP_EQUALVERIFY OP_CHECKSIG +88ac +num items in witness 1 +02 +length of sig +48 +3045022100aa5d8aa40a90f23ce2c3d11bc845ca4a12acd99cbea37de6b9f6d86edebba8cb0220 +22dedc2aa0a255f74d04c0b76ece2d7c691f9dd11a64a8ac49f62a99c3a05f9d01 +length of scriptSig +23 +length of pubkey +21 +pubkey +03596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71 +CHECKSIG +ac +locktime +00000000 + +" +Example with SIGHASH_SINGLE|SIGHASH_ANYONECANPAY +version +01000000 +marker +00 +flag +01 +num in +04 +in1 txid +0001000000000000000000000000000000000000000000000000000000000000 +in 1 index +0200000000 +in 1 sequence +ffffffff +0001000000000000000000000000000000000000000000000000000000000000 +0100000000 +ffffffff +0001000000000000000000000000000000000000000000000000000000000000 +0000000000 +ffffffff +0001000000000000000000000000000000000000000000000000000000000000 +0300000000 +ffffffff +num outs +05 +out 0 amount +540b000000000000 +length +01 +OP_TRUE - looks like anyonecanspend +51 +out 1 +amount +d007000000000000 +length +01 +OP_TRUE +51 +out 2 +amount +8403000000000000 +length +01 +OP_TRUE +51 +out 3 +amount +3c0f000000000000 +length +01 +OP_TRUE +51 +out 4 +amount +2c01000000000000 +length +01 +OP_TRUE +51 +witness starts here +first txin witness - none +00 +second witness item +num items in witness +02 +sig length +48 +signature +304502210092f4777a0f17bf5aeb8ae768dec5f2c14feabf9d1fe2c89c78dfed0f13fdb869 +02206da90a86042e252bcd1e80a168c719e4a1ddcc3cebea24b9812c5453c79107e983 - SIGHASH_SINGLE|SIGHASH_ANYONECANPAY +length pubkey +21 +pubkey +03596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71 +locktime +000000000000 + + +"01000000 +00 +01 +01 +0001000000000000000000000000000000000000000000000000000000000000 +0000000000 +ffffffff +01 +e803000000000000 +19 +76a9 +14 +4c9c3dfac4207d5d8cb89df5722cb3d712385e3f +88 +ac +02 +48 +3045022100aa5d8aa40a90f23ce2c3d11bc845ca4a12acd99cbea37de6b9f6d86edebba8cb +022022dedc2aa0a255f74d04c0b76ece2d7c691f9dd11a64a8ac49f62a99c3a05f9d01 +23 +21 +03596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71 +ac +00000000", "P2SH,WITNESS"], + + +["Valid P2SH(P2WPKH)"], +[[["0000000000000000000000000000000000000000000000000000000000000100", +0, +**NOTE: this hash160 is of 00 14 ** - how P2SHP2WPKH works +"HASH160 0x14 0xfe9c7dacc9fcfbf7e3b7d5ad06aa2b28c5a7b7e3 EQUAL", 1000]], + +" +01000000 +00 +01 +01 +0001000000000000000000000000000000000000000000000000000000000000 +00000000 +length of scriptsig +17 +length of item +16 +witness versoin byte +00 +length of item +14 +hash160 - of PUBKEY +4c9c3dfac4207d5d8cb89df5722cb3d712385e3f +sequence +ffffffff +num outs +01 +amount +e803000000000000 +output +1976a9144c9c3dfac4207d5d8cb89df5722cb3d712385e3f88ac +witness for input 0 +num items +02 +48 +3045022100cfb07164b36ba64c1b1e8c7720a56ad64d96f6ef332d3d37f9cb3c96477dc445 +02200a464cd7a9cf94cd70f66ce4f4f0625ef650052c7afcfe29d7d7e01830ff91ed01 +len pub +21 +pub +03596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71 +locktime +00000000", "P2SH,WITNESS"], +''' diff --git a/test/tx_segwit_valid.json b/test/tx_segwit_valid.json new file mode 100644 index 00000000..7fe0cdd8 --- /dev/null +++ b/test/tx_segwit_valid.json @@ -0,0 +1,98 @@ +[ +["Valid P2WPKH (Private key of segwit tests is L5AQtV2HDm4xGsseLokK2VAT2EtYKcTm3c7HwqnJBFt9LdaQULsM)"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1000]], +"0100000000010100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff01e8030000000000001976a9144c9c3dfac4207d5d8cb89df5722cb3d712385e3f88ac02483045022100cfb07164b36ba64c1b1e8c7720a56ad64d96f6ef332d3d37f9cb3c96477dc44502200a464cd7a9cf94cd70f66ce4f4f0625ef650052c7afcfe29d7d7e01830ff91ed012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc7100000000", "P2SH,WITNESS"], + +["Valid P2WSH"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x00 0x20 0xff25429251b5a84f452230a3c75fd886b7fc5a7865ce4a7bb7a9d7c5be6da3db", 1000]], +"0100000000010100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff01e8030000000000001976a9144c9c3dfac4207d5d8cb89df5722cb3d712385e3f88ac02483045022100aa5d8aa40a90f23ce2c3d11bc845ca4a12acd99cbea37de6b9f6d86edebba8cb022022dedc2aa0a255f74d04c0b76ece2d7c691f9dd11a64a8ac49f62a99c3a05f9d01232103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ac00000000", "P2SH,WITNESS"], + +["Valid P2SH(P2WPKH)"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0xfe9c7dacc9fcfbf7e3b7d5ad06aa2b28c5a7b7e3 EQUAL", 1000]], +"01000000000101000100000000000000000000000000000000000000000000000000000000000000000000171600144c9c3dfac4207d5d8cb89df5722cb3d712385e3fffffffff01e8030000000000001976a9144c9c3dfac4207d5d8cb89df5722cb3d712385e3f88ac02483045022100cfb07164b36ba64c1b1e8c7720a56ad64d96f6ef332d3d37f9cb3c96477dc44502200a464cd7a9cf94cd70f66ce4f4f0625ef650052c7afcfe29d7d7e01830ff91ed012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc7100000000", "P2SH,WITNESS"], + +["Valid P2SH(P2WSH)"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x2135ab4f0981830311e35600eebc7376dce3a914 EQUAL", 1000]], +"0100000000010100010000000000000000000000000000000000000000000000000000000000000000000023220020ff25429251b5a84f452230a3c75fd886b7fc5a7865ce4a7bb7a9d7c5be6da3dbffffffff01e8030000000000001976a9144c9c3dfac4207d5d8cb89df5722cb3d712385e3f88ac02483045022100aa5d8aa40a90f23ce2c3d11bc845ca4a12acd99cbea37de6b9f6d86edebba8cb022022dedc2aa0a255f74d04c0b76ece2d7c691f9dd11a64a8ac49f62a99c3a05f9d01232103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ac00000000", "P2SH,WITNESS"], + +["Witness with SigHash Single|AnyoneCanPay"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1100], +["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000], +["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3100], +["0000000000000000000000000000000000000000000000000000000000000100", 3, "0x51", 4100]], +"0100000000010400010000000000000000000000000000000000000000000000000000000000000200000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000300000000ffffffff05540b0000000000000151d0070000000000000151840300000000000001513c0f00000000000001512c010000000000000151000248304502210092f4777a0f17bf5aeb8ae768dec5f2c14feabf9d1fe2c89c78dfed0f13fdb86902206da90a86042e252bcd1e80a168c719e4a1ddcc3cebea24b9812c5453c79107e9832103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71000000000000", "P2SH,WITNESS"], + +["Witness with SigHash Single|AnyoneCanPay (same signature as previous)"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000], +["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000], +["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]], +"0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff03e8030000000000000151d0070000000000000151b80b0000000000000151000248304502210092f4777a0f17bf5aeb8ae768dec5f2c14feabf9d1fe2c89c78dfed0f13fdb86902206da90a86042e252bcd1e80a168c719e4a1ddcc3cebea24b9812c5453c79107e9832103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"], + +["Witness with SigHash Single"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000], +["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000], +["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]], +"0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff0484030000000000000151d0070000000000000151540b0000000000000151c800000000000000015100024730440220699e6b0cfe015b64ca3283e6551440a34f901ba62dd4c72fe1cb815afb2e6761022021cc5e84db498b1479de14efda49093219441adc6c543e5534979605e273d80b032103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"], + +["Witness with SigHash Single (same signature as previous)"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000], +["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000], +["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]], +"0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff03e8030000000000000151d0070000000000000151b80b000000000000015100024730440220699e6b0cfe015b64ca3283e6551440a34f901ba62dd4c72fe1cb815afb2e6761022021cc5e84db498b1479de14efda49093219441adc6c543e5534979605e273d80b032103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"], + +["Witness with SigHash None|AnyoneCanPay"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1100], +["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000], +["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3100], +["0000000000000000000000000000000000000000000000000000000000000100", 3, "0x51", 4100]], +"0100000000010400010000000000000000000000000000000000000000000000000000000000000200000000ffffffff00010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000300000000ffffffff04b60300000000000001519e070000000000000151860b00000000000001009600000000000000015100000248304502210091b32274295c2a3fa02f5bce92fb2789e3fc6ea947fbe1a76e52ea3f4ef2381a022079ad72aefa3837a2e0c033a8652a59731da05fa4a813f4fc48e87c075037256b822103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"], + +["Witness with SigHash None|AnyoneCanPay (same signature as previous)"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000], +["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000], +["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]], +"0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff03e8030000000000000151d0070000000000000151b80b0000000000000151000248304502210091b32274295c2a3fa02f5bce92fb2789e3fc6ea947fbe1a76e52ea3f4ef2381a022079ad72aefa3837a2e0c033a8652a59731da05fa4a813f4fc48e87c075037256b822103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"], + +["Witness with SigHash None"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000], +["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000], +["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]], +"0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff04b60300000000000001519e070000000000000151860b0000000000000100960000000000000001510002473044022022fceb54f62f8feea77faac7083c3b56c4676a78f93745adc8a35800bc36adfa022026927df9abcf0a8777829bcfcce3ff0a385fa54c3f9df577405e3ef24ee56479022103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"], + +["Witness with SigHash None (same signature as previous)"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000], +["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000], +["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]], +"0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff03e8030000000000000151d0070000000000000151b80b00000000000001510002473044022022fceb54f62f8feea77faac7083c3b56c4676a78f93745adc8a35800bc36adfa022026927df9abcf0a8777829bcfcce3ff0a385fa54c3f9df577405e3ef24ee56479022103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"], + +["Witness with SigHash None (same signature, only sequences changed)"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000], +["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000], +["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]], +"01000000000103000100000000000000000000000000000000000000000000000000000000000000000000000200000000010000000000000000000000000000000000000000000000000000000000000100000000ffffffff000100000000000000000000000000000000000000000000000000000000000002000000000200000003e8030000000000000151d0070000000000000151b80b00000000000001510002473044022022fceb54f62f8feea77faac7083c3b56c4676a78f93745adc8a35800bc36adfa022026927df9abcf0a8777829bcfcce3ff0a385fa54c3f9df577405e3ef24ee56479022103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"], + +["Witness with SigHash All|AnyoneCanPay"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1100], +["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000], +["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3100], +["0000000000000000000000000000000000000000000000000000000000000100", 3, "0x51", 4100]], +"0100000000010400010000000000000000000000000000000000000000000000000000000000000200000000ffffffff00010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000300000000ffffffff03e8030000000000000151d0070000000000000151b80b0000000000000151000002483045022100a3cec69b52cba2d2de623eeef89e0ba1606184ea55476c0f8189fda231bc9cbb022003181ad597f7c380a7d1c740286b1d022b8b04ded028b833282e055e03b8efef812103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"], + +["Witness with SigHash All|AnyoneCanPay (same signature as previous)"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000], +["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000], +["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]], +"0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff03e8030000000000000151d0070000000000000151b80b00000000000001510002483045022100a3cec69b52cba2d2de623eeef89e0ba1606184ea55476c0f8189fda231bc9cbb022003181ad597f7c380a7d1c740286b1d022b8b04ded028b833282e055e03b8efef812103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"], + +["Unknown witness program version with invalid signature"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000], +["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x51 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000], +["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]], +"0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff03e8030000000000000151d0070000000000000151b80b00000000000001510002483045022100a3cec69b52cba2d2de623ffffffffff1606184ea55476c0f8189fda231bc9cbb022003181ad597f7c380a7d1c740286b1d022b8b04ded028b833282e055e03b8efef812103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"], + +["Witness with a push of 520 bytes"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x00 0x20 0x33198a9bfef674ebddb9ffaa52928017b8472791e54c609cb95f278ac6b1e349", 1000]], +"0100000000010100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff010000000000000000015102fd08020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002755100000000", "P2SH,WITNESS"], + +["Make diffs cleaner by leaving a comment here without comma at the end"] +]