Skip to content

Commit

Permalink
FORKS are always sorted, use binary_search to find current fork (#1473)
Browse files Browse the repository at this point in the history
  • Loading branch information
kpp authored Nov 18, 2024
1 parent 3f164e6 commit 0a9060e
Show file tree
Hide file tree
Showing 17 changed files with 61 additions and 67 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

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

8 changes: 4 additions & 4 deletions bin/citrea/src/rollup/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ pub trait CitreaRollupBlueprint: RollupBlueprint {
.map(|(l2_height, _)| l2_height)
.unwrap_or(BatchNumber(0));

let mut fork_manager = ForkManager::new(FORKS.to_vec(), current_l2_height.0);
let mut fork_manager = ForkManager::new(FORKS, current_l2_height.0);
fork_manager.register_handler(Box::new(ledger_db.clone()));

let seq = CitreaSequencer::new(
Expand Down Expand Up @@ -232,7 +232,7 @@ pub trait CitreaRollupBlueprint: RollupBlueprint {
.map(|(l2_height, _)| l2_height)
.unwrap_or(BatchNumber(0));

let mut fork_manager = ForkManager::new(FORKS.to_vec(), current_l2_height.0);
let mut fork_manager = ForkManager::new(FORKS, current_l2_height.0);
fork_manager.register_handler(Box::new(ledger_db.clone()));

let runner = CitreaFullnode::new(
Expand Down Expand Up @@ -356,7 +356,7 @@ pub trait CitreaRollupBlueprint: RollupBlueprint {
.map(|(l2_height, _)| l2_height)
.unwrap_or(BatchNumber(0));

let mut fork_manager = ForkManager::new(FORKS.to_vec(), current_l2_height.0);
let mut fork_manager = ForkManager::new(FORKS, current_l2_height.0);
fork_manager.register_handler(Box::new(ledger_db.clone()));

let runner = CitreaBatchProver::new(
Expand Down Expand Up @@ -446,7 +446,7 @@ pub trait CitreaRollupBlueprint: RollupBlueprint {
.map(|(l2_height, _)| l2_height)
.unwrap_or(BatchNumber(0));

let mut fork_manager = ForkManager::new(FORKS.to_vec(), current_l2_height.0);
let mut fork_manager = ForkManager::new(FORKS, current_l2_height.0);
fork_manager.register_handler(Box::new(ledger_db.clone()));

let runner = CitreaLightClientProver::new(
Expand Down
2 changes: 1 addition & 1 deletion crates/batch-prover/src/proving.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ where
info!("Verifying proof!");

let last_active_spec_id =
fork_from_block_number(FORKS.to_vec(), circuit_output.last_l2_height).spec_id;
fork_from_block_number(FORKS, circuit_output.last_l2_height).spec_id;
let code_commitment = code_commitments_by_spec
.get(&last_active_spec_id)
.expect("Proof public input must contain valid spec id");
Expand Down
2 changes: 0 additions & 2 deletions crates/citrea-stf/src/verifier.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use std::marker::PhantomData;

use citrea_primitives::forks::FORKS;
use sov_rollup_interface::da::{BlockHeaderTrait, DaNamespace, DaVerifier};
use sov_rollup_interface::stf::{ApplySequencerCommitmentsOutput, StateTransitionFunction};
use sov_rollup_interface::zk::{
Expand Down Expand Up @@ -86,7 +85,6 @@ where
data.da_block_headers_of_soft_confirmations,
data.soft_confirmations,
data.preproven_commitments.clone(),
FORKS.to_vec(),
);

println!("out of apply_soft_confirmations_from_sequencer_commitments");
Expand Down
2 changes: 1 addition & 1 deletion crates/evm/src/evm/conversions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ pub(crate) fn sealed_block_to_block_env(
.excess_blob_gas
.or_else(|| {
if citrea_spec_id_to_evm_spec_id(
fork_from_block_number(FORKS.to_vec(), sealed_header.number).spec_id,
fork_from_block_number(FORKS, sealed_header.number).spec_id,
) >= SpecId::CANCUN
{
Some(0)
Expand Down
15 changes: 7 additions & 8 deletions crates/evm/src/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -366,9 +366,8 @@ impl<C: sov_modules_api::Context> Evm<C> {

let block_number = self.block_number_for_id(&block_number, working_set)?;

let current_spec = citrea_spec_id_to_evm_spec_id(
fork_from_block_number(FORKS.to_vec(), block_number).spec_id,
);
let current_spec =
citrea_spec_id_to_evm_spec_id(fork_from_block_number(FORKS, block_number).spec_id);

self.set_state_to_end_of_evm_block_by_block_id(block_id, working_set)?;

Expand Down Expand Up @@ -563,7 +562,7 @@ impl<C: sov_modules_api::Context> Evm<C> {
.get(working_set)
.expect("EVM chain config should be set");

let citrea_spec_id = fork_from_block_number(FORKS.to_vec(), block_num).spec_id;
let citrea_spec_id = fork_from_block_number(FORKS, block_num).spec_id;
let evm_spec_id = citrea_spec_id_to_evm_spec_id(citrea_spec_id);

let cfg_env = get_cfg_env(cfg, evm_spec_id);
Expand Down Expand Up @@ -658,7 +657,7 @@ impl<C: sov_modules_api::Context> Evm<C> {
.get(working_set)
.expect("EVM chain config should be set");

let citrea_spec_id = fork_from_block_number(FORKS.to_vec(), block_num).spec_id;
let citrea_spec_id = fork_from_block_number(FORKS, block_num).spec_id;
let evm_spec_id = citrea_spec_id_to_evm_spec_id(citrea_spec_id);

let cfg_env = get_cfg_env(cfg, evm_spec_id);
Expand Down Expand Up @@ -770,7 +769,7 @@ impl<C: sov_modules_api::Context> Evm<C> {
.expect("EVM chain config should be set");

let citrea_spec_id =
fork_from_block_number(FORKS.to_vec(), block_env.number.saturating_to()).spec_id;
fork_from_block_number(FORKS, block_env.number.saturating_to()).spec_id;
let evm_spec_id = citrea_spec_id_to_evm_spec_id(citrea_spec_id);

let cfg_env = get_cfg_env(cfg, evm_spec_id);
Expand Down Expand Up @@ -1197,7 +1196,7 @@ impl<C: sov_modules_api::Context> Evm<C> {
// set state to end of the previous block
set_state_to_end_of_evm_block(block_number - 1, working_set);

let citrea_spec_id = fork_from_block_number(FORKS.to_vec(), block_number).spec_id;
let citrea_spec_id = fork_from_block_number(FORKS, block_number).spec_id;
let evm_spec_id = citrea_spec_id_to_evm_spec_id(citrea_spec_id);

let block_env = sealed_block_to_block_env(&sealed_block.header);
Expand Down Expand Up @@ -1837,7 +1836,7 @@ fn get_pending_block_env<C: sov_modules_api::Context>(
.next_block_excess_blob_gas()
.or_else(|| {
if citrea_spec_id_to_evm_spec_id(
fork_from_block_number(FORKS.to_vec(), block_env.number.saturating_to()).spec_id,
fork_from_block_number(FORKS, block_env.number.saturating_to()).spec_id,
) >= SpecId::CANCUN
{
Some(0)
Expand Down
2 changes: 1 addition & 1 deletion crates/fullnode/src/da_block_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ where
}

let last_active_spec_id =
fork_from_block_number(FORKS.to_vec(), batch_proof_output.last_l2_height).spec_id;
fork_from_block_number(FORKS, batch_proof_output.last_l2_height).spec_id;
let code_commitment = self
.code_commitments_by_spec
.get(&last_active_spec_id)
Expand Down
2 changes: 0 additions & 2 deletions crates/fullnode/tests/hash_stf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ use sov_modules_api::Context;
use sov_modules_stf_blueprint::StfBlueprintTrait;
use sov_prover_storage_manager::{new_orphan_storage, SnapshotManager};
use sov_rollup_interface::da::{BlobReaderTrait, BlockHeaderTrait, DaSpec};
use sov_rollup_interface::fork::Fork;
use sov_rollup_interface::spec::SpecId;
use sov_rollup_interface::stf::{
ApplySequencerCommitmentsOutput, SlotResult, SoftConfirmationReceipt, SoftConfirmationResult,
Expand Down Expand Up @@ -242,7 +241,6 @@ impl<Da: DaSpec> StateTransitionFunction<Da> for HashStf {
Vec<sov_modules_api::SignedSoftConfirmation>,
>,
_preproven_commitment_indicies: Vec<usize>,
_forks: Vec<Fork>,
) -> ApplySequencerCommitmentsOutput<Self::StateRoot> {
todo!()
}
Expand Down
4 changes: 2 additions & 2 deletions crates/fullnode/tests/runner_initialization_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ fn initialize_runner(
sov_modules_api::default_context::DefaultContext,
LedgerDB,
> {
let forks = vec![Fork::new(SpecId::Genesis, 0)];
static T_FORKS: &[Fork] = &[Fork::new(SpecId::Genesis, 0)];
let da_storage_path = storage_path.join("da").to_path_buf();
let rollup_storage_path = storage_path.join("rollup").to_path_buf();

Expand Down Expand Up @@ -113,7 +113,7 @@ fn initialize_runner(
// let vm = MockZkvm::new(MockValidityCond::default());
// let verifier = MockDaVerifier::default();

let fork_manager = ForkManager::new(forks, 0);
let fork_manager = ForkManager::new(T_FORKS, 0);

let mut code_commitments_by_spec = HashMap::new();
code_commitments_by_spec.insert(SpecId::Genesis, MockCodeCommitment([1u8; 32]));
Expand Down
19 changes: 17 additions & 2 deletions crates/primitives/src/forks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use sov_rollup_interface::spec::SpecId;
/// This defines the list of forks which will be activated
/// at specific heights.
#[cfg(not(feature = "testing"))]
pub const FORKS: [Fork; 2] = [
pub const FORKS: &[Fork] = &[
Fork {
spec_id: SpecId::Genesis,
activation_height: 0,
Expand All @@ -18,7 +18,7 @@ pub const FORKS: [Fork; 2] = [
];

#[cfg(feature = "testing")]
pub const FORKS: [Fork; 3] = [
pub const FORKS: &[Fork] = &[
Fork {
spec_id: SpecId::Genesis,
activation_height: 0,
Expand All @@ -32,3 +32,18 @@ pub const FORKS: [Fork; 3] = [
activation_height: 2000,
},
];

const _CHECK_FORKS_ARE_SORTED: () = {
const fn check_forks_are_sorted() {
let mut height = FORKS[0].activation_height;
let mut i = 1;
while i < FORKS.len() {
let fork = FORKS[i];
let fork_height = fork.activation_height;
assert!(fork_height > height, "FORKS are not sorted!");
height = fork_height;
i += 1;
}
}
check_forks_are_sorted()
};
2 changes: 0 additions & 2 deletions crates/sovereign-sdk/full-node/sov-stf-runner/src/mock/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ use std::marker::PhantomData;

use sov_modules_api::hooks::SoftConfirmationError;
use sov_rollup_interface::da::DaSpec;
use sov_rollup_interface::fork::Fork;
use sov_rollup_interface::spec::SpecId;
use sov_rollup_interface::stf::{
ApplySequencerCommitmentsOutput, BatchReceipt, SlotResult, SoftConfirmationResult,
Expand Down Expand Up @@ -100,7 +99,6 @@ impl<Da: DaSpec> StateTransitionFunction<Da> for MockStf {
Vec<sov_modules_api::SignedSoftConfirmation>,
>,
_preproven_commitment_indicies: Vec<usize>,
_forks: Vec<Fork>,
) -> ApplySequencerCommitmentsOutput<Self::StateRoot> {
todo!()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ serde = { workspace = true, features = ["derive"] }
tracing = { workspace = true, optional = true }

# Sovereign-SDK deps
citrea-primitives = { path = "../../../primitives", default-features = false }
sov-modules-api = { path = "../sov-modules-api", default-features = false }
sov-rollup-interface = { path = "../../rollup-interface" }
sov-state = { path = "../sov-state" }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#![doc = include_str!("../README.md")]

use borsh::BorshDeserialize;
use citrea_primitives::forks::FORKS;
use itertools::Itertools;
use rs_merkle::algorithms::Sha256;
use rs_merkle::MerkleTree;
Expand All @@ -15,7 +16,7 @@ use sov_modules_api::{
Genesis, Signature, Spec, StateCheckpoint, UnsignedSoftConfirmation, WorkingSet,
};
use sov_rollup_interface::da::DaDataBatchProof;
use sov_rollup_interface::fork::{Fork, ForkManager};
use sov_rollup_interface::fork::ForkManager;
use sov_rollup_interface::soft_confirmation::SignedSoftConfirmation;
use sov_rollup_interface::spec::SpecId;
use sov_rollup_interface::stf::{
Expand Down Expand Up @@ -554,7 +555,6 @@ where
slot_headers: std::collections::VecDeque<Vec<<Da as DaSpec>::BlockHeader>>,
soft_confirmations: std::collections::VecDeque<Vec<SignedSoftConfirmation>>,
preproven_commitment_indices: Vec<usize>,
forks: Vec<Fork>,
) -> ApplySequencerCommitmentsOutput<Self::StateRoot> {
let mut state_diff = CumulativeStateDiff::default();

Expand Down Expand Up @@ -625,7 +625,7 @@ where
let mut previous_batch_hash = soft_confirmations[0][0].prev_hash();
let mut last_commitment_end_height: Option<u64> = None;

let mut fork_manager = ForkManager::new(forks, sequencer_commitments_range.0 as u64);
let mut fork_manager = ForkManager::new(FORKS, sequencer_commitments_range.0 as u64);

// should panic if number of sequencer commitments, soft confirmations, slot headers and witnesses don't match
for (((sequencer_commitment, soft_confirmations), da_block_headers), witnesses) in
Expand Down
29 changes: 12 additions & 17 deletions crates/sovereign-sdk/rollup-interface/src/fork/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,20 @@ use alloc::vec::Vec;
use super::{Fork, ForkMigration};

pub struct ForkManager {
forks: Vec<Fork>,
forks: &'static [Fork],
active_fork_idx: usize,
migration_handlers: Vec<Box<dyn ForkMigration + Sync + Send>>,
}

impl ForkManager {
pub fn new(mut forks: Vec<Fork>, current_l2_height: u64) -> Self {
// Make sure the list of specs is sorted by the block number at which they activate.
forks.sort_by_key(|fork| fork.activation_height);
pub fn new(forks: &'static [Fork], current_l2_height: u64) -> Self {
// FORKS from citrea-primitives are checked at compile time to be sorted.

// TODO: binary search here and assume forks is always sorted
let mut active_fork_idx = 0;
for (idx, fork) in forks.iter().enumerate() {
if current_l2_height >= fork.activation_height {
active_fork_idx = idx;
} else {
break;
}
}
let pos = forks.binary_search_by(|fork| fork.activation_height.cmp(&current_l2_height));
let active_fork_idx = match pos {
Ok(idx) => idx,
Err(idx) => idx.saturating_sub(1),
};

Self {
forks,
Expand All @@ -36,8 +31,8 @@ impl ForkManager {
self.migration_handlers.push(handler);
}

pub fn active_fork(&self) -> &Fork {
&self.forks[self.active_fork_idx]
pub fn active_fork(&self) -> Fork {
self.forks[self.active_fork_idx]
}

pub fn register_block(&mut self, height: u64) -> anyhow::Result<()> {
Expand Down Expand Up @@ -71,6 +66,6 @@ impl ForkManager {

/// Simple search for the fork to which a specific block number blongs.
/// This assumes that the list of forks is sorted by block number in ascending fashion.
pub fn fork_from_block_number(forks: Vec<Fork>, block_number: u64) -> Fork {
ForkManager::new(forks, block_number).active_fork().clone()
pub fn fork_from_block_number(forks: &'static [Fork], block_number: u64) -> Fork {
ForkManager::new(forks, block_number).active_fork()
}
4 changes: 2 additions & 2 deletions crates/sovereign-sdk/rollup-interface/src/fork/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ pub use migration::*;
use crate::spec::SpecId;

/// Fork is a wrapper struct that contains spec id and it's activation height
#[derive(Debug, Clone)]
#[derive(Debug, Clone, Copy)]
pub struct Fork {
/// Spec id for this fork
pub spec_id: SpecId,
Expand All @@ -21,7 +21,7 @@ pub struct Fork {

impl Fork {
/// Creates new Fork instance
pub fn new(spec_id: SpecId, activation_height: u64) -> Self {
pub const fn new(spec_id: SpecId, activation_height: u64) -> Self {
Self {
spec_id,
activation_height,
Expand Down
Loading

0 comments on commit 0a9060e

Please sign in to comment.