Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
206 changes: 104 additions & 102 deletions chia/_tests/blockchain/test_blockchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,124 +160,126 @@ async def test_genesis_validate_1(self, empty_blockchain: Blockchain, bt: BlockT


class TestBlockHeaderValidation:
@pytest.mark.limit_consensus_modes(reason="save time")
@pytest.mark.anyio
async def test_long_chain(self, empty_blockchain: Blockchain, default_1000_blocks: list[FullBlock]) -> None:
blocks = default_1000_blocks
fork_info = ForkInfo(blocks[0].height - 1, blocks[0].height - 1, blocks[0].prev_header_hash)
for block in blocks:
if (
len(block.finished_sub_slots) > 0
and block.finished_sub_slots[0].challenge_chain.subepoch_summary_hash is not None
len(block.finished_sub_slots) == 0
or block.finished_sub_slots[0].challenge_chain.subepoch_summary_hash is None
):
# Sub/Epoch. Try using a bad ssi and difficulty to test 2m and 2n
new_finished_ss = recursive_replace(
block.finished_sub_slots[0],
"challenge_chain.new_sub_slot_iters",
uint64(10_000_000),
)
block_bad = recursive_replace(
block, "finished_sub_slots", [new_finished_ss, *block.finished_sub_slots[1:]]
)
header_block_bad = get_block_header(block_bad)
# 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)
expected_vs = ValidationState(expected_sub_slot_iters, expected_difficulty, None)
_, error = validate_finished_header_block(
empty_blockchain.constants, empty_blockchain, header_block_bad, False, expected_vs
)
assert error is not None
assert error.code == Err.INVALID_NEW_SUB_SLOT_ITERS
await _validate_and_add_block(empty_blockchain, block, fork_info=fork_info)
continue

# Also fails calling the outer methods, but potentially with a different error
await _validate_and_add_block(
empty_blockchain, block_bad, expected_result=AddBlockResult.INVALID_BLOCK, fork_info=fork_info
)
# TODO: deduplicate the test code, perhaps by parameterizing the
# test

new_finished_ss_2 = recursive_replace(
block.finished_sub_slots[0],
"challenge_chain.new_difficulty",
uint64(10_000_000),
)
block_bad_2 = recursive_replace(
block, "finished_sub_slots", [new_finished_ss_2, *block.finished_sub_slots[1:]]
)
# Sub/Epoch. Try using a bad ssi and difficulty to test 2m and 2n
new_finished_ss = recursive_replace(
block.finished_sub_slots[0],
"challenge_chain.new_sub_slot_iters",
uint64(10_000_000),
)
block_bad = recursive_replace(block, "finished_sub_slots", [new_finished_ss, *block.finished_sub_slots[1:]])
header_block_bad = get_block_header(block_bad)
# 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)
expected_vs = ValidationState(expected_sub_slot_iters, expected_difficulty, None)
_, error = validate_finished_header_block(
empty_blockchain.constants, empty_blockchain, header_block_bad, False, expected_vs
)
assert error is not None
assert error.code == Err.INVALID_NEW_SUB_SLOT_ITERS

header_block_bad_2 = get_block_header(block_bad_2)
# 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)
expected_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_vs
)
assert error is not None
assert error.code == Err.INVALID_NEW_DIFFICULTY
# Also fails calling the outer methods, but potentially with a different error
await _validate_and_add_block(
empty_blockchain, block_bad, expected_result=AddBlockResult.INVALID_BLOCK, fork_info=fork_info
)

# Also fails calling the outer methods, but potentially with a different error
await _validate_and_add_block(
empty_blockchain, block_bad_2, expected_result=AddBlockResult.INVALID_BLOCK, fork_info=fork_info
)
new_finished_ss = recursive_replace(
block.finished_sub_slots[0],
"challenge_chain.new_difficulty",
uint64(10_000_000),
)
block_bad = recursive_replace(block, "finished_sub_slots", [new_finished_ss, *block.finished_sub_slots[1:]])

header_block_bad = get_block_header(block_bad)
# 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)
expected_vs = ValidationState(expected_sub_slot_iters, expected_difficulty, None)
_, error = validate_finished_header_block(
empty_blockchain.constants, empty_blockchain, header_block_bad, False, expected_vs
)
assert error is not None
assert error.code == Err.INVALID_NEW_DIFFICULTY

