update the StateChangeSummary to not keep full NPCResult objects (#16793)

This commit is contained in:
Arvid Norberg 2023-11-22 00:06:49 +01:00 committed by GitHub
parent c0deb18405
commit 5318514582
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 52 additions and 126 deletions

View File

@ -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]]]
new_rewards: List[Coin]
@ -539,7 +542,7 @@ class Blockchain(BlockchainInterface):
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
@ -569,7 +572,9 @@ class Blockchain(BlockchainInterface):
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)
@ -586,8 +591,11 @@ class Blockchain(BlockchainInterface):
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
@ -613,7 +621,8 @@ class Blockchain(BlockchainInterface):
block_record,
uint32(max(fork_info.fork_height, 0)),
list(rolled_back_state.values()),
npc_results,
removals,
additions,
reward_coins,
)

View File

@ -416,7 +416,7 @@ class FullNode:
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
)
@ -1325,7 +1325,8 @@ class FullNode:
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:
@ -1362,7 +1363,7 @@ class FullNode:
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
)
@ -1545,10 +1546,7 @@ class FullNode:
)
# 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
)

View File

@ -3,9 +3,7 @@ from __future__ import annotations
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(
@ -31,27 +29,23 @@ def get_hints_and_subscription_coin_ids(
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))
if len(hint) == 32:
add_if_ph_subscription(bytes32(hint), addition_coin_name)
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) > 0:
assert len(hint) <= 32
hints_to_add.append((addition_coin_name, hint))
# Goes through all new reward coins
for reward_coin in state_change_summary.new_rewards:

View File

@ -6,12 +6,10 @@ import pytest
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
@ -19,80 +17,15 @@ 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),
]
@ -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)}
@ -129,17 +58,13 @@ 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
@ -147,8 +72,8 @@ async def test_lookup_coin_ids(bt: BlockTools, empty_blockchain: Blockchain) ->
_, 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
@ -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