Skip to content

Commit 2b7a453

Browse files
authored
promote block-creation setting to user-facing (#19545)
* make the mempool block creation more configurable * update tests to cover both block creation functions
1 parent 5617026 commit 2b7a453

File tree

7 files changed

+110
-76
lines changed

7 files changed

+110
-76
lines changed

benchmarks/mempool.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ async def add_spend_bundles(spend_bundles: list[SpendBundle]) -> None:
243243
with enable_profiler(True, f"create-{suffix}"):
244244
start = monotonic()
245245
for _ in range(10):
246-
mempool.create_block_generator(last_tb_header_hash=rec.header_hash)
246+
mempool.create_block_generator(rec.header_hash, 2.0)
247247
stop = monotonic()
248248
print(f" time: {stop - start:0.4f}s")
249249
print(f" per call: {(stop - start) / 10 * 1000:0.2f}ms")
@@ -252,7 +252,7 @@ async def add_spend_bundles(spend_bundles: list[SpendBundle]) -> None:
252252
with enable_profiler(True, f"create2-{suffix}"):
253253
start = monotonic()
254254
for _ in range(10):
255-
mempool.create_block_generator2(last_tb_header_hash=rec.header_hash)
255+
mempool.create_block_generator2(rec.header_hash, 2.0)
256256
stop = monotonic()
257257
print(f" time: {stop - start:0.4f}s")
258258
print(f" per call: {(stop - start) / 10 * 1000:0.2f}ms")

chia/_tests/core/full_node/test_full_node.py

Lines changed: 77 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import pytest
1313
from chia_rs import (
1414
AugSchemeMPL,
15+
ConsensusConstants,
1516
Foliage,
1617
FoliageTransactionBlock,
1718
FullBlock,
@@ -38,7 +39,11 @@
3839
from chia._tests.core.make_block_generator import make_spend_bundle
3940
from chia._tests.core.node_height import node_height_at_least
4041
from chia._tests.util.misc import wallet_height_at_least
41-
from chia._tests.util.setup_nodes import OldSimulatorsAndWallets, SimulatorsAndWalletsServices
42+
from chia._tests.util.setup_nodes import (
43+
OldSimulatorsAndWallets,
44+
SimulatorsAndWalletsServices,
45+
setup_simulators_and_wallets,
46+
)
4247
from chia._tests.util.time_out_assert import time_out_assert, time_out_assert_custom_interval, time_out_messages
4348
from chia.consensus.augmented_chain import AugmentedBlockchain
4449
from chia.consensus.block_body_validation import ForkInfo
@@ -2912,87 +2917,97 @@ async def test_eviction_from_bls_cache(one_node_one_block: tuple[FullNodeSimulat
29122917

29132918

29142919
@pytest.mark.limit_consensus_modes(allowed=[ConsensusMode.HARD_FORK_2_0], reason="irrelevant")
2920+
@pytest.mark.parametrize("block_creation", [0, 1, 2])
29152921
@pytest.mark.anyio
29162922
async def test_declare_proof_of_space_no_overflow(
2917-
wallet_nodes: tuple[
2918-
FullNodeSimulator, FullNodeSimulator, ChiaServer, ChiaServer, WalletTool, WalletTool, BlockTools
2919-
],
2923+
blockchain_constants: ConsensusConstants,
29202924
self_hostname: str,
2921-
bt: BlockTools,
2925+
block_creation: int,
29222926
) -> None:
2923-
full_node_api, _, server_1, _, _, _, _ = wallet_nodes
2924-
wallet = WalletTool(test_constants)
2925-
coinbase_puzzlehash = wallet.get_new_puzzlehash()
2926-
blocks = bt.get_consecutive_blocks(
2927-
num_blocks=10,
2928-
skip_overflow=True,
2929-
force_overflow=False,
2930-
farmer_reward_puzzle_hash=coinbase_puzzlehash,
2931-
guarantee_transaction_block=True,
2932-
)
2933-
await add_blocks_in_batches(blocks, full_node_api.full_node)
2934-
_, dummy_node_id = await add_dummy_connection(server_1, self_hostname, 12312)
2935-
dummy_peer = server_1.all_connections[dummy_node_id]
2936-
assert full_node_api.full_node.blockchain.get_peak_height() == blocks[-1].height
2937-
for i in range(10, 100):
2938-
sb = await add_tx_to_mempool(
2939-
full_node_api, wallet, blocks[-8], coinbase_puzzlehash, bytes32(i.to_bytes(32, "big")), uint64(i)
2940-
)
2927+
async with setup_simulators_and_wallets(
2928+
1, 1, blockchain_constants, config_overrides={"full_node.block_creation": block_creation}
2929+
) as new:
2930+
full_node_api = new.simulators[0].peer_api
2931+
server_1 = full_node_api.full_node.server
2932+
bt = new.bt
2933+
2934+
wallet = WalletTool(test_constants)
2935+
coinbase_puzzlehash = wallet.get_new_puzzlehash()
29412936
blocks = bt.get_consecutive_blocks(
2942-
block_list_input=blocks,
2943-
num_blocks=1,
2937+
num_blocks=10,
2938+
skip_overflow=True,
2939+
force_overflow=False,
29442940
farmer_reward_puzzle_hash=coinbase_puzzlehash,
29452941
guarantee_transaction_block=True,
2946-
transaction_data=sb,
29472942
)
2948-
block = blocks[-1]
2949-
unfinised_block = await declare_pos_unfinished_block(full_node_api, dummy_peer, block)
2950-
compare_unfinished_blocks(unfinished_from_full_block(block), unfinised_block)
2951-
await full_node_api.full_node.add_block(block)
2952-
assert full_node_api.full_node.blockchain.get_peak_height() == block.height
2943+
await add_blocks_in_batches(blocks, full_node_api.full_node)
2944+
_, dummy_node_id = await add_dummy_connection(server_1, self_hostname, 12312)
2945+
dummy_peer = server_1.all_connections[dummy_node_id]
2946+
assert full_node_api.full_node.blockchain.get_peak_height() == blocks[-1].height
2947+
for i in range(10, 100):
2948+
sb = await add_tx_to_mempool(
2949+
full_node_api, wallet, blocks[-8], coinbase_puzzlehash, bytes32(i.to_bytes(32, "big")), uint64(i)
2950+
)
2951+
blocks = bt.get_consecutive_blocks(
2952+
block_list_input=blocks,
2953+
num_blocks=1,
2954+
farmer_reward_puzzle_hash=coinbase_puzzlehash,
2955+
guarantee_transaction_block=True,
2956+
transaction_data=sb,
2957+
)
2958+
block = blocks[-1]
2959+
unfinised_block = await declare_pos_unfinished_block(full_node_api, dummy_peer, block)
2960+
compare_unfinished_blocks(unfinished_from_full_block(block), unfinised_block)
2961+
await full_node_api.full_node.add_block(block)
2962+
assert full_node_api.full_node.blockchain.get_peak_height() == block.height
29532963

29542964

29552965
@pytest.mark.limit_consensus_modes(allowed=[ConsensusMode.HARD_FORK_2_0], reason="irrelevant")
2966+
@pytest.mark.parametrize("block_creation", [0, 1, 2])
29562967
@pytest.mark.anyio
29572968
async def test_declare_proof_of_space_overflow(
2958-
wallet_nodes: tuple[
2959-
FullNodeSimulator, FullNodeSimulator, ChiaServer, ChiaServer, WalletTool, WalletTool, BlockTools
2960-
],
2969+
blockchain_constants: ConsensusConstants,
29612970
self_hostname: str,
2962-
bt: BlockTools,
2971+
block_creation: int,
29632972
) -> None:
2964-
full_node_api, _, server_1, _, _, _, _ = wallet_nodes
2965-
wallet = WalletTool(test_constants)
2966-
coinbase_puzzlehash = wallet.get_new_puzzlehash()
2967-
blocks = bt.get_consecutive_blocks(
2968-
num_blocks=10,
2969-
farmer_reward_puzzle_hash=coinbase_puzzlehash,
2970-
guarantee_transaction_block=True,
2971-
)
2972-
await add_blocks_in_batches(blocks, full_node_api.full_node)
2973-
_, dummy_node_id = await add_dummy_connection(server_1, self_hostname, 12312)
2974-
dummy_peer = server_1.all_connections[dummy_node_id]
2975-
assert full_node_api.full_node.blockchain.get_peak_height() == blocks[-1].height
2976-
for i in range(10, 100):
2977-
sb = await add_tx_to_mempool(
2978-
full_node_api, wallet, blocks[-8], coinbase_puzzlehash, bytes32(i.to_bytes(32, "big")), uint64(i)
2979-
)
2980-
2973+
async with setup_simulators_and_wallets(
2974+
1, 1, blockchain_constants, config_overrides={"full_node.block_creation": block_creation}
2975+
) as new:
2976+
full_node_api = new.simulators[0].peer_api
2977+
server_1 = full_node_api.full_node.server
2978+
bt = new.bt
2979+
2980+
wallet = WalletTool(test_constants)
2981+
coinbase_puzzlehash = wallet.get_new_puzzlehash()
29812982
blocks = bt.get_consecutive_blocks(
2982-
block_list_input=blocks,
2983-
num_blocks=1,
2984-
skip_overflow=False,
2985-
force_overflow=(i % 10 == 0),
2983+
num_blocks=10,
29862984
farmer_reward_puzzle_hash=coinbase_puzzlehash,
29872985
guarantee_transaction_block=True,
2988-
transaction_data=sb,
29892986
)
2987+
await add_blocks_in_batches(blocks, full_node_api.full_node)
2988+
_, dummy_node_id = await add_dummy_connection(server_1, self_hostname, 12312)
2989+
dummy_peer = server_1.all_connections[dummy_node_id]
2990+
assert full_node_api.full_node.blockchain.get_peak_height() == blocks[-1].height
2991+
for i in range(10, 100):
2992+
sb = await add_tx_to_mempool(
2993+
full_node_api, wallet, blocks[-8], coinbase_puzzlehash, bytes32(i.to_bytes(32, "big")), uint64(i)
2994+
)
2995+
2996+
blocks = bt.get_consecutive_blocks(
2997+
block_list_input=blocks,
2998+
num_blocks=1,
2999+
skip_overflow=False,
3000+
force_overflow=(i % 10 == 0),
3001+
farmer_reward_puzzle_hash=coinbase_puzzlehash,
3002+
guarantee_transaction_block=True,
3003+
transaction_data=sb,
3004+
)
29903005

2991-
block = blocks[-1]
2992-
unfinised_block = await declare_pos_unfinished_block(full_node_api, dummy_peer, block)
2993-
compare_unfinished_blocks(unfinished_from_full_block(block), unfinised_block)
2994-
await full_node_api.full_node.add_block(block)
2995-
assert full_node_api.full_node.blockchain.get_peak_height() == block.height
3006+
block = blocks[-1]
3007+
unfinised_block = await declare_pos_unfinished_block(full_node_api, dummy_peer, block)
3008+
compare_unfinished_blocks(unfinished_from_full_block(block), unfinised_block)
3009+
await full_node_api.full_node.add_block(block)
3010+
assert full_node_api.full_node.blockchain.get_peak_height() == block.height
29963011

29973012

29983013
@pytest.mark.anyio

chia/_tests/core/mempool/test_mempool_manager.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2979,7 +2979,7 @@ async def test_check_removals_with_block_creation(flags: int, old: bool) -> None
29792979
assert bundle_add_info2.status == MempoolInclusionStatus.SUCCESS
29802980
assert mempool_manager.peak is not None
29812981
create_block = mempool_manager.create_block_generator if old else mempool_manager.create_block_generator2
2982-
new_block_gen = create_block(mempool_manager.peak.header_hash)
2982+
new_block_gen = create_block(mempool_manager.peak.header_hash, 10.0)
29832983
assert new_block_gen is not None
29842984
assert len(new_block_gen.additions) == 1
29852985
assert set(new_block_gen.additions) == {

chia/full_node/full_node_api.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -865,13 +865,18 @@ async def declare_proof_of_space(
865865
curr_l_tb = self.full_node.blockchain.block_record(curr_l_tb.prev_hash)
866866
try:
867867
# TODO: once we're confident in the new block creation,
868-
# switch to it by default
869-
if self.full_node.config.get("original_block_creation", True):
868+
# make it default to 1
869+
block_version = self.full_node.config.get("block_creation", 0)
870+
block_timeout = self.full_node.config.get("block_creation_timeout", 2.0)
871+
if block_version == 0:
870872
create_block = self.full_node.mempool_manager.create_block_generator
871-
else:
873+
elif block_version == 1:
872874
create_block = self.full_node.mempool_manager.create_block_generator2
875+
else:
876+
self.log.warning(f"Unknown 'block_creation' config: {block_version}")
877+
create_block = self.full_node.mempool_manager.create_block_generator
873878

874-
new_block_gen = create_block(curr_l_tb.header_hash)
879+
new_block_gen = create_block(curr_l_tb.header_hash, block_timeout)
875880

876881
if (
877882
new_block_gen is not None and peak.height < self.full_node.constants.HARD_FORK_HEIGHT

chia/full_node/mempool_manager.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -370,17 +370,15 @@ def create_bundle_from_mempool(self, last_tb_header_hash: bytes32) -> Optional[t
370370
return None
371371
return self.mempool.create_bundle_from_mempool_items(self.constants, self.peak.height)
372372

373-
def create_block_generator(self, last_tb_header_hash: bytes32, timeout: float = 2.0) -> Optional[NewBlockGenerator]:
373+
def create_block_generator(self, last_tb_header_hash: bytes32, timeout: float) -> Optional[NewBlockGenerator]:
374374
"""
375375
Returns a block generator program, the aggregate signature and all additions and removals, for a new block
376376
"""
377377
if self.peak is None or self.peak.header_hash != last_tb_header_hash:
378378
return None
379379
return self.mempool.create_block_generator(self.constants, self.peak.height, timeout)
380380

381-
def create_block_generator2(
382-
self, last_tb_header_hash: bytes32, timeout: float = 2.0
383-
) -> Optional[NewBlockGenerator]:
381+
def create_block_generator2(self, last_tb_header_hash: bytes32, timeout: float) -> Optional[NewBlockGenerator]:
384382
"""
385383
Returns a block generator program, the aggregate signature and all additions, for a new block
386384
"""
@@ -560,12 +558,13 @@ async def validate_spend_bundle(
560558
get_unspent_lineage_info_for_puzzle_hash: Callable[[bytes32], Awaitable[Optional[UnspentLineageInfo]]],
561559
) -> tuple[Optional[Err], Optional[MempoolItem], list[bytes32]]:
562560
"""
563-
Validates new_spend with the given NPCResult, and spend_name, and the current mempool. The mempool should
561+
Validates new_spend with the given SpendBundleConditions, and
562+
spend_name, and the current mempool. The mempool should
564563
be locked during this call (blockchain lock).
565564
566565
Args:
567566
new_spend: spend bundle to validate
568-
conds: result of running the clvm transaction in a fake block
567+
conds: result of running the clvm transaction
569568
spend_name: hash of the spend bundle data, passed in as an optimization
570569
first_added_height: The block height that `new_spend` first entered this node's mempool.
571570
Used to estimate how long a spend has taken to be included on the chain.

chia/rpc/full_node_rpc_api.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -869,7 +869,7 @@ async def create_block_generator(self, _: dict[str, Any]) -> EndpointResult:
869869
start_time = time.monotonic()
870870

871871
try:
872-
maybe_gen = self.service.mempool_manager.create_block_generator2(curr_l_tb.header_hash)
872+
maybe_gen = self.service.mempool_manager.create_block_generator2(curr_l_tb.header_hash, 2.0)
873873
if maybe_gen is None:
874874
self.service.log.error(f"failed to create block generator, peak: {peak}")
875875
else:

chia/util/initial-config.yaml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,21 @@ full_node:
305305
# the particular system we're running on. Defaults to "full".
306306
db_sync: "auto"
307307

308+
# Determine which version of block creation function to use:
309+
# 0: Original function, first fill a block with transactions, then compress
310+
# it, then run it to compute its cost. The final block may not use all
311+
# available block cost.
312+
# 1: Compressed block function. Compress transactions into the block as they
313+
# are added. Use the new, optimized, compression function. This produces
314+
# blocks that fill up the allowed block cost.
315+
316+
# block_creation: 0
317+
318+
# If we spend more than this many seconds forming the new transactions block
319+
# generator, stop and just go with what we have so far. This is a safety
320+
# measure to not spend too much time building the block generator.
321+
# block_creation_timeout: 2.0
322+
308323
# the number of threads used to read from the blockchain database
309324
# concurrently. There's always only 1 writer, but the number of readers is
310325
# configurable

0 commit comments

Comments
 (0)