Skip to content

Commit

Permalink
Make PreValidationResult take SpendBundleConditions instead of NPCRes…
Browse files Browse the repository at this point in the history
…ult.
  • Loading branch information
AmineKhaldi committed Sep 27, 2024
1 parent b7fbc6b commit e51a4c8
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 45 deletions.
11 changes: 7 additions & 4 deletions chia/_tests/blockchain/test_blockchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -2641,7 +2641,10 @@ async def test_cost_exceeds_max(
diff = b.constants.DIFFICULTY_STARTING
err = (
await b.add_block(
blocks[-1], PreValidationResult(None, uint64(1), npc_result, True, uint32(0)), None, sub_slot_iters=ssi
blocks[-1],
PreValidationResult(None, uint64(1), npc_result.conds, True, uint32(0)),
None,
sub_slot_iters=ssi,
)
)[1]
assert err in [Err.BLOCK_COST_EXCEEDS_MAX]
Expand Down Expand Up @@ -2717,7 +2720,7 @@ async def test_invalid_cost_in_block(
)
ssi = b.constants.SUB_SLOT_ITERS_STARTING
_, err, _ = await b.add_block(
block_2, PreValidationResult(None, uint64(1), npc_result, False, uint32(0)), None, sub_slot_iters=ssi
block_2, PreValidationResult(None, uint64(1), npc_result.conds, False, uint32(0)), None, sub_slot_iters=ssi
)
assert err == Err.INVALID_BLOCK_COST

Expand Down Expand Up @@ -2746,7 +2749,7 @@ async def test_invalid_cost_in_block(
constants=bt.constants,
)
_, err, _ = await b.add_block(
block_2, PreValidationResult(None, uint64(1), npc_result, False, uint32(0)), None, sub_slot_iters=ssi
block_2, PreValidationResult(None, uint64(1), npc_result.conds, False, uint32(0)), None, sub_slot_iters=ssi
)
assert err == Err.INVALID_BLOCK_COST

Expand Down Expand Up @@ -2777,7 +2780,7 @@ async def test_invalid_cost_in_block(
)

result, err, _ = await b.add_block(
block_2, PreValidationResult(None, uint64(1), npc_result, False, uint32(0)), None, sub_slot_iters=ssi
block_2, PreValidationResult(None, uint64(1), npc_result.conds, False, uint32(0)), None, sub_slot_iters=ssi
)
assert err == Err.INVALID_BLOCK_COST

Expand Down
36 changes: 13 additions & 23 deletions chia/consensus/block_body_validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,12 +125,12 @@ async def validate_block_body(
get_coin_records: Callable[[Collection[bytes32]], Awaitable[List[CoinRecord]]],
block: Union[FullBlock, UnfinishedBlock],
height: uint32,
npc_result: Optional[NPCResult],
conds: Optional[SpendBundleConditions],
fork_info: ForkInfo,
bls_cache: Optional[BLSCache],
*,
validate_signature: bool = True,
) -> Tuple[Optional[Err], Optional[NPCResult]]:
) -> Tuple[Optional[Err], Optional[SpendBundleConditions]]:
"""
This assumes the header block has been completely validated.
Validates the transactions and body of the block. Returns None for the first value if everything
Expand Down Expand Up @@ -291,8 +291,7 @@ async def validate_block_body(
if block.transactions_generator is not None:
# Get List of names removed, puzzles hashes for removed coins and conditions created

assert npc_result is not None
cost = uint64(0 if npc_result.conds is None else npc_result.conds.cost)
cost = uint64(0 if conds is None else conds.cost)

# 7. Check that cost <= MAX_BLOCK_COST_CLVM
log.debug(
Expand All @@ -303,19 +302,16 @@ async def validate_block_body(
return Err.BLOCK_COST_EXCEEDS_MAX, None

# 8. The CLVM program must not return any errors
if npc_result.error is not None:
return Err(npc_result.error), None
assert conds is not None

assert npc_result.conds is not None

for spend in npc_result.conds.spends:
for spend in conds.spends:
removals.append(bytes32(spend.coin_id))
removals_puzzle_dic[bytes32(spend.coin_id)] = bytes32(spend.puzzle_hash)
for puzzle_hash, amount, _ in spend.create_coin:
c = Coin(bytes32(spend.coin_id), bytes32(puzzle_hash), uint64(amount))
additions.append((c, c.name()))
else:
assert npc_result is None
assert conds is None

# 9. Check that the correct cost is in the transactions info
if block.transactions_info.cost != cost:
Expand Down Expand Up @@ -459,10 +455,7 @@ async def validate_block_body(

# reserve fee cannot be greater than UINT64_MAX per consensus rule.
# run_generator() would fail
assert_fee_sum: uint64 = uint64(0)
if npc_result:
assert npc_result.conds is not None
assert_fee_sum = uint64(npc_result.conds.reserve_fee)
assert_fee_sum = uint64(0 if conds is None else conds.reserve_fee)

# 17. Check that the assert fee sum <= fees, and that each reserved fee is non-negative
if fees < assert_fee_sum:
Expand All @@ -483,24 +476,21 @@ async def validate_block_body(

# 21. Verify conditions
# verify absolute/relative height/time conditions
if npc_result is not None:
assert npc_result.conds is not None

if conds is not None:
error = mempool_check_time_locks(
removal_coin_records,
npc_result.conds,
conds,
prev_transaction_block_height,
prev_transaction_block_timestamp,
)
if error:
if error is not None:
return error, None

# create hash_key list for aggsig check
pairs_pks: List[G1Element] = []
pairs_msgs: List[bytes] = []
if npc_result:
assert npc_result.conds is not None
pairs_pks, pairs_msgs = pkm_pairs(npc_result.conds, constants.AGG_SIG_ME_ADDITIONAL_DATA)
if conds is not None:
pairs_pks, pairs_msgs = pkm_pairs(conds, constants.AGG_SIG_ME_ADDITIONAL_DATA)

# 22. Verify aggregated signature
# TODO: move this to pre_validate_blocks_multiprocessing so we can sync faster
Expand All @@ -520,4 +510,4 @@ async def validate_block_body(
if not bls_cache.aggregate_verify(pairs_pks, pairs_msgs, block.transactions_info.aggregated_signature):
return Err.BAD_AGGREGATE_SIGNATURE, None

return None, npc_result
return None, conds
11 changes: 5 additions & 6 deletions chia/consensus/blockchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from pathlib import Path
from typing import TYPE_CHECKING, ClassVar, Dict, List, Optional, Set, Tuple, cast

from chia_rs import BLSCache
from chia_rs import BLSCache, SpendBundleConditions

from chia.consensus.block_body_validation import ForkInfo, validate_block_body
from chia.consensus.block_header_validation import validate_unfinished_header_block
Expand Down Expand Up @@ -338,7 +338,6 @@ async def add_block(
if prev_block.height + 1 != block.height:
return AddBlockResult.INVALID_BLOCK, Err.INVALID_HEIGHT, None

npc_result: Optional[NPCResult] = pre_validation_result.npc_result
required_iters = pre_validation_result.required_iters
if pre_validation_result.error is not None:
return AddBlockResult.INVALID_BLOCK, Err(pre_validation_result.error), None
Expand Down Expand Up @@ -412,7 +411,7 @@ async def add_block(
# main chain, we still need to re-run it to update the additions and
# removals in fork_info.
await self.advance_fork_info(block, fork_info)
fork_info.include_spends(None if npc_result is None else npc_result.conds, block, header_hash)
fork_info.include_spends(pre_validation_result.conds, block, header_hash)
self.add_block_record(block_rec)
return AddBlockResult.ALREADY_HAVE_BLOCK, None, None

Expand All @@ -431,7 +430,7 @@ async def add_block(
self.coin_store.get_coin_records,
block,
block.height,
npc_result,
pre_validation_result.conds,
fork_info,
bls_cache,
# If we did not already validate the signature, validate it now
Expand All @@ -444,7 +443,7 @@ async def add_block(
# case we're validating blocks on a fork, the next block validation will
# need to know of these additions and removals. Also, _reconsider_peak()
# will need these results
fork_info.include_spends(None if npc_result is None else npc_result.conds, block, header_hash)
fork_info.include_spends(pre_validation_result.conds, block, header_hash)

# block_to_block_record() require the previous block in the cache
if not genesis and prev_block is not None:
Expand Down Expand Up @@ -781,7 +780,7 @@ async def validate_unfinished_block(
self.coin_store.get_coin_records,
block,
uint32(prev_height + 1),
npc_result,
None if npc_result is None else npc_result.conds,
fork_info,
None,
validate_signature=False, # Signature was already validated before calling this method, no need to validate
Expand Down
14 changes: 6 additions & 8 deletions chia/consensus/multiprocess_validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
class PreValidationResult(Streamable):
error: Optional[uint16]
required_iters: Optional[uint64] # Iff error is None
npc_result: Optional[NPCResult] # Iff error is None and block is a transaction block
conds: Optional[SpendBundleConditions] # Iff error is None and block is a transaction block
validated_signature: bool
timing: uint32 # the time (in milliseconds) it took to pre-validate the block

Expand Down Expand Up @@ -95,7 +95,7 @@ def batch_pre_validate_blocks(
validation_time = time.monotonic() - validation_start
results.append(
PreValidationResult(
uint16(npc_result.error), None, npc_result, False, uint32(validation_time * 1000)
uint16(npc_result.error), None, npc_result.conds, False, uint32(validation_time * 1000)
)
)
continue
Expand Down Expand Up @@ -144,7 +144,7 @@ def batch_pre_validate_blocks(
PreValidationResult(
error_int,
required_iters,
None if conds is None else NPCResult(None, conds),
conds,
successfully_validated_signatures,
uint32(validation_time * 1000),
)
Expand All @@ -164,7 +164,7 @@ async def pre_validate_blocks_multiprocessing(
block_records: BlocksProtocol,
blocks: Sequence[FullBlock],
pool: Executor,
npc_results: Dict[uint32, NPCResult],
block_height_conds_map: Dict[uint32, SpendBundleConditions],
*,
sub_slot_iters: uint64,
difficulty: uint64,
Expand Down Expand Up @@ -275,10 +275,8 @@ async def pre_validate_blocks_multiprocessing(
prev_ses_block = block_rec

conditions_pickled = {}
for k, v in npc_results.items():
assert v.error is None
assert v.conds is not None
conditions_pickled[k] = bytes(v.conds)
for k, v in block_height_conds_map.items():
conditions_pickled[k] = bytes(v)
futures = []
# Pool of workers to validate blocks concurrently
recent_blocks_bytes = {bytes(k): bytes(v) for k, v in recent_blocks.items()} # convert to bytes
Expand Down
8 changes: 4 additions & 4 deletions chia/full_node/full_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -1846,9 +1846,9 @@ async def add_block(
return None
validation_start = time.monotonic()
# Tries to add the block to the blockchain, if we already validated transactions, don't do it again
npc_results = {}
if pre_validation_result is not None and pre_validation_result.npc_result is not None:
npc_results[block.height] = pre_validation_result.npc_result
block_height_conds_map = {}
if pre_validation_result is not None and pre_validation_result.conds is not None:
block_height_conds_map[block.height] = pre_validation_result.conds

# Don't validate signatures because we want to validate them in the main thread later, since we have a
# cache available
Expand All @@ -1868,7 +1868,7 @@ async def add_block(
self.blockchain,
[block],
self.blockchain.pool,
npc_results,
block_height_conds_map,
sub_slot_iters=ssi,
difficulty=diff,
prev_ses_block=prev_ses_block,
Expand Down

0 comments on commit e51a4c8

Please sign in to comment.