Changeset View
Changeset View
Standalone View
Standalone View
test/functional/abc-sigops-mempool-mining.py
Show All 27 Lines | from test_framework.messages import ( | ||||
CTxOut, | CTxOut, | ||||
FromHex, | FromHex, | ||||
ToHex, | ToHex, | ||||
) | ) | ||||
from test_framework.mininode import ( | from test_framework.mininode import ( | ||||
P2PDataStore, | P2PDataStore, | ||||
) | ) | ||||
from test_framework.script import ( | from test_framework.script import ( | ||||
OP_CHECKSIG, | |||||
OP_CHECKMULTISIG, | OP_CHECKMULTISIG, | ||||
OP_RETURN, | OP_RETURN, | ||||
OP_TRUE, | OP_TRUE, | ||||
) | ) | ||||
from test_framework.test_framework import BitcoinTestFramework | from test_framework.test_framework import BitcoinTestFramework | ||||
from test_framework.util import ( | from test_framework.util import ( | ||||
assert_equal, | assert_equal, | ||||
assert_raises_rpc_error, | assert_raises_rpc_error, | ||||
▲ Show 20 Lines • Show All 137 Lines • ▼ Show 20 Lines | def run_test(self): | ||||
txid_child = node.sendrawtransaction(ToHex(ctx_child)) | txid_child = node.sendrawtransaction(ToHex(ctx_child)) | ||||
# make one with 270 sat/byte, but only 0.4 sat/vbyte. | # make one with 270 sat/byte, but only 0.4 sat/vbyte. | ||||
ctx = create_var_transaction( | ctx = create_var_transaction( | ||||
self.spendable_outputs.popleft(), script_4000_sigops, 300, 80000) | self.spendable_outputs.popleft(), script_4000_sigops, 300, 80000) | ||||
txid_highsigops = node.sendrawtransaction(ToHex(ctx)) | txid_highsigops = node.sendrawtransaction(ToHex(ctx)) | ||||
self.log.info( | self.log.info( | ||||
"Create a mixed-sigops package where child would be low sat/vbyte in isolation.") | |||||
# Parent is 0-sigops at 1.5 sat/byte. | |||||
ctx = create_var_transaction( | |||||
self.spendable_outputs.popleft(), b'', 1000, 1500) | |||||
txid_parent2 = node.sendrawtransaction(ToHex(ctx)) | |||||
# Child is 0.32 sat/vbyte in isolation (400 sat / 1250 vbyte), but | |||||
# incrementally is 1.6 sat/vbyte (+400 sat / +250 vbyte). Whole package | |||||
# is 1.52 sat/vbyte (1900 sat / 1250 vbyte). | |||||
script_25_sigops = bytes([OP_CHECKSIG] * 25) | |||||
ctx_child = create_var_transaction(ctx, | |||||
script_25_sigops, 200, 400) | |||||
txid_child2 = node.sendrawtransaction(ToHex(ctx_child)) | |||||
self.log.info( | |||||
"Flood the mempool with 10-kB transactions @ 9.9 sat/byte and 0.495 sat/vbyte, until it is full") | "Flood the mempool with 10-kB transactions @ 9.9 sat/byte and 0.495 sat/vbyte, until it is full") | ||||
# About 500 should fill up our 5 MB mempool. | # About 500 should fill up our 5 MB mempool. | ||||
# Note that even starting from an empty pool, somewhat fewer than 500 | # Note that even starting from an empty pool, somewhat fewer than 500 | ||||
# would be accepted depending on mempool data structure sizes. | # would be accepted depending on mempool data structure sizes. | ||||
for i in range(500): | for i in range(500): | ||||
spendfrom = self.spendable_outputs.popleft() | spendfrom = self.spendable_outputs.popleft() | ||||
ctx = create_var_transaction( | ctx = create_var_transaction( | ||||
spendfrom, script_4000_sigops, 10000, 99000) | spendfrom, script_4000_sigops, 10000, 99000) | ||||
Show All 13 Lines | def run_test(self): | ||||
mempool_txids = set(node.getrawmempool()) | mempool_txids = set(node.getrawmempool()) | ||||
# The 9.9 sat/byte txes caused the 270 sat/byte tx to get evicted, because | # The 9.9 sat/byte txes caused the 270 sat/byte tx to get evicted, because | ||||
# the latter was more dense in sigops. | # the latter was more dense in sigops. | ||||
assert txid_highsigops not in mempool_txids | assert txid_highsigops not in mempool_txids | ||||
# Other txes did get kept, including txid_parent which had ultralow | # Other txes did get kept, including txid_parent which had ultralow | ||||
# virtual feerate (but its child supplied enough fee). | # virtual feerate (but its child supplied enough fee), and txid_child2 | ||||
settxids = set([txid1, txid_parent, txid_child]) | # where its high sigops density was cancelled by its low sigops parent. | ||||
settxids = set([txid1, txid_parent, txid_child, | |||||
txid_parent2, txid_child2]) | |||||
assert_equal(settxids.difference(mempool_txids), set()) | assert_equal(settxids.difference(mempool_txids), set()) | ||||
self.log.info('Mempool fee floor has jumped to 1.495 sat/vbyte') | self.log.info('Mempool fee floor has jumped to 1.495 sat/vbyte') | ||||
# The removed txes have feerate 495 sat/kvbyte and the fee floor jumps by | # The removed txes have feerate 495 sat/kvbyte and the fee floor jumps by | ||||
# 1000 sat/kbyte (MEMPOOL_FULL_FEE_INCREMENT) on top of that: | # 1000 sat/kbyte (MEMPOOL_FULL_FEE_INCREMENT) on top of that: | ||||
assert_equal(node.getmempoolinfo()[ | assert_equal(node.getmempoolinfo()[ | ||||
'mempoolminfee'], Decimal('0.00001495')) | 'mempoolminfee'], Decimal('0.00001495')) | ||||
self.log.info( | self.log.info( | ||||
"Try a child with low sat/vbyte the same way now.") | |||||
# Parent is 0-sigops at 1.5 sat/byte. | |||||
ctx = create_var_transaction( | |||||
self.spendable_outputs.popleft(), b'', 1000, 1500) | |||||
txid_parent3 = node.sendrawtransaction(ToHex(ctx)) | |||||
# Child is 0.32 sat/vbyte in isolation (400 sat / 1250 vbyte), which | |||||
# causes it to be rejected, even though incrementally it would be 1.6 | |||||
# sat/vbyte (+400 sat / +250 vbyte) and it wouldn't be evicted if it had | |||||
# gotten in before the flooding (see txid_child2). | |||||
ctx_child = create_var_transaction(ctx, | |||||
script_25_sigops, 200, 400) | |||||
assert_raises_rpc_error(-26, "mempool min fee not met", node.sendrawtransaction, | |||||
ToHex(ctx_child)) | |||||
settxids.add(txid_parent3) | |||||
self.log.info( | |||||
'Broadcasting a regular tx still works, because wallet knows what fee to use.') | 'Broadcasting a regular tx still works, because wallet knows what fee to use.') | ||||
txid2 = node.sendtoaddress(node.getnewaddress(), 0.001) | txid2 = node.sendtoaddress(node.getnewaddress(), 0.001) | ||||
settxids.add(txid2) | settxids.add(txid2) | ||||
self.log.info( | self.log.info( | ||||
"But, a regular 1 sat/byte transaction can't get in now.") | "But, a regular 1 sat/byte transaction can't get in now.") | ||||
spendfrom = self.spendable_outputs.popleft() | spendfrom = self.spendable_outputs.popleft() | ||||
assert_raises_rpc_error(-26, "mempool min fee not met", node.sendrawtransaction, | assert_raises_rpc_error(-26, "mempool min fee not met", node.sendrawtransaction, | ||||
▲ Show 20 Lines • Show All 84 Lines • Show Last 20 Lines |