# 3c
new_finished_ss_3: EndOfSubSlotBundle = recursive_replace(
block.finished_sub_slots[0],
"challenge_chain.subepoch_summary_hash",
bytes([0] * 32),
)
new_finished_ss_3 = recursive_replace(
new_finished_ss_3,
"reward_chain.challenge_chain_sub_slot_hash",
new_finished_ss_3.challenge_chain.get_hash(),
)
log.warning(f"Number of slots: {len(block.finished_sub_slots)}")
block_bad_3 = recursive_replace(block, "finished_sub_slots", [new_finished_ss_3])
# Also fails calling the outer methods, but potentially with a different error
await _validate_and_add_block(
empty_blockchain, block_bad, expected_result=AddBlockResult.INVALID_BLOCK, fork_info=fork_info
)

header_block_bad_3 = get_block_header(block_bad_3)
# 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)
expected_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_vs
)
assert error is not None
assert error.code == Err.INVALID_SUB_EPOCH_SUMMARY
# 3c
new_finished_ss = recursive_replace(
block.finished_sub_slots[0],
"challenge_chain.subepoch_summary_hash",
bytes([0] * 32),
)
new_finished_ss = recursive_replace(
new_finished_ss,
"reward_chain.challenge_chain_sub_slot_hash",
new_finished_ss.challenge_chain.get_hash(),
)
log.warning(f"Number of slots: {len(block.finished_sub_slots)}")
block_bad = recursive_replace(block, "finished_sub_slots", [new_finished_ss])

header_block_bad = get_block_header(block_bad)
# 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)
expected_vs = ValidationState(expected_sub_slot_iters, expected_difficulty, None)
_, error = validate_finished_header_block(
empty_blockchain.constants, empty_blockchain, header_block_bad, False, expected_vs
)
assert error is not None
assert error.code == Err.INVALID_SUB_EPOCH_SUMMARY

# Also fails calling the outer methods, but potentially with a different error
await _validate_and_add_block(
empty_blockchain, block_bad_3, expected_result=AddBlockResult.INVALID_BLOCK, fork_info=fork_info
)
# Also fails calling the outer methods, but potentially with a different error
await _validate_and_add_block(
empty_blockchain, block_bad, expected_result=AddBlockResult.INVALID_BLOCK, fork_info=fork_info
)

# 3d
new_finished_ss_4 = recursive_replace(
block.finished_sub_slots[0],
"challenge_chain.subepoch_summary_hash",
std_hash(b"123"),
)
new_finished_ss_4 = recursive_replace(
new_finished_ss_4,
"reward_chain.challenge_chain_sub_slot_hash",
new_finished_ss_4.challenge_chain.get_hash(),
)
block_bad_4 = recursive_replace(block, "finished_sub_slots", [new_finished_ss_4])
# 3d
new_finished_ss = recursive_replace(
block.finished_sub_slots[0],
"challenge_chain.subepoch_summary_hash",
std_hash(b"123"),
)
new_finished_ss = recursive_replace(
new_finished_ss,
"reward_chain.challenge_chain_sub_slot_hash",
new_finished_ss.challenge_chain.get_hash(),
)
block_bad = recursive_replace(block, "finished_sub_slots", [new_finished_ss])

header_block_bad = get_block_header(block_bad)
# 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)
expected_vs = ValidationState(expected_sub_slot_iters, expected_difficulty, None)
_, error = validate_finished_header_block(
empty_blockchain.constants, empty_blockchain, header_block_bad, False, expected_vs
)
assert error is not None
assert error.code == Err.INVALID_SUB_EPOCH_SUMMARY

header_block_bad_4 = get_block_header(block_bad_4)
# 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)
expected_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_vs
)
assert error is not None
assert error.code == Err.INVALID_SUB_EPOCH_SUMMARY
# Also fails calling the outer methods, but potentially with a different error
await _validate_and_add_block(
empty_blockchain, block_bad, expected_result=AddBlockResult.INVALID_BLOCK, fork_info=fork_info
)

# Also fails calling the outer methods, but potentially with a different error
await _validate_and_add_block(
empty_blockchain, block_bad_4, expected_result=AddBlockResult.INVALID_BLOCK, fork_info=fork_info
)
await _validate_and_add_block(empty_blockchain, block, fork_info=fork_info)
log.info(
f"Added block {block.height} total iters {block.total_iters} new slot? {len(block.finished_sub_slots)}"
Expand Down Expand Up @@ -1443,7 +1445,7 @@ async def test_pool_target_contract(
new_fsb_sig = bt.get_plot_signature(new_m, blocks[-1].reward_chain_block.proof_of_space.plot_public_key)
block_bad = recursive_replace(block_bad, "foliage.foliage_block_data_signature", new_fsb_sig)
await _validate_and_add_block(empty_blockchain, block_bad, expected_error=Err.INVALID_POOL_TARGET)
return None
return
attempts += 1

@pytest.mark.anyio
Expand Down
Loading