|
|
|
@ -4,6 +4,7 @@
|
|
|
|
|
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
|
|
|
"""Test the wallet accounts properly when there are cloned transactions with malleated scriptsigs."""
|
|
|
|
|
|
|
|
|
|
import io
|
|
|
|
|
from test_framework.test_framework import BitcoinTestFramework
|
|
|
|
|
from test_framework.util import (
|
|
|
|
|
assert_equal,
|
|
|
|
@ -11,6 +12,7 @@ from test_framework.util import (
|
|
|
|
|
disconnect_nodes,
|
|
|
|
|
sync_blocks,
|
|
|
|
|
)
|
|
|
|
|
from test_framework.messages import CTransaction, COIN
|
|
|
|
|
|
|
|
|
|
class TxnMallTest(BitcoinTestFramework):
|
|
|
|
|
def set_test_params(self):
|
|
|
|
@ -72,19 +74,14 @@ class TxnMallTest(BitcoinTestFramework):
|
|
|
|
|
clone_raw = self.nodes[0].createrawtransaction(clone_inputs, clone_outputs, clone_locktime)
|
|
|
|
|
|
|
|
|
|
# createrawtransaction randomizes the order of its outputs, so swap them if necessary.
|
|
|
|
|
# output 0 is at version+#inputs+input+sigstub+sequence+#outputs
|
|
|
|
|
# 40 BTC serialized is 00286bee00000000
|
|
|
|
|
pos0 = 2 * (4 + 1 + 36 + 1 + 4 + 1)
|
|
|
|
|
hex40 = "00286bee00000000"
|
|
|
|
|
output_len = 16 + 2 + 2 * int("0x" + clone_raw[pos0 + 16:pos0 + 16 + 2], 0)
|
|
|
|
|
if (rawtx1["vout"][0]["value"] == 40 and clone_raw[pos0:pos0 + 16] != hex40 or rawtx1["vout"][0]["value"] != 40 and clone_raw[pos0:pos0 + 16] == hex40):
|
|
|
|
|
output0 = clone_raw[pos0:pos0 + output_len]
|
|
|
|
|
output1 = clone_raw[pos0 + output_len:pos0 + 2 * output_len]
|
|
|
|
|
clone_raw = clone_raw[:pos0] + output1 + output0 + clone_raw[pos0 + 2 * output_len:]
|
|
|
|
|
clone_tx = CTransaction()
|
|
|
|
|
clone_tx.deserialize(io.BytesIO(bytes.fromhex(clone_raw)))
|
|
|
|
|
if (rawtx1["vout"][0]["value"] == 40 and clone_tx.vout[0].nValue != 40*COIN or rawtx1["vout"][0]["value"] != 40 and clone_tx.vout[0].nValue == 40*COIN):
|
|
|
|
|
(clone_tx.vout[0], clone_tx.vout[1]) = (clone_tx.vout[1], clone_tx.vout[0])
|
|
|
|
|
|
|
|
|
|
# Use a different signature hash type to sign. This creates an equivalent but malleated clone.
|
|
|
|
|
# Don't send the clone anywhere yet
|
|
|
|
|
tx1_clone = self.nodes[0].signrawtransactionwithwallet(clone_raw, None, "ALL|ANYONECANPAY")
|
|
|
|
|
tx1_clone = self.nodes[0].signrawtransactionwithwallet(clone_tx.serialize().hex(), None, "ALL|ANYONECANPAY")
|
|
|
|
|
assert_equal(tx1_clone["complete"], True)
|
|
|
|
|
|
|
|
|
|
# Have node0 mine a block, if requested:
|
|
|
|
|