Skip to content

Commit 9109d89

Browse files
authored
CHIA-1525 Make PreValidationResult take SpendBundleConditions instead of NPCResult (#18647)
Make PreValidationResult take SpendBundleConditions instead of NPCResult.
1 parent b413765 commit 9109d89

File tree

6 files changed

+44
-53
lines changed

6 files changed

+44
-53
lines changed

chia/_tests/blockchain/test_blockchain.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2641,7 +2641,10 @@ async def test_cost_exceeds_max(
26412641
diff = b.constants.DIFFICULTY_STARTING
26422642
err = (
26432643
await b.add_block(
2644-
blocks[-1], PreValidationResult(None, uint64(1), npc_result, True, uint32(0)), None, sub_slot_iters=ssi
2644+
blocks[-1],
2645+
PreValidationResult(None, uint64(1), npc_result.conds, True, uint32(0)),
2646+
None,
2647+
sub_slot_iters=ssi,
26452648
)
26462649
)[1]
26472650
assert err in [Err.BLOCK_COST_EXCEEDS_MAX]
@@ -2717,7 +2720,7 @@ async def test_invalid_cost_in_block(
27172720
)
27182721
ssi = b.constants.SUB_SLOT_ITERS_STARTING
27192722
_, err, _ = await b.add_block(
2720-
block_2, PreValidationResult(None, uint64(1), npc_result, False, uint32(0)), None, sub_slot_iters=ssi
2723+
block_2, PreValidationResult(None, uint64(1), npc_result.conds, False, uint32(0)), None, sub_slot_iters=ssi
27212724
)
27222725
assert err == Err.INVALID_BLOCK_COST
27232726

@@ -2746,7 +2749,7 @@ async def test_invalid_cost_in_block(
27462749
constants=bt.constants,
27472750
)
27482751
_, err, _ = await b.add_block(
2749-
block_2, PreValidationResult(None, uint64(1), npc_result, False, uint32(0)), None, sub_slot_iters=ssi
2752+
block_2, PreValidationResult(None, uint64(1), npc_result.conds, False, uint32(0)), None, sub_slot_iters=ssi
27502753
)
27512754
assert err == Err.INVALID_BLOCK_COST
27522755

@@ -2777,7 +2780,7 @@ async def test_invalid_cost_in_block(
27772780
)
27782781

27792782
result, err, _ = await b.add_block(
2780-
block_2, PreValidationResult(None, uint64(1), npc_result, False, uint32(0)), None, sub_slot_iters=ssi
2783+
block_2, PreValidationResult(None, uint64(1), npc_result.conds, False, uint32(0)), None, sub_slot_iters=ssi
27812784
)
27822785
assert err == Err.INVALID_BLOCK_COST
27832786

chia/_tests/core/full_node/test_full_node.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -741,9 +741,8 @@ async def test_respond_unfinished(self, wallet_nodes, self_hostname):
741741
assert entry is not None
742742
result = entry.result
743743
assert result is not None
744-
assert result.npc_result is not None
745-
assert result.npc_result.conds is not None
746-
assert result.npc_result.conds.cost > 0
744+
assert result.conds is not None
745+
assert result.conds.cost > 0
747746

748747
assert not full_node_1.full_node.blockchain.contains_block(block.header_hash)
749748
assert block.transactions_generator is not None

chia/consensus/block_body_validation.py

Lines changed: 21 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
from chia.consensus.blockchain_interface import BlockRecordsProtocol
1515
from chia.consensus.coinbase import create_farmer_coin, create_pool_coin
1616
from chia.consensus.constants import ConsensusConstants
17-
from chia.consensus.cost_calculator import NPCResult
1817
from chia.full_node.mempool_check_conditions import mempool_check_time_locks
1918
from chia.types.blockchain_format.coin import Coin
2019
from chia.types.blockchain_format.sized_bytes import bytes32
@@ -125,19 +124,22 @@ async def validate_block_body(
125124
get_coin_records: Callable[[Collection[bytes32]], Awaitable[List[CoinRecord]]],
126125
block: Union[FullBlock, UnfinishedBlock],
127126
height: uint32,
128-
npc_result: Optional[NPCResult],
127+
conds: Optional[SpendBundleConditions],
129128
fork_info: ForkInfo,
130129
bls_cache: Optional[BLSCache],
131130
*,
132131
validate_signature: bool = True,
133-
) -> Tuple[Optional[Err], Optional[NPCResult]]:
132+
) -> Tuple[Optional[Err], Optional[SpendBundleConditions]]:
134133
"""
135134
This assumes the header block has been completely validated.
136-
Validates the transactions and body of the block. Returns None for the first value if everything
137-
validates correctly, or an Err if something does not validate. For the second value, returns a CostResult
138-
only if validation succeeded, and there are transactions. In other cases it returns None. The NPC result is
139-
the result of running the generator with the previous generators refs. It is only present for transaction
140-
blocks which have spent coins.
135+
Validates the transactions and body of the block.
136+
Returns None for the first value if everything validates correctly, or an
137+
Err if something does not validate.
138+
For the second value, returns a SpendBundleConditions only if validation
139+
succeeded, and there are transactions. In other cases it returns None.
140+
conds is the result of running the generator with the previous generators
141+
refs. It must be set for transaction blocks and must be None for
142+
non-transaction blocks.
141143
fork_info specifies the fork context of this block. In case the block
142144
extends the main chain, it can be empty, but if the block extends a fork
143145
of the main chain, the fork info is mandatory in order to validate the block.
@@ -291,8 +293,7 @@ async def validate_block_body(
291293
if block.transactions_generator is not None:
292294
# Get List of names removed, puzzles hashes for removed coins and conditions created
293295

294-
assert npc_result is not None
295-
cost = uint64(0 if npc_result.conds is None else npc_result.conds.cost)
296+
cost = uint64(0 if conds is None else conds.cost)
296297

297298
# 7. Check that cost <= MAX_BLOCK_COST_CLVM
298299
log.debug(
@@ -303,19 +304,16 @@ async def validate_block_body(
303304
return Err.BLOCK_COST_EXCEEDS_MAX, None
304305

305306
# 8. The CLVM program must not return any errors
306-
if npc_result.error is not None:
307-
return Err(npc_result.error), None
307+
assert conds is not None
308308

309-
assert npc_result.conds is not None
310-
311-
for spend in npc_result.conds.spends:
309+
for spend in conds.spends:
312310
removals.append(bytes32(spend.coin_id))
313311
removals_puzzle_dic[bytes32(spend.coin_id)] = bytes32(spend.puzzle_hash)
314312
for puzzle_hash, amount, _ in spend.create_coin:
315313
c = Coin(bytes32(spend.coin_id), bytes32(puzzle_hash), uint64(amount))
316314
additions.append((c, c.name()))
317315
else:
318-
assert npc_result is None
316+
assert conds is None
319317

320318
# 9. Check that the correct cost is in the transactions info
321319
if block.transactions_info.cost != cost:
@@ -459,10 +457,7 @@ async def validate_block_body(
459457

460458
# reserve fee cannot be greater than UINT64_MAX per consensus rule.
461459
# run_generator() would fail
462-
assert_fee_sum: uint64 = uint64(0)
463-
if npc_result:
464-
assert npc_result.conds is not None
465-
assert_fee_sum = uint64(npc_result.conds.reserve_fee)
460+
assert_fee_sum = uint64(0 if conds is None else conds.reserve_fee)
466461

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

484479
# 21. Verify conditions
485480
# verify absolute/relative height/time conditions
486-
if npc_result is not None:
487-
assert npc_result.conds is not None
488-
481+
if conds is not None:
489482
error = mempool_check_time_locks(
490483
removal_coin_records,
491-
npc_result.conds,
484+
conds,
492485
prev_transaction_block_height,
493486
prev_transaction_block_timestamp,
494487
)
495-
if error:
488+
if error is not None:
496489
return error, None
497490

498491
# create hash_key list for aggsig check
499492
pairs_pks: List[G1Element] = []
500493
pairs_msgs: List[bytes] = []
501-
if npc_result:
502-
assert npc_result.conds is not None
503-
pairs_pks, pairs_msgs = pkm_pairs(npc_result.conds, constants.AGG_SIG_ME_ADDITIONAL_DATA)
494+
if conds is not None:
495+
pairs_pks, pairs_msgs = pkm_pairs(conds, constants.AGG_SIG_ME_ADDITIONAL_DATA)
504496

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

523-
return None, npc_result
515+
return None, conds

chia/consensus/blockchain.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,6 @@ async def add_block(
338338
if prev_block.height + 1 != block.height:
339339
return AddBlockResult.INVALID_BLOCK, Err.INVALID_HEIGHT, None
340340

341-
npc_result: Optional[NPCResult] = pre_validation_result.npc_result
342341
required_iters = pre_validation_result.required_iters
343342
if pre_validation_result.error is not None:
344343
return AddBlockResult.INVALID_BLOCK, Err(pre_validation_result.error), None
@@ -412,7 +411,7 @@ async def add_block(
412411
# main chain, we still need to re-run it to update the additions and
413412
# removals in fork_info.
414413
await self.advance_fork_info(block, fork_info)
415-
fork_info.include_spends(None if npc_result is None else npc_result.conds, block, header_hash)
414+
fork_info.include_spends(pre_validation_result.conds, block, header_hash)
416415
self.add_block_record(block_rec)
417416
return AddBlockResult.ALREADY_HAVE_BLOCK, None, None
418417

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

449448
# block_to_block_record() require the previous block in the cache
450449
if not genesis and prev_block is not None:
@@ -781,7 +780,7 @@ async def validate_unfinished_block(
781780
self.coin_store.get_coin_records,
782781
block,
783782
uint32(prev_height + 1),
784-
npc_result,
783+
None if npc_result is None else npc_result.conds,
785784
fork_info,
786785
None,
787786
validate_signature=False, # Signature was already validated before calling this method, no need to validate

chia/consensus/multiprocess_validation.py

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
class PreValidationResult(Streamable):
4444
error: Optional[uint16]
4545
required_iters: Optional[uint64] # Iff error is None
46-
npc_result: Optional[NPCResult] # Iff error is None and block is a transaction block
46+
conds: Optional[SpendBundleConditions] # Iff error is None and block is a transaction block
4747
validated_signature: bool
4848
timing: uint32 # the time (in milliseconds) it took to pre-validate the block
4949

@@ -95,7 +95,7 @@ def batch_pre_validate_blocks(
9595
validation_time = time.monotonic() - validation_start
9696
results.append(
9797
PreValidationResult(
98-
uint16(npc_result.error), None, npc_result, False, uint32(validation_time * 1000)
98+
uint16(npc_result.error), None, npc_result.conds, False, uint32(validation_time * 1000)
9999
)
100100
)
101101
continue
@@ -144,7 +144,7 @@ def batch_pre_validate_blocks(
144144
PreValidationResult(
145145
error_int,
146146
required_iters,
147-
None if conds is None else NPCResult(None, conds),
147+
conds,
148148
successfully_validated_signatures,
149149
uint32(validation_time * 1000),
150150
)
@@ -164,7 +164,7 @@ async def pre_validate_blocks_multiprocessing(
164164
block_records: BlocksProtocol,
165165
blocks: Sequence[FullBlock],
166166
pool: Executor,
167-
npc_results: Dict[uint32, NPCResult],
167+
block_height_conds_map: Dict[uint32, SpendBundleConditions],
168168
*,
169169
sub_slot_iters: uint64,
170170
difficulty: uint64,
@@ -275,10 +275,8 @@ async def pre_validate_blocks_multiprocessing(
275275
prev_ses_block = block_rec
276276

277277
conditions_pickled = {}
278-
for k, v in npc_results.items():
279-
assert v.error is None
280-
assert v.conds is not None
281-
conditions_pickled[k] = bytes(v.conds)
278+
for k, v in block_height_conds_map.items():
279+
conditions_pickled[k] = bytes(v)
282280
futures = []
283281
# Pool of workers to validate blocks concurrently
284282
recent_blocks_bytes = {bytes(k): bytes(v) for k, v in recent_blocks.items()} # convert to bytes

chia/full_node/full_node.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1846,9 +1846,9 @@ async def add_block(
18461846
return None
18471847
validation_start = time.monotonic()
18481848
# Tries to add the block to the blockchain, if we already validated transactions, don't do it again
1849-
npc_results = {}
1850-
if pre_validation_result is not None and pre_validation_result.npc_result is not None:
1851-
npc_results[block.height] = pre_validation_result.npc_result
1849+
block_height_conds_map = {}
1850+
if pre_validation_result is not None and pre_validation_result.conds is not None:
1851+
block_height_conds_map[block.height] = pre_validation_result.conds
18521852

18531853
# Don't validate signatures because we want to validate them in the main thread later, since we have a
18541854
# cache available
@@ -1868,7 +1868,7 @@ async def add_block(
18681868
self.blockchain,
18691869
[block],
18701870
self.blockchain.pool,
1871-
npc_results,
1871+
block_height_conds_map,
18721872
sub_slot_iters=ssi,
18731873
difficulty=diff,
18741874
prev_ses_block=prev_ses_block,

0 commit comments

Comments
 (0)