Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 37 additions & 3 deletions crates/full-node/sov-sequencer/src/preferred/initialization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::preferred::db::SequencerRole;
use anyhow::Context;
use anyhow::Result;
use sov_db::ledger_db::LedgerDb;
use sov_modules_api::capabilities::SequencerRemuneration;
use sov_modules_api::rest::StateUpdateReceiver;
use std::net::SocketAddr;
use std::path::Path;
Expand Down Expand Up @@ -64,6 +65,10 @@ where
.await
.context("Sequencer must have DaService configured with submit support")?;

// Early check: verify that this node's DA signer matches the preferred
// sequencer registered in the runtime.
Self::check_runtime_address_match(&latest_state_update, da_address)?;

debug!(
?latest_state_update,
%da_address,
Expand Down Expand Up @@ -277,6 +282,35 @@ where
Ok((seq, handles))
}

fn check_runtime_address_match(
latest_state_update: &StateUpdateInfo<<S as Spec>::Storage>,
da_address: <<S as Spec>::Da as DaSpec>::Address,
) -> anyhow::Result<()> {
let mut runtime: Rt = Default::default();
let mut checkpoint =
StateCheckpoint::new(latest_state_update.storage.clone(), &runtime.kernel(), None);
let registry_preferred = runtime
.sequencer_remuneration()
.preferred_sequencer(&mut checkpoint);
match registry_preferred {
Some(ref expected) if *expected == da_address => Ok(()),
Some(expected) => {
anyhow::bail!(
"DA address mismatch: this node's DaService signer address is {da_address}, \
but the preferred sequencer DA address in the sequencer registry is {expected}. \
Check your DA service configuration."
);
}
None => {
anyhow::bail!(
"No preferred sequencer is registered in the sequencer registry, \
but this node is configured as a preferred sequencer. \
Check the sequencer registry genesis configuration."
);
}
}
}

fn api_state(
storage: S::Storage,
) -> (
Expand All @@ -285,9 +319,9 @@ where
) {
let mut runtime: Rt = Default::default();
assert!(
accepts_preferred_batches(runtime.blob_selector()),
"Attempting to use preferred sequencer with an incompatible rollup. Set your sequencer config to `standard` in your rollup's config.toml file or change your kernel to be compatible with soft confirmations."
);
accepts_preferred_batches(runtime.blob_selector()),
"Attempting to use preferred sequencer with an incompatible rollup. Set your sequencer config to `standard` in your rollup's config.toml file or change your kernel to be compatible with soft confirmations."
);
let checkpoint = StateCheckpoint::new(storage, &runtime.kernel(), None);
// Preferred sequencer deliberately treats the latest available slot as finalized
// when initializing API state (soft-confirmation semantics).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ use sov_rollup_interface::node::da::DaService;
use sov_rollup_interface::node::ledger_api::IncludeChildren;
use sov_sequencer::{SequencerKindConfig, StateUpdateNotification};
use sov_test_modules::hooks_count::HooksCount;
use sov_test_utils::runtime::genesis::optimistic::HighLevelOptimisticGenesisConfig;
use sov_test_utils::runtime::genesis::optimistic::{
HighLevelOptimisticGenesisConfig, MinimalOptimisticGenesisConfig,
};
use sov_test_utils::test_rollup::FullNodeBlueprint;
use sov_test_utils::test_rollup::StoragePath;
use sov_test_utils::test_rollup::{GenesisSource, RollupBuilder, RollupProverConfig, TestRollup};
Expand Down Expand Up @@ -3725,6 +3727,74 @@ fn tx_assert_state_root(
encode_call::<TestRuntime<TestSpec>>(key, nonce, &msg)
}

#[tokio::test(flavor = "multi_thread")]
#[should_panic(expected = "DA address mismatch")]
async fn preferred_sequencer_fails_on_da_address_mismatch() {
let genesis_config = HighLevelOptimisticGenesisConfig::generate();
let genesis_params = GenesisParams {
runtime: <TestRuntime<TestSpec> as Runtime<TestSpec>>::GenesisConfig::from_minimal_config(
genesis_config.into(),
ValueSetterConfig {
admin: sov_modules_api::Address::from([0; 28]),
},
(),
PaymasterConfig::default(),
(),
(),
),
};

RollupBuilder::<TestBlueprint>::new(
GenesisSource::CustomParams(genesis_params),
DEFAULT_BLOCK_PRODUCING_CONFIG,
0,
)
.set_config(|conf| {
conf.sequencer_config = SequencerKindConfig::Preferred(Default::default());
})
.start()
.await
.unwrap();
}

#[tokio::test(flavor = "multi_thread")]
#[should_panic(expected = "No preferred sequencer is registered in the sequencer registry")]
async fn preferred_sequencer_fails_when_no_preferred_sequencer_in_registry() {
let genesis_config = HighLevelOptimisticGenesisConfig::generate();
let seq_da_address = HighLevelOptimisticGenesisConfig::<TestSpec>::sequencer_da_addr();
let mut minimal: MinimalOptimisticGenesisConfig<TestSpec> = genesis_config.into();
minimal
.config
.sequencer_registry
.sequencer_config
.is_preferred_sequencer = false;
let genesis_params = GenesisParams {
runtime: <TestRuntime<TestSpec> as Runtime<TestSpec>>::GenesisConfig::from_minimal_config(
minimal,
ValueSetterConfig {
admin: sov_modules_api::Address::from([0; 28]),
},
(),
PaymasterConfig::default(),
(),
(),
),
};

RollupBuilder::<TestBlueprint>::new(
GenesisSource::CustomParams(genesis_params),
DEFAULT_BLOCK_PRODUCING_CONFIG,
0,
)
.set_config(|conf| {
conf.sequencer_config = SequencerKindConfig::Preferred(Default::default());
})
.set_da_config(|c| c.sender_address = seq_da_address)
.start()
.await
.unwrap();
}

mod tests_with_basic_kernel {
use sov_modules_stf_blueprint::GenesisParams;
use sov_test_utils::test_rollup::{GenesisSource, RollupBuilder};
Expand All @@ -3745,6 +3815,7 @@ mod tests_with_basic_kernel {
)]
async fn preferred_sequencer_panics_with_basic_kernel() {
let genesis_config = HighLevelOptimisticGenesisConfig::generate();
let seq_da_address = HighLevelOptimisticGenesisConfig::<TestSpec>::sequencer_da_addr();
let genesis_params = GenesisParams {
runtime: GenesisConfig::from_minimal_config(genesis_config.into()),
};
Expand All @@ -3758,6 +3829,7 @@ mod tests_with_basic_kernel {
conf.sequencer_config =
sov_sequencer::SequencerKindConfig::Preferred(Default::default());
})
.set_da_config(|c| c.sender_address = seq_da_address)
.start()
.await
.unwrap();
Expand Down
Loading