Skip to content

Conversation

@clydemeng
Copy link

📋 Summary

This PR implements the complete BSC (Binance Smart Chain) consensus validation system, enabling full BSC testnet synchronization with proper Parlia consensus rules. The implementation includes critical seal verification, validator set management, and snapshot handling that were missing from the initial BSC support.

🎉 Status: Full BSC testnet node successfully synced and continuously syncing on EC2!


🔧 Key Features Implemented

1. Complete Seal Hash Validation

  • Fixed critical ECDSA signature verification with proper BSC-specific seal hash calculation
  • Implemented post-EIP-4844 conditional RLP encoding matching zoro_reth approach
  • Added recover_proposer_from_seal function with correct recovery ID handling
  • Resolves: Block validation failures like "Invalid difficulty" and "Unauthorized proposer"

2. Validator Set Snapshot Management

  • Complete snapshot provider implementation with MDBX database persistence
  • Epoch boundary detection and checkpoint header fetching for validator updates
  • Real-time validator set parsing from system contract upgrade transactions
  • Snapshot caching and persistence every 1024 blocks for performance

3. BSC-Specific Consensus Rules

  • Turn-based proposing validation with proper difficulty checks (in-turn=2, out-of-turn=1)
  • Block time validation for Ramanujan fork timestamp rules
  • System transaction validation with proper BSC transaction splitting
  • Gas limit validation with BSC-specific hardfork-aware rules

4. Enhanced Database Integration

  • Custom ParliaSnapshots database table for efficient snapshot storage
  • Proper checkpoint header lookup from storage during execution
  • Ancestor map handling for out-of-order block processing
  • Database-backed snapshot provider with fallback mechanisms

🐛 Critical Issues Fixed

Issue #1: Seal Hash Calculation

❌ Before: "Invalid difficulty" errors during block validation
✅ After: Correct ECDSA signature verification with proper seal hash

Issue #2: Validator Set Snapshots

❌ Before: Empty/incorrect validator sets causing "Unauthorized proposer" 
✅ After: Accurate validator sets loaded from checkpoint headers

Issue #3: Database Integration

❌ Before: Snapshots not persisted, validation always failed
✅ After: Proper MDBX storage with efficient lookup and caching

📁 Files Changed

Core Consensus Logic

  • src/consensus/parlia/consensus.rs - Main consensus implementation
  • src/consensus/parlia/validation.rs - NEW: BSC-specific validation rules
  • src/consensus/parlia/snapshot.rs - Enhanced snapshot management
  • src/consensus/parlia/provider.rs - Database-backed snapshot provider

Executor Integration

  • src/node/evm/executor.rs - Validator set parsing during execution
  • src/consensus/parlia/db.rs - NEW: Custom database table implementation

Networking & Configuration

  • src/node/bsc_consensus.rs - DELETED: Simplified architecture
  • src/consensus/parlia/engine/ - DELETED: Removed redundant engine modules

🧪 Testing & Validation

Unit Tests

  • ✅ Seal recovery tests for real BSC blocks (block 43132201 for testnet)
  • ✅ Snapshot creation and validator set parsing
  • ✅ Database persistence and lookup functionality

Integration Testing

  • Full BSC testnet sync from genesis to latest block
  • Continuous sync maintaining consensus with BSC network
  • Real validator set updates at epoch boundaries (every 200 blocks)

Performance Validation

  • Efficient snapshot caching (1024-block intervals)
  • Optimized database queries for validator lookup
  • Memory-efficient validator set management

🔍 Technical Implementation Details

Seal Verification Algorithm

// Post-EIP-4844 conditional RLP encoding (matching zoro_reth)
fn calculate_seal_hash(header: &Header) -> B256 {
    let mut rlp_header = header.clone();
    rlp_header.extra_data = header.extra_data[..header.extra_data.len() - 65].into();
    
    // Conditional fields for post-4844 blocks
    if header.parent_beacon_block_root.is_some() {
        rlp_header.blob_gas_used = header.blob_gas_used;
        rlp_header.excess_blob_gas = header.excess_blob_gas;
        rlp_header.parent_beacon_block_root = header.parent_beacon_block_root;
    }
    
    keccak256(alloy_rlp::encode(&rlp_header))
}

Validator Set Management

// Real-time validator parsing from system contracts
fn parse_validator_set_update(receipt: &Receipt) -> Option<ValidatorUpdate> {
    // Parse system contract logs for validator changes
    // Extract new validator addresses and vote addresses
    // Update snapshot with new validator set
}

Database Schema

/// Custom table for Parlia snapshots
#[derive(Debug)]
pub struct ParliaSnapshots;

impl Table for ParliaSnapshots {
    type Key = u64;           // Block number
    type Value = Snapshot;    // Serialized snapshot data
}

🎯 Before vs After

Before This PR:

  • ❌ BSC blocks failed validation with "Invalid difficulty"
  • ❌ Validator sets were empty or incorrect
  • ❌ No database persistence for snapshots
  • ❌ Could not sync past early BSC blocks

After This PR:

  • Full BSC testnet synchronization working
  • Accurate validator set tracking with real-time updates
  • Efficient database-backed snapshots with persistence
  • Production-ready BSC node continuously syncing

🚀 Impact & Benefits

For Developers

  • Complete BSC consensus implementation ready for mainnet
  • Clean, well-documented codebase following Rust best practices
  • Comprehensive test coverage for all consensus rules

For Operations

  • Stable BSC full node with proven sync capability
  • Efficient resource usage with optimized snapshot caching
  • Production-ready database integration with MDBX

For BSC Ecosystem

  • Full compatibility with BSC testnet and mainnet
  • Accurate validator tracking for staking and governance
  • Foundation for BSC-specific features (RPC endpoints, etc.)

clydemeng added 30 commits July 3, 2025 15:21
…sus/FullConsensus) to plug into the pipeline
clydemeng and others added 29 commits August 4, 2025 21:10
…ks (#2)

fix: Post-4844 support: Conditional field encoding for newer BSC blocks
* chore: polish parlia

* chore: try polish parlia snap related code

* chore: add more log

* chore: try fix request hash

* chore: polish trivals
* chore: try polish snap apply workflow

* chore: polish some trivals

* chore: polish seal hash func
will-2012 added a commit to will-2012/reth-bsc that referenced this pull request Dec 20, 2025
* feat: seal block with signing_key

* remove redundant code

* try get signed tx from txpool

* feat: seal block in the validator

* feat: import block to local and network

* feat: add support of miner engine

* feat: seal block before ensure_well_formed_payload

* feat: add a init genesis_local.json to pass the cargo check (loocapro#37)

* feat: use TransactionSigned Pool (loocapro#38)

* chore: polish some trivals by failed action (loocapro#39)

* chore: polish trival by failed action

* chore: polish trival

* Dike miner (loocapro#41)

* feat: succeed to mine block

* feat: mine block but receive the RecoverECDSAInnerError

* remove useless code

* initial implementation

* fix blob header validation

* feat: add support of bsc protocol

* Update src/main.rs

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* feat: add payload builder skeleton (loocapro#44)

* feat: add payload builder skeleton

* chore: refine payload builder skeleton

* chore: polish some args

* chore: refine payload builder skeleton

* chore: polish some trivals

* chore: add prepare args for miner new block

* chore: refine prepare timestamp

* chore: add some todos

* chore: polish some trivals

* chore: add is_miner for payload builder

* chore: polish some codes

* chore: polish some trivals

* chore: add system-contract and system-tx in miner mode

* chore: add signer for system tx and block seal

* chore: polish some trivals

* chore: polish finalize new header workflow

* chore: add new block seal workflow

* chore: refine some trivals

* chore: refine some trivals

* chore: refine code by failed actions

* chore: polish some code again

* chore: fix parent ts

* fix: add keystore parser (loocapro#48)

Co-authored-by: Clyde <clyde.m@nodereal.io>

* fix: fix signature in the seal block (loocapro#49)

* chore: refine miner skeleton (loocapro#50)

* chore: refine miner skeleton

* chore: fix failed action

* chore: fix failed action

* chore: remove useless code to more clear (loocapro#54)

* chore: add chan-head event loop (loocapro#57)

* chore: add chan-head event loop

* chore: remove stale ut

* chore: polish some trivals and add some todos (loocapro#58)

* chore: polish some trivals to easy debug (loocapro#60)

* chore: polish some trivals to easy debug

* chore: refine by failed action

* fix: remove  duplicate hash calcu (loocapro#61)

* chore: bypass newblock systemts check (loocapro#62)

* chore: fix parent_beacon_block_root (loocapro#63)

* chore: fix parent_beacon_block_root

* chore: polish by clippy

* fix: state root mismatch in engine-tree rerun (loocapro#64)

* chore: add new-work-worker to make schedule logic more clear (loocapro#70)

* add support of user transaction to validator (#72)

* chore: add main-work-worker to make miner skeleton more clear (#74)

* chore: add mainWorkWorker to more clear

* chore: polish main-worker to more clear

* chore: polish some trivals

* chore: polish some trivals

* chore: add blockbuilder to assemble system-tx (#75)

* chore: add system-txs to miner assemble

chore: polish some trivals

chore: make system-tx included

chore: some polishes

chore: polish block builder

* chore: polish some trivals

* chore: polish by failed action

* feat: implement reorg logic

* bsc: match geth system-tx gas; enforce Parlia scheduling; remove env bypasses

- Compute intrinsic normally and subtract post-exec for system tx; zero refunds (geth parity)
- Remove RETH_BSC_IGNORE_* flags; enforce backoff/time, sign-recently, and in-turn checks
- Fix fast finality gating per header in reorg_needed_with_fast_finality
- Minor cleanups (imports, miner wiring)

* revert: restore revm_spec_by_timestamp_and_block_number ordering (Cancun after Haber)

- Revert preference of Cancun before other timestamp forks; match prior behavior (14f2bbf)
- Keeps dynamic ordering for Gibbs/Moran/Nano; no other logic changes

* revert: drop London gating and fallback in revm_spec_by_timestamp_and_block_number

- Remove external London/Shanghai gating and prefer pure timestamp ordering
- Keep dynamic Gibbs/Moran/Nano, followed by remaining block-based forks

* chore: fix PR review and clippy

* some clean up

* chore: fix hf bug to pass 8th block in devnet (#81)

* chore: fix some bugs about hf to pass 8th block

* chore: fix hf bug to pass 8th block in devnet

* chore: polish some trivals

* chore: fix the epoch length (#82)

* Revert "chore: fix the epoch length (#82)" (#83)

This reverts commit b92b10a428188b5ec99a1e86489a399a0a653629.

* Revert "chore: fix hf bug to pass 8th block in devnet (#81)" (#84)

This reverts commit cd4972760a9c28e439caf219e612c57da0b05a6d.

* Revert "Re org logic" (#85)

* chore: clean up prague HF

* add support of FF reorg (#87)

* add support of FF reorg

* fix review comments

* chore: convert execution-err to validation-err and avoid thread exit (#89)

* chore: enhance header/snapshot index by block_hash (#90)

* chore: add snap_by_hash workflow

* chore: add rebuild snapshot by hash

* chore: polish by_hash query

* chore: polish by-hash index

* chore: polish some trivals

* chore: polish by failed action

* chore: add new_block_hashes handler to make miner less slashed (#92)

* chore: add new_block_hashes handler to catch head more timely

* chore: polish some trivals

* chore: polish by review tips

* chore: try mine at startup to reduce slash (#94)

* feat: add support of bls keys and improve key manager

* feat: blob impl (#93)

* feat(parlia+network): produce/broadcast votes; fix attestation target hash

* feat: assigned the blob sidecar of the seal block (#99)

* review fixes

* chore: make miner payload-build workflow asynced  (#104)

* chore: polish some trivals

* chore: add some todos

* chore: add main worker

* chore: add payload job

* chore: add draft payload job wrapper

* chore: add result worker

* chore: main-work-woker async build payload

* chore: polish abort workflow

* chore: polish some trivals

* chore: polish some trivals

* chore: polish some trivals

* chore: polish some trivals

* chore: refine by review tips

* chore: refine by failed action

* feat(evn): EVN full-broadcast via BSC subprotocol + NodeIDs mgmt and periodic refresh; CLI-driven StakeHub NodeIDs tx build/sign

* chore: add retry and pick best payload workflow (#106)

* chore: add retry and pick best workflow

* chore: polish some codes

* chore: add retries limit

* chore: refine code skeleton

* chore: polish some trivals

* chore: polish some trivals

* chore: enhance mining delay more details

* chore: polish by review tips

* chore: polish trivals

* fix: fix retry workflow (#112)

* fix: fix retry-work workflow

* chore: polish some trivals

* chore: polish some trivlas

* chore: polish some trivals

* builder: support to reserve system tx gas; (#114)

Co-authored-by: galaio <galaio@users.noreply.github.com>

* feat(evn): implement second part of EVN support

* parlia: opt reorg & FCU logic; (#113)

* parlia: opt reorg & FCU logic;

* parlia: opt reorg & FCU logic;

* parlia: opt reorg & FCU logic;

* chore: fix some ci issues;

---------

Co-authored-by: galaio <galaio@users.noreply.github.com>

* builder: fill miner missed logic, and fix some issues; (#121)

* builder: opt delay time for validator;

* chore: opt hard fork logic;

* chore: opt assemble logic;

* builder: support FF vote aggregation;

* builder: opt validator cache, query by hash;

---------

Co-authored-by: galaio <galaio@users.noreply.github.com>

* chore: polish off-turn mine workflow (#119)

* chore: try offturn mine

* chore: try some debug

* chore: make result worker no blocking

* chore: polish off-turn workflow

* chore: polish some codes

* chore: polish trivals

* review comments

* feat: add vote journal

* builder: opt fcu td query issue;

* chore: resolve ci issues;

* feat: loop wait impl (#126)

* feat: loop wait impl

* fix: clippy error

* perf: code style and log

---------

Co-authored-by: cbh876 <3930922419@qq.com>

* chore: add double sign check in result-worker (#124)

* chore: polish some trivals

* chore: polish some trivals

* chore: refactor header cache and snapshot cache;

* chore: fix CI issues;

* chore: refactor header cache and snapshot cache;

* chore(evn): fix node registration and unregistration

* fix pr reviews

* chore: add bsc-reorg check in mine workflow (#129)

* chore: add bsc-reorg check in mine workflow

* chore: refine codes

* chore: polish some trivals

* chore: fix  ut

* feat: bid function (#120)

* feat: bid init

* feat: bid simulate function

* feat: communication between simulator and miner

* feat: register mev api

* fix: mev api

* fix: some bug

* fix: miner and simulator interaction

* feat: bid init

* feat: bid simulate function

* feat: rebase validator-dev

* feat: validator-dev

* fix: mev api

* fix: some bug

* fix: miner and simulator interaction

* perf: debug log

* feat: loop wait impl (#125)

* feat: process optimization

* feat: add blob support

* feat: blob sidecar store

* perf: unuse code and debug log

* fix: magic number

---------

Co-authored-by: cbh876 <3930922419@qq.com>

* fix: fix validate_reorg func to reduce slash (#131)

* fix: fix validate reorg to reduce slash

* chore: fix return under exception handling

* chore: polish some trivals

* chore: add more warn log

* chore: polish trivals

* chore: polish trivals

* chore: polish some trivals

* chore: update reth deps

* chore: update deps

* chore: polish qa hf ts

* chore: remove useless code

* chore: update deps

* parlia: fix FF voting issues, support peer TD updates; (#134)

* p2p: opt bsc protocol;

* parlia: opt FF voting logic;

* chore: fix some ci issues;

* chore: fix some ci issues;

---------

Co-authored-by: galaio <galaio@users.noreply.github.com>

* chore: update deps

* chore: polish assembler inital func (#135)

* chore: update reth deps (#136)

---------

Co-authored-by: Matus Kysel <matus.kysel@bnbchain.org>
Co-authored-by: will-2012 <117156346+will-2012@users.noreply.github.com>
Co-authored-by: Matus Kysel <MatusKysel@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: ruojunm <46366167+ruojunm@users.noreply.github.com>
Co-authored-by: Clyde <clyde.m@nodereal.io>
Co-authored-by: constwz <122766871+constwz@users.noreply.github.com>
Co-authored-by: Matus Kysel <matuskysel1@gmail.com>
Co-authored-by: galaio <12880651+galaio@users.noreply.github.com>
Co-authored-by: galaio <galaio@users.noreply.github.com>
Co-authored-by: cbh876 <3930922419@qq.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.

4 participants