Skip to content
This repository has been archived by the owner on Feb 6, 2025. It is now read-only.

Commit

Permalink
add BscEVMProcessor
Browse files Browse the repository at this point in the history
  • Loading branch information
pythonberg1997 committed May 9, 2024
1 parent ed14753 commit f422a6d
Show file tree
Hide file tree
Showing 18 changed files with 719 additions and 813 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 2 additions & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -393,10 +393,5 @@ test-fuzz = "5"

[patch.crates-io]
# TODO: update to official version
revm = { git = "https://github.com/bnb-chain/revm", rev = "dee51654d63f2a8c0197ae804e3efe985ec39557", features = [
"std",
"secp256k1",
], default-features = false }
revm-primitives = { git = "https://github.com/bnb-chain/revm", rev = "dee51654d63f2a8c0197ae804e3efe985ec39557", eatures = [
"std",
], default-features = false }
revm = { git = "https://github.com/bnb-chain/revm", rev = "dee51654d63f2a8c0197ae804e3efe985ec39557" }
revm-primitives = { git = "https://github.com/bnb-chain/revm", rev = "dee51654d63f2a8c0197ae804e3efe985ec39557" }
1 change: 1 addition & 0 deletions crates/consensus/parlia/src/go_rng.rs
Original file line number Diff line number Diff line change
Expand Up @@ -634,6 +634,7 @@ pub fn seed_rand(mut x: i32) -> i32 {
x
}

#[allow(missing_debug_implementations)]
pub struct RngSource {
tap: usize, // index into vec
feed: usize, // index into vec
Expand Down
29 changes: 14 additions & 15 deletions crates/consensus/parlia/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,16 @@ use std::{
};

use reth_consensus_common::validation::validate_4844_header_standalone;
use reth_db::models::parlia::{
Snapshot, ValidatorInfo, VoteAddress, VoteAttestation, CHECKPOINT_INTERVAL,
MAX_ATTESTATION_EXTRA_LENGTH,
};
use reth_interfaces::consensus::{Consensus, ConsensusError, ParliaConsensusError};
use reth_primitives::{
constants::EMPTY_MIX_HASH, transaction::TransactionKind, Address, BlockNumber, Bytes,
ChainSpec, GotExpected, Hardfork, Header, SealedBlock, SealedHeader, Transaction, TxLegacy,
B256, EMPTY_OMMER_ROOT_HASH, U256,
};
use reth_rpc_types::beacon::BlsPublicKey;

mod util;
pub use util::*;
Expand All @@ -44,14 +47,9 @@ pub use constants::*;

pub mod contract_upgrade;
mod feynman_fork;
mod go_rng;

use crate::go_rng::{RngSource, Shuffle};
pub use feynman_fork::*;
use reth_db::models::parlia::{
Snapshot, ValidatorInfo, VoteAddress, VoteAttestation, CHECKPOINT_INTERVAL,
MAX_ATTESTATION_EXTRA_LENGTH,
};
pub mod go_rng;
use crate::go_rng::{RngSource, Shuffle};

const RECOVERED_PROPOSER_CACHE_NUM: usize = 4096;
const SNAP_CACHE_NUM: usize = 2048;
Expand Down Expand Up @@ -345,8 +343,7 @@ impl<P> Parlia<P> {
if proposer != header.beneficiary {
return Err(ParliaConsensusError::WrongHeaderSigner {
block_number,
expected: header.beneficiary,
got: proposer,
signer: GotExpected { got: proposer, expected: header.beneficiary }.into(),
}
.into());
}
Expand Down Expand Up @@ -852,7 +849,7 @@ impl<P: HeaderProvider> Parlia<P> {
})
.into());
}
let mut vote_addrs: Vec<BlsPublicKey> = Vec::with_capacity(bit_set_count);
let mut vote_addrs: Vec<VoteAddress> = Vec::with_capacity(bit_set_count);
for (i, val) in snap.validators.iter().enumerate() {
if !vote_bit_set.test(i) {
continue;
Expand All @@ -862,7 +859,7 @@ impl<P: HeaderProvider> Parlia<P> {
.validators_map
.get(val)
.ok_or(ParliaConsensusError::VoteAddrNotFoundInSnap { address: *val })?;
vote_addrs.push(BlsPublicKey::from_slice(&val_info.vote_addr[..]));
vote_addrs.push(val_info.vote_addr.clone());
}

// check if voted validator count satisfied 2/3+1
Expand All @@ -876,8 +873,10 @@ impl<P: HeaderProvider> Parlia<P> {
}

// check bls aggregate sig
let vote_addrs: Vec<PublicKey> =
vote_addrs.iter().map(|bytes| PublicKey::from_bytes(&bytes[..]).unwrap()).collect();
let vote_addrs: Vec<PublicKey> = vote_addrs
.iter()
.map(|addr| PublicKey::from_bytes(addr.as_slice()).unwrap())
.collect();
let vote_addrs: Vec<&PublicKey> = vote_addrs.iter().collect();

let sig = Signature::from_bytes(&attestation.agg_signature[..])
Expand Down Expand Up @@ -1216,8 +1215,8 @@ impl<P: Debug + Send + Sync> Consensus for Parlia<P> {

#[cfg(test)]
mod tests {
use reth_primitives::{address, hex};
use super::*;
use reth_primitives::{address, hex};

#[test]
fn abi_encode() {
Expand Down
73 changes: 60 additions & 13 deletions crates/interfaces/src/consensus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use reth_primitives::{
Address, BlockHash, BlockNumber, GotExpected, GotExpectedBoxed, Header, HeaderValidationError,
InvalidTransactionError, SealedBlock, SealedHeader, B256, U256,
};
use std::{any::Any, fmt::Debug};
use std::fmt::Debug;

/// Re-export fork choice state
pub use reth_rpc_types::engine::ForkchoiceState;
Expand Down Expand Up @@ -305,59 +305,106 @@ pub enum ParliaConsensusError {

/// Error when the block signer is not authorized
#[error("proposer {proposer} at height {block_number} is not authorized")]
SignerUnauthorized { block_number: BlockNumber, proposer: Address },
SignerUnauthorized {
/// The block number
block_number: BlockNumber,
/// The proposer address
proposer: Address
},

/// Error when the block signer is over limit
#[error("proposer {proposer} is over limit")]
SignerOverLimit { proposer: Address },
SignerOverLimit {
/// The proposer address
proposer: Address
},

/// Error when the header is unknown
#[error("unknown header [number={block_number}, hash={hash}]")]
UnknownHeader { block_number: BlockNumber, hash: B256 },
UnknownHeader {
/// The block number
block_number: BlockNumber,
/// The block hash
hash: B256
},

/// Error when the header is not in epoch
#[error("{block_number} is not in epoch")]
NotInEpoch { block_number: BlockNumber },
NotInEpoch {
/// The block number
block_number: BlockNumber
},

/// Error when apply snapshot failed
#[error("apply snapshot failed")]
ApplySnapshotFailed,

/// Error when the block proposer is in the backoff period
#[error("block [number={block_number}, hash={hash}] proposer is in the backoff period")]
FutureBlock { block_number: BlockNumber, hash: B256 },
FutureBlock {
/// The block number
block_number: BlockNumber,
/// The block hash
hash: B256
},

/// Error when the block's parent is unknown
#[error("unknown ancestor of block [number={block_number}, hash={hash}]")]
UnknownAncestor { block_number: BlockNumber, hash: B256 },
UnknownAncestor {
/// The block number
block_number: BlockNumber,
/// The block hash
hash: B256
},

/// Error when the vote's signature is invalid
#[error("invalid vote signature")]
InvalidVoteSignature,

/// Error when the attestation's extra length is too large
#[error("attestation extra length {extra_len} is too large")]
TooLargeAttestationExtraLen { extra_len: usize },
TooLargeAttestationExtraLen {
/// The extra length
extra_len: usize
},

/// Error when the attestation's target is invalid
#[error("invalid attestation target: number {block_number}, hash {block_hash}")]
InvalidAttestationTarget { block_number: GotExpected<u64>, block_hash: GotExpectedBoxed<B256> },
InvalidAttestationTarget {
/// The expected and got block number
block_number: GotExpected<u64>,
/// The expected and got block hash
block_hash: GotExpectedBoxed<B256>
},

/// Error when the attestation's source is invalid
#[error("invalid attestation source: number {block_number}, hash {block_hash}")]
InvalidAttestationSource { block_number: GotExpected<u64>, block_hash: GotExpectedBoxed<B256> },
InvalidAttestationSource {
/// The expected and got block number
block_number: GotExpected<u64>,
/// The expected and got block hash
block_hash: GotExpectedBoxed<B256>
},

/// Error when the attestation's vote count is invalid
#[error("invalid attestation vote count: {0}")]
InvalidAttestationVoteCount(GotExpected<u64>),

/// Error when the vote address is not found
#[error("vote address not found: {address}")]
VoteAddrNotFoundInSnap { address: Address },
VoteAddrNotFoundInSnap {
/// The vote address
address: Address
},

/// Error when the block's header signer is invalid
#[error("wrong header signer: block number {block_number}, expected {expected}, got {got}")]
WrongHeaderSigner { block_number: BlockNumber, expected: Address, got: Address },
#[error("wrong header signer: block number {block_number}, signer {signer}")]
WrongHeaderSigner {
/// The block number
block_number: BlockNumber,
/// The expected and got signer address
signer: GotExpectedBoxed<Address>,
},

/// Error when the system transaction is unexpected
#[error("unexpected system transaction")]
Expand Down
1 change: 1 addition & 0 deletions crates/primitives/src/constants/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ pub const EMPTY_TRANSACTIONS: B256 = EMPTY_ROOT_HASH;
/// Withdrawals root of empty withdrawals set.
pub const EMPTY_WITHDRAWALS: B256 = EMPTY_ROOT_HASH;

/// Empty mix hash
pub const EMPTY_MIX_HASH: B256 =
b256!("0000000000000000000000000000000000000000000000000000000000000000");

Expand Down
83 changes: 83 additions & 0 deletions crates/revm/src/bsc/factory.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
use crate::{
bsc::processor::BscEVMProcessor,
database::StateProviderDatabase,
stack::{InspectorStack, InspectorStackConfig},
};
use reth_evm::ConfigureEvm;
use reth_interfaces::executor::BlockExecutionError;
use reth_parlia_consensus::{Parlia, ParliaConfig};
use reth_primitives::ChainSpec;
use reth_provider::{
ExecutorFactory, HeaderProvider, ParliaSnapshotReader, ParliaSnapshotWriter,
PrunableBlockExecutor, StateProvider,
};
use std::{fmt::Debug, sync::Arc};

/// Factory for creating [BscEVMProcessor].
#[derive(Clone, Debug)]
pub struct BscEvmProcessorFactory<EvmConfig> {
chain_spec: Arc<ChainSpec>,
stack: Option<InspectorStack>,
/// Type that defines how the produced EVM should be configured.
evm_config: EvmConfig,
/// Parlia consensus config
parlia_config: ParliaConfig,
}

impl<EvmConfig> BscEvmProcessorFactory<EvmConfig> {
/// Create new factory
pub fn new(
chain_spec: Arc<ChainSpec>,
evm_config: EvmConfig,
parlia_config: ParliaConfig,
) -> Self {
Self { chain_spec, stack: None, evm_config, parlia_config }
}

/// Sets the inspector stack for all generated executors.
pub fn with_stack(mut self, stack: InspectorStack) -> Self {
self.stack = Some(stack);
self
}

/// Sets the inspector stack for all generated executors using the provided config.
pub fn with_stack_config(mut self, config: InspectorStackConfig) -> Self {
self.stack = Some(InspectorStack::new(config));
self
}
}

impl<EvmConfig> ExecutorFactory for BscEvmProcessorFactory<EvmConfig>
where
EvmConfig: ConfigureEvm + Send + Sync + Clone + 'static,
{
fn with_state<'a, SP: StateProvider + 'a>(
&'a self,
_sp: SP,
) -> Box<dyn PrunableBlockExecutor<Error = BlockExecutionError> + 'a> {
panic!("Please use with_state_and_provider instead")
}

fn with_state_and_provider<
'a,
SP: StateProvider + 'a,
P: HeaderProvider + ParliaSnapshotReader + ParliaSnapshotWriter + 'a,
>(
&'a self,
sp: SP,
p: P,
) -> Box<dyn PrunableBlockExecutor<Error = BlockExecutionError> + 'a> {
let database_state = StateProviderDatabase::new(sp);
let mut evm = BscEVMProcessor::new_with_db(
self.chain_spec.clone(),
database_state,
self.evm_config.clone(),
);
if let Some(stack) = &self.stack {
evm.set_stack(stack.clone());
}
evm.set_parlia(Arc::new(Parlia::new(self.chain_spec.clone(), self.parlia_config.clone())));
evm.parlia_consensus.set_provider(p);
Box::new(evm)
}
}
1 change: 1 addition & 0 deletions crates/revm/src/bsc/mod.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
/// Bsc-specific processor implementation for the `EVMProcessor`
pub mod processor;
pub mod factory;
Loading

0 comments on commit f422a6d

Please sign in to comment.