Skip to content

fix: prev_randao#279

Open
constwz wants to merge 2 commits intofeat/update-to-latest-rethfrom
fix-prev_randao
Open

fix: prev_randao#279
constwz wants to merge 2 commits intofeat/update-to-latest-rethfrom
fix-prev_randao

Conversation

@constwz
Copy link
Contributor

@constwz constwz commented Mar 10, 2026

Summary

  • Bug: The PREVRANDAO opcode returns different values during block building vs block validation, causing state root mismatches for any contract that reads PREVRANDAO
  • Root cause: Block building path set prevrandao = mix_hash (B256::ZERO or millisecond timestamp), while validation path set prevrandao = header.difficulty() (Parlia INTURN=2 / NOTURN=1)
  • Fix: Set prev_randao to the calculated difficulty in prepare_new_attributes, and restore the correct mix_hash in finalize_new_header (since the assembler derives mix_hash from prevrandao)

Details

In BSC's Parlia consensus, the PREVRANDAO EVM opcode returns the block difficulty (not a random value like Ethereum PoS). Two code paths configure the EVM environment:

Path prevrandao value Used for
BscEvmConfig::evm_env (validation) header.difficulty() Verifying existing blocks
BscEvmConfig::next_evm_env (building) attributes.prev_randao = mix_hash Building new blocks

The mix_hash field in BSC is B256::ZERO (pre-Lorentz) or encodes the millisecond timestamp part (post-Lorentz) — neither matches the difficulty value. This causes the PREVRANDAO opcode to return different results during building vs validation.

Changes in src/node/miner/util.rs

  1. prepare_new_attributes: Changed prev_randao from new_header.mix_hash to calculate_difficulty(&snapshot, signer).into() — matching the validation path
  2. finalize_new_header: Added mix_hash restoration after the assembler sets it from prevrandao. Recomputes the correct value using block_time_for_ramanujan_fork (B256::ZERO pre-Lorentz, millisecond part post-Lorentz)

Test plan

  • Verify cargo check passes (confirmed locally)
  • Run validator node on testnet and confirm blocks are accepted by peers
  • Verify mix_hash in produced block headers matches expected format (zero pre-Lorentz, ms-encoded post-Lorentz)

🤖 Generated with Claude Code

@constwz constwz requested a review from joey0612 as a code owner March 10, 2026 08:13
…d building paths

Three tests verify the PREVRANDAO opcode behavior in BSC's post-merge EVM:

1. prevrandao_opcode_returns_prevrandao_not_difficulty: confirms opcode 0x44
   reads from BlockEnv.prevrandao (not difficulty) in post-merge spec
2. prevrandao_mismatch_between_validation_and_building_paths: reproduces
   the bug where validation sets prevrandao=difficulty but building (before
   fix) sets prevrandao=mix_hash, causing different opcode outputs
3. prevrandao_consistency_for_noturn_difficulty: covers the DIFF_NOTURN case

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants