openethereum/crates/ethcore/sync/src/chain/fork_filter.rs

122 lines
3.6 KiB
Rust

//! This module contains a wrapper that connects this codebase with `ethereum-forkid` crate which provides `FORK_ID`
//! to support Ethereum network protocol, version 64 and above.
// Re-export ethereum-forkid crate contents here.
pub use ethereum_forkid::{BlockNumber, ForkId, RejectReason};
use ethcore::client::ChainInfo;
use ethereum_forkid::ForkFilter;
/// Wrapper around fork filter that provides integration with `ForkFilter`.
pub struct ForkFilterApi {
inner: ForkFilter,
}
impl ForkFilterApi {
/// Create `ForkFilterApi` from `ChainInfo` and an `Iterator` over the hard forks.
pub fn new<C: ?Sized + ChainInfo, I: IntoIterator<Item = BlockNumber>>(
client: &C,
forks: I,
) -> Self {
let chain_info = client.chain_info();
let genesis_hash = primitive_types07::H256::from_slice(&chain_info.genesis_hash.0);
Self {
inner: ForkFilter::new(chain_info.best_block_number, genesis_hash, forks),
}
}
#[cfg(test)]
/// Dummy version of ForkFilterApi with no forks.
pub fn new_dummy<C: ?Sized + ChainInfo>(client: &C) -> Self {
let chain_info = client.chain_info();
Self {
inner: ForkFilter::new(
chain_info.best_block_number,
primitive_types07::H256::from_slice(&chain_info.genesis_hash.0),
vec![],
),
}
}
fn update_head<C: ?Sized + ChainInfo>(&mut self, client: &C) {
self.inner.set_head(client.chain_info().best_block_number);
}
/// Wrapper for `ForkFilter::current`
pub fn current<C: ?Sized + ChainInfo>(&mut self, client: &C) -> ForkId {
self.update_head(client);
self.inner.current()
}
/// Wrapper for `ForkFilter::is_compatible`
pub fn is_compatible<C: ?Sized + ChainInfo>(
&mut self,
client: &C,
fork_id: ForkId,
) -> Result<(), RejectReason> {
self.update_head(client);
self.inner.is_compatible(fork_id)
}
}
#[cfg(test)]
mod tests {
use super::*;
use ethcore::{client::TestBlockChainClient, ethereum, spec::Spec};
fn test_spec<F: Fn() -> Spec>(spec_builder: F, forks: Vec<BlockNumber>) {
let spec = (spec_builder)();
let genesis_hash = spec.genesis_header().hash();
let spec_forks = spec.hard_forks.clone();
let client = TestBlockChainClient::new_with_spec(spec);
assert_eq!(
ForkFilterApi::new(&client, spec_forks).inner,
ForkFilter::new(
0,
primitive_types07::H256::from_slice(&genesis_hash.0),
forks
)
);
}
#[test]
fn ethereum_spec() {
test_spec(
|| ethereum::new_foundation(&String::new()),
vec![
1_150_000, 1_920_000, 2_463_000, 2_675_000, 4_370_000, 7_280_000, 9_069_000,
9_200_000, 12_244_000, 12_965_000,
],
)
}
#[test]
fn ropsten_spec() {
test_spec(
|| ethereum::new_ropsten(&String::new()),
vec![
10, 1_700_000, 4_230_000, 4_939_394, 6_485_846, 7_117_117, 9_812_189, 10_499_401,
],
)
}
#[test]
fn rinkeby_spec() {
test_spec(
|| ethereum::new_rinkeby(&String::new()),
vec![
1, 2, 3, 1_035_301, 3_660_663, 4_321_234, 5_435_345, 8_290_928, 8_897_988,
],
)
}
#[test]
fn goerli_spec() {
test_spec(
|| ethereum::new_goerli(&String::new()),
vec![1_561_651, 4_460_644, 5_062_605],
)
}
}