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

[CHIA-691] simplify MempoolItem #18143

Merged
merged 1 commit into from
Jul 8, 2024
Merged
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
6 changes: 3 additions & 3 deletions benchmarks/mempool-long-lived.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,9 @@ async def get_coin_record(coin_ids: Collection[bytes32]) -> List[CoinRecord]:
coin.name(): CoinRecord(coin, uint32(height // 2), uint32(0), False, uint64(timestamp // 2))
}
spend_bundle_id = sb.name()
npc = await mempool.pre_validate_spendbundle(sb, None, spend_bundle_id)
assert npc is not None
await mempool.add_spend_bundle(sb, npc, spend_bundle_id, uint32(height))
sbc = await mempool.pre_validate_spendbundle(sb, None, spend_bundle_id)
assert sbc is not None
await mempool.add_spend_bundle(sb, sbc, spend_bundle_id, uint32(height))

if height % 100 == 0:
print(
Expand Down
2 changes: 1 addition & 1 deletion chia/_tests/core/mempool/test_mempool.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ def make_item(
return MempoolItem(
SpendBundle([], G2Element()),
fee,
NPCResult(None, SpendBundleConditions([], 0, 0, 0, None, None, [], cost, 0, 0)),
SpendBundleConditions([], 0, 0, 0, None, None, [], cost, 0, 0),
spend_bundle_name,
uint32(0),
assert_height,
Expand Down
5 changes: 3 additions & 2 deletions chia/_tests/core/mempool/test_mempool_item_queries.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,12 @@ def make_item(coin_spends: List[CoinSpend]) -> MempoolItem:
npc_result = get_name_puzzle_conditions(
generator=generator, max_cost=INFINITE_COST, mempool_mode=True, height=uint32(0), constants=DEFAULT_CONSTANTS
)
bundle_coin_spends, fee = make_bundle_spends_map_and_fee(spend_bundle, npc_result)
assert npc_result.conds is not None
bundle_coin_spends, fee = make_bundle_spends_map_and_fee(spend_bundle, npc_result.conds)
return MempoolItem(
spend_bundle=spend_bundle,
fee=fee,
npc_result=npc_result,
conds=npc_result.conds,
spend_bundle_name=spend_bundle.name(),
height_added_to_mempool=TEST_HEIGHT,
bundle_coin_spends=bundle_coin_spends,
Expand Down
47 changes: 21 additions & 26 deletions chia/_tests/core/mempool/test_mempool_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
from chia._tests.util.misc import invariant_check_mempool
from chia._tests.util.setup_nodes import OldSimulatorsAndWallets
from chia.consensus.constants import ConsensusConstants
from chia.consensus.cost_calculator import NPCResult
from chia.consensus.default_constants import DEFAULT_CONSTANTS
from chia.full_node.bundle_tools import simple_solution_generator
from chia.full_node.mempool import MAX_SKIPPED_ITEMS, PRIORITY_TX_THRESHOLD
Expand Down Expand Up @@ -385,8 +384,8 @@ def spend_bundle_from_conditions(
async def add_spendbundle(
mempool_manager: MempoolManager, sb: SpendBundle, sb_name: bytes32
) -> Tuple[Optional[uint64], MempoolInclusionStatus, Optional[Err]]:
npc_result = await mempool_manager.pre_validate_spendbundle(sb, None, sb_name)
ret = await mempool_manager.add_spend_bundle(sb, npc_result, sb_name, TEST_HEIGHT)
sbc = await mempool_manager.pre_validate_spendbundle(sb, None, sb_name)
ret = await mempool_manager.add_spend_bundle(sb, sbc, sb_name, TEST_HEIGHT)
invariant_check_mempool(mempool_manager.mempool)
return ret.cost, ret.status, ret.error

Expand All @@ -404,14 +403,13 @@ async def generate_and_add_spendbundle(


def make_bundle_spends_map_and_fee(
spend_bundle: SpendBundle, npc_result: NPCResult
spend_bundle: SpendBundle, conds: SpendBundleConditions
) -> Tuple[Dict[bytes32, BundleCoinSpend], uint64]:
bundle_coin_spends: Dict[bytes32, BundleCoinSpend] = {}
eligibility_and_additions: Dict[bytes32, EligibilityAndAdditions] = {}
removals_amount = 0
additions_amount = 0
assert npc_result.conds is not None
for spend in npc_result.conds.spends:
for spend in conds.spends:
coin_id = bytes32(spend.coin_id)
spend_additions = []
for puzzle_hash, amount, _ in spend.create_coin:
Expand Down Expand Up @@ -443,11 +441,12 @@ def mempool_item_from_spendbundle(spend_bundle: SpendBundle) -> MempoolItem:
npc_result = get_name_puzzle_conditions(
generator=generator, max_cost=INFINITE_COST, mempool_mode=True, height=uint32(0), constants=DEFAULT_CONSTANTS
)
bundle_coin_spends, fee = make_bundle_spends_map_and_fee(spend_bundle, npc_result)
assert npc_result.conds is not None
bundle_coin_spends, fee = make_bundle_spends_map_and_fee(spend_bundle, npc_result.conds)
return MempoolItem(
spend_bundle=spend_bundle,
fee=fee,
npc_result=npc_result,
conds=npc_result.conds,
spend_bundle_name=spend_bundle.name(),
height_added_to_mempool=TEST_HEIGHT,
bundle_coin_spends=bundle_coin_spends,
Expand Down Expand Up @@ -478,8 +477,8 @@ async def test_valid_addition_amount() -> None:
conditions = [[ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, max_amount]]
coin = Coin(IDENTITY_PUZZLE_HASH, IDENTITY_PUZZLE_HASH, max_amount)
sb = spend_bundle_from_conditions(conditions, coin)
npc_result = await mempool_manager.pre_validate_spendbundle(sb, None, sb.name())
assert npc_result.error is None
# ensure this does not throw
_ = await mempool_manager.pre_validate_spendbundle(sb, None, sb.name())


@pytest.mark.anyio
Expand Down Expand Up @@ -530,8 +529,7 @@ async def test_minting_coin() -> None:
mempool_manager = await instantiate_mempool_manager(zero_calls_get_coin_records)
conditions = [[ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, TEST_COIN_AMOUNT]]
sb = spend_bundle_from_conditions(conditions)
npc_result = await mempool_manager.pre_validate_spendbundle(sb, None, sb.name())
assert npc_result.error is None
_ = await mempool_manager.pre_validate_spendbundle(sb, None, sb.name())
conditions = [[ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, TEST_COIN_AMOUNT + 1]]
sb = spend_bundle_from_conditions(conditions)
with pytest.raises(ValidationError, match="MINTING_COIN"):
Expand All @@ -543,8 +541,7 @@ async def test_reserve_fee_condition() -> None:
mempool_manager = await instantiate_mempool_manager(zero_calls_get_coin_records)
conditions = [[ConditionOpcode.RESERVE_FEE, TEST_COIN_AMOUNT]]
sb = spend_bundle_from_conditions(conditions)
npc_result = await mempool_manager.pre_validate_spendbundle(sb, None, sb.name())
assert npc_result.error is None
_ = await mempool_manager.pre_validate_spendbundle(sb, None, sb.name())
conditions = [[ConditionOpcode.RESERVE_FEE, TEST_COIN_AMOUNT + 1]]
sb = spend_bundle_from_conditions(conditions)
with pytest.raises(ValidationError, match="RESERVE_FEE_CONDITION_FAILED"):
Expand Down Expand Up @@ -750,11 +747,11 @@ def mk_item(
coin_spend=spend, eligible_for_dedup=False, eligible_for_fast_forward=False, additions=[]
)
spend_bundle = SpendBundle(coin_spends, G2Element())
npc_result = NPCResult(None, make_test_conds(cost=cost, spend_ids=spend_ids))
conds = make_test_conds(cost=cost, spend_ids=spend_ids)
return MempoolItem(
spend_bundle=spend_bundle,
fee=uint64(fee),
npc_result=npc_result,
conds=conds,
spend_bundle_name=spend_bundle.name(),
height_added_to_mempool=uint32(0),
assert_height=None if assert_height is None else uint32(assert_height),
Expand Down Expand Up @@ -1388,10 +1385,9 @@ def test_dedup_info_nothing_to_do() -> None:
]
sb = spend_bundle_from_conditions(conditions, TEST_COIN, sig)
mempool_item = mempool_item_from_spendbundle(sb)
assert mempool_item.npc_result.conds is not None
eligible_coin_spends = EligibleCoinSpends()
unique_coin_spends, cost_saving, unique_additions = eligible_coin_spends.get_deduplication_info(
bundle_coin_spends=mempool_item.bundle_coin_spends, max_cost=mempool_item.npc_result.conds.cost
bundle_coin_spends=mempool_item.bundle_coin_spends, max_cost=mempool_item.conds.cost
)
assert unique_coin_spends == sb.coin_spends
assert cost_saving == 0
Expand All @@ -1407,11 +1403,11 @@ def test_dedup_info_eligible_1st_time() -> None:
]
sb = spend_bundle_from_conditions(conditions, TEST_COIN)
mempool_item = mempool_item_from_spendbundle(sb)
assert mempool_item.npc_result.conds is not None
assert mempool_item.conds is not None
eligible_coin_spends = EligibleCoinSpends()
solution = SerializedProgram.to(conditions)
unique_coin_spends, cost_saving, unique_additions = eligible_coin_spends.get_deduplication_info(
bundle_coin_spends=mempool_item.bundle_coin_spends, max_cost=mempool_item.npc_result.conds.cost
bundle_coin_spends=mempool_item.bundle_coin_spends, max_cost=mempool_item.conds.cost
)
assert unique_coin_spends == sb.coin_spends
assert cost_saving == 0
Expand All @@ -1433,10 +1429,9 @@ def test_dedup_info_eligible_but_different_solution() -> None:
conditions = [[ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, 2]]
sb = spend_bundle_from_conditions(conditions, TEST_COIN)
mempool_item = mempool_item_from_spendbundle(sb)
assert mempool_item.npc_result.conds is not None
with pytest.raises(ValueError, match="Solution is different from what we're deduplicating on"):
eligible_coin_spends.get_deduplication_info(
bundle_coin_spends=mempool_item.bundle_coin_spends, max_cost=mempool_item.npc_result.conds.cost
bundle_coin_spends=mempool_item.bundle_coin_spends, max_cost=mempool_item.conds.cost
)


Expand All @@ -1454,9 +1449,9 @@ def test_dedup_info_eligible_2nd_time_and_another_1st_time() -> None:
sb2 = spend_bundle_from_conditions(second_conditions, TEST_COIN2)
sb = SpendBundle.aggregate([sb1, sb2])
mempool_item = mempool_item_from_spendbundle(sb)
assert mempool_item.npc_result.conds is not None
assert mempool_item.conds is not None
unique_coin_spends, cost_saving, unique_additions = eligible_coin_spends.get_deduplication_info(
bundle_coin_spends=mempool_item.bundle_coin_spends, max_cost=mempool_item.npc_result.conds.cost
bundle_coin_spends=mempool_item.bundle_coin_spends, max_cost=mempool_item.conds.cost
)
# Only the eligible one that we encountered more than once gets deduplicated
assert unique_coin_spends == sb2.coin_spends
Expand Down Expand Up @@ -1502,9 +1497,9 @@ def test_dedup_info_eligible_3rd_time_another_2nd_time_and_one_non_eligible() ->
sb3 = spend_bundle_from_conditions(sb3_conditions, TEST_COIN3, sig)
sb = SpendBundle.aggregate([sb1, sb2, sb3])
mempool_item = mempool_item_from_spendbundle(sb)
assert mempool_item.npc_result.conds is not None
assert mempool_item.conds is not None
unique_coin_spends, cost_saving, unique_additions = eligible_coin_spends.get_deduplication_info(
bundle_coin_spends=mempool_item.bundle_coin_spends, max_cost=mempool_item.npc_result.conds.cost
bundle_coin_spends=mempool_item.bundle_coin_spends, max_cost=mempool_item.conds.cost
)
assert unique_coin_spends == sb3.coin_spends
saved_cost2 = uint64(1800044)
Expand Down
12 changes: 3 additions & 9 deletions chia/_tests/core/mempool/test_singleton_fast_forward.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,7 @@ async def get_unspent_lineage_info_for_puzzle_hash(_: bytes32) -> Optional[Unspe
item = mempool_item_from_spendbundle(sb)
# This coin is not eligible for fast forward
assert item.bundle_coin_spends[TEST_COIN_ID].eligible_for_fast_forward is False
internal_mempool_item = InternalMempoolItem(
sb, item.npc_result, item.height_added_to_mempool, item.bundle_coin_spends
)
internal_mempool_item = InternalMempoolItem(sb, item.conds, item.height_added_to_mempool, item.bundle_coin_spends)
original_version = dataclasses.replace(internal_mempool_item)
eligible_coin_spends = EligibleCoinSpends()
await eligible_coin_spends.process_fast_forward_spends(
Expand Down Expand Up @@ -87,9 +85,7 @@ async def get_unspent_lineage_info_for_puzzle_hash(puzzle_hash: bytes32) -> Opti
item = mempool_item_from_spendbundle(sb)
# The coin is eligible for fast forward
assert item.bundle_coin_spends[test_coin.name()].eligible_for_fast_forward is True
internal_mempool_item = InternalMempoolItem(
sb, item.npc_result, item.height_added_to_mempool, item.bundle_coin_spends
)
internal_mempool_item = InternalMempoolItem(sb, item.conds, item.height_added_to_mempool, item.bundle_coin_spends)
eligible_coin_spends = EligibleCoinSpends()
# We have no fast forward records yet, so we'll process this coin for the
# first time here, but the DB lookup will return None
Expand Down Expand Up @@ -131,9 +127,7 @@ async def get_unspent_lineage_info_for_puzzle_hash(puzzle_hash: bytes32) -> Opti
sb = spend_bundle_from_conditions(conditions, test_coin)
item = mempool_item_from_spendbundle(sb)
assert item.bundle_coin_spends[test_coin.name()].eligible_for_fast_forward is True
internal_mempool_item = InternalMempoolItem(
sb, item.npc_result, item.height_added_to_mempool, item.bundle_coin_spends
)
internal_mempool_item = InternalMempoolItem(sb, item.conds, item.height_added_to_mempool, item.bundle_coin_spends)
original_version = dataclasses.replace(internal_mempool_item)
eligible_coin_spends = EligibleCoinSpends()
await eligible_coin_spends.process_fast_forward_spends(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
instantiate_mempool_manager,
zero_calls_get_coin_records,
)
from chia.consensus.cost_calculator import NPCResult
from chia.full_node.bitcoin_fee_estimator import create_bitcoin_fee_estimator
from chia.full_node.fee_estimation import (
EmptyFeeMempoolInfo,
Expand Down Expand Up @@ -47,7 +46,7 @@ def make_mempoolitem() -> MempoolItem:
mempool_item = MempoolItem(
spend_bundle,
fee,
NPCResult(None, conds),
conds,
spend_bundle.name(),
uint32(block_height),
)
Expand Down
6 changes: 2 additions & 4 deletions chia/clvm/spend_sim.py
Original file line number Diff line number Diff line change
Expand Up @@ -337,14 +337,12 @@ def __init__(self, service: SpendSim) -> None:
async def push_tx(self, spend_bundle: SpendBundle) -> Tuple[MempoolInclusionStatus, Optional[Err]]:
try:
spend_bundle_id = spend_bundle.name()
cost_result: NPCResult = await self.service.mempool_manager.pre_validate_spendbundle(
spend_bundle, None, spend_bundle_id
)
sbc = await self.service.mempool_manager.pre_validate_spendbundle(spend_bundle, None, spend_bundle_id)
except ValidationError as e:
return MempoolInclusionStatus.FAILED, e.code
assert self.service.mempool_manager.peak is not None
info = await self.service.mempool_manager.add_spend_bundle(
spend_bundle, cost_result, spend_bundle_id, self.service.mempool_manager.peak.height
spend_bundle, sbc, spend_bundle_id, self.service.mempool_manager.peak.height
)
return info.status, info.error

Expand Down
6 changes: 3 additions & 3 deletions chia/full_node/full_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -2350,6 +2350,7 @@ async def add_transaction(
except Exception:
self.mempool_manager.remove_seen(spend_name)
raise

async with self.blockchain.priority_mutex.acquire(priority=BlockchainMutexPriority.low):
if self.mempool_manager.get_spendbundle(spend_name) is not None:
self.mempool_manager.remove_seen(spend_name)
Expand Down Expand Up @@ -2400,8 +2401,7 @@ async def broadcast_added_tx(
else:
await self.server.send_to_all([msg], NodeType.FULL_NODE, current_peer.peer_node_id)

conds = mempool_item.npc_result.conds
assert conds is not None
conds = mempool_item.conds

all_peers = {
peer_id
Expand Down Expand Up @@ -2457,7 +2457,7 @@ async def broadcast_removed_tx(self, mempool_removals: List[MempoolRemoveInfo])

for removal_info in mempool_removals:
for internal_mempool_item in removal_info.items:
conds = internal_mempool_item.npc_result.conds
conds = internal_mempool_item.conds
assert conds is not None

hints_for_removals = await self.hint_store.get_hints([bytes32(spend.coin_id) for spend in conds.spends])
Expand Down
16 changes: 8 additions & 8 deletions chia/full_node/mempool.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ def _row_to_item(self, row: sqlite3.Row) -> MempoolItem:
return MempoolItem(
item.spend_bundle,
uint64(fee),
item.npc_result,
item.conds,
name,
uint32(item.height_added_to_mempool),
assert_height,
Expand Down Expand Up @@ -177,7 +177,7 @@ def items_with_coin_ids(self, coin_ids: Set[bytes32]) -> List[bytes32]:
transaction_ids: List[bytes32] = []

for transaction_id, item in self._items.items():
conds = item.npc_result.conds
conds = item.conds
assert conds is not None

for spend in conds.spends:
Expand Down Expand Up @@ -206,7 +206,7 @@ def items_with_puzzle_hashes(self, puzzle_hashes: Set[bytes32], include_hints: b
transaction_ids: List[bytes32] = []

for transaction_id, item in self._items.items():
conds = item.npc_result.conds
conds = item.conds
assert conds is not None

for spend in conds.spends:
Expand Down Expand Up @@ -374,7 +374,7 @@ def add_to_pool(self, item: MempoolItem) -> MempoolAddInfo:
"""

assert item.fee < MEMPOOL_ITEM_FEE_LIMIT
assert item.npc_result.conds is not None
assert item.conds is not None
assert item.cost <= self.mempool_info.max_block_clvm_cost

removals: List[MempoolRemoveInfo] = []
Expand Down Expand Up @@ -452,11 +452,11 @@ def add_to_pool(self, item: MempoolItem) -> MempoolAddInfo:
item.fee / item.cost,
),
)
all_coin_spends = [(s.coin_id, item.name) for s in item.npc_result.conds.spends]
all_coin_spends = [(s.coin_id, item.name) for s in item.conds.spends]
conn.executemany("INSERT INTO spends VALUES(?, ?)", all_coin_spends)

self._items[item.name] = InternalMempoolItem(
item.spend_bundle, item.npc_result, item.height_added_to_mempool, item.bundle_coin_spends
item.spend_bundle, item.conds, item.height_added_to_mempool, item.bundle_coin_spends
)
self._total_cost += item.cost
self._total_fee += item.fee
Expand Down Expand Up @@ -505,8 +505,8 @@ async def create_bundle_from_mempool_items(
if not item_inclusion_filter(name):
continue
try:
assert item.npc_result.conds is not None
cost = item.npc_result.conds.cost
assert item.conds is not None
cost = item.conds.cost
if skipped_items >= PRIORITY_TX_THRESHOLD:
# If we've encountered `PRIORITY_TX_THRESHOLD` number of
# transactions that don't fit in the remaining block size,
Expand Down
Loading
Loading