Changeset View
Changeset View
Standalone View
Standalone View
test/functional/mempool_accept.py
Show First 20 Lines • Show All 65 Lines • ▼ Show 20 Lines | def run_test(self): | ||||
self.log.info('A transaction already in the blockchain') | self.log.info('A transaction already in the blockchain') | ||||
# Pick a random coin(base) to spend | # Pick a random coin(base) to spend | ||||
coin = coins.pop() | coin = coins.pop() | ||||
raw_tx_in_block = node.signrawtransactionwithwallet(node.createrawtransaction( | raw_tx_in_block = node.signrawtransactionwithwallet(node.createrawtransaction( | ||||
inputs=[{'txid': coin['txid'], 'vout': coin['vout']}], | inputs=[{'txid': coin['txid'], 'vout': coin['vout']}], | ||||
outputs=[{node.getnewaddress(): 0.3}, {node.getnewaddress(): 49}], | outputs=[{node.getnewaddress(): 0.3}, {node.getnewaddress(): 49}], | ||||
))['hex'] | ))['hex'] | ||||
txid_in_block = node.sendrawtransaction( | txid_in_block = node.sendrawtransaction( | ||||
hexstring=raw_tx_in_block, allowhighfees=True) | hexstring=raw_tx_in_block, maxfeerate=0) | ||||
node.generate(1) | node.generate(1) | ||||
self.mempool_size = 0 | self.mempool_size = 0 | ||||
self.check_mempool_result( | self.check_mempool_result( | ||||
result_expected=[{'txid': txid_in_block, 'allowed': False, | result_expected=[{'txid': txid_in_block, 'allowed': False, | ||||
'reject-reason': '18: txn-already-known'}], | 'reject-reason': '18: txn-already-known'}], | ||||
rawtxs=[raw_tx_in_block], | rawtxs=[raw_tx_in_block], | ||||
) | ) | ||||
Show All 18 Lines | def run_test(self): | ||||
inputs=[{'txid': coin['txid'], 'vout': coin['vout'], | inputs=[{'txid': coin['txid'], 'vout': coin['vout'], | ||||
"sequence": 0xffffffff}], # SEQUENCE_FINAL | "sequence": 0xffffffff}], # SEQUENCE_FINAL | ||||
outputs=[{node.getnewaddress(): 0.025}], | outputs=[{node.getnewaddress(): 0.025}], | ||||
locktime=node.getblockcount() + 2000, # Can be anything | locktime=node.getblockcount() + 2000, # Can be anything | ||||
))['hex'] | ))['hex'] | ||||
tx = FromHex(CTransaction(), raw_tx_final) | tx = FromHex(CTransaction(), raw_tx_final) | ||||
self.check_mempool_result( | self.check_mempool_result( | ||||
result_expected=[{'txid': tx.rehash(), 'allowed': True}], | result_expected=[{'txid': tx.rehash(), 'allowed': True}], | ||||
rawtxs=[ToHex(tx)], | rawtxs=[tx.serialize().hex()], | ||||
allowhighfees=True, | maxfeerate=0, | ||||
) | ) | ||||
node.sendrawtransaction(hexstring=raw_tx_final, allowhighfees=True) | node.sendrawtransaction(hexstring=raw_tx_final, maxfeerate=0) | ||||
self.mempool_size += 1 | self.mempool_size += 1 | ||||
self.log.info('A transaction in the mempool') | self.log.info('A transaction in the mempool') | ||||
node.sendrawtransaction(hexstring=raw_tx_0) | node.sendrawtransaction(hexstring=raw_tx_0) | ||||
self.mempool_size += 1 | self.mempool_size += 1 | ||||
self.check_mempool_result( | self.check_mempool_result( | ||||
result_expected=[{'txid': txid_0, 'allowed': False, | result_expected=[{'txid': txid_0, 'allowed': False, | ||||
'reject-reason': '18: txn-already-in-mempool'}], | 'reject-reason': '18: txn-already-in-mempool'}], | ||||
rawtxs=[raw_tx_0], | rawtxs=[raw_tx_0], | ||||
) | ) | ||||
# Removed RBF test | # Removed RBF test | ||||
# self.log.info('A transaction that replaces a mempool transaction') | # self.log.info('A transaction that replaces a mempool transaction') | ||||
# ... | # ... | ||||
self.log.info('A transaction that conflicts with an unconfirmed tx') | self.log.info('A transaction that conflicts with an unconfirmed tx') | ||||
# Send the transaction that conflicts with the mempool transaction | # Send the transaction that conflicts with the mempool transaction | ||||
node.sendrawtransaction( | node.sendrawtransaction(hexstring=tx.serialize().hex(), maxfeerate=0) | ||||
hexstring=ToHex(tx), allowhighfees=True) | |||||
# take original raw_tx_0 | # take original raw_tx_0 | ||||
tx = FromHex(CTransaction(), raw_tx_0) | tx = FromHex(CTransaction(), raw_tx_0) | ||||
tx.vout[0].nValue -= int(4 * fee * COIN) # Set more fee | tx.vout[0].nValue -= int(4 * fee * COIN) # Set more fee | ||||
# skip re-signing the tx | # skip re-signing the tx | ||||
self.check_mempool_result( | self.check_mempool_result( | ||||
result_expected=[{'txid': tx.rehash( | result_expected=[{'txid': tx.rehash(), | ||||
), 'allowed': False, 'reject-reason': '18: txn-mempool-conflict'}], | 'allowed': False, | ||||
rawtxs=[ToHex(tx)], | 'reject-reason': '18: txn-mempool-conflict'}], | ||||
allowhighfees=True, | rawtxs=[tx.serialize().hex()], | ||||
maxfeerate=0, | |||||
) | ) | ||||
self.log.info('A transaction with missing inputs, that never existed') | self.log.info('A transaction with missing inputs, that never existed') | ||||
tx = FromHex(CTransaction(), raw_tx_0) | tx = FromHex(CTransaction(), raw_tx_0) | ||||
tx.vin[0].prevout = COutPoint(hash=int('ff' * 32, 16), n=14) | tx.vin[0].prevout = COutPoint(hash=int('ff' * 32, 16), n=14) | ||||
# skip re-signing the tx | # skip re-signing the tx | ||||
self.check_mempool_result( | self.check_mempool_result( | ||||
result_expected=[ | result_expected=[ | ||||
{'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'missing-inputs'}], | {'txid': tx.rehash(), 'allowed': False, 'reject-reason': 'missing-inputs'}], | ||||
rawtxs=[ToHex(tx)], | rawtxs=[ToHex(tx)], | ||||
) | ) | ||||
self.log.info( | self.log.info( | ||||
'A transaction with missing inputs, that existed once in the past') | 'A transaction with missing inputs, that existed once in the past') | ||||
tx = FromHex(CTransaction(), raw_tx_0) | tx = FromHex(CTransaction(), raw_tx_0) | ||||
# Set vout to 1, to spend the other outpoint (49 coins) of the | # Set vout to 1, to spend the other outpoint (49 coins) of the | ||||
# in-chain-tx we want to double spend | # in-chain-tx we want to double spend | ||||
tx.vin[0].prevout.n = 1 | tx.vin[0].prevout.n = 1 | ||||
raw_tx_1 = node.signrawtransactionwithwallet( | raw_tx_1 = node.signrawtransactionwithwallet( | ||||
ToHex(tx))['hex'] | ToHex(tx))['hex'] | ||||
txid_1 = node.sendrawtransaction( | txid_1 = node.sendrawtransaction(hexstring=raw_tx_1, maxfeerate=0) | ||||
hexstring=raw_tx_1, allowhighfees=True) | |||||
# Now spend both to "clearly hide" the outputs, ie. remove the coins | # Now spend both to "clearly hide" the outputs, ie. remove the coins | ||||
# from the utxo set by spending them | # from the utxo set by spending them | ||||
raw_tx_spend_both = node.signrawtransactionwithwallet(node.createrawtransaction( | raw_tx_spend_both = node.signrawtransactionwithwallet(node.createrawtransaction( | ||||
inputs=[ | inputs=[ | ||||
{'txid': txid_0, 'vout': 0}, | {'txid': txid_0, 'vout': 0}, | ||||
{'txid': txid_1, 'vout': 0}, | {'txid': txid_1, 'vout': 0}, | ||||
], | ], | ||||
outputs=[{node.getnewaddress(): 0.1}] | outputs=[{node.getnewaddress(): 0.1}] | ||||
))['hex'] | ))['hex'] | ||||
txid_spend_both = node.sendrawtransaction( | txid_spend_both = node.sendrawtransaction( | ||||
hexstring=raw_tx_spend_both, allowhighfees=True) | hexstring=raw_tx_spend_both, maxfeerate=0) | ||||
node.generate(1) | node.generate(1) | ||||
self.mempool_size = 0 | self.mempool_size = 0 | ||||
# Now see if we can add the coins back to the utxo set by sending the | # Now see if we can add the coins back to the utxo set by sending the | ||||
# exact txs again | # exact txs again | ||||
self.check_mempool_result( | self.check_mempool_result( | ||||
result_expected=[ | result_expected=[ | ||||
{'txid': txid_0, 'allowed': False, 'reject-reason': 'missing-inputs'}], | {'txid': txid_0, 'allowed': False, 'reject-reason': 'missing-inputs'}], | ||||
rawtxs=[raw_tx_0], | rawtxs=[raw_tx_0], | ||||
▲ Show 20 Lines • Show All 151 Lines • ▼ Show 20 Lines | def run_test(self): | ||||
self.log.info('A transaction that is locked by BIP68 sequence logic') | self.log.info('A transaction that is locked by BIP68 sequence logic') | ||||
tx = FromHex(CTransaction(), raw_tx_reference) | tx = FromHex(CTransaction(), raw_tx_reference) | ||||
# We could include it in the second block mined from now, but not the | # We could include it in the second block mined from now, but not the | ||||
# very next one | # very next one | ||||
tx.vin[0].nSequence = 2 | tx.vin[0].nSequence = 2 | ||||
# Can skip re-signing the tx because of early rejection | # Can skip re-signing the tx because of early rejection | ||||
self.check_mempool_result( | self.check_mempool_result( | ||||
result_expected=[ | result_expected=[{'txid': tx.rehash(), | ||||
{'txid': tx.rehash(), 'allowed': False, 'reject-reason': '64: non-BIP68-final'}], | 'allowed': False, | ||||
rawtxs=[ToHex(tx)], | 'reject-reason': '64: non-BIP68-final'}], | ||||
allowhighfees=True, | rawtxs=[tx.serialize().hex()], | ||||
maxfeerate=0, | |||||
) | ) | ||||
if __name__ == '__main__': | if __name__ == '__main__': | ||||
MempoolAcceptanceTest().main() | MempoolAcceptanceTest().main() |