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

update the StateChangeSummary to not keep full NPCResult objects #16793

Merged
merged 1 commit into from
Nov 21, 2023
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
21 changes: 15 additions & 6 deletions chia/consensus/blockchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,10 @@ class StateChangeSummary:
peak: BlockRecord
fork_height: uint32
rolled_back_records: List[CoinRecord]
new_npc_results: List[NPCResult]
# list of coin-id, puzzle-hash pairs
removals: List[Tuple[bytes32, bytes32]]
# new coin and hint
additions: List[Tuple[Coin, Optional[bytes]]]
Quexington marked this conversation as resolved.
Show resolved Hide resolved
new_rewards: List[Coin]


Expand Down Expand Up @@ -539,7 +542,7 @@ async def _reconsider_peak(
await self.block_store.set_in_chain([(block_record.header_hash,)])
await self.block_store.set_peak(block_record.header_hash)
return [block_record], StateChangeSummary(
block_record, uint32(0), [], [], list(block.get_included_reward_coins())
block_record, uint32(0), [], [], [], list(block.get_included_reward_coins())
)
return [], None

Expand Down Expand Up @@ -569,7 +572,9 @@ async def _reconsider_peak(
curr = fetched_block_record.prev_hash

records_to_add: List[BlockRecord] = []
npc_results: List[NPCResult] = []
# coin-id, puzzle-hash
removals: List[Tuple[bytes32, bytes32]] = []
additions: List[Tuple[Coin, Optional[bytes]]] = []
reward_coins: List[Coin] = []
for fetched_full_block, fetched_block_record in reversed(blocks_to_add):
records_to_add.append(fetched_block_record)
Expand All @@ -586,8 +591,11 @@ async def _reconsider_peak(
tx_removals, tx_additions, npc_res = await self.get_tx_removals_and_additions(fetched_full_block, None)

# Collect the NPC results for later post-processing
if npc_res is not None:
npc_results.append(npc_res)
if npc_res is not None and npc_res.conds is not None:
for spend in npc_res.conds.spends:
removals.append((bytes32(spend.coin_id), bytes32(spend.puzzle_hash)))
for ph, amount, hint in spend.create_coin:
additions.append((Coin(spend.coin_id, ph, amount), hint))

# Apply the coin store changes for each block that is now in the blockchain
assert fetched_full_block.foliage_transaction_block is not None
Expand All @@ -613,7 +621,8 @@ async def _reconsider_peak(
block_record,
uint32(max(fork_info.fork_height, 0)),
list(rolled_back_state.values()),
npc_results,
removals,
additions,
reward_coins,
)

Expand Down
12 changes: 5 additions & 7 deletions chia/full_node/full_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,7 @@ async def _start(self) -> None:

full_peak: Optional[FullBlock] = await self.blockchain.get_full_peak()
assert full_peak is not None
state_change_summary = StateChangeSummary(peak, uint32(max(peak.height - 1, 0)), [], [], [])
state_change_summary = StateChangeSummary(peak, uint32(max(peak.height - 1, 0)), [], [], [], [])
ppp_result: PeakPostProcessingResult = await self.peak_post_processing(
full_peak, state_change_summary, None
)
Expand Down Expand Up @@ -1315,7 +1315,8 @@ async def add_block_batch(
state_change_summary.peak,
agg_state_change_summary.fork_height,
agg_state_change_summary.rolled_back_records + state_change_summary.rolled_back_records,
agg_state_change_summary.new_npc_results + state_change_summary.new_npc_results,
agg_state_change_summary.removals + state_change_summary.removals,
agg_state_change_summary.additions + state_change_summary.additions,
agg_state_change_summary.new_rewards + state_change_summary.new_rewards,
)
elif result == AddBlockResult.INVALID_BLOCK or result == AddBlockResult.DISCONNECTED_BLOCK:
Expand Down Expand Up @@ -1352,7 +1353,7 @@ async def _finish_sync(self) -> None:
peak_fb: Optional[FullBlock] = await self.blockchain.get_full_peak()
if peak_fb is not None:
assert peak is not None
state_change_summary = StateChangeSummary(peak, uint32(max(peak.height - 1, 0)), [], [], [])
state_change_summary = StateChangeSummary(peak, uint32(max(peak.height - 1, 0)), [], [], [], [])
ppp_result: PeakPostProcessingResult = await self.peak_post_processing(
peak_fb, state_change_summary, None
)
Expand Down Expand Up @@ -1535,10 +1536,7 @@ async def peak_post_processing(
)

# Update the mempool (returns successful pending transactions added to the mempool)
spent_coins: Optional[List[bytes32]] = None
new_npc_results: List[NPCResult] = state_change_summary.new_npc_results
if len(new_npc_results) > 0 and new_npc_results[-1].conds is not None:
spent_coins = [bytes32(s.coin_id) for s in new_npc_results[-1].conds.spends]
spent_coins: List[bytes32] = [coin_id for coin_id, _ in state_change_summary.removals]
mempool_new_peak_result: List[Tuple[SpendBundle, NPCResult, bytes32]] = await self.mempool_manager.new_peak(
self.blockchain.get_peak(), spent_coins
)
Expand Down
38 changes: 16 additions & 22 deletions chia/full_node/hint_management.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@
from typing import Callable, List, Optional, Set, Tuple

from chia.consensus.blockchain import StateChangeSummary
from chia.types.blockchain_format.coin import Coin
from chia.types.blockchain_format.sized_bytes import bytes32
from chia.util.ints import uint64


def get_hints_and_subscription_coin_ids(
Expand All @@ -31,27 +29,23 @@ def add_if_ph_subscription(puzzle_hash: bytes32, coin_id: bytes32) -> None:
if has_ph_subscription(puzzle_hash):
lookup_coin_ids.add(coin_id)

for npc_result in state_change_summary.new_npc_results:
if npc_result.conds is None:
for spend_id, puzzle_hash in state_change_summary.removals:
# Record all coin_ids that we are interested in, that had changes
add_if_coin_subscription(spend_id)
add_if_ph_subscription(puzzle_hash, spend_id)

for addition_coin, hint in state_change_summary.additions:
addition_coin_name = addition_coin.name()
add_if_coin_subscription(addition_coin_name)
add_if_ph_subscription(addition_coin.puzzle_hash, addition_coin_name)
if hint is None:
continue
for spend in npc_result.conds.spends:
# Record all coin_ids that we are interested in, that had changes
add_if_coin_subscription(bytes32(spend.coin_id))
add_if_ph_subscription(bytes32(spend.puzzle_hash), bytes32(spend.coin_id))

for new_ph, new_am, hint in spend.create_coin:
addition_coin: Coin = Coin(bytes32(spend.coin_id), bytes32(new_ph), uint64(new_am))
addition_coin_name = addition_coin.name()
add_if_coin_subscription(addition_coin_name)
add_if_ph_subscription(addition_coin.puzzle_hash, addition_coin_name)
if hint is None:
continue
if len(hint) == 32:
add_if_ph_subscription(bytes32(hint), addition_coin_name)

if len(hint) > 0:
assert len(hint) <= 32
hints_to_add.append((addition_coin_name, hint))
if len(hint) == 32:
add_if_ph_subscription(bytes32(hint), addition_coin_name)

if len(hint) > 0:
assert len(hint) <= 32
hints_to_add.append((addition_coin_name, hint))
Quexington marked this conversation as resolved.
Show resolved Hide resolved

# Goes through all new reward coins
for reward_coin in state_change_summary.new_rewards:
Expand Down
109 changes: 17 additions & 92 deletions tests/core/full_node/test_hint_management.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,93 +6,26 @@

from chia.consensus.block_record import BlockRecord
from chia.consensus.blockchain import Blockchain, StateChangeSummary
from chia.consensus.cost_calculator import NPCResult
from chia.full_node.hint_management import get_hints_and_subscription_coin_ids
from chia.simulator.block_tools import BlockTools
from chia.types.blockchain_format.coin import Coin
from chia.types.blockchain_format.sized_bytes import bytes32
from chia.types.spend_bundle_conditions import Spend, SpendBundleConditions
from chia.util.hash import std_hash
from chia.util.ints import uint32, uint64
from tests.blockchain.blockchain_test_utils import _validate_and_add_block

coin_ids = [std_hash(i.to_bytes(4, "big")) for i in range(10)]
parent_ids = [std_hash(i.to_bytes(4, "big")) for i in range(10)]
phs = [std_hash(i.to_bytes(4, "big")) for i in range(10)]
spends: List[Spend] = [
Spend(
coin_ids[0],
parent_ids[0],
phs[0],
123,
None,
uint64(5),
None,
None,
None,
None,
[
(phs[2], uint64(123), b""),
(phs[4], uint64(3), b"1" * 32),
],
[],
[],
[],
[],
[],
[],
[],
0,
),
Spend(
coin_ids[2],
parent_ids[2],
phs[0],
123,
None,
uint64(6),
None,
None,
None,
None,
[
(phs[7], uint64(123), b""),
(phs[4], uint64(6), b""),
(phs[9], uint64(123), b"1" * 32),
],
[],
[],
[],
[],
[],
[],
[],
0,
),
Spend(
coin_ids[1],
parent_ids[1],
phs[7],
123,
None,
uint64(2),
None,
None,
None,
None,
[
(phs[5], uint64(123), b""),
(phs[6], uint64(5), b"1" * 3),
],
[],
[],
[],
[],
[],
[],
[],
0,
),
removals = [(coin_ids[0], phs[0]), (coin_ids[2], phs[0]), (coin_ids[1], phs[7])]
additions = [
(Coin(coin_ids[0], phs[2], 123), None),
(Coin(coin_ids[0], phs[4], 3), b"1" * 32),
(Coin(coin_ids[2], phs[7], 123), None),
(Coin(coin_ids[2], phs[4], 6), None),
(Coin(coin_ids[2], phs[9], 123), b"1" * 32),
(Coin(coin_ids[1], phs[5], 123), None),
(Coin(coin_ids[1], phs[6], 5), b"1" * 3),
]


Expand All @@ -107,18 +40,14 @@ async def test_hints_to_add(bt: BlockTools, empty_blockchain: Blockchain) -> Non
await _validate_and_add_block(empty_blockchain, blocks[1])
br: Optional[BlockRecord] = empty_blockchain.get_peak()
assert br is not None
sbc: SpendBundleConditions = SpendBundleConditions(
spends, uint64(0), uint32(0), uint64(0), None, None, [], uint64(0), 0, 0
)
npc_res = [NPCResult(None, None, uint64(0)), NPCResult(None, sbc, uint64(0))]

scs = StateChangeSummary(br, uint32(0), [], npc_res, [])
scs = StateChangeSummary(br, uint32(0), [], removals, additions, [])
hints_to_add, lookup_coin_ids = get_hints_and_subscription_coin_ids(scs, no_sub, no_sub)
assert len(lookup_coin_ids) == 0

first_coin_id: bytes32 = Coin(bytes32(spends[0].coin_id), bytes32(phs[4]), uint64(3)).name()
second_coin_id: bytes32 = Coin(bytes32(spends[2].coin_id), bytes32(phs[6]), uint64(5)).name()
third_coin_id: bytes32 = Coin(bytes32(spends[1].coin_id), bytes32(phs[9]), uint64(123)).name()
first_coin_id: bytes32 = Coin(bytes32(coin_ids[0]), bytes32(phs[4]), uint64(3)).name()
second_coin_id: bytes32 = Coin(bytes32(coin_ids[1]), bytes32(phs[6]), uint64(5)).name()
third_coin_id: bytes32 = Coin(bytes32(coin_ids[2]), bytes32(phs[9]), uint64(123)).name()
assert set(hints_to_add) == {(first_coin_id, b"1" * 32), (second_coin_id, b"1" * 3), (third_coin_id, b"1" * 32)}


Expand All @@ -129,26 +58,22 @@ async def test_lookup_coin_ids(bt: BlockTools, empty_blockchain: Blockchain) ->
await _validate_and_add_block(empty_blockchain, blocks[1])
br: Optional[BlockRecord] = empty_blockchain.get_peak()
assert br is not None
sbc: SpendBundleConditions = SpendBundleConditions(
spends, uint64(0), uint32(0), uint64(0), None, None, [], uint64(0), 0, 0
)
npc_res = [NPCResult(None, None, uint64(0)), NPCResult(None, sbc, uint64(0))]

rewards: List[Coin] = [
Coin(coin_ids[8], phs[8], uint64(1)),
Coin(coin_ids[9], phs[9], uint64(2)),
Coin(coin_ids[5], phs[8], uint64(1234)),
]
scs = StateChangeSummary(br, uint32(0), [], npc_res, rewards)
scs = StateChangeSummary(br, uint32(0), [], removals, additions, rewards)

# Removal ID and addition PH
has_coin_sub = lambda c: c == coin_ids[1] # noqa: E731
has_ph_sub = lambda ph: ph == phs[4] # noqa: E731

_, lookup_coin_ids = get_hints_and_subscription_coin_ids(scs, has_coin_sub, has_ph_sub)

first_coin_id: bytes32 = Coin(bytes32(spends[0].coin_id), bytes32(phs[4]), uint64(3)).name()
second_coin_id: bytes32 = Coin(bytes32(spends[1].coin_id), bytes32(phs[4]), uint64(6)).name()
first_coin_id: bytes32 = Coin(bytes32(coin_ids[0]), bytes32(phs[4]), uint64(3)).name()
second_coin_id: bytes32 = Coin(bytes32(coin_ids[2]), bytes32(phs[4]), uint64(6)).name()
assert set(lookup_coin_ids) == {coin_ids[1], first_coin_id, second_coin_id}

# Removal PH and addition ID
Expand All @@ -159,7 +84,7 @@ async def test_lookup_coin_ids(bt: BlockTools, empty_blockchain: Blockchain) ->
assert set(lookup_coin_ids) == {first_coin_id, coin_ids[0], coin_ids[2]}

# Subscribe to hint
third_coin_id: bytes32 = Coin(bytes32(spends[1].coin_id), phs[9], uint64(123)).name()
third_coin_id: bytes32 = Coin(bytes32(coin_ids[2]), phs[9], uint64(123)).name()

has_ph_sub = lambda ph: ph == bytes32(b"1" * 32) # noqa: E731

Expand Down