diff --git a/examples/demo-rollup/src/main.rs b/examples/demo-rollup/src/main.rs index 0a2fc8a04..ef24864b2 100644 --- a/examples/demo-rollup/src/main.rs +++ b/examples/demo-rollup/src/main.rs @@ -183,7 +183,7 @@ fn register_ledger( ledger_db: LedgerDB, methods: &mut jsonrpsee::RpcModule<()>, ) -> Result<(), anyhow::Error> { - let ledger_rpc = get_ledger_rpc::(ledger_db); + let ledger_rpc = get_ledger_rpc::, TxEffect>(ledger_db); methods .merge(ledger_rpc) .context("Failed to merge ledger RPC modules") diff --git a/examples/demo-stf/src/hooks_impl.rs b/examples/demo-stf/src/hooks_impl.rs index 2b9fe518c..e12827391 100644 --- a/examples/demo-stf/src/hooks_impl.rs +++ b/examples/demo-stf/src/hooks_impl.rs @@ -3,6 +3,7 @@ use sov_modules_api::transaction::Transaction; use sov_modules_api::{Context, Spec}; use sov_modules_stf_template::SequencerOutcome; use sov_rollup_interface::da::BlobReaderTrait; +use sov_sequencer_registry::SequencerRegistry; use sov_state::WorkingSet; use tracing::info; @@ -28,13 +29,13 @@ impl TxHooks for Runtime { } } -impl ApplyBlobHooks for Runtime { +impl ApplyBlobHooks for Runtime { type Context = C; - type BlobResult = SequencerOutcome; + type BlobResult = SequencerOutcome; fn begin_blob_hook( &self, - blob: &mut impl BlobReaderTrait, + blob: &mut B, working_set: &mut WorkingSet<::Storage>, ) -> anyhow::Result<()> { self.sequencer_registry.begin_blob_hook(blob, working_set) @@ -48,7 +49,8 @@ impl ApplyBlobHooks for Runtime { match result { SequencerOutcome::Rewarded(_reward) => { // TODO: Process reward here or above. - self.sequencer_registry.end_blob_hook( + as ApplyBlobHooks>::end_blob_hook( + &self.sequencer_registry, sov_sequencer_registry::SequencerOutcome::Completed, working_set, ) @@ -58,10 +60,11 @@ impl ApplyBlobHooks for Runtime { reason, sequencer_da_address, } => { - info!("Sequencer slashed: {:?}", reason); - self.sequencer_registry.end_blob_hook( + info!("Sequencer {} slashed: {:?}", sequencer_da_address, reason); + as ApplyBlobHooks>::end_blob_hook( + &self.sequencer_registry, sov_sequencer_registry::SequencerOutcome::Slashed { - sequencer: sequencer_da_address, + sequencer: sequencer_da_address.as_ref().to_vec(), }, working_set, ) diff --git a/examples/demo-stf/src/runtime.rs b/examples/demo-stf/src/runtime.rs index 379e3b8e1..8b3d93863 100644 --- a/examples/demo-stf/src/runtime.rs +++ b/examples/demo-stf/src/runtime.rs @@ -115,8 +115,11 @@ impl SlotHooks for Runtime { } } -impl sov_modules_stf_template::Runtime - for Runtime +impl sov_modules_stf_template::Runtime for Runtime +where + C: Context, + Cond: ValidityCondition, + B: BlobReaderTrait, { } diff --git a/examples/demo-stf/src/tests/tx_revert_tests.rs b/examples/demo-stf/src/tests/tx_revert_tests.rs index 7c60fa316..1d1085a02 100644 --- a/examples/demo-stf/src/tests/tx_revert_tests.rs +++ b/examples/demo-stf/src/tests/tx_revert_tests.rs @@ -7,6 +7,7 @@ use sov_modules_api::default_signature::private_key::DefaultPrivateKey; use sov_modules_api::transaction::Transaction; use sov_modules_api::{EncodeCall, PrivateKey, PublicKey}; use sov_modules_stf_template::{Batch, RawTx, SequencerOutcome, SlashingReason}; +use sov_rollup_interface::da::BlobReaderTrait; use sov_rollup_interface::mocks::{MockZkvm, TestBlock}; use sov_rollup_interface::stf::StateTransitionFunction; use sov_state::{ProverStorage, WorkingSet}; @@ -231,6 +232,7 @@ fn test_tx_bad_sig() { let txs = simulate_da_with_bad_sig(election_admin_private_key); let blob = new_test_blob_from_batch(Batch { txs }, &DEMO_SEQUENCER_DA_ADDRESS, [0; 32]); + let blob_sender = blob.sender(); let mut blobs = [blob]; let data = TestBlock::default(); @@ -247,7 +249,7 @@ fn test_tx_bad_sig() { assert_eq!( SequencerOutcome::Slashed{ reason:SlashingReason::StatelessVerificationFailed, - sequencer_da_address: DEMO_SEQUENCER_DA_ADDRESS.to_vec(), + sequencer_da_address: blob_sender, }, apply_blob_outcome.inner, "Unexpected outcome: Stateless verification should have failed due to invalid signature" @@ -315,6 +317,7 @@ fn test_tx_bad_serialization() { let txs = simulate_da_with_bad_serialization(election_admin_private_key); let blob = new_test_blob_from_batch(Batch { txs }, &DEMO_SEQUENCER_DA_ADDRESS, [0; 32]); + let blob_sender = blob.sender(); let mut blobs = [blob]; let data = TestBlock::default(); @@ -331,7 +334,7 @@ fn test_tx_bad_serialization() { assert_eq!( SequencerOutcome::Slashed { reason: SlashingReason::InvalidTransactionEncoding , - sequencer_da_address: DEMO_SEQUENCER_DA_ADDRESS.to_vec(), + sequencer_da_address: blob_sender, }, apply_blob_outcome.inner, "Unexpected outcome: Stateless verification should have failed due to invalid signature" diff --git a/module-system/module-implementations/integration-tests/src/chain_state/helpers.rs b/module-system/module-implementations/integration-tests/src/chain_state/helpers.rs index 3eaf4b4f6..47ed0cf33 100644 --- a/module-system/module-implementations/integration-tests/src/chain_state/helpers.rs +++ b/module-system/module-implementations/integration-tests/src/chain_state/helpers.rs @@ -39,13 +39,15 @@ impl TxHooks for TestRuntime { } } -impl ApplyBlobHooks for TestRuntime { +impl ApplyBlobHooks + for TestRuntime +{ type Context = C; - type BlobResult = SequencerOutcome; + type BlobResult = SequencerOutcome; fn begin_blob_hook( &self, - _blob: &mut impl BlobReaderTrait, + _blob: &mut B, _working_set: &mut WorkingSet<::Storage>, ) -> anyhow::Result<()> { Ok(()) @@ -90,7 +92,10 @@ impl BlobSelector for TestRuntime } } -impl Runtime for TestRuntime {} +impl Runtime + for TestRuntime +{ +} pub(crate) fn create_demo_genesis_config( admin: ::Address, diff --git a/module-system/module-implementations/sov-sequencer-registry/src/hooks.rs b/module-system/module-implementations/sov-sequencer-registry/src/hooks.rs index aed6103e0..e0d72567e 100644 --- a/module-system/module-implementations/sov-sequencer-registry/src/hooks.rs +++ b/module-system/module-implementations/sov-sequencer-registry/src/hooks.rs @@ -5,13 +5,13 @@ use sov_state::WorkingSet; use crate::{SequencerOutcome, SequencerRegistry}; -impl ApplyBlobHooks for SequencerRegistry { +impl ApplyBlobHooks for SequencerRegistry { type Context = C; type BlobResult = SequencerOutcome; fn begin_blob_hook( &self, - blob: &mut impl BlobReaderTrait, + blob: &mut B, working_set: &mut WorkingSet<::Storage>, ) -> anyhow::Result<()> { if !self.is_sender_allowed(&blob.sender(), working_set) { diff --git a/module-system/module-implementations/sov-sequencer-registry/tests/hooks_test.rs b/module-system/module-implementations/sov-sequencer-registry/tests/hooks_test.rs index f08a2dd41..360c61064 100644 --- a/module-system/module-implementations/sov-sequencer-registry/tests/hooks_test.rs +++ b/module-system/module-implementations/sov-sequencer-registry/tests/hooks_test.rs @@ -89,10 +89,12 @@ fn end_blob_hook_success() { .begin_blob_hook(&mut test_blob, working_set) .unwrap(); - test_sequencer - .registry - .end_blob_hook(SequencerOutcome::Completed, working_set) - .unwrap(); + as ApplyBlobHooks>>::end_blob_hook( + &test_sequencer.registry, + SequencerOutcome::Completed, + working_set, + ) + .unwrap(); let resp = test_sequencer.query_balance_via_bank(working_set).unwrap(); assert_eq!(balance_after_genesis, resp.amount.unwrap()); let resp = test_sequencer @@ -128,10 +130,12 @@ fn end_blob_hook_slash() { let result = SequencerOutcome::Slashed { sequencer: GENESIS_SEQUENCER_DA_ADDRESS.to_vec(), }; - test_sequencer - .registry - .end_blob_hook(result, working_set) - .unwrap(); + as ApplyBlobHooks>>::end_blob_hook( + &test_sequencer.registry, + result, + working_set, + ) + .unwrap(); let resp = test_sequencer.query_balance_via_bank(working_set).unwrap(); assert_eq!(balance_after_genesis, resp.amount.unwrap()); @@ -187,10 +191,12 @@ fn end_blob_hook_slash_preferred_sequencer() { let result = SequencerOutcome::Slashed { sequencer: GENESIS_SEQUENCER_DA_ADDRESS.to_vec(), }; - test_sequencer - .registry - .end_blob_hook(result, working_set) - .unwrap(); + as ApplyBlobHooks>>::end_blob_hook( + &test_sequencer.registry, + result, + working_set, + ) + .unwrap(); let resp = test_sequencer.query_balance_via_bank(working_set).unwrap(); assert_eq!(balance_after_genesis, resp.amount.unwrap()); @@ -233,10 +239,12 @@ fn end_blob_hook_slash_unknown_sequencer() { let result = SequencerOutcome::Slashed { sequencer: UNKNOWN_SEQUENCER_DA_ADDRESS.to_vec(), }; - test_sequencer - .registry - .end_blob_hook(result, working_set) - .unwrap(); + as ApplyBlobHooks>>::end_blob_hook( + &test_sequencer.registry, + result, + working_set, + ) + .unwrap(); let resp = test_sequencer .registry diff --git a/module-system/sov-modules-api/src/hooks.rs b/module-system/sov-modules-api/src/hooks.rs index 299692059..460b19ac0 100644 --- a/module-system/sov-modules-api/src/hooks.rs +++ b/module-system/sov-modules-api/src/hooks.rs @@ -32,7 +32,7 @@ pub trait TxHooks { /// Hooks related to the Sequencer functionality. /// In essence, the sequencer locks a bond at the beginning of the `StateTransitionFunction::apply_blob`, /// and is rewarded once a blob of transactions is processed. -pub trait ApplyBlobHooks { +pub trait ApplyBlobHooks { type Context: Context; type BlobResult; @@ -40,7 +40,7 @@ pub trait ApplyBlobHooks { /// If this hook returns Err, batch is not applied fn begin_blob_hook( &self, - blob: &mut impl BlobReaderTrait, + blob: &mut B, working_set: &mut WorkingSet<::Storage>, ) -> anyhow::Result<()>; diff --git a/module-system/sov-modules-stf-template/src/app_template.rs b/module-system/sov-modules-stf-template/src/app_template.rs index f056188ea..f11a9be2a 100644 --- a/module-system/sov-modules-stf-template/src/app_template.rs +++ b/module-system/sov-modules-stf-template/src/app_template.rs @@ -5,19 +5,25 @@ use sov_modules_api::{Context, DispatchCall}; use sov_rollup_interface::da::{BlobReaderTrait, CountedBufReader}; use sov_rollup_interface::stf::{BatchReceipt, TransactionReceipt}; use sov_rollup_interface::zk::ValidityCondition; -use sov_rollup_interface::Buf; +use sov_rollup_interface::{AddressTrait, Buf}; use sov_state::StateCheckpoint; use tracing::{debug, error}; use crate::tx_verifier::{verify_txs_stateless, TransactionAndRawHash}; use crate::{Batch, Runtime, SequencerOutcome, SlashingReason, TxEffect}; -type ApplyBatchResult = Result; +type ApplyBatchResult = Result>; /// An implementation of the /// [`StateTransitionFunction`](sov_rollup_interface::stf::StateTransitionFunction) /// that is specifically designed to work with the module-system. -pub struct AppTemplate, B> { +pub struct AppTemplate< + C: Context, + Cond: ValidityCondition, + Vm, + RT: Runtime, + B: BlobReaderTrait, +> { /// State storage used by the rollup. pub current_storage: C::Storage, /// The runtime includes all the modules that the rollup supports. @@ -28,19 +34,19 @@ pub struct AppTemplate, } -pub(crate) enum ApplyBatchError { +pub(crate) enum ApplyBatchError { // Contains batch hash Ignored([u8; 32]), Slashed { // Contains batch hash hash: [u8; 32], reason: SlashingReason, - sequencer_da_address: Vec, + sequencer_da_address: A, }, } -impl From for BatchReceipt { - fn from(value: ApplyBatchError) -> Self { +impl From> for BatchReceipt, TxEffect> { + fn from(value: ApplyBatchError) -> Self { match value { ApplyBatchError::Ignored(hash) => BatchReceipt { batch_hash: hash, @@ -63,10 +69,12 @@ impl From for BatchReceipt { } } -impl, B: BlobReaderTrait> - AppTemplate +impl AppTemplate where - RT: Runtime, + C: Context, + Cond: ValidityCondition, + B: BlobReaderTrait, + RT: Runtime, { /// [`AppTemplate`] constructor. pub fn new(storage: C::Storage, runtime: RT) -> Self { @@ -83,7 +91,7 @@ where pub(crate) fn apply_blob( &mut self, blob: &mut B, - ) -> ApplyBatchResult> { + ) -> ApplyBatchResult, TxEffect>, B::Address> { debug!( "Applying batch from sequencer: 0x{}", hex::encode(blob.sender()) @@ -116,7 +124,7 @@ where Err(reason) => { // Explicitly revert on slashing, even though nothing has changed in pre_process. let mut batch_workspace = batch_workspace.revert().to_revertable(); - let sequencer_da_address = blob.sender().as_ref().to_vec(); + let sequencer_da_address = blob.sender(); let sequencer_outcome = SequencerOutcome::Slashed { reason, sequencer_da_address: sequencer_da_address.clone(), diff --git a/module-system/sov-modules-stf-template/src/lib.rs b/module-system/sov-modules-stf-template/src/lib.rs index 9f83a5fc0..399dea1ee 100644 --- a/module-system/sov-modules-stf-template/src/lib.rs +++ b/module-system/sov-modules-stf-template/src/lib.rs @@ -13,17 +13,18 @@ use sov_rollup_interface::da::BlobReaderTrait; use sov_rollup_interface::services::da::SlotData; use sov_rollup_interface::stf::{SlotResult, StateTransitionFunction}; use sov_rollup_interface::zk::{ValidityCondition, Zkvm}; +use sov_rollup_interface::AddressTrait; use sov_state::{StateCheckpoint, Storage, WorkingSet}; use tracing::info; pub use tx_verifier::RawTx; /// This trait has to be implemented by a runtime in order to be used in `AppTemplate`. -pub trait Runtime: +pub trait Runtime: DispatchCall + Genesis + TxHooks + SlotHooks - + ApplyBlobHooks + + ApplyBlobHooks> + BlobSelector { } @@ -38,20 +39,17 @@ pub enum TxEffect { } #[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] -// TODO: Should be generic for Address for pretty printing https://github.com/Sovereign-Labs/sovereign-sdk/issues/465 /// Represents the different outcomes that can occur for a sequencer after batch processing. -pub enum SequencerOutcome { +pub enum SequencerOutcome { /// Sequencer receives reward amount in defined token and can withdraw its deposit Rewarded(u64), /// Sequencer loses its deposit and receives no reward Slashed { /// Reason why sequencer was slashed. reason: SlashingReason, - // Keep this comment for so it doesn't need to investigate serde issue again. - // https://github.com/Sovereign-Labs/sovereign-sdk/issues/465 - // #[serde(bound(deserialize = ""))] + #[serde(bound(deserialize = ""))] /// Sequencer address on DA. - sequencer_da_address: Vec, + sequencer_da_address: A, }, /// Batch was ignored, sequencer deposit left untouched. Ignored, @@ -68,10 +66,13 @@ pub enum SlashingReason { InvalidTransactionEncoding, } -impl - AppTemplate +impl AppTemplate where - RT: Runtime, + C: Context, + Vm: Zkvm, + Cond: ValidityCondition, + B: BlobReaderTrait, + RT: Runtime, { fn begin_slot( &mut self, @@ -102,10 +103,13 @@ where } } -impl - StateTransitionFunction for AppTemplate +impl StateTransitionFunction for AppTemplate where - RT: Runtime, + C: Context, + Vm: Zkvm, + Cond: ValidityCondition, + B: BlobReaderTrait, + RT: Runtime, { type StateRoot = jmt::RootHash; @@ -113,7 +117,7 @@ where type TxReceiptContents = TxEffect; - type BatchReceiptContents = SequencerOutcome; + type BatchReceiptContents = SequencerOutcome; type Witness = <::Storage as Storage>::Witness; diff --git a/module-system/utils/sov-data-generators/src/lib.rs b/module-system/utils/sov-data-generators/src/lib.rs index 2942a5601..1e7838230 100644 --- a/module-system/utils/sov-data-generators/src/lib.rs +++ b/module-system/utils/sov-data-generators/src/lib.rs @@ -13,6 +13,7 @@ use sov_modules_stf_template::RawTx; use sov_modules_stf_template::{Batch, SequencerOutcome, TxEffect}; use sov_rollup_interface::mocks::TestBlob; use sov_rollup_interface::stf::BatchReceipt; +use sov_rollup_interface::AddressTrait; #[cfg(feature = "native")] pub mod bank_data; @@ -27,7 +28,9 @@ pub fn new_test_blob_from_batch(batch: Batch, address: &[u8], hash: [u8; 32]) -> TestBlob::new(data, address, hash) } -pub fn has_tx_events(apply_blob_outcome: &BatchReceipt) -> bool { +pub fn has_tx_events( + apply_blob_outcome: &BatchReceipt, TxEffect>, +) -> bool { let events = apply_blob_outcome .tx_receipts .iter() diff --git a/rollup-interface/src/state_machine/mocks.rs b/rollup-interface/src/state_machine/mocks.rs index ebdbf7926..42bfc24b7 100644 --- a/rollup-interface/src/state_machine/mocks.rs +++ b/rollup-interface/src/state_machine/mocks.rs @@ -249,10 +249,6 @@ impl BlobReaderTrait for TestBlob
{ self.address.clone() } - fn hash(&self) -> [u8; 32] { - self.hash - } - fn data_mut(&mut self) -> &mut CountedBufReader { &mut self.data } @@ -260,6 +256,10 @@ impl BlobReaderTrait for TestBlob
{ fn data(&self) -> &CountedBufReader { &self.data } + + fn hash(&self) -> [u8; 32] { + self.hash + } } impl TestBlob
{