test: refactor out same-txid-diff-wtxid tx to reuse in other tests
useful to easily create transactions with same txid, different wtxid and valid witness for testing scenarios in other places (ex: private broadcast connections)
This commit is contained in:
1 parent
084eee0291
commit
afaaba69ed
2 files changed
+59
-42
No files matched your search
@@ -7,34 +7,18 @@ Test mempool acceptance in case of an already known transaction
|
|||||||
with identical non-witness data but different witness.
|
with identical non-witness data but different witness.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from copy import deepcopy
|
|
||||||
from test_framework.messages import (
|
from test_framework.messages import (
|
||||||
COIN,
|
COIN,
|
||||||
COutPoint,
|
|
||||||
CTransaction,
|
|
||||||
CTxIn,
|
|
||||||
CTxInWitness,
|
|
||||||
CTxOut,
|
|
||||||
sha256,
|
|
||||||
)
|
)
|
||||||
from test_framework.p2p import P2PTxInvStore
|
from test_framework.p2p import P2PTxInvStore
|
||||||
from test_framework.script import (
|
from test_framework.script_util import ValidWitnessMalleatedTx
|
||||||
CScript,
|
|
||||||
OP_0,
|
|
||||||
OP_ELSE,
|
|
||||||
OP_ENDIF,
|
|
||||||
OP_EQUAL,
|
|
||||||
OP_HASH160,
|
|
||||||
OP_IF,
|
|
||||||
OP_TRUE,
|
|
||||||
hash160,
|
|
||||||
)
|
|
||||||
from test_framework.test_framework import BitcoinTestFramework
|
from test_framework.test_framework import BitcoinTestFramework
|
||||||
from test_framework.util import (
|
from test_framework.util import (
|
||||||
assert_not_equal,
|
assert_not_equal,
|
||||||
assert_equal,
|
assert_equal,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class MempoolWtxidTest(BitcoinTestFramework):
|
class MempoolWtxidTest(BitcoinTestFramework):
|
||||||
def set_test_params(self):
|
def set_test_params(self):
|
||||||
self.num_nodes = 1
|
self.num_nodes = 1
|
||||||
@@ -50,38 +34,19 @@ class MempoolWtxidTest(BitcoinTestFramework):
|
|||||||
assert_equal(node.getmempoolinfo()['size'], 0)
|
assert_equal(node.getmempoolinfo()['size'], 0)
|
||||||
|
|
||||||
self.log.info("Submit parent with multiple script branches to mempool")
|
self.log.info("Submit parent with multiple script branches to mempool")
|
||||||
hashlock = hash160(b'Preimage')
|
txgen = ValidWitnessMalleatedTx()
|
||||||
witness_script = CScript([OP_IF, OP_HASH160, hashlock, OP_EQUAL, OP_ELSE, OP_TRUE, OP_ENDIF])
|
parent = txgen.build_parent_tx(txid, 9.99998 * COIN)
|
||||||
witness_program = sha256(witness_script)
|
|
||||||
script_pubkey = CScript([OP_0, witness_program])
|
|
||||||
|
|
||||||
parent = CTransaction()
|
|
||||||
parent.vin.append(CTxIn(COutPoint(int(txid, 16), 0), b""))
|
|
||||||
parent.vout.append(CTxOut(int(9.99998 * COIN), script_pubkey))
|
|
||||||
|
|
||||||
privkeys = [node.get_deterministic_priv_key().key]
|
privkeys = [node.get_deterministic_priv_key().key]
|
||||||
raw_parent = node.signrawtransactionwithkey(hexstring=parent.serialize().hex(), privkeys=privkeys)['hex']
|
raw_parent = node.signrawtransactionwithkey(hexstring=parent.serialize().hex(), privkeys=privkeys)['hex']
|
||||||
parent_txid = node.sendrawtransaction(hexstring=raw_parent, maxfeerate=0)
|
signed_parent_txid = node.sendrawtransaction(hexstring=raw_parent, maxfeerate=0)
|
||||||
self.generate(node, 1)
|
self.generate(node, 1)
|
||||||
|
|
||||||
peer_wtxid_relay = node.add_p2p_connection(P2PTxInvStore())
|
peer_wtxid_relay = node.add_p2p_connection(P2PTxInvStore())
|
||||||
|
|
||||||
# Create a new transaction with witness solving first branch
|
child_one, child_two = txgen.build_malleated_children(signed_parent_txid, 9.99996 * COIN)
|
||||||
child_witness_script = CScript([OP_TRUE])
|
|
||||||
child_witness_program = sha256(child_witness_script)
|
|
||||||
child_script_pubkey = CScript([OP_0, child_witness_program])
|
|
||||||
|
|
||||||
child_one = CTransaction()
|
|
||||||
child_one.vin.append(CTxIn(COutPoint(int(parent_txid, 16), 0), b""))
|
|
||||||
child_one.vout.append(CTxOut(int(9.99996 * COIN), child_script_pubkey))
|
|
||||||
child_one.wit.vtxinwit.append(CTxInWitness())
|
|
||||||
child_one.wit.vtxinwit[0].scriptWitness.stack = [b'Preimage', b'\x01', witness_script]
|
|
||||||
child_one_wtxid = child_one.wtxid_hex
|
child_one_wtxid = child_one.wtxid_hex
|
||||||
child_one_txid = child_one.txid_hex
|
child_one_txid = child_one.txid_hex
|
||||||
|
|
||||||
# Create another identical transaction with witness solving second branch
|
|
||||||
child_two = deepcopy(child_one)
|
|
||||||
child_two.wit.vtxinwit[0].scriptWitness.stack = [b'', witness_script]
|
|
||||||
child_two_wtxid = child_two.wtxid_hex
|
child_two_wtxid = child_two.wtxid_hex
|
||||||
child_two_txid = child_two.txid_hex
|
child_two_txid = child_two.txid_hex
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,16 @@
|
|||||||
"""Useful Script constants and utils."""
|
"""Useful Script constants and utils."""
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
|
from copy import deepcopy
|
||||||
|
|
||||||
|
from test_framework.messages import (
|
||||||
|
COutPoint,
|
||||||
|
CTransaction,
|
||||||
|
CTxIn,
|
||||||
|
CTxInWitness,
|
||||||
|
CTxOut,
|
||||||
|
sha256,
|
||||||
|
)
|
||||||
from test_framework.script import (
|
from test_framework.script import (
|
||||||
CScript,
|
CScript,
|
||||||
OP_0,
|
OP_0,
|
||||||
@@ -14,12 +24,15 @@ from test_framework.script import (
|
|||||||
OP_CHECKMULTISIG,
|
OP_CHECKMULTISIG,
|
||||||
OP_CHECKSIG,
|
OP_CHECKSIG,
|
||||||
OP_DUP,
|
OP_DUP,
|
||||||
|
OP_ELSE,
|
||||||
|
OP_ENDIF,
|
||||||
OP_EQUAL,
|
OP_EQUAL,
|
||||||
OP_EQUALVERIFY,
|
OP_EQUALVERIFY,
|
||||||
OP_HASH160,
|
OP_HASH160,
|
||||||
|
OP_IF,
|
||||||
OP_RETURN,
|
OP_RETURN,
|
||||||
|
OP_TRUE,
|
||||||
hash160,
|
hash160,
|
||||||
sha256,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# To prevent a "tx-size-small" policy rule error, a transaction has to have a
|
# To prevent a "tx-size-small" policy rule error, a transaction has to have a
|
||||||
@@ -131,6 +144,45 @@ def check_script(script):
|
|||||||
assert False
|
assert False
|
||||||
|
|
||||||
|
|
||||||
|
class ValidWitnessMalleatedTx:
|
||||||
|
"""
|
||||||
|
Creates a valid witness malleation transaction test case:
|
||||||
|
- Parent transaction with a script supporting 2 branches
|
||||||
|
- 2 child transactions with the same txid but different wtxids
|
||||||
|
"""
|
||||||
|
def __init__(self):
|
||||||
|
hashlock = hash160(b'Preimage')
|
||||||
|
self.witness_script = CScript([OP_IF, OP_HASH160, hashlock, OP_EQUAL, OP_ELSE, OP_TRUE, OP_ENDIF])
|
||||||
|
|
||||||
|
def build_parent_tx(self, funding_txid, amount):
|
||||||
|
# Create an unsigned parent transaction paying to the witness script.
|
||||||
|
witness_program = sha256(self.witness_script)
|
||||||
|
script_pubkey = CScript([OP_0, witness_program])
|
||||||
|
|
||||||
|
parent = CTransaction()
|
||||||
|
parent.vin.append(CTxIn(COutPoint(int(funding_txid, 16), 0), b""))
|
||||||
|
parent.vout.append(CTxOut(int(amount), script_pubkey))
|
||||||
|
return parent
|
||||||
|
|
||||||
|
def build_malleated_children(self, signed_parent_txid, amount):
|
||||||
|
# Create 2 valid children that differ only in witness data.
|
||||||
|
# 1. Create a new transaction with witness solving first branch
|
||||||
|
child_witness_script = CScript([OP_TRUE])
|
||||||
|
child_witness_program = sha256(child_witness_script)
|
||||||
|
child_script_pubkey = CScript([OP_0, child_witness_program])
|
||||||
|
|
||||||
|
child_one = CTransaction()
|
||||||
|
child_one.vin.append(CTxIn(COutPoint(int(signed_parent_txid, 16), 0), b""))
|
||||||
|
child_one.vout.append(CTxOut(int(amount), child_script_pubkey))
|
||||||
|
child_one.wit.vtxinwit.append(CTxInWitness())
|
||||||
|
child_one.wit.vtxinwit[0].scriptWitness.stack = [b'Preimage', b'\x01', self.witness_script]
|
||||||
|
|
||||||
|
# 2. Create another identical transaction with witness solving second branch
|
||||||
|
child_two = deepcopy(child_one)
|
||||||
|
child_two.wit.vtxinwit[0].scriptWitness.stack = [b'', self.witness_script]
|
||||||
|
return child_one, child_two
|
||||||
|
|
||||||
|
|
||||||
class TestFrameworkScriptUtil(unittest.TestCase):
|
class TestFrameworkScriptUtil(unittest.TestCase):
|
||||||
def test_multisig(self):
|
def test_multisig(self):
|
||||||
fake_pubkey = bytes([0]*33)
|
fake_pubkey = bytes([0]*33)
|
||||||
|
|||||||
Reference in new issue
Block a user