MCPcopy Create free account
hub / github.com/ElementsProject/elements / run_test

Method run_test

test/functional/wallet_txn_clone.py:44–152  ·  view source on GitHub ↗
(self)

Source from the content-addressed store, hash-verified

42 return self.nodes[0].sendrawtransaction(tx['hex'])
43
44 def run_test(self):
45 if self.options.segwit:
46 output_type = "p2sh-segwit"
47 else:
48 output_type = "legacy"
49
50 # All nodes should start with 1,250 BTC:
51 starting_balance = 1250
52 for i in range(3):
53 assert_equal(self.nodes[i].getbalance()['bitcoin'], starting_balance)
54
55 self.nodes[0].settxfee(.001)
56
57 node0_address1 = self.nodes[0].getnewaddress(address_type=output_type)
58 node0_txid1 = self.nodes[0].sendtoaddress(node0_address1, 1219)
59 node0_tx1 = self.nodes[0].gettransaction(node0_txid1)
60 self.nodes[0].lockunspent(False, [{"txid":node0_txid1, "vout": find_vout_for_address(self.nodes[0], node0_txid1, node0_address1)}])
61
62 node0_address2 = self.nodes[0].getnewaddress(address_type=output_type)
63 node0_txid2 = self.nodes[0].sendtoaddress(node0_address2, 29)
64 node0_tx2 = self.nodes[0].gettransaction(node0_txid2)
65
66 assert_equal(self.nodes[0].getbalance()['bitcoin'],
67 starting_balance + node0_tx1["fee"]['bitcoin'] + node0_tx2["fee"]['bitcoin'])
68
69 # Coins are sent to node1_address
70 node1_address = self.nodes[1].getnewaddress()
71
72 # Send tx1, and another transaction tx2 that won't be cloned
73 txid1 = self.spend_txid(node0_txid1, find_vout_for_address(self.nodes[0], node0_txid1, node0_address1), [{node1_address: 40}])
74 txid2 = self.spend_txid(node0_txid2, find_vout_for_address(self.nodes[0], node0_txid2, node0_address2), [{node1_address: 20}])
75
76 # Construct a clone of tx1, to be malleated
77 rawtx1 = self.nodes[0].getrawtransaction(txid1, 1)
78 clone_inputs = [{"txid": rawtx1["vin"][0]["txid"], "vout": rawtx1["vin"][0]["vout"], "sequence": rawtx1["vin"][0]["sequence"]}]
79 clone_outputs = [
80 {rawtx1["vout"][0]["scriptPubKey"]["address"]: rawtx1["vout"][0]["value"]},
81 {rawtx1["vout"][1]["scriptPubKey"]["address"]: rawtx1["vout"][1]["value"]},
82 ]
83 assert_equal(rawtx1["vout"][2]["scriptPubKey"]["type"], "fee")
84 clone_outputs.append({"fee": rawtx1["vout"][2]["value"]})
85 clone_locktime = rawtx1["locktime"]
86 clone_raw = self.nodes[0].createrawtransaction(clone_inputs, clone_outputs, clone_locktime)
87
88 # createrawtransaction randomizes the order of its outputs, so swap them if necessary.
89 clone_tx = tx_from_hex(clone_raw)
90 if (rawtx1["vout"][0]["value"] == 40 and clone_tx.vout[0].nValue.getAmount() != 40*COIN or rawtx1["vout"][0]["value"] != 40 and clone_tx.vout[0].nValue.getAmount() == 40*COIN):
91 (clone_tx.vout[0], clone_tx.vout[1]) = (clone_tx.vout[1], clone_tx.vout[0])
92
93 # Use a different signature hash type to sign. This creates an equivalent but malleated clone.
94 # Don't send the clone anywhere yet
95 tx1_clone = self.nodes[0].signrawtransactionwithwallet(clone_tx.serialize().hex(), None, "ALL|ANYONECANPAY")
96 assert_equal(tx1_clone["complete"], True)
97
98 # Have node0 mine a block, if requested:
99 if (self.options.mine_block):
100 self.generate(self.nodes[0], 1, sync_fun=lambda: self.sync_blocks(self.nodes[0:2]))
101

Callers

nothing calls this directly

Calls 11

spend_txidMethod · 0.95
assert_equalFunction · 0.90
find_vout_for_addressFunction · 0.90
tx_from_hexFunction · 0.90
getAmountMethod · 0.80
hexMethod · 0.80
sendrawtransactionMethod · 0.80
connect_nodesMethod · 0.80
serializeMethod · 0.45
generateMethod · 0.45
sync_blocksMethod · 0.45

Tested by

no test coverage detected