Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

remove the block fill rate limit of 70% when farming a block #19005

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -1065,36 +1066,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 @@ -2045,9 +2073,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
Loading