Skip to content

Commit

Permalink
remove the block fill rate limit of 70% when farming a block (#19005)
Browse files Browse the repository at this point in the history
* remove the block fill rate limit of 70% when farming a block

* Addendum to 100% block fill rate. (#19006)

* break down 'magic number' in test into its components

* Attempt to clarify why we add many aggsig conditions in make_and_send_big_cost_sb (#19026)

Attempt to clarify why we add many aggsig conditions in make_and_send_big_cost_sb.

---------

Co-authored-by: Amine Khaldi <[email protected]>
  • Loading branch information
arvidn and AmineKhaldi authored Dec 12, 2024
1 parent beff6e2 commit 1a1209c
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 21 deletions.
64 changes: 45 additions & 19 deletions chia/_tests/core/mempool/test_mempool_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from chia._tests.conftest import ConsensusMode
from chia._tests.util.misc import invariant_check_mempool
from chia._tests.util.setup_nodes import OldSimulatorsAndWallets, setup_simulators_and_wallets
from chia.consensus.condition_costs import ConditionCost
from chia.consensus.constants import ConsensusConstants
from chia.consensus.default_constants import DEFAULT_CONSTANTS
from chia.full_node.mempool import MAX_SKIPPED_ITEMS, PRIORITY_TX_THRESHOLD
Expand Down Expand Up @@ -170,7 +171,7 @@ async def get_coin_records(coin_ids: Collection[bytes32]) -> list[CoinRecord]:

constants = DEFAULT_CONSTANTS
if max_block_clvm_cost is not None:
constants = constants.replace(MAX_BLOCK_COST_CLVM=uint64(max_block_clvm_cost))
constants = constants.replace(MAX_BLOCK_COST_CLVM=uint64(max_block_clvm_cost + TEST_BLOCK_OVERHEAD))
if mempool_block_buffer is not None:
constants = constants.replace(MEMPOOL_BLOCK_BUFFER=uint8(mempool_block_buffer))
mempool_manager = await instantiate_mempool_manager(
Expand Down Expand Up @@ -1036,36 +1037,63 @@ async def send_spends_to_mempool(coin_spends: list[CoinSpend]) -> None:
@pytest.mark.parametrize("num_skipped_items", [PRIORITY_TX_THRESHOLD, MAX_SKIPPED_ITEMS])
@pytest.mark.anyio
async def test_create_bundle_from_mempool_on_max_cost(num_skipped_items: int, caplog: pytest.LogCaptureFixture) -> None:
"""
This test exercises the path where an item's inclusion would exceed the
maximum cumulative cost, so it gets skipped as a result.
NOTE:
1. After PRIORITY_TX_THRESHOLD, we skip items with eligible coins.
2. After skipping MAX_SKIPPED_ITEMS, we stop processing further items.
"""

async def get_unspent_lineage_info_for_puzzle_hash(_: bytes32) -> Optional[UnspentLineageInfo]:
assert False # pragma: no cover

# This test exercises the path where an item's inclusion would exceed the
# maximum cumulative cost, so it gets skipped as a result
MAX_BLOCK_CLVM_COST = 550_000_000

# NOTE:
# 1. After PRIORITY_TX_THRESHOLD, we skip items with eligible coins.
# 2. After skipping MAX_SKIPPED_ITEMS, we stop processing further items.
mempool_manager, coins = await setup_mempool_with_coins(
coin_amounts=list(range(1_000_000_000, 1_000_000_030)),
max_block_clvm_cost=MAX_BLOCK_CLVM_COST,
max_tx_clvm_cost=uint64(MAX_BLOCK_CLVM_COST),
mempool_block_buffer=20,
)

async def make_and_send_big_cost_sb(coin: Coin) -> None:
"""
Creates a spend bundle with a big enough cost that gets it close to the
maximum block clvm cost limit.
"""
conditions = []
sk = AugSchemeMPL.key_gen(b"7" * 32)
g1 = sk.get_g1()
sig = AugSchemeMPL.sign(sk, IDENTITY_PUZZLE_HASH, g1)
aggsig = G2Element()
for _ in range(169):
# Let's get as close to `MAX_BLOCK_CLVM_COST` (550_000_000) as possible.
# We start by accounting for execution cost
spend_bundle_cost = 44
# And then the created coin
conditions.append([ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, coin.amount - 10_000_000])
TEST_CREATE_COIN_SPEND_BYTESIZE = 93
TEST_CREATE_COIN_CONDITION_COST = (
ConditionCost.CREATE_COIN.value + TEST_CREATE_COIN_SPEND_BYTESIZE * DEFAULT_CONSTANTS.COST_PER_BYTE
)
spend_bundle_cost += TEST_CREATE_COIN_CONDITION_COST
# We're using agg sig conditions to increase the spend bundle's cost
# and reach our target cost.
TEST_AGG_SIG_SPEND_BYTESIZE = 88
TEST_AGGSIG_CONDITION_COST = (
ConditionCost.AGG_SIG.value + TEST_AGG_SIG_SPEND_BYTESIZE * DEFAULT_CONSTANTS.COST_PER_BYTE
)
while spend_bundle_cost + TEST_AGGSIG_CONDITION_COST < MAX_BLOCK_CLVM_COST:
conditions.append([ConditionOpcode.AGG_SIG_UNSAFE, g1, IDENTITY_PUZZLE_HASH])
aggsig += sig
conditions.append([ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, coin.amount - 10_000_000])
# Create a spend bundle with a big enough cost that gets it close to the limit
spend_bundle_cost += TEST_AGGSIG_CONDITION_COST
# We now have a spend bundle with a big enough cost that gets it close to the limit
_, _, res = await generate_and_add_spendbundle(mempool_manager, conditions, coin, aggsig)
assert res[1] == MempoolInclusionStatus.SUCCESS
cost, status, _ = res
assert status == MempoolInclusionStatus.SUCCESS
assert cost == spend_bundle_cost

mempool_manager, coins = await setup_mempool_with_coins(
coin_amounts=list(range(1_000_000_000, 1_000_000_030)),
max_block_clvm_cost=550_000_000,
max_tx_clvm_cost=uint64(550_000_000),
mempool_block_buffer=20,
)
# Create the spend bundles with a big enough cost that they get close to the limit
for i in range(num_skipped_items):
await make_and_send_big_cost_sb(coins[i])
Expand Down Expand Up @@ -2016,9 +2044,7 @@ async def fill_mempool_with_test_sbs(
# and without them we won't be able to get the test bundle in.
# This defaults to `MAX_BLOCK_COST_CLVM // 2`
full_node_api.full_node._mempool_manager.max_tx_clvm_cost = max_block_clvm_cost
# This defaults to `MAX_BLOCK_COST_CLVM * BLOCK_SIZE_LIMIT_FACTOR`
# TODO: Revisit this when we eventually raise the fille rate to 100%
# and `BLOCK_SIZE_LIMIT_FACTOR` is no longer relevant.
# This defaults to `MAX_BLOCK_COST_CLVM - BLOCK_OVERHEAD`
full_node_api.full_node._mempool_manager.mempool.mempool_info = dataclasses.replace(
full_node_api.full_node._mempool_manager.mempool.mempool_info,
max_block_clvm_cost=CLVMCost(max_block_clvm_cost),
Expand Down
3 changes: 1 addition & 2 deletions chia/full_node/mempool_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,12 +162,11 @@ def __init__(
# spends.
self.nonzero_fee_minimum_fpc = 5

BLOCK_SIZE_LIMIT_FACTOR = 0.7
# We need to deduct the block overhead, which consists of the wrapping
# quote opcode's bytes cost as well as its execution cost.
BLOCK_OVERHEAD = QUOTE_BYTES * self.constants.COST_PER_BYTE + QUOTE_EXECUTION_COST

self.max_block_clvm_cost = uint64(self.constants.MAX_BLOCK_COST_CLVM * BLOCK_SIZE_LIMIT_FACTOR - BLOCK_OVERHEAD)
self.max_block_clvm_cost = uint64(self.constants.MAX_BLOCK_COST_CLVM - BLOCK_OVERHEAD)
self.max_tx_clvm_cost = (
max_tx_clvm_cost if max_tx_clvm_cost is not None else uint64(self.constants.MAX_BLOCK_COST_CLVM // 2)
)
Expand Down

0 comments on commit 1a1209c

Please sign in to comment.