Fix genesis bad signage point rc
This commit is contained in:
parent
d90d76446b
commit
cf84a9f339
|
@ -71,7 +71,7 @@ async def validate_unfinished_header_block(
|
|||
|
||||
overflow = is_overflow_sub_block(constants, header_block.reward_chain_sub_block.signage_point_index)
|
||||
|
||||
# 4. Check finished slots that have been crossed since prev_sb
|
||||
# 2. Check finished slots that have been crossed since prev_sb
|
||||
ses_hash: Optional[bytes32] = None
|
||||
if new_sub_slot:
|
||||
# Finished a slot(s) since previous block. The first sub-slot must have at least one sub-block, and all
|
||||
|
@ -82,7 +82,7 @@ async def validate_unfinished_header_block(
|
|||
|
||||
if finished_sub_slot_n == 0:
|
||||
if genesis_block:
|
||||
# 4a. check sub-slot challenge hash for genesis block
|
||||
# 2a. check sub-slot challenge hash for genesis block
|
||||
if challenge_hash != constants.FIRST_CC_CHALLENGE:
|
||||
return None, ValidationError(Err.INVALID_PREV_CHALLENGE_SLOT_HASH)
|
||||
else:
|
||||
|
@ -90,11 +90,11 @@ async def validate_unfinished_header_block(
|
|||
while not curr.first_in_sub_slot:
|
||||
curr = sub_blocks[curr.prev_hash]
|
||||
|
||||
# 4b. check sub-slot challenge hash for non-genesis block
|
||||
# 2b. check sub-slot challenge hash for non-genesis block
|
||||
if not curr.finished_challenge_slot_hashes[-1] == challenge_hash:
|
||||
return None, ValidationError(Err.INVALID_PREV_CHALLENGE_SLOT_HASH)
|
||||
else:
|
||||
# 4c. check sub-slot challenge hash for empty slot
|
||||
# 2c. check sub-slot challenge hash for empty slot
|
||||
if (
|
||||
not header_block.finished_sub_slots[finished_sub_slot_n - 1].challenge_chain.get_hash()
|
||||
== challenge_hash
|
||||
|
@ -102,7 +102,7 @@ async def validate_unfinished_header_block(
|
|||
return None, ValidationError(Err.INVALID_PREV_CHALLENGE_SLOT_HASH)
|
||||
|
||||
if genesis_block:
|
||||
# 4d. Validate that genesis block has no ICC
|
||||
# 2d. Validate that genesis block has no ICC
|
||||
if sub_slot.infused_challenge_chain is not None:
|
||||
return None, ValidationError(Err.SHOULD_NOT_HAVE_ICC)
|
||||
else:
|
||||
|
@ -147,11 +147,11 @@ async def validate_unfinished_header_block(
|
|||
icc_iters_proof = icc_iters_committed
|
||||
icc_vdf_input = ClassgroupElement.get_default_element()
|
||||
|
||||
# 4e. Validate that there is not icc iff icc_challenge hash is None
|
||||
# 2e. Validate that there is not icc iff icc_challenge hash is None
|
||||
assert (sub_slot.infused_challenge_chain is None) == (icc_challenge_hash is None)
|
||||
if sub_slot.infused_challenge_chain is not None:
|
||||
assert icc_vdf_input is not None
|
||||
# 4f. Check infused challenge chain sub-slot VDF
|
||||
# 2f. Check infused challenge chain sub-slot VDF
|
||||
# Only validate from prev_sb to optimize
|
||||
target_vdf_info = VDFInfo(
|
||||
icc_challenge_hash,
|
||||
|
@ -170,7 +170,7 @@ async def validate_unfinished_header_block(
|
|||
):
|
||||
return None, ValidationError(Err.INVALID_ICC_EOS_VDF)
|
||||
|
||||
# 4g. Check infused challenge sub-slot hash in challenge sub-slot
|
||||
# 2g. Check infused challenge sub-slot hash in challenge sub-slot
|
||||
if sub_slot.reward_chain.deficit == constants.MIN_SUB_BLOCKS_PER_CHALLENGE_BLOCK:
|
||||
if (
|
||||
sub_slot.infused_challenge_chain.get_hash()
|
||||
|
@ -181,7 +181,7 @@ async def validate_unfinished_header_block(
|
|||
if sub_slot.challenge_chain.infused_challenge_chain_sub_slot_hash is not None:
|
||||
return None, ValidationError(Err.INVALID_ICC_HASH_CC)
|
||||
|
||||
# 4h. Check infused challenge sub-slot hash in reward sub-slot
|
||||
# 2h. Check infused challenge sub-slot hash in reward sub-slot
|
||||
if (
|
||||
sub_slot.infused_challenge_chain.get_hash()
|
||||
!= sub_slot.reward_chain.infused_challenge_chain_sub_slot_hash
|
||||
|
@ -198,12 +198,12 @@ async def validate_unfinished_header_block(
|
|||
assert ses_hash is None # Only one of the slots can have it
|
||||
ses_hash = sub_slot.challenge_chain.subepoch_summary_hash
|
||||
|
||||
# 4i. check sub-epoch summary hash is None for empty slots
|
||||
# 2i. check sub-epoch summary hash is None for empty slots
|
||||
if finished_sub_slot_n != 0:
|
||||
if sub_slot.challenge_chain.subepoch_summary_hash is not None:
|
||||
return None, ValidationError(Err.INVALID_SUB_EPOCH_SUMMARY_HASH)
|
||||
|
||||
# 4j. Check new difficulty
|
||||
# 2j. Check new difficulty
|
||||
if finishes_epoch:
|
||||
if sub_slot.challenge_chain.new_ips != ips:
|
||||
return None, ValidationError(Err.INVALID_NEW_IPS)
|
||||
|
@ -215,14 +215,14 @@ async def validate_unfinished_header_block(
|
|||
if sub_slot.challenge_chain.new_difficulty is not None:
|
||||
return None, ValidationError(Err.INVALID_NEW_DIFFICULTY)
|
||||
|
||||
# 4k. Check challenge sub-slot hash in reward sub-slot
|
||||
# 2k. Check challenge sub-slot hash in reward sub-slot
|
||||
if sub_slot.challenge_chain.get_hash() != sub_slot.reward_chain.challenge_chain_sub_slot_hash:
|
||||
return None, ValidationError(
|
||||
Err.INVALID_CHALLENGE_SLOT_HASH_RC, "sub-slot hash in reward sub-slot mismatch"
|
||||
)
|
||||
|
||||
# 4l. Check challenge chain sub-slot VDF
|
||||
# 4m. Check end of reward slot VDF
|
||||
# 2l. Check challenge chain sub-slot VDF
|
||||
# 2m. Check end of reward slot VDF
|
||||
sub_slot_iters = calculate_sub_slot_iters(constants, ips)
|
||||
eos_vdf_iters: uint64 = sub_slot_iters
|
||||
cc_start_element: ClassgroupElement = ClassgroupElement.get_default_element()
|
||||
|
@ -279,7 +279,7 @@ async def validate_unfinished_header_block(
|
|||
if not sub_slot.proofs.challenge_chain_slot_proof.is_valid(constants, partial_cc_vdf_info, None):
|
||||
return None, ValidationError(Err.INVALID_CC_EOS_VDF)
|
||||
|
||||
# 4n. Check deficit (5 deficit edge case for genesis block)
|
||||
# 2n. Check deficit (5 deficit edge case for genesis block)
|
||||
if genesis_block:
|
||||
if sub_slot.reward_chain.deficit != constants.MIN_SUB_BLOCKS_PER_CHALLENGE_BLOCK:
|
||||
return None, ValidationError(
|
||||
|
@ -301,20 +301,20 @@ async def validate_unfinished_header_block(
|
|||
if sub_slot.reward_chain.deficit != prev_sb.deficit:
|
||||
return None, ValidationError(Err.INVALID_DEFICIT, "deficit is wrong at slot end")
|
||||
|
||||
# 5. Check sub-epoch summary
|
||||
# 3. Check sub-epoch summary
|
||||
# Note that the subepoch summary is the summary of the previous subepoch (not the one that just finished)
|
||||
if ses_hash is not None:
|
||||
# 5a. Check that genesis block does not have sub-epoch summary
|
||||
# 3a. Check that genesis block does not have sub-epoch summary
|
||||
if genesis_block:
|
||||
return None, ValidationError(Err.INVALID_SUB_EPOCH_SUMMARY, "genesis with sub-epoch-summary hash")
|
||||
|
||||
# 5b. Check that we finished a slot and we finished a sub-epoch
|
||||
# 3b. Check that we finished a slot and we finished a sub-epoch
|
||||
if not new_sub_slot or not finishes_se:
|
||||
return None, ValidationError(
|
||||
Err.INVALID_SUB_EPOCH_SUMMARY, f"new sub-slot: {new_sub_slot} finishes sub-epoch {finishes_se}"
|
||||
)
|
||||
|
||||
# 5c. Check the actual sub-epoch is correct
|
||||
# 3c. Check the actual sub-epoch is correct
|
||||
expected_sub_epoch_summary = make_sub_epoch_summary(
|
||||
constants,
|
||||
sub_blocks,
|
||||
|
@ -329,7 +329,7 @@ async def validate_unfinished_header_block(
|
|||
Err.INVALID_SUB_EPOCH_SUMMARY, f"expected ses hash: {expected_hash} got {ses_hash} "
|
||||
)
|
||||
elif new_sub_slot and not genesis_block:
|
||||
# 5d. Check that we don't have to include a sub-epoch summary
|
||||
# 3d. Check that we don't have to include a sub-epoch summary
|
||||
if finishes_sub_epoch(constants, prev_sb.height, prev_sb.deficit, False, sub_blocks, prev_sb.prev_hash):
|
||||
return None, ValidationError(
|
||||
Err.INVALID_SUB_EPOCH_SUMMARY, "block finishes sub-epoch but ses-hash is None"
|
||||
|
@ -366,7 +366,7 @@ async def validate_unfinished_header_block(
|
|||
challenge = reversed_challenge_hashes[challenges_to_look_for - 1]
|
||||
assert challenge is not None
|
||||
|
||||
# 2. Check proof of space
|
||||
# 4. Check proof of space
|
||||
if header_block.reward_chain_sub_block.challenge_chain_sp_vdf is None:
|
||||
# Edge case of first sp (start of slot), where sp_iters == 0
|
||||
cc_sp_hash: bytes32 = challenge
|
||||
|
@ -386,13 +386,19 @@ async def validate_unfinished_header_block(
|
|||
difficulty,
|
||||
cc_sp_hash,
|
||||
)
|
||||
# 3. check signage point index
|
||||
# 5. check signage point index is between 0 and 31
|
||||
if (
|
||||
header_block.reward_chain_sub_block.signage_point_index < 0
|
||||
or header_block.reward_chain_sub_block.signage_point_index >= constants.NUM_SPS_SUB_SLOT
|
||||
):
|
||||
return None, ValidationError(Err.INVALID_SP_INDEX)
|
||||
|
||||
# 6. check signage point index 0 has no sp
|
||||
if (header_block.reward_chain_sub_block.signage_point_index == 0) != (
|
||||
header_block.reward_chain_sub_block.challenge_chain_sp_vdf is None
|
||||
):
|
||||
return None, ValidationError(Err.INVALID_SP_INDEX)
|
||||
|
||||
sp_iters: uint64 = calculate_sp_iters(constants, ips, header_block.reward_chain_sub_block.signage_point_index)
|
||||
ip_iters: uint64 = calculate_ip_iters(
|
||||
constants, ips, header_block.reward_chain_sub_block.signage_point_index, required_iters
|
||||
|
@ -402,7 +408,7 @@ async def validate_unfinished_header_block(
|
|||
# Blocks with very low required iters are not overflow blocks
|
||||
assert not overflow
|
||||
|
||||
# 6. Check no overflows in the first sub-slot of a new epoch (although they are OK in the second sub-slot)
|
||||
# 7. Check no overflows in the first sub-slot of a new epoch (although they are OK in the second sub-slot)
|
||||
if overflow and finishes_epoch and len(header_block.finished_sub_slots) < 2:
|
||||
return None, ValidationError(Err.NO_OVERFLOWS_IN_FIRST_SUB_SLOT_NEW_EPOCH)
|
||||
|
||||
|
|
|
@ -267,6 +267,7 @@ class BlockTools:
|
|||
# If did not reach the target slots to skip, don't make any proofs for this sub-slot
|
||||
num_empty_slots_added += 1
|
||||
else:
|
||||
# Loop over every signage point (Except for the last ones, which are used for overflows)
|
||||
for signage_point_index in range(0, constants.NUM_SPS_SUB_SLOT - constants.NUM_SP_INTERVALS_EXTRA):
|
||||
curr = latest_sub_block
|
||||
while curr.total_iters > sub_slot_start_total_iters + calculate_sp_iters(
|
||||
|
@ -486,6 +487,7 @@ class BlockTools:
|
|||
for signage_point_index in range(
|
||||
constants.NUM_SPS_SUB_SLOT - constants.NUM_SP_INTERVALS_EXTRA, constants.NUM_SPS_SUB_SLOT
|
||||
):
|
||||
# note that we are passing in the finished slots which include the last slot
|
||||
signage_point: SignagePoint = get_signage_point(
|
||||
constants,
|
||||
sub_blocks,
|
||||
|
@ -588,7 +590,6 @@ class BlockTools:
|
|||
# Keep trying until we get a good proof of space that also passes sp filter
|
||||
while True:
|
||||
cc_challenge, rc_challenge = get_genesis_challenges(constants, finished_sub_slots)
|
||||
|
||||
for signage_point_index in range(0, constants.NUM_SPS_SUB_SLOT):
|
||||
signage_point: SignagePoint = get_signage_point(
|
||||
constants,
|
||||
|
@ -676,58 +677,60 @@ class BlockTools:
|
|||
constants.DIFFICULTY_STARTING,
|
||||
)
|
||||
|
||||
# Finish the end of sub-slot and try again next sub-slot
|
||||
cc_vdf, cc_proof = get_vdf_info_and_proof(
|
||||
constants,
|
||||
ClassgroupElement.get_default_element(),
|
||||
cc_challenge,
|
||||
sub_slot_iters,
|
||||
)
|
||||
rc_vdf, rc_proof = get_vdf_info_and_proof(
|
||||
constants,
|
||||
ClassgroupElement.get_default_element(),
|
||||
rc_challenge,
|
||||
sub_slot_iters,
|
||||
)
|
||||
cc_slot = ChallengeChainSubSlot(cc_vdf, None, None, None, None)
|
||||
finished_sub_slots.append(
|
||||
EndOfSubSlotBundle(
|
||||
cc_slot,
|
||||
None,
|
||||
RewardChainSubSlot(
|
||||
rc_vdf,
|
||||
cc_slot.get_hash(),
|
||||
if signage_point_index == constants.NUM_SPS_SUB_SLOT - constants.NUM_SP_INTERVALS_EXTRA - 1:
|
||||
# Finish the end of sub-slot and try again next sub-slot
|
||||
cc_vdf, cc_proof = get_vdf_info_and_proof(
|
||||
constants,
|
||||
ClassgroupElement.get_default_element(),
|
||||
cc_challenge,
|
||||
sub_slot_iters,
|
||||
)
|
||||
rc_vdf, rc_proof = get_vdf_info_and_proof(
|
||||
constants,
|
||||
ClassgroupElement.get_default_element(),
|
||||
rc_challenge,
|
||||
sub_slot_iters,
|
||||
)
|
||||
cc_slot = ChallengeChainSubSlot(cc_vdf, None, None, None, None)
|
||||
finished_sub_slots.append(
|
||||
EndOfSubSlotBundle(
|
||||
cc_slot,
|
||||
None,
|
||||
RewardChainSubSlot(
|
||||
rc_vdf,
|
||||
cc_slot.get_hash(),
|
||||
None,
|
||||
uint8(constants.MIN_SUB_BLOCKS_PER_CHALLENGE_BLOCK),
|
||||
),
|
||||
SubSlotProofs(cc_proof, None, rc_proof),
|
||||
)
|
||||
)
|
||||
|
||||
if unfinished_block is not None:
|
||||
cc_ip_vdf, cc_ip_proof = get_vdf_info_and_proof(
|
||||
constants,
|
||||
ClassgroupElement.get_default_element(),
|
||||
finished_sub_slots[-1].challenge_chain.get_hash(),
|
||||
ip_iters,
|
||||
)
|
||||
rc_ip_vdf, rc_ip_proof = get_vdf_info_and_proof(
|
||||
constants,
|
||||
ClassgroupElement.get_default_element(),
|
||||
finished_sub_slots[-1].reward_chain.get_hash(),
|
||||
ip_iters,
|
||||
)
|
||||
return unfinished_block_to_full_block(
|
||||
unfinished_block,
|
||||
cc_ip_vdf,
|
||||
cc_ip_proof,
|
||||
rc_ip_vdf,
|
||||
rc_ip_proof,
|
||||
None,
|
||||
uint8(constants.MIN_SUB_BLOCKS_PER_CHALLENGE_BLOCK),
|
||||
),
|
||||
SubSlotProofs(cc_proof, None, rc_proof),
|
||||
)
|
||||
)
|
||||
if unfinished_block is not None:
|
||||
cc_ip_vdf, cc_ip_proof = get_vdf_info_and_proof(
|
||||
constants,
|
||||
ClassgroupElement.get_default_element(),
|
||||
finished_sub_slots[-1].challenge_chain.get_hash(),
|
||||
ip_iters,
|
||||
)
|
||||
rc_ip_vdf, rc_ip_proof = get_vdf_info_and_proof(
|
||||
constants,
|
||||
ClassgroupElement.get_default_element(),
|
||||
finished_sub_slots[-1].reward_chain.get_hash(),
|
||||
ip_iters,
|
||||
)
|
||||
return unfinished_block_to_full_block(
|
||||
unfinished_block,
|
||||
cc_ip_vdf,
|
||||
cc_ip_proof,
|
||||
rc_ip_vdf,
|
||||
rc_ip_proof,
|
||||
None,
|
||||
None,
|
||||
finished_sub_slots,
|
||||
None,
|
||||
constants.DIFFICULTY_STARTING,
|
||||
)
|
||||
None,
|
||||
finished_sub_slots,
|
||||
None,
|
||||
constants.DIFFICULTY_STARTING,
|
||||
)
|
||||
sub_slot_total_iters += sub_slot_iters
|
||||
|
||||
def get_pospaces_for_challenge(
|
||||
|
|
|
@ -193,6 +193,7 @@ class TestAddingMoreBlocks:
|
|||
for i in range(num_blocks):
|
||||
blocks = bt.get_consecutive_blocks(test_constants, 1, block_list=blocks, skip_slots=2, force_overflow=True)
|
||||
result, err, _ = await blockchain.receive_block(blocks[-1])
|
||||
assert err is None
|
||||
assert result == ReceiveBlockResult.NEW_PEAK
|
||||
assert blockchain.get_peak().height == num_blocks - 1
|
||||
|
||||
|
|
Loading…
Reference in New Issue