Skip to content

Commit

Permalink
update the StateUpdateSummary to not keep full NPCResult objects, but…
Browse files Browse the repository at this point in the history
… just the parts we need
  • Loading branch information
arvidn committed Nov 8, 2023
1 parent 64d6fb5 commit db1d954
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 127 deletions.
25 changes: 19 additions & 6 deletions chia/consensus/blockchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,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]


Expand Down Expand Up @@ -354,7 +357,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 @@ -393,7 +396,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 @@ -410,8 +415,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 @@ -434,7 +442,12 @@ async def _reconsider_peak(
await self.block_store.set_peak(block_record.header_hash)

return records_to_add, StateChangeSummary(
block_record, uint32(max(fork_height, 0)), list(rolled_back_state.values()), npc_results, reward_coins
block_record,
uint32(max(fork_height, 0)),
list(rolled_back_state.values()),
removals,
additions,
reward_coins,
)

async def get_tx_removals_and_additions(
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 @@ -405,7 +405,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 @@ -1247,7 +1247,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 @@ -1283,7 +1284,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 @@ -1466,10 +1467,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] = [s[0] for s 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))

# 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

0 comments on commit db1d954

Please sign in to comment.