Changeset View
Changeset View
Standalone View
Standalone View
test/functional/wallet_txn_doublespend.py
Show All 28 Lines | class TxnMallTest(BitcoinTestFramework): | ||||
def setup_network(self): | def setup_network(self): | ||||
# Start with split network: | # Start with split network: | ||||
super().setup_network() | super().setup_network() | ||||
disconnect_nodes(self.nodes[1], self.nodes[2]) | disconnect_nodes(self.nodes[1], self.nodes[2]) | ||||
def run_test(self): | def run_test(self): | ||||
# All nodes should start with 1,250 BCH: | # All nodes should start with 1,250 BCH: | ||||
starting_balance = 1250 | starting_balance = 1250000000 | ||||
# All nodes should be out of IBD. | # All nodes should be out of IBD. | ||||
# If the nodes are not all out of IBD, that can interfere with | # If the nodes are not all out of IBD, that can interfere with | ||||
# blockchain sync later in the test when nodes are connected, due to | # blockchain sync later in the test when nodes are connected, due to | ||||
# timing issues. | # timing issues. | ||||
for n in self.nodes: | for n in self.nodes: | ||||
assert n.getblockchaininfo()["initialblockdownload"] is False | assert n.getblockchaininfo()["initialblockdownload"] is False | ||||
for i in range(4): | for i in range(4): | ||||
assert_equal(self.nodes[i].getbalance(), starting_balance) | assert_equal(self.nodes[i].getbalance(), starting_balance) | ||||
# bug workaround, coins generated assigned to first getnewaddress! | # bug workaround, coins generated assigned to first getnewaddress! | ||||
self.nodes[i].getnewaddress("") | self.nodes[i].getnewaddress("") | ||||
# Assign coins to foo and bar addresses: | # Assign coins to foo and bar addresses: | ||||
node0_address_foo = self.nodes[0].getnewaddress() | node0_address_foo = self.nodes[0].getnewaddress() | ||||
fund_foo_txid = self.nodes[0].sendtoaddress(node0_address_foo, 1219) | fund_foo_txid = self.nodes[0].sendtoaddress( | ||||
node0_address_foo, 1219000000) | |||||
fund_foo_tx = self.nodes[0].gettransaction(fund_foo_txid) | fund_foo_tx = self.nodes[0].gettransaction(fund_foo_txid) | ||||
node0_address_bar = self.nodes[0].getnewaddress() | node0_address_bar = self.nodes[0].getnewaddress() | ||||
fund_bar_txid = self.nodes[0].sendtoaddress(node0_address_bar, 29) | fund_bar_txid = self.nodes[0].sendtoaddress( | ||||
node0_address_bar, 29000000) | |||||
fund_bar_tx = self.nodes[0].gettransaction(fund_bar_txid) | fund_bar_tx = self.nodes[0].gettransaction(fund_bar_txid) | ||||
assert_equal(self.nodes[0].getbalance(), | assert_equal(self.nodes[0].getbalance(), | ||||
starting_balance + fund_foo_tx["fee"] + fund_bar_tx["fee"]) | starting_balance + fund_foo_tx["fee"] + fund_bar_tx["fee"]) | ||||
# Coins are sent to node1_address | # Coins are sent to node1_address | ||||
node1_address = self.nodes[1].getnewaddress() | node1_address = self.nodes[1].getnewaddress() | ||||
# First: use raw transaction API to send 1240 BCH to node1_address, | # First: use raw transaction API to send 1240 BCH to node1_address, | ||||
# but don't broadcast: | # but don't broadcast: | ||||
doublespend_fee = Decimal('-.02') | doublespend_fee = Decimal('-20000') | ||||
rawtx_input_0 = {} | rawtx_input_0 = {} | ||||
rawtx_input_0["txid"] = fund_foo_txid | rawtx_input_0["txid"] = fund_foo_txid | ||||
rawtx_input_0["vout"] = find_output(self.nodes[0], fund_foo_txid, 1219) | rawtx_input_0["vout"] = find_output( | ||||
self.nodes[0], fund_foo_txid, 1219000000) | |||||
rawtx_input_1 = {} | rawtx_input_1 = {} | ||||
rawtx_input_1["txid"] = fund_bar_txid | rawtx_input_1["txid"] = fund_bar_txid | ||||
rawtx_input_1["vout"] = find_output(self.nodes[0], fund_bar_txid, 29) | rawtx_input_1["vout"] = find_output( | ||||
self.nodes[0], fund_bar_txid, 29000000) | |||||
inputs = [rawtx_input_0, rawtx_input_1] | inputs = [rawtx_input_0, rawtx_input_1] | ||||
change_address = self.nodes[0].getnewaddress() | change_address = self.nodes[0].getnewaddress() | ||||
outputs = {} | outputs = {} | ||||
outputs[node1_address] = 1240 | outputs[node1_address] = 1240000000 | ||||
outputs[change_address] = 1248 - 1240 + doublespend_fee | outputs[change_address] = 1248000000 - 1240000000 + doublespend_fee | ||||
rawtx = self.nodes[0].createrawtransaction(inputs, outputs) | rawtx = self.nodes[0].createrawtransaction(inputs, outputs) | ||||
doublespend = self.nodes[0].signrawtransactionwithwallet(rawtx) | doublespend = self.nodes[0].signrawtransactionwithwallet(rawtx) | ||||
assert_equal(doublespend["complete"], True) | assert_equal(doublespend["complete"], True) | ||||
# Create two spends using 1 50 BCH coin each | # Create two spends using 1 50 BCH coin each | ||||
txid1 = self.nodes[0].sendtoaddress(node1_address, 40) | txid1 = self.nodes[0].sendtoaddress(node1_address, 40000000) | ||||
txid2 = self.nodes[0].sendtoaddress(node1_address, 20) | txid2 = self.nodes[0].sendtoaddress(node1_address, 20000000) | ||||
# Have node0 mine a block: | # Have node0 mine a block: | ||||
if (self.options.mine_block): | if (self.options.mine_block): | ||||
self.nodes[0].generate(1) | self.nodes[0].generate(1) | ||||
self.sync_blocks(self.nodes[0:2]) | self.sync_blocks(self.nodes[0:2]) | ||||
tx1 = self.nodes[0].gettransaction(txid1) | tx1 = self.nodes[0].gettransaction(txid1) | ||||
tx2 = self.nodes[0].gettransaction(txid2) | tx2 = self.nodes[0].gettransaction(txid2) | ||||
# Node0's balance should be starting balance, plus 50BTC for another | # Node0's balance should be starting balance, plus 50BTC for another | ||||
# matured block, minus 40, minus 20, and minus transaction fees: | # matured block, minus 40, minus 20, and minus transaction fees: | ||||
expected = starting_balance + fund_foo_tx["fee"] + fund_bar_tx["fee"] | expected = starting_balance + fund_foo_tx["fee"] + fund_bar_tx["fee"] | ||||
if self.options.mine_block: | if self.options.mine_block: | ||||
expected += 50 | expected += 50000000 | ||||
expected += tx1["amount"] + tx1["fee"] | expected += tx1["amount"] + tx1["fee"] | ||||
expected += tx2["amount"] + tx2["fee"] | expected += tx2["amount"] + tx2["fee"] | ||||
assert_equal(self.nodes[0].getbalance(), expected) | assert_equal(self.nodes[0].getbalance(), expected) | ||||
if self.options.mine_block: | if self.options.mine_block: | ||||
assert_equal(tx1["confirmations"], 1) | assert_equal(tx1["confirmations"], 1) | ||||
assert_equal(tx2["confirmations"], 1) | assert_equal(tx2["confirmations"], 1) | ||||
# Node1's balance should be both transaction amounts: | # Node1's balance should be both transaction amounts: | ||||
Show All 23 Lines | def run_test(self): | ||||
# Both transactions should be conflicted | # Both transactions should be conflicted | ||||
assert_equal(tx1["confirmations"], -2) | assert_equal(tx1["confirmations"], -2) | ||||
assert_equal(tx2["confirmations"], -2) | assert_equal(tx2["confirmations"], -2) | ||||
# Node0's total balance should be starting balance, plus 100BTC for | # Node0's total balance should be starting balance, plus 100BTC for | ||||
# two more matured blocks, minus 1240 for the double-spend, plus fees (which are | # two more matured blocks, minus 1240 for the double-spend, plus fees (which are | ||||
# negative): | # negative): | ||||
expected = starting_balance + 100 - 1240 + \ | expected = starting_balance + 100000000 - 1240000000 + \ | ||||
fund_foo_tx["fee"] + fund_bar_tx["fee"] + doublespend_fee | fund_foo_tx["fee"] + fund_bar_tx["fee"] + doublespend_fee | ||||
assert_equal(self.nodes[0].getbalance(), expected) | assert_equal(self.nodes[0].getbalance(), expected) | ||||
# Node1's balance should be its initial balance (1250 for 25 block | # Node1's balance should be its initial balance (1250 for 25 block | ||||
# rewards) plus the doublespend: | # rewards) plus the doublespend: | ||||
assert_equal(self.nodes[1].getbalance(), 1250 + 1240) | assert_equal(self.nodes[1].getbalance(), 1250000000 + 1240000000) | ||||
if __name__ == '__main__': | if __name__ == '__main__': | ||||
TxnMallTest().main() | TxnMallTest().main() |