Changeset View
Changeset View
Standalone View
Standalone View
test/functional/abandonconflict.py
Show First 20 Lines • Show All 61 Lines • ▼ Show 20 Lines | def run_test(self): | ||||
txAB1 = self.nodes[0].sendrawtransaction(signed["hex"]) | txAB1 = self.nodes[0].sendrawtransaction(signed["hex"]) | ||||
# Identify the 14.99998btc output | # Identify the 14.99998btc output | ||||
nAB = next(i for i, vout in enumerate(self.nodes[0].getrawtransaction( | nAB = next(i for i, vout in enumerate(self.nodes[0].getrawtransaction( | ||||
txAB1, 1)["vout"]) if vout["value"] == Decimal("14.99998")) | txAB1, 1)["vout"]) if vout["value"] == Decimal("14.99998")) | ||||
# Create a child tx spending AB1 and C | # Create a child tx spending AB1 and C | ||||
inputs = [] | inputs = [] | ||||
# Amount 14.99998 BCH | |||||
inputs.append({"txid": txAB1, "vout": nAB}) | inputs.append({"txid": txAB1, "vout": nAB}) | ||||
# Amount 10 BCH | |||||
inputs.append({"txid": txC, "vout": nC}) | inputs.append({"txid": txC, "vout": nC}) | ||||
outputs = {} | outputs = {} | ||||
outputs[self.nodes[0].getnewaddress()] = Decimal("24.9996") | outputs[self.nodes[0].getnewaddress()] = Decimal("24.9996") | ||||
signed2 = self.nodes[0].signrawtransaction( | signed2 = self.nodes[0].signrawtransaction( | ||||
self.nodes[0].createrawtransaction(inputs, outputs)) | self.nodes[0].createrawtransaction(inputs, outputs)) | ||||
txABC2 = self.nodes[0].sendrawtransaction(signed2["hex"]) | txABC2 = self.nodes[0].sendrawtransaction(signed2["hex"]) | ||||
# In mempool txs from self should increase balance from change | # In mempool txs from self should increase balance from change | ||||
newbalance = self.nodes[0].getbalance() | newbalance = self.nodes[0].getbalance() | ||||
assert_equal(newbalance, balance - Decimal("30") + Decimal("24.9996")) | assert_equal(newbalance, balance - Decimal("30") + Decimal("24.9996")) | ||||
balance = newbalance | balance = newbalance | ||||
# Restart the node with a higher min relay fee so the parent tx is no longer in mempool | # Restart the node with a higher min relay fee so the parent tx is no longer in mempool | ||||
# TODO: redo with eviction | # TODO: redo with eviction | ||||
self.stop_node(0) | self.stop_node(0) | ||||
self.start_node(0, extra_args=["-minrelaytxfee=0.0001"]) | self.start_node(0, extra_args=["-minrelaytxfee=0.0001"]) | ||||
# Verify txs no longer in either node's mempool | # Verify txs no longer in either node's mempool | ||||
assert_equal(len(self.nodes[0].getrawmempool()), 0) | assert_equal(len(self.nodes[0].getrawmempool()), 0) | ||||
assert_equal(len(self.nodes[1].getrawmempool()), 0) | assert_equal(len(self.nodes[1].getrawmempool()), 0) | ||||
# Not in mempool txs from self should only reduce balance | # Transactions which are not in the mempool should only reduce wallet balance. | ||||
# inputs are still spent, but change not received | # Transaction inputs should still be spent, but the change not yet received. | ||||
newbalance = self.nodes[0].getbalance() | newbalance = self.nodes[0].getbalance() | ||||
assert_equal(newbalance, balance - Decimal("24.9996")) | assert_equal(newbalance, balance - Decimal("24.9996")) | ||||
# Unconfirmed received funds that are not in mempool, also shouldn't show | # Unconfirmed received funds that are not in mempool also shouldn't show | ||||
# up in unconfirmed balance | # up in unconfirmed balance. Note that the transactions stored in the wallet | ||||
# are not necessarily in the node's mempool. | |||||
unconfbalance = self.nodes[0].getunconfirmedbalance( | unconfbalance = self.nodes[0].getunconfirmedbalance( | ||||
) + self.nodes[0].getbalance() | ) + self.nodes[0].getbalance() | ||||
assert_equal(unconfbalance, newbalance) | assert_equal(unconfbalance, newbalance) | ||||
# Also shouldn't show up in listunspent | # Unconfirmed transactions which are not in the mempool should also | ||||
# not be in listunspent | |||||
assert(not txABC2 in [utxo["txid"] | assert(not txABC2 in [utxo["txid"] | ||||
for utxo in self.nodes[0].listunspent(0)]) | for utxo in self.nodes[0].listunspent(0)]) | ||||
balance = newbalance | balance = newbalance | ||||
# Abandon original transaction and verify inputs are available again | # Abandon original transaction and verify inputs are available again | ||||
# including that the child tx was also abandoned | # including that the child tx was also abandoned | ||||
self.nodes[0].abandontransaction(txAB1) | self.nodes[0].abandontransaction(txAB1) | ||||
newbalance = self.nodes[0].getbalance() | newbalance = self.nodes[0].getbalance() | ||||
assert_equal(newbalance, balance + Decimal("30")) | assert_equal(newbalance, balance + Decimal("30")) | ||||
balance = newbalance | balance = newbalance | ||||
# Verify that even with a low min relay fee, the tx is not reaccepted from wallet on startup once abandoned | # Verify that even with a low min relay fee, the tx is not re-accepted | ||||
# from wallet on startup once abandoned. | |||||
self.stop_node(0) | self.stop_node(0) | ||||
self.start_node(0, extra_args=["-minrelaytxfee=0.00001"]) | self.start_node(0, extra_args=["-minrelaytxfee=0.00001"]) | ||||
assert_equal(len(self.nodes[0].getrawmempool()), 0) | assert_equal(len(self.nodes[0].getrawmempool()), 0) | ||||
assert_equal(self.nodes[0].getbalance(), balance) | assert_equal(self.nodes[0].getbalance(), balance) | ||||
# But if its received again then it is unabandoned | # If the transaction is re-sent the wallet also unabandons it. The | ||||
# And since now in mempool, the change is available | # change should be available, and it's child transaction should remain | ||||
# But its child tx remains abandoned | # abandoned. | ||||
# NOTE: Abandoned transactions are internal to the wallet, and tracked | |||||
# separately from other indices. | |||||
self.nodes[0].sendrawtransaction(signed["hex"]) | self.nodes[0].sendrawtransaction(signed["hex"]) | ||||
newbalance = self.nodes[0].getbalance() | newbalance = self.nodes[0].getbalance() | ||||
assert_equal(newbalance, balance - Decimal("20") + Decimal("14.99998")) | assert_equal(newbalance, balance - Decimal("20") + Decimal("14.99998")) | ||||
balance = newbalance | balance = newbalance | ||||
# Send child tx again so its unabandoned | # Send child tx again so it is not longer abandoned. | ||||
self.nodes[0].sendrawtransaction(signed2["hex"]) | self.nodes[0].sendrawtransaction(signed2["hex"]) | ||||
newbalance = self.nodes[0].getbalance() | newbalance = self.nodes[0].getbalance() | ||||
assert_equal(newbalance, balance - Decimal("10") - | assert_equal(newbalance, balance - Decimal("10") - | ||||
Decimal("14.99998") + Decimal("24.9996")) | Decimal("14.99998") + Decimal("24.9996")) | ||||
balance = newbalance | balance = newbalance | ||||
# Remove using high relay fee again | # Reset to a higher relay fee so that we abandon a transaction | ||||
self.stop_node(0) | self.stop_node(0) | ||||
self.start_node(0, extra_args=["-minrelaytxfee=0.0001"]) | self.start_node(0, extra_args=["-minrelaytxfee=0.0001"]) | ||||
assert_equal(len(self.nodes[0].getrawmempool()), 0) | assert_equal(len(self.nodes[0].getrawmempool()), 0) | ||||
newbalance = self.nodes[0].getbalance() | newbalance = self.nodes[0].getbalance() | ||||
assert_equal(newbalance, balance - Decimal("24.9996")) | assert_equal(newbalance, balance - Decimal("24.9996")) | ||||
balance = newbalance | balance = newbalance | ||||
# Create a double spend of AB1 by spending again from only A's 10 output | # Create a double spend of AB1. Spend it again from only A's 10 output. | ||||
# Mine double spend from node 1 | # Mine double spend from node 1. | ||||
inputs = [] | inputs = [] | ||||
inputs.append({"txid": txA, "vout": nA}) | inputs.append({"txid": txA, "vout": nA}) | ||||
outputs = {} | outputs = {} | ||||
outputs[self.nodes[1].getnewaddress()] = Decimal("9.9999") | outputs[self.nodes[1].getnewaddress()] = Decimal("9.9999") | ||||
tx = self.nodes[0].createrawtransaction(inputs, outputs) | tx = self.nodes[0].createrawtransaction(inputs, outputs) | ||||
signed = self.nodes[0].signrawtransaction(tx) | signed = self.nodes[0].signrawtransaction(tx) | ||||
self.nodes[1].sendrawtransaction(signed["hex"]) | self.nodes[1].sendrawtransaction(signed["hex"]) | ||||
self.nodes[1].generate(1) | self.nodes[1].generate(1) | ||||
Show All 24 Lines |