From 4f00f639fc86ca01e75de6b50a9107236c184ac3 Mon Sep 17 00:00:00 2001 From: Amine Khaldi Date: Tue, 22 Oct 2024 20:15:26 +0100 Subject: [PATCH] CHIA-1565 Pass a ValidationState to validate_finished_header_block (#18712) Pass a ValidationState to validate_finished_header_block. --- chia/_tests/blockchain/test_blockchain.py | 76 +++++++---------------- chia/consensus/block_header_validation.py | 17 +++-- chia/consensus/multiprocess_validation.py | 4 +- chia/full_node/weight_proof.py | 4 +- chia/wallet/wallet_blockchain.py | 6 +- 5 files changed, 37 insertions(+), 70 deletions(-) diff --git a/chia/_tests/blockchain/test_blockchain.py b/chia/_tests/blockchain/test_blockchain.py index ae86f87b1399..55bbbe453a6d 100644 --- a/chia/_tests/blockchain/test_blockchain.py +++ b/chia/_tests/blockchain/test_blockchain.py @@ -172,13 +172,9 @@ async def test_long_chain(self, empty_blockchain: Blockchain, default_1000_block # TODO: Inspect these block values as they are currently None expected_difficulty = block.finished_sub_slots[0].challenge_chain.new_difficulty or uint64(0) expected_sub_slot_iters = block.finished_sub_slots[0].challenge_chain.new_sub_slot_iters or uint64(0) + vs = ValidationState(expected_sub_slot_iters, expected_difficulty, None) _, error = validate_finished_header_block( - empty_blockchain.constants, - empty_blockchain, - header_block_bad, - False, - expected_difficulty, - expected_sub_slot_iters, + empty_blockchain.constants, empty_blockchain, header_block_bad, False, vs ) assert error is not None assert error.code == Err.INVALID_NEW_SUB_SLOT_ITERS @@ -199,13 +195,9 @@ async def test_long_chain(self, empty_blockchain: Blockchain, default_1000_block # TODO: Inspect these block values as they are currently None expected_difficulty = block.finished_sub_slots[0].challenge_chain.new_difficulty or uint64(0) expected_sub_slot_iters = block.finished_sub_slots[0].challenge_chain.new_sub_slot_iters or uint64(0) + vs = ValidationState(expected_sub_slot_iters, expected_difficulty, None) _, error = validate_finished_header_block( - empty_blockchain.constants, - empty_blockchain, - header_block_bad_2, - False, - expected_difficulty, - expected_sub_slot_iters, + empty_blockchain.constants, empty_blockchain, header_block_bad_2, False, vs ) assert error is not None assert error.code == Err.INVALID_NEW_DIFFICULTY @@ -233,13 +225,9 @@ async def test_long_chain(self, empty_blockchain: Blockchain, default_1000_block # TODO: Inspect these block values as they are currently None expected_difficulty = block.finished_sub_slots[0].challenge_chain.new_difficulty or uint64(0) expected_sub_slot_iters = block.finished_sub_slots[0].challenge_chain.new_sub_slot_iters or uint64(0) + vs = ValidationState(expected_sub_slot_iters, expected_difficulty, None) _, error = validate_finished_header_block( - empty_blockchain.constants, - empty_blockchain, - header_block_bad_3, - False, - expected_difficulty, - expected_sub_slot_iters, + empty_blockchain.constants, empty_blockchain, header_block_bad_3, False, vs ) assert error is not None assert error.code == Err.INVALID_SUB_EPOCH_SUMMARY @@ -266,13 +254,9 @@ async def test_long_chain(self, empty_blockchain: Blockchain, default_1000_block # TODO: Inspect these block values as they are currently None expected_difficulty = block.finished_sub_slots[0].challenge_chain.new_difficulty or uint64(0) expected_sub_slot_iters = block.finished_sub_slots[0].challenge_chain.new_sub_slot_iters or uint64(0) + vs = ValidationState(expected_sub_slot_iters, expected_difficulty, None) _, error = validate_finished_header_block( - empty_blockchain.constants, - empty_blockchain, - header_block_bad_4, - False, - expected_difficulty, - expected_sub_slot_iters, + empty_blockchain.constants, empty_blockchain, header_block_bad_4, False, vs ) assert error is not None assert error.code == Err.INVALID_SUB_EPOCH_SUMMARY @@ -523,13 +507,11 @@ async def test_invalid_sub_slot_challenge_hash_genesis(self, empty_blockchain: B ) header_block_bad = get_block_header(block_0_bad, [], []) + vs = ValidationState( + empty_blockchain.constants.SUB_SLOT_ITERS_STARTING, empty_blockchain.constants.DIFFICULTY_STARTING, None + ) _, error = validate_finished_header_block( - empty_blockchain.constants, - empty_blockchain, - header_block_bad, - False, - empty_blockchain.constants.DIFFICULTY_STARTING, - empty_blockchain.constants.SUB_SLOT_ITERS_STARTING, + empty_blockchain.constants, empty_blockchain, header_block_bad, False, vs ) assert error is not None @@ -557,13 +539,9 @@ async def test_invalid_sub_slot_challenge_hash_non_genesis( # TODO: Inspect these block values as they are currently None expected_difficulty = blocks[1].finished_sub_slots[0].challenge_chain.new_difficulty or uint64(0) expected_sub_slot_iters = blocks[1].finished_sub_slots[0].challenge_chain.new_sub_slot_iters or uint64(0) + vs = ValidationState(expected_sub_slot_iters, expected_difficulty, None) _, error = validate_finished_header_block( - empty_blockchain.constants, - empty_blockchain, - header_block_bad, - False, - expected_difficulty, - expected_sub_slot_iters, + empty_blockchain.constants, empty_blockchain, header_block_bad, False, vs ) assert error is not None assert error.code == Err.INVALID_PREV_CHALLENGE_SLOT_HASH @@ -588,13 +566,9 @@ async def test_invalid_sub_slot_challenge_hash_empty_ss(self, empty_blockchain: # TODO: Inspect these block values as they are currently None expected_difficulty = blocks[1].finished_sub_slots[0].challenge_chain.new_difficulty or uint64(0) expected_sub_slot_iters = blocks[1].finished_sub_slots[0].challenge_chain.new_sub_slot_iters or uint64(0) + vs = ValidationState(expected_sub_slot_iters, expected_difficulty, None) _, error = validate_finished_header_block( - empty_blockchain.constants, - empty_blockchain, - header_block_bad, - False, - expected_difficulty, - expected_sub_slot_iters, + empty_blockchain.constants, empty_blockchain, header_block_bad, False, vs ) assert error is not None assert error.code == Err.INVALID_PREV_CHALLENGE_SLOT_HASH @@ -747,13 +721,9 @@ async def test_invalid_icc_into_cc(self, empty_blockchain: Blockchain, bt: Block # TODO: Inspect these block values as they are currently None expected_difficulty = block.finished_sub_slots[0].challenge_chain.new_difficulty or uint64(0) expected_sub_slot_iters = block.finished_sub_slots[0].challenge_chain.new_sub_slot_iters or uint64(0) + vs = ValidationState(expected_sub_slot_iters, expected_difficulty, None) _, error = validate_finished_header_block( - empty_blockchain.constants, - empty_blockchain, - header_block_bad, - False, - expected_difficulty, - expected_sub_slot_iters, + empty_blockchain.constants, empty_blockchain, header_block_bad, False, vs ) assert error is not None assert error.code == Err.INVALID_ICC_HASH_CC @@ -819,13 +789,11 @@ async def test_empty_slot_no_ses(self, empty_blockchain: Blockchain, bt: BlockTo ) header_block_bad = get_block_header(block_bad, [], []) + vs = ValidationState( + empty_blockchain.constants.SUB_SLOT_ITERS_STARTING, empty_blockchain.constants.DIFFICULTY_STARTING, None + ) _, error = validate_finished_header_block( - empty_blockchain.constants, - empty_blockchain, - header_block_bad, - False, - empty_blockchain.constants.DIFFICULTY_STARTING, - empty_blockchain.constants.SUB_SLOT_ITERS_STARTING, + empty_blockchain.constants, empty_blockchain, header_block_bad, False, vs ) assert error is not None assert error.code == Err.INVALID_SUB_EPOCH_SUMMARY_HASH diff --git a/chia/consensus/block_header_validation.py b/chia/consensus/block_header_validation.py index e2e5f3c19b67..4f1bd396463e 100644 --- a/chia/consensus/block_header_validation.py +++ b/chia/consensus/block_header_validation.py @@ -29,6 +29,7 @@ from chia.types.end_of_slot_bundle import EndOfSubSlotBundle from chia.types.header_block import HeaderBlock from chia.types.unfinished_header_block import UnfinishedHeaderBlock +from chia.types.validation_state import ValidationState from chia.util.errors import Err, ValidationError from chia.util.hash import std_hash from chia.util.ints import uint8, uint32, uint64, uint128 @@ -834,10 +835,8 @@ def validate_finished_header_block( blocks: BlockRecordsProtocol, header_block: HeaderBlock, check_filter: bool, - expected_difficulty: uint64, - expected_sub_slot_iters: uint64, + vs: ValidationState, check_sub_epoch_summary: bool = True, - prev_ses_block: Optional[BlockRecord] = None, ) -> tuple[Optional[uint64], Optional[ValidationError]]: """ Fully validates the header of a block. A header block is the same as a full block, but @@ -858,11 +857,11 @@ def validate_finished_header_block( blocks, unfinished_header_block, check_filter, - expected_difficulty, - expected_sub_slot_iters, + vs.current_difficulty, + vs.current_ssi, False, check_sub_epoch_summary=check_sub_epoch_summary, - prev_ses_block=prev_ses_block, + prev_ses_block=vs.prev_ses_block, ) genesis_block = False @@ -880,7 +879,7 @@ def validate_finished_header_block( ip_iters: uint64 = calculate_ip_iters( constants, - expected_sub_slot_iters, + vs.current_ssi, header_block.reward_chain_block.signage_point_index, required_iters, ) @@ -891,8 +890,8 @@ def validate_finished_header_block( return None, ValidationError(Err.INVALID_HEIGHT) # 28. Check weight - if header_block.weight != prev_b.weight + expected_difficulty: - log.error(f"INVALID WEIGHT: {header_block} {prev_b} {expected_difficulty}") + if header_block.weight != prev_b.weight + vs.current_difficulty: + log.error(f"INVALID WEIGHT: {header_block} {prev_b} {vs.current_difficulty}") return None, ValidationError(Err.INVALID_WEIGHT) else: # 27b. Check genesis block height, weight, and prev block hash diff --git a/chia/consensus/multiprocess_validation.py b/chia/consensus/multiprocess_validation.py index a4a1e542bc8b..2450135afb71 100644 --- a/chia/consensus/multiprocess_validation.py +++ b/chia/consensus/multiprocess_validation.py @@ -94,9 +94,7 @@ def pre_validate_block( blockchain, header_block, True, # check_filter - vs.current_difficulty, - vs.current_ssi, - prev_ses_block=vs.prev_ses_block, + vs, ) error_int: Optional[uint16] = None if error is not None: diff --git a/chia/full_node/weight_proof.py b/chia/full_node/weight_proof.py index f94309712731..f5f2c29dd713 100644 --- a/chia/full_node/weight_proof.py +++ b/chia/full_node/weight_proof.py @@ -31,6 +31,7 @@ from chia.types.blockchain_format.vdf import VDFInfo, VDFProof, validate_vdf from chia.types.end_of_slot_bundle import EndOfSubSlotBundle from chia.types.header_block import HeaderBlock +from chia.types.validation_state import ValidationState from chia.types.weight_proof import ( RecentChainData, SubEpochChallengeSegment, @@ -1253,8 +1254,9 @@ def validate_recent_blocks( adjusted = True deficit = get_deficit(constants, deficit, prev_block_record, overflow, len(block.finished_sub_slots)) if sub_slots > 2 and transaction_blocks > 11 and (tip_height - block.height < last_blocks_to_validate): + vs = ValidationState(ssi, diff, None) caluclated_required_iters, error = validate_finished_header_block( - constants, sub_blocks, block, False, diff, ssi, ses_blocks > 2 + constants, sub_blocks, block, False, vs, ses_blocks > 2 ) if error is not None: log.error(f"block {block.header_hash} failed validation {error}") diff --git a/chia/wallet/wallet_blockchain.py b/chia/wallet/wallet_blockchain.py index 24e7036c8596..11bea1374760 100644 --- a/chia/wallet/wallet_blockchain.py +++ b/chia/wallet/wallet_blockchain.py @@ -11,6 +11,7 @@ from chia.consensus.full_block_to_block_record import block_to_block_record from chia.types.blockchain_format.sized_bytes import bytes32 from chia.types.header_block import HeaderBlock +from chia.types.validation_state import ValidationState from chia.types.weight_proof import WeightProof from chia.util.errors import Err from chia.util.ints import uint32, uint64 @@ -110,9 +111,8 @@ async def add_block(self, block: HeaderBlock) -> tuple[AddBlockResult, Optional[ difficulty = self._difficulty # Validation requires a block cache (self) that goes back to a subepoch barrier - required_iters, error = validate_finished_header_block( - self.constants, self, block, False, difficulty, sub_slot_iters, False - ) + vs = ValidationState(sub_slot_iters, difficulty, None) + required_iters, error = validate_finished_header_block(self.constants, self, block, False, vs, False) if error is not None: return AddBlockResult.INVALID_BLOCK, error.code if required_iters is None: