|
18 | 18 | TIME_GENESIS_BLOCK,
|
19 | 19 | )
|
20 | 20 | from test_framework.messages import (
|
| 21 | + BLOCK_HEADER_SIZE, |
21 | 22 | CBlock,
|
22 | 23 | CBlockHeader,
|
23 |
| - BLOCK_HEADER_SIZE, |
| 24 | + COIN, |
24 | 25 | ser_uint256,
|
25 | 26 | )
|
26 | 27 | from test_framework.p2p import P2PDataStore
|
27 | 28 | from test_framework.test_framework import BitcoinTestFramework
|
28 | 29 | from test_framework.util import (
|
29 | 30 | assert_equal,
|
30 | 31 | assert_raises_rpc_error,
|
| 32 | + get_fee, |
31 | 33 | )
|
32 | 34 | from test_framework.wallet import MiniWallet
|
33 | 35 |
|
34 | 36 |
|
35 | 37 | VERSIONBITS_TOP_BITS = 0x20000000
|
36 | 38 | VERSIONBITS_DEPLOYMENT_TESTDUMMY_BIT = 28
|
| 39 | +DEFAULT_BLOCK_MIN_TX_FEE = 1000 # default `-blockmintxfee` setting [sat/kvB] |
37 | 40 |
|
38 | 41 |
|
39 | 42 | def assert_template(node, block, expect, rehash=True):
|
@@ -73,6 +76,45 @@ def mine_chain(self):
|
73 | 76 | self.restart_node(0)
|
74 | 77 | self.connect_nodes(0, 1)
|
75 | 78 |
|
| 79 | + def test_blockmintxfee_parameter(self): |
| 80 | + self.log.info("Test -blockmintxfee setting") |
| 81 | + self.restart_node(0, extra_args=['-minrelaytxfee=0', '-persistmempool=0']) |
| 82 | + node = self.nodes[0] |
| 83 | + |
| 84 | + # test default (no parameter), zero and a bunch of arbitrary blockmintxfee rates [sat/kvB] |
| 85 | + for blockmintxfee_sat_kvb in (DEFAULT_BLOCK_MIN_TX_FEE, 0, 50, 100, 500, 2500, 5000, 21000, 333333, 2500000): |
| 86 | + blockmintxfee_btc_kvb = blockmintxfee_sat_kvb / Decimal(COIN) |
| 87 | + if blockmintxfee_sat_kvb == DEFAULT_BLOCK_MIN_TX_FEE: |
| 88 | + self.log.info(f"-> Default -blockmintxfee setting ({blockmintxfee_sat_kvb} sat/kvB)...") |
| 89 | + else: |
| 90 | + blockmintxfee_parameter = f"-blockmintxfee={blockmintxfee_btc_kvb:.8f}" |
| 91 | + self.log.info(f"-> Test {blockmintxfee_parameter} ({blockmintxfee_sat_kvb} sat/kvB)...") |
| 92 | + self.restart_node(0, extra_args=[blockmintxfee_parameter, '-minrelaytxfee=0', '-persistmempool=0']) |
| 93 | + self.wallet.rescan_utxos() # to avoid spending outputs of txs that are not in mempool anymore after restart |
| 94 | + |
| 95 | + # submit one tx with exactly the blockmintxfee rate, and one slightly below |
| 96 | + tx_with_min_feerate = self.wallet.send_self_transfer(from_node=node, fee_rate=blockmintxfee_btc_kvb) |
| 97 | + assert_equal(tx_with_min_feerate["fee"], get_fee(tx_with_min_feerate["tx"].get_vsize(), blockmintxfee_btc_kvb)) |
| 98 | + if blockmintxfee_btc_kvb > 0: |
| 99 | + lowerfee_btc_kvb = blockmintxfee_btc_kvb - Decimal(10)/COIN # 0.01 sat/vbyte lower |
| 100 | + tx_below_min_feerate = self.wallet.send_self_transfer(from_node=node, fee_rate=lowerfee_btc_kvb) |
| 101 | + assert_equal(tx_below_min_feerate["fee"], get_fee(tx_below_min_feerate["tx"].get_vsize(), lowerfee_btc_kvb)) |
| 102 | + else: # go below zero fee by using modified fees |
| 103 | + tx_below_min_feerate = self.wallet.send_self_transfer(from_node=node, fee_rate=blockmintxfee_btc_kvb) |
| 104 | + node.prioritisetransaction(tx_below_min_feerate["txid"], 0, -1) |
| 105 | + |
| 106 | + # check that tx below specified fee-rate is neither in template nor in the actual block |
| 107 | + block_template = node.getblocktemplate(NORMAL_GBT_REQUEST_PARAMS) |
| 108 | + block_template_txids = [tx['txid'] for tx in block_template['transactions']] |
| 109 | + self.generate(self.wallet, 1, sync_fun=self.no_op) |
| 110 | + block = node.getblock(node.getbestblockhash(), verbosity=2) |
| 111 | + block_txids = [tx['txid'] for tx in block['tx']] |
| 112 | + |
| 113 | + assert tx_with_min_feerate['txid'] in block_template_txids |
| 114 | + assert tx_with_min_feerate['txid'] in block_txids |
| 115 | + assert tx_below_min_feerate['txid'] not in block_template_txids |
| 116 | + assert tx_below_min_feerate['txid'] not in block_txids |
| 117 | + |
76 | 118 | def run_test(self):
|
77 | 119 | node = self.nodes[0]
|
78 | 120 | self.wallet = MiniWallet(node)
|
@@ -279,6 +321,8 @@ def chain_tip(b_hash, *, status='headers-only', branchlen=1):
|
279 | 321 | node.submitheader(hexdata=CBlockHeader(bad_block_root).serialize().hex())
|
280 | 322 | assert_equal(node.submitblock(hexdata=block.serialize().hex()), 'duplicate') # valid
|
281 | 323 |
|
| 324 | + self.test_blockmintxfee_parameter() |
| 325 | + |
282 | 326 |
|
283 | 327 | if __name__ == '__main__':
|
284 | 328 | MiningTest().main()
|
0 commit comments