From da61c7e2a7fd8dcab0cdb06ad2f35391307b4a4e Mon Sep 17 00:00:00 2001 From: Farhad Shabani Date: Fri, 12 Apr 2024 22:32:38 -0700 Subject: [PATCH 1/6] impl: enhance light client implementation to address shortfalls --- Cargo.lock | 46 ++- Cargo.toml | 1 + clients/README.md | 4 +- .../sov-celestia-cw/src/context/client_ctx.rs | 2 +- clients/sov-celestia-cw/src/context/mod.rs | 2 +- clients/sov-celestia-cw/src/handlers.rs | 3 - clients/sov-celestia-cw/src/tests/fixture.rs | 45 ++- clients/sov-celestia-cw/src/types/error.rs | 3 +- clients/sov-celestia-cw/src/types/msgs.rs | 1 - clients/sov-celestia-cw/src/types/response.rs | 3 - clients/sov-celestia/Cargo.toml | 3 - .../sov-celestia/src/client_state/common.rs | 26 +- .../src/client_state/execution.rs | 130 ++++---- .../src/client_state/misbehaviour.rs | 4 +- clients/sov-celestia/src/client_state/mod.rs | 2 +- .../src/client_state/update_client.rs | 36 ++- .../src/client_state/validation.rs | 55 ++-- clients/sov-celestia/src/consensus_state.rs | 10 +- clients/sov-celestia/src/lib.rs | 2 - clients/sov-celestia/types/Cargo.toml | 13 +- .../types/src/client_message/header.rs | 61 ++-- .../types/src/client_message/misbehaviour.rs | 89 +++--- .../types/src/client_message/mod.rs | 72 +---- .../types/src/client_state/da_params.rs | 54 ++-- .../types/src/client_state/definition.rs | 175 ++++------- .../types/src/client_state/mod.rs | 71 ++--- .../types/src/consensus_state/da_params.rs | 4 +- .../types/src/consensus_state/definition.rs | 61 ++-- clients/sov-celestia/types/src/lib.rs | 11 +- clients/sov-types/Cargo.toml | 53 ++++ .../src}/aggregated_proof.rs | 179 +++++++++-- clients/sov-types/src/client_params.rs | 252 +++++++++++++++ clients/sov-types/src/consensus_params.rs | 67 ++++ .../types => sov-types}/src/error.rs | 23 +- .../src => sov-types/src/helpers}/codec.rs | 0 clients/sov-types/src/helpers/mod.rs | 5 + .../src/helpers}/pretty.rs | 0 clients/sov-types/src/lib.rs | 25 ++ mocks/src/configs.rs | 7 +- mocks/src/cosmos/core.rs | 5 + mocks/src/cosmos/manual.rs | 4 +- mocks/src/relayer/builder.rs | 5 +- mocks/src/sovereign/rollup.rs | 21 +- mocks/src/sovereign/runner.rs | 10 + .../src/celestia_da.rs | 23 +- .../src/mock_da.rs | 30 +- ...{sov_tendermint.proto => tendermint.proto} | 73 ++--- .../lightclients/sovereign/v1/sovereign.proto | 61 ++++ .../sovereign/types/v1/types.proto | 17 +- proto/src/lib.rs | 5 + ...bc.lightclients.sovereign.tendermint.v1.rs | 112 +++---- ...htclients.sovereign.tendermint.v1.serde.rs | 140 ++------- .../prost/ibc.lightclients.sovereign.v1.rs | 72 +++++ .../ibc.lightclients.sovereign.v1.serde.rs | 294 ++++++++++++++++++ proto/src/prost/proto_descriptor.bin | Bin 162728 -> 165059 bytes proto/src/prost/sovereign.types.v1.rs | 53 +++- proto/src/prost/sovereign.types.v1.serde.rs | 117 ++++++- 57 files changed, 1763 insertions(+), 879 deletions(-) create mode 100644 clients/sov-types/Cargo.toml rename clients/{sov-celestia/types/src/client_message => sov-types/src}/aggregated_proof.rs (66%) create mode 100644 clients/sov-types/src/client_params.rs create mode 100644 clients/sov-types/src/consensus_params.rs rename clients/{sov-celestia/types => sov-types}/src/error.rs (87%) rename clients/{sov-celestia/types/src => sov-types/src/helpers}/codec.rs (100%) create mode 100644 clients/sov-types/src/helpers/mod.rs rename clients/{sov-celestia/types/src/client_message => sov-types/src/helpers}/pretty.rs (100%) create mode 100644 clients/sov-types/src/lib.rs rename proto/definitions/ibc/lightclients/sovereign/tendermint/v1/{sov_tendermint.proto => tendermint.proto} (58%) create mode 100644 proto/definitions/ibc/lightclients/sovereign/v1/sovereign.proto create mode 100644 proto/src/prost/ibc.lightclients.sovereign.v1.rs create mode 100644 proto/src/prost/ibc.lightclients.sovereign.v1.serde.rs diff --git a/Cargo.lock b/Cargo.lock index 4b45dda7..3d102568 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -807,9 +807,9 @@ dependencies = [ [[package]] name = "bnum" -version = "0.8.1" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab9008b6bb9fc80b5277f2fe481c09e828743d9151203e804583eb4c9e15b31d" +checksum = "56953345e39537a3e18bdaeba4cb0c58a78c1f61f361dc0fa7c5c7340ae87c5f" [[package]] name = "bonsai-sdk" @@ -1233,9 +1233,9 @@ dependencies = [ [[package]] name = "cosmwasm-crypto" -version = "1.5.2" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ed6aa9f904de106fa16443ad14ec2abe75e94ba003bb61c681c0e43d4c58d2a" +checksum = "9934c79e58d9676edfd592557dee765d2a6ef54c09d5aa2edb06156b00148966" dependencies = [ "digest 0.10.7", "ecdsa", @@ -1280,9 +1280,9 @@ dependencies = [ [[package]] name = "cosmwasm-std" -version = "1.5.2" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad011ae7447188e26e4a7dbca2fcd0fc186aa21ae5c86df0503ea44c78f9e469" +checksum = "ef8666e572a3a2519010dde88c04d16e9339ae751b56b2bb35081fe3f7d6be74" dependencies = [ "base64 0.21.7", "bech32 0.9.1", @@ -1302,9 +1302,9 @@ dependencies = [ [[package]] name = "cosmwasm-vm" -version = "1.5.2" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ebdf59ae3b9fe66d1eb845cf69aa537c77107d816452595c5796c332af061f" +checksum = "011bc44b0d617f440ea509b38e543437511a196c6e2a0ebd3425edd912902fb2" dependencies = [ "bitflags 1.3.2", "bytecheck", @@ -3432,9 +3432,9 @@ dependencies = [ [[package]] name = "k256" -version = "0.13.3" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "956ff9b67e26e1a6a866cb758f12c6f8746208489e3e4a4b5580802f2f0a587b" +checksum = "cadb76004ed8e97623117f3df85b17aaa6626ab0b0831e6573f104df16cd1bcc" dependencies = [ "cfg-if", "ecdsa", @@ -5522,7 +5522,6 @@ dependencies = [ "derive_more", "ibc-client-tendermint", "ibc-core", - "ics23", "jmt", "prost", "schemars", @@ -5559,17 +5558,15 @@ dependencies = [ name = "sov-celestia-client-types" version = "0.1.0" dependencies = [ - "bytes", "derive_more", "hex", "ibc-client-tendermint", "ibc-client-wasm-types", "ibc-core", - "ics23", - "jmt", "prost", "schemars", "serde", + "sov-client-types", "sov-ibc-proto", "tendermint 0.34.1", "tendermint-light-client-verifier", @@ -5593,6 +5590,21 @@ dependencies = [ "tracing", ] +[[package]] +name = "sov-client-types" +version = "0.1.0" +dependencies = [ + "derive_more", + "hex", + "ibc-core", + "jmt", + "prost", + "schemars", + "serde", + "sov-ibc-proto", + "typed-builder", +] + [[package]] name = "sov-consensus-state-tracker" version = "0.1.0" @@ -6493,7 +6505,7 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "winnow 0.6.5", + "winnow 0.6.6", ] [[package]] @@ -7394,9 +7406,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.6.5" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dffa400e67ed5a4dd237983829e66475f0a4a26938c4b04c21baede6262215b8" +checksum = "f0c976aaaa0e1f90dbb21e9587cdaf1d9679a1cde8875c0d6bd83ab96a208352" dependencies = [ "memchr", ] diff --git a/Cargo.toml b/Cargo.toml index 7aab98b7..4fbe6d19 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,6 +3,7 @@ resolver = "2" members = [ "proto", "proto/compiler", + "clients/sov-types", "clients/sov-celestia/types", "clients/sov-celestia", "clients/sov-celestia-cw", diff --git a/clients/README.md b/clients/README.md index c7e58e39..42ce7676 100644 --- a/clients/README.md +++ b/clients/README.md @@ -1 +1,3 @@ -# `sov-celestia-client` +
+

Sovereign IBC Light Clients

+
diff --git a/clients/sov-celestia-cw/src/context/client_ctx.rs b/clients/sov-celestia-cw/src/context/client_ctx.rs index a1760319..a04d0373 100644 --- a/clients/sov-celestia-cw/src/context/client_ctx.rs +++ b/clients/sov-celestia-cw/src/context/client_ctx.rs @@ -8,7 +8,7 @@ use ibc_core::host::types::identifiers::ClientId; use ibc_core::host::types::path::{iteration_key, ClientConsensusStatePath, ClientStatePath}; use ibc_core::primitives::proto::{Any, Protobuf}; use ibc_core::primitives::Timestamp; -use sov_celestia_client::types::codec::AnyCodec; +use sov_celestia_client::types::sovereign::AnyCodec; use super::Context; use crate::types::ClientType; diff --git a/clients/sov-celestia-cw/src/context/mod.rs b/clients/sov-celestia-cw/src/context/mod.rs index d66208e6..2252e829 100644 --- a/clients/sov-celestia-cw/src/context/mod.rs +++ b/clients/sov-celestia-cw/src/context/mod.rs @@ -15,7 +15,7 @@ use ibc_core::host::types::path::{ }; use ibc_core::primitives::proto::{Any, Protobuf}; use prost::Message; -use sov_celestia_client::types::codec::AnyCodec; +use sov_celestia_client::types::sovereign::AnyCodec; use crate::types::{ parse_height, ClientType, ContractError, GenesisMetadata, HeightTravel, MigrationPrefix, diff --git a/clients/sov-celestia-cw/src/handlers.rs b/clients/sov-celestia-cw/src/handlers.rs index 5f7a77f6..e4cb7e31 100644 --- a/clients/sov-celestia-cw/src/handlers.rs +++ b/clients/sov-celestia-cw/src/handlers.rs @@ -1,7 +1,4 @@ use cosmwasm_std::{to_json_binary, Binary}; -use ibc_core::client::context::client_state::{ - ClientStateCommon, ClientStateExecution, ClientStateValidation, -}; use ibc_core::client::context::prelude::*; use ibc_core::host::types::path::ClientConsensusStatePath; use ibc_core::primitives::proto::Any; diff --git a/clients/sov-celestia-cw/src/tests/fixture.rs b/clients/sov-celestia-cw/src/tests/fixture.rs index 3cd3224f..76a0cf40 100644 --- a/clients/sov-celestia-cw/src/tests/fixture.rs +++ b/clients/sov-celestia-cw/src/tests/fixture.rs @@ -1,4 +1,4 @@ -use std::ops::Add; +use std::ops::{Add, Sub}; use std::time::Duration; use cosmwasm_std::testing::{mock_env, mock_info}; @@ -8,14 +8,14 @@ use ibc_core::client::types::{Height, Status}; use ibc_core::host::types::identifiers::ChainId; use ibc_core::primitives::Timestamp; use sov_celestia_client::types::client_message::test_util::dummy_sov_header; -use sov_celestia_client::types::client_message::{Root, SovTmHeader}; +use sov_celestia_client::types::client_message::SovTmHeader; use sov_celestia_client::types::client_state::test_util::{ dummy_checksum, dummy_sov_consensus_state, mock_celestia_chain_id, ClientStateConfig, TendermintParamsConfig, }; use sov_celestia_client::types::client_state::SovTmClientState; -use sov_celestia_client::types::codec::AnyCodec; use sov_celestia_client::types::consensus_state::SovTmConsensusState; +use sov_celestia_client::types::sovereign::{AnyCodec, Root, SovereignParamsConfig}; use tendermint_testgen::{Generator, Validator}; use crate::entrypoints::SovTmContext; @@ -29,7 +29,8 @@ use crate::types::{ pub struct Fixture { pub chain_id: ChainId, pub trusted_timestamp: Timestamp, - pub trusted_height: Height, + pub genesis_da_height: Height, + pub trusted_da_height: Height, pub target_height: Height, pub validators: Vec, pub migration_mode: bool, @@ -43,7 +44,8 @@ impl Default for Fixture { // timestamp of the `mock_env()`. trusted_timestamp: Timestamp::from_nanoseconds(1_571_797_419_879_305_533) .expect("never fails"), - trusted_height: Height::new(0, 5).unwrap(), + genesis_da_height: Height::new(0, 3).unwrap(), + trusted_da_height: Height::new(0, 5).unwrap(), target_height: Height::new(0, 10).unwrap(), validators: vec![ Validator::new("1").voting_power(40), @@ -82,14 +84,22 @@ impl Fixture { } pub fn dummy_instantiate_msg(&self) -> InstantiateMsg { - // Setting the `trusting_period`` to 1 second allows for a quick client - // freeze in the `happy_cw_client_recovery` test - let tendermint_params = TendermintParamsConfig::builder() + // Setting the `trusting_period` to 1 second allows the quick client + // freeze for the `happy_cw_client_recovery` test. + let sovereign_params = SovereignParamsConfig::builder() + .genesis_da_height(self.genesis_da_height) .trusting_period(Duration::from_secs(1)) + .latest_height( + self.trusted_da_height + .sub(self.genesis_da_height.revision_height()) + .unwrap(), + ) .build(); + let tendermint_params = TendermintParamsConfig::builder().build(); + let sov_client_state = ClientStateConfig::builder() - .latest_height(self.trusted_height) + .sovereign_params(sovereign_params) .tendermint_params(tendermint_params) .build(); @@ -126,14 +136,18 @@ impl Fixture { let tm_header = Header { signed_header: light_block.signed_header, validator_set: light_block.validators, - trusted_height: self.trusted_height, + trusted_height: self.trusted_da_height, trusted_next_validator_set: light_block.next_validators, }; let sov_header = dummy_sov_header( tm_header, - self.trusted_height, - header_height, + self.trusted_da_height + .revision_height() + .sub(self.genesis_da_height.revision_height()), + header_height + .revision_height() + .sub(self.genesis_da_height.revision_height()), Root::from([0; 32]), ); @@ -141,13 +155,16 @@ impl Fixture { } pub fn dummy_client_message(&self) -> Vec { - self.dummy_header(self.target_height) + self.dummy_header( + self.target_height + .add(self.genesis_da_height.revision_height()), + ) } /// Constructs a dummy misbehaviour message that is one block behind the /// trusted height, but with a future timestamp. pub fn dummy_misbehaviour_message(&self) -> Vec { - let prev_height = self.trusted_height.decrement().expect("never fails"); + let prev_height = self.trusted_da_height.decrement().expect("never fails"); self.dummy_header(prev_height) } diff --git a/clients/sov-celestia-cw/src/types/error.rs b/clients/sov-celestia-cw/src/types/error.rs index d0fd99c1..b177cd7c 100644 --- a/clients/sov-celestia-cw/src/types/error.rs +++ b/clients/sov-celestia-cw/src/types/error.rs @@ -1,4 +1,3 @@ -use alloc::string::String; use std::error::Error; use cosmwasm_std::StdError; @@ -8,7 +7,7 @@ use ibc_core::commitment_types::error::CommitmentError; use ibc_core::handler::types::error::ContextError; use ibc_core::host::types::error::IdentifierError; use ibc_core::host::types::path::PathError; -use sov_celestia_client::types::error::Error as SovCelestiaClientError; +use sov_celestia_client::types::sovereign::Error as SovCelestiaClientError; #[derive(From, Display, Debug)] pub enum ContractError { diff --git a/clients/sov-celestia-cw/src/types/msgs.rs b/clients/sov-celestia-cw/src/types/msgs.rs index 5f45184a..e9ff9dce 100644 --- a/clients/sov-celestia-cw/src/types/msgs.rs +++ b/clients/sov-celestia-cw/src/types/msgs.rs @@ -1,6 +1,5 @@ //! Contains the definition of the messages that can be sent to the CosmWasm contract. -use alloc::vec::Vec; use std::str::FromStr; use cosmwasm_schema::cw_serde; diff --git a/clients/sov-celestia-cw/src/types/response.rs b/clients/sov-celestia-cw/src/types/response.rs index e7466673..6b814cd1 100644 --- a/clients/sov-celestia-cw/src/types/response.rs +++ b/clients/sov-celestia-cw/src/types/response.rs @@ -1,6 +1,3 @@ -use alloc::string::String; -use alloc::vec::Vec; - use cosmwasm_schema::cw_serde; use ibc_core::client::types::Height; diff --git a/clients/sov-celestia/Cargo.toml b/clients/sov-celestia/Cargo.toml index 1736a12a..b30a61be 100644 --- a/clients/sov-celestia/Cargo.toml +++ b/clients/sov-celestia/Cargo.toml @@ -31,7 +31,6 @@ typed-builder = { version = "0.18.0", optional = true } ibc-core = { workspace = true } ibc-client-tendermint = { workspace = true } sov-celestia-client-types = { path = "./types", default-features = false } -ics23 = { version = "0.11", default-features = false } # DA layer dependencies tendermint = { workspace = true } @@ -44,7 +43,6 @@ std = [ "ibc-core/std", "ibc-client-tendermint/std", "sov-celestia-client-types/std", - "ics23/std", "prost/std", "serde/std", "tendermint/std" @@ -53,7 +51,6 @@ serde = [ "ibc-core/serde", "ibc-client-tendermint/serde", "sov-celestia-client-types/serde", - "ics23/serde", "dep:serde", ] json-schema = [ diff --git a/clients/sov-celestia/src/client_state/common.rs b/clients/sov-celestia/src/client_state/common.rs index ae91c039..39f59fe0 100644 --- a/clients/sov-celestia/src/client_state/common.rs +++ b/clients/sov-celestia/src/client_state/common.rs @@ -1,5 +1,3 @@ -use alloc::vec::Vec; - use borsh::de::BorshDeserialize; use borsh::BorshSerialize; use ibc_core::client::context::client_state::ClientStateCommon; @@ -16,7 +14,7 @@ use ibc_core::primitives::prelude::*; use ibc_core::primitives::proto::Any; use ibc_core::primitives::ToVec; use jmt::proof::SparseMerkleProof; -use sov_celestia_client_types::client_state::{sov_client_type, SovTmClientState}; +use sov_celestia_client_types::client_state::{sov_celestia_client_type, SovTmClientState}; use super::ClientState; use crate::consensus_state::ConsensusState; @@ -34,11 +32,11 @@ impl ClientStateCommon for ClientState { } fn client_type(&self) -> ClientType { - sov_client_type() + sov_celestia_client_type() } fn latest_height(&self) -> Height { - self.0.latest_height() + self.0.latest_height_in_sov() } fn validate_proof_height(&self, proof_height: Height) -> Result<(), ClientError> { @@ -113,13 +111,13 @@ pub fn verify_upgrade_client( // Make sure that the consensus type is of Tendermint type `ConsensusState` ConsensusState::try_from(upgraded_consensus_state.clone())?; - let latest_height = client_state.latest_height; + let latest_height = client_state.latest_height_in_sov(); let upgraded_tm_client_state_height = upgraded_tm_client_state.latest_height(); // Make sure the latest height of the current client is not greater than the - // upgrade height This condition checks both the revision number and the - // height + // upgrade height. This condition checks both the revision number and the + // height. if latest_height >= upgraded_tm_client_state_height { Err(UpgradeClientError::LowUpgradeHeight { upgraded_height: latest_height, @@ -127,16 +125,16 @@ pub fn verify_upgrade_client( })?; } - let upgrade_path_prefix = client_state.upgrade_path.clone().try_into()?; - - let last_height = latest_height.revision_height(); + let upgrade_path_prefix = client_state.upgrade_path().clone().try_into()?; // Verify the proof of the upgraded client state verify_membership( &upgrade_path_prefix, &proof_upgrade_client, root, - Path::UpgradeClient(UpgradeClientPath::UpgradedClientState(last_height)), + Path::UpgradeClient(UpgradeClientPath::UpgradedClientState( + latest_height.revision_height(), + )), upgraded_client_state.to_vec(), )?; @@ -145,7 +143,9 @@ pub fn verify_upgrade_client( &upgrade_path_prefix, &proof_upgrade_consensus_state, root, - Path::UpgradeClient(UpgradeClientPath::UpgradedClientConsensusState(last_height)), + Path::UpgradeClient(UpgradeClientPath::UpgradedClientConsensusState( + latest_height.revision_height(), + )), upgraded_consensus_state.to_vec(), )?; diff --git a/clients/sov-celestia/src/client_state/execution.rs b/clients/sov-celestia/src/client_state/execution.rs index e6d3c513..56e8e881 100644 --- a/clients/sov-celestia/src/client_state/execution.rs +++ b/clients/sov-celestia/src/client_state/execution.rs @@ -1,5 +1,3 @@ -use alloc::vec::Vec; - use ibc_core::client::context::client_state::ClientStateExecution; use ibc_core::client::types::error::ClientError; use ibc_core::client::types::Height; @@ -8,10 +6,11 @@ use ibc_core::host::types::path::{ClientConsensusStatePath, ClientStatePath}; use ibc_core::primitives::prelude::*; use ibc_core::primitives::proto::Any; use sov_celestia_client_types::client_message::Header; -use sov_celestia_client_types::client_state::{SovTmClientState, TmClientParams}; +use sov_celestia_client_types::client_state::SovTmClientState; use sov_celestia_client_types::consensus_state::{ ConsensusState as ConsensusStateType, SovTmConsensusState, TmConsensusParams, }; +use sov_celestia_client_types::sovereign::SovereignConsensusParams; use super::ClientState; use crate::consensus_state::ConsensusState; @@ -62,7 +61,7 @@ where upgraded_consensus_state: Any, ) -> Result { update_state_on_upgrade( - self.inner(), + self.inner().clone(), ctx, client_id, upgraded_client_state, @@ -101,6 +100,8 @@ where let sov_consensus_state = SovTmConsensusState::try_from(consensus_state)?; + let latest_height = client_state.latest_height_in_sov(); + ctx.store_client_state( ClientStatePath::new(client_id.clone()), client_state.clone().into(), @@ -108,14 +109,14 @@ where ctx.store_consensus_state( ClientConsensusStatePath::new( client_id.clone(), - client_state.latest_height().revision_number(), - client_state.latest_height().revision_height(), + latest_height.revision_number(), + latest_height.revision_height(), ), sov_consensus_state.into(), )?; ctx.store_update_meta( client_id.clone(), - client_state.latest_height(), + latest_height, host_timestamp, host_height, )?; @@ -159,13 +160,13 @@ where let host_height = SovValidationContext::host_height(ctx)?; let new_consensus_state = ConsensusStateType::from(header.clone()); - let new_client_state = client_state.clone().with_header(header.da_header)?; + let new_client_state = client_state.clone().with_da_header(header.da_header)?; ctx.store_consensus_state( ClientConsensusStatePath::new( client_id.clone(), - new_client_state.latest_height.revision_number(), - new_client_state.latest_height.revision_height(), + header_height.revision_number(), + header_height.revision_height(), ), new_consensus_state.into(), )?; @@ -206,7 +207,7 @@ where } pub fn update_state_on_upgrade( - client_state: &SovTmClientState, + client_state: SovTmClientState, ctx: &mut E, client_id: &ClientId, upgraded_client_state: Any, @@ -218,53 +219,51 @@ where E::ConsensusStateRef: ConsensusStateConverter, { let mut upgraded_client_state = SovTmClientState::try_from(upgraded_client_state)?; - let upgraded_tm_cons_state = ConsensusState::try_from(upgraded_consensus_state)?; + let upgraded_consensus_state = ConsensusState::try_from(upgraded_consensus_state)?; upgraded_client_state.zero_custom_fields(); - // Constructs the new client state. All rollup-chosen parameters come from - // `upgraded_client_state` except the `genesis_state_root`. All - // relayer-chosen parameters come from the current client. - let new_da_params = TmClientParams::new( - upgraded_client_state.da_params.chain_id, - client_state.da_params.trust_level, - client_state.da_params.trusting_period, - upgraded_client_state.da_params.unbonding_period, - client_state.da_params.max_clock_drift, - ); - - let new_client_state = SovTmClientState::new( - client_state.genesis_state_root.clone(), - upgraded_client_state.code_commitment, - upgraded_client_state.latest_height, - None, - upgraded_client_state.upgrade_path, - new_da_params, - ); - - // The new consensus state is merely used as a trusted kernel against - // which headers on the new chain can be verified. The root is just a - // stand-in sentinel value as it cannot be known in advance, thus no - // proof verification will pass. The timestamp and the - // NextValidatorsHash of the consensus state is the blocktime and - // NextValidatorsHash of the last block committed by the old chain. This - // will allow the first block of the new chain to be verified against - // the last validators of the old chain so long as it is submitted - // within the TrustingPeriod of this client. - // NOTE: We do not set processed time for this consensus state since - // this consensus state should not be used for packet verification as - // the root is empty. The next consensus state submitted using update + // Creates new Sovereign client parameters. The `genesis_da_height` and + // `genesis_state_root` are considered immutable properties of the client. + // Changing them implies creating a client that could potentially be compatible + // with other rollups. + let new_sovereign_params = client_state + .sovereign_params + .update_on_upgrade(upgraded_client_state.sovereign_params); + + // Creates new Tendermint client parameters. All chain-chosen parameters + // come from committed client, all relayer-chosen parameters come from + // current client. + let new_tendermint_params = client_state + .da_params + .update_on_upgrade(upgraded_client_state.da_params); + + let new_client_state = SovTmClientState::new(new_sovereign_params, new_tendermint_params); + + // The new consensus state is merely used as a trusted kernel against which + // headers on the new rollup can be verified. The root is just a stand-in + // sentinel value as it cannot be known in advance, thus no proof + // verification will pass. The next consensus state submitted using update // will be usable for packet-verification. let sentinel_root = "sentinel_root".as_bytes().to_vec(); - let new_consensus_state = SovTmConsensusState::new( - sentinel_root.into(), - TmConsensusParams { - timestamp: upgraded_tm_cons_state.timestamp(), - next_validators_hash: upgraded_tm_cons_state.next_validators_hash(), - }, - ); - - let latest_height = new_client_state.latest_height; + + let new_sovereign_consensus_params = + SovereignConsensusParams::new(sentinel_root.clone().into()); + + // The `timestamp` and the `next_validators_hash` of the consensus state is + // the block time and `next_validators_hash` of the last block committed by + // the old chain. This will allow the first block of the new chain to be + // verified against the last validators of the old chain so long as it is + // submitted within the DA `trusting_period` of this client. + let new_tm_consensus_params = TmConsensusParams { + timestamp: upgraded_consensus_state.timestamp(), + next_validators_hash: upgraded_consensus_state.next_validators_hash(), + }; + + let new_consensus_state = + SovTmConsensusState::new(new_sovereign_consensus_params, new_tm_consensus_params); + + let latest_height = new_client_state.latest_height_in_sov(); let host_timestamp = SovValidationContext::host_timestamp(ctx)?; let host_height = SovValidationContext::host_height(ctx)?; @@ -307,22 +306,17 @@ where { let substitute_client_state = ClientState::try_from(substitute_client_state)?.into_inner(); - let chain_id = substitute_client_state.da_params.chain_id; - let trusting_period = substitute_client_state.da_params.trusting_period; - let latest_height = substitute_client_state.latest_height; + let latest_height = substitute_client_state.latest_height_in_sov(); - let new_client_state = SovTmClientState::new( - subject_client_state.genesis_state_root, - subject_client_state.code_commitment, - latest_height, - None, - subject_client_state.upgrade_path, - TmClientParams { - chain_id, - trusting_period, - ..subject_client_state.da_params - }, - ); + let new_sovereign_params = subject_client_state + .sovereign_params + .update_on_recovery(substitute_client_state.sovereign_params); + + let new_da_params = subject_client_state + .da_params + .update_on_recovery(substitute_client_state.da_params); + + let new_client_state = SovTmClientState::new(new_sovereign_params, new_da_params); let host_timestamp = E::host_timestamp(ctx)?; let host_height = E::host_height(ctx)?; diff --git a/clients/sov-celestia/src/client_state/misbehaviour.rs b/clients/sov-celestia/src/client_state/misbehaviour.rs index e0634cbe..731814a4 100644 --- a/clients/sov-celestia/src/client_state/misbehaviour.rs +++ b/clients/sov-celestia/src/client_state/misbehaviour.rs @@ -23,7 +23,7 @@ where { misbehaviour.validate_basic()?; - let header_1 = misbehaviour.header1(); + let header_1 = misbehaviour.header_1(); let trusted_consensus_state_1 = { let consensus_state_path = ClientConsensusStatePath::new( client_id.clone(), @@ -35,7 +35,7 @@ where consensus_state.try_into()? }; - let header_2 = misbehaviour.header2(); + let header_2 = misbehaviour.header_2(); let trusted_consensus_state_2 = { let consensus_state_path = ClientConsensusStatePath::new( client_id.clone(), diff --git a/clients/sov-celestia/src/client_state/mod.rs b/clients/sov-celestia/src/client_state/mod.rs index 112a6aa4..6d226f5b 100644 --- a/clients/sov-celestia/src/client_state/mod.rs +++ b/clients/sov-celestia/src/client_state/mod.rs @@ -16,7 +16,7 @@ pub use misbehaviour::*; use sov_celestia_client_types::client_state::{ SovTmClientState, SOV_TENDERMINT_CLIENT_STATE_TYPE_URL, }; -use sov_celestia_client_types::proto::tendermint::v1::ClientState as RawSovTmClientState; +use sov_celestia_client_types::proto::v1::ClientState as RawSovTmClientState; pub use update_client::*; /// Newtype wrapper exists so that we can bypass Rust's orphan rules and diff --git a/clients/sov-celestia/src/client_state/update_client.rs b/clients/sov-celestia/src/client_state/update_client.rs index 95d3479a..4e4a1542 100644 --- a/clients/sov-celestia/src/client_state/update_client.rs +++ b/clients/sov-celestia/src/client_state/update_client.rs @@ -1,16 +1,14 @@ use ibc_client_tendermint::context::TmVerifier; +use ibc_client_tendermint::types::error::IntoResult; use ibc_client_tendermint::types::Header as TmHeader; use ibc_core::client::types::error::ClientError; use ibc_core::client::types::Height; -use ibc_core::host::types::identifiers::{ChainId, ClientId}; +use ibc_core::host::types::identifiers::ClientId; use ibc_core::host::types::path::ClientConsensusStatePath; -use sov_celestia_client_types::client_message::{ - AggregatedProof, CodeCommitment, Root, SovTmHeader, -}; +use sov_celestia_client_types::client_message::SovTmHeader; use sov_celestia_client_types::client_state::SovTmClientState; use sov_celestia_client_types::consensus_state::SovTmConsensusState; -use sov_celestia_client_types::error::IntoResult; -use tendermint_light_client_verifier::options::Options; +use sov_celestia_client_types::sovereign::{AggregatedProof, CodeCommitment, Root}; use tendermint_light_client_verifier::types::{TrustedBlockState, UntrustedBlockState}; use tendermint_light_client_verifier::Verifier; @@ -32,15 +30,13 @@ where // Checks the sanity of the fields in the header. header.validate_basic()?; - verify_da_header( - ctx, - &header.da_header, - client_id, - client_state.chain_id(), - &client_state.as_light_client_options()?, - verifier, + header.validate_da_height_offset( + client_state.genesis_da_height(), + client_state.latest_height_in_sov(), )?; + verify_da_header(ctx, client_state, &header.da_header, client_id, verifier)?; + verify_aggregated_proof( ctx, client_state.genesis_state_root(), @@ -55,16 +51,17 @@ where /// trusted state. pub fn verify_da_header( ctx: &V, + client_state: &SovTmClientState, da_header: &TmHeader, client_id: &ClientId, - chain_id: &ChainId, - options: &Options, verifier: &impl TmVerifier, ) -> Result<(), ClientError> where V: SovValidationContext, V::ConsensusStateRef: ConsensusStateConverter, { + let chain_id = client_state.chain_id(); + // The revision number of the `ChainId` tracked by the client state must // match the `ChainId` in the DA header. da_header @@ -73,7 +70,7 @@ where description: format!("failed to verify chain id: {e}"), })?; - let trusted_height = da_header.trusted_height; + let trusted_height = client_state.latest_height_in_sov(); let trusted_state = { let trusted_client_cons_state_path = ClientConsensusStatePath::new( @@ -126,7 +123,12 @@ where // main header verification, delegated to the tendermint-light-client crate. verifier .verifier() - .verify_update_header(untrusted_state, trusted_state, options, now) + .verify_update_header( + untrusted_state, + trusted_state, + &client_state.as_light_client_options()?, + now, + ) .into_result()?; Ok(()) diff --git a/clients/sov-celestia/src/client_state/validation.rs b/clients/sov-celestia/src/client_state/validation.rs index cec76fbe..59543513 100644 --- a/clients/sov-celestia/src/client_state/validation.rs +++ b/clients/sov-celestia/src/client_state/validation.rs @@ -96,16 +96,18 @@ where match client_message.type_url.as_str() { SOV_TENDERMINT_HEADER_TYPE_URL => { let header = SovTmHeader::try_from(client_message)?; - check_da_misbehaviour_on_update(ctx, header, client_id, &client_state.latest_height) - - // TODO: Determine if we need any sort of misbehaviour check for the - // rollup (aggregated proof) part. + check_da_misbehaviour_on_update( + ctx, + header, + client_id, + &client_state.latest_height_in_sov(), + ) } SOV_TENDERMINT_MISBEHAVIOUR_TYPE_URL => { let misbehaviour = SovTmMisbehaviour::try_from(client_message)?; check_for_misbehaviour_on_misbehavior( - &misbehaviour.header1().da_header, - &misbehaviour.header2().da_header, + &misbehaviour.header_1().da_header, + &misbehaviour.header_2().da_header, ) // TODO: Determine if we need any sort of misbehaviour check for the @@ -133,8 +135,8 @@ where let latest_consensus_state = { match ctx.consensus_state(&ClientConsensusStatePath::new( client_id.clone(), - client_state.latest_height.revision_number(), - client_state.latest_height.revision_height(), + client_state.latest_height_in_sov().revision_number(), + client_state.latest_height_in_sov().revision_height(), )) { Ok(cs) => cs.try_into()?, // if the client state does not have an associated consensus state for its latest height @@ -150,7 +152,7 @@ where if let Some(elapsed_since_latest_consensus_state) = now.duration_since(&latest_consensus_state.timestamp().into()) { - if elapsed_since_latest_consensus_state > client_state.da_params.trusting_period { + if elapsed_since_latest_consensus_state > client_state.trusting_period() { return Ok(Status::Expired); } } @@ -162,7 +164,7 @@ where /// /// The subject and substitute client states match if all their respective /// client state parameters match except for frozen height, latest height, -/// trusting period, and chain ID. +/// trusting periods, and chain ID. pub fn check_substitute( subject_client_state: &SovTmClientState, substitute_client_state: Any, @@ -171,32 +173,17 @@ where V: SovValidationContext, V::ConsensusStateRef: ConsensusStateConverter, { - let SovTmClientState { - genesis_state_root: subject_genesis_state_root, - code_commitment: subject_code_commitment, - latest_height: _, - frozen_height: _, - upgrade_path: subject_upgrade_path, - da_params: subject_da_params, - } = subject_client_state; - let substitute_client_state = SovTmClientState::try_from(substitute_client_state)?; - let SovTmClientState { - genesis_state_root: substitute_genesis_state_root, - code_commitment: substitute_code_commitment, - latest_height: _, - frozen_height: _, - upgrade_path: substitute_upgrade_path, - da_params: substitute_da_params, - } = substitute_client_state; - - (subject_genesis_state_root == &substitute_genesis_state_root - && subject_code_commitment == &substitute_code_commitment - && subject_upgrade_path == &substitute_upgrade_path - && subject_da_params.trust_level == substitute_da_params.trust_level - && subject_da_params.max_clock_drift == substitute_da_params.max_clock_drift - && subject_da_params.unbonding_period == substitute_da_params.unbonding_period) + let sov_params_matches = subject_client_state + .sovereign_params + .check_on_recovery(&substitute_client_state.sovereign_params); + + let da_params_matches = subject_client_state + .da_params + .check_on_recovery(&substitute_client_state.da_params); + + (sov_params_matches && da_params_matches) .then_some(()) .ok_or(ClientError::ClientRecoveryStateMismatch) } diff --git a/clients/sov-celestia/src/consensus_state.rs b/clients/sov-celestia/src/consensus_state.rs index 27beae00..4c68c5f8 100644 --- a/clients/sov-celestia/src/consensus_state.rs +++ b/clients/sov-celestia/src/consensus_state.rs @@ -4,13 +4,13 @@ use ibc_core::commitment_types::commitment::CommitmentRoot; use ibc_core::primitives::proto::{Any, Protobuf}; use ibc_core::primitives::Timestamp; use sov_celestia_client_types::consensus_state::SovTmConsensusState; -use sov_celestia_client_types::proto::tendermint::v1::ConsensusState as RawConsensusState; +use sov_celestia_client_types::proto::v1::ConsensusState as RawConsensusState; use tendermint::{Hash, Time}; /// Newtype wrapper around the `ConsensusState` type imported from the -/// `ibc-client-tendermint-types` crate. This wrapper exists so that we can -/// bypass Rust's orphan rules and implement traits from -/// `ibc::core::client::context` on the `ConsensusState` type. +/// `sov-client-celestia-types` crate. This wrapper exists so that we can bypass +/// Rust's orphan rules and implement traits from `ibc::core::client::context` +/// on the `ConsensusState` type. #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[derive(Clone, Debug, PartialEq, derive_more::From)] pub struct ConsensusState(SovTmConsensusState); @@ -67,7 +67,7 @@ impl From for Any { impl ConsensusStateTrait for ConsensusState { fn root(&self) -> &CommitmentRoot { - &self.0.root + &self.0.sovereign_params.root } fn timestamp(&self) -> Timestamp { diff --git a/clients/sov-celestia/src/lib.rs b/clients/sov-celestia/src/lib.rs index 906e7505..ecefbee0 100644 --- a/clients/sov-celestia/src/lib.rs +++ b/clients/sov-celestia/src/lib.rs @@ -1,5 +1,3 @@ -extern crate alloc; - pub mod client_state; pub mod consensus_state; pub mod context; diff --git a/clients/sov-celestia/types/Cargo.toml b/clients/sov-celestia/types/Cargo.toml index ab4eca36..673bd22a 100644 --- a/clients/sov-celestia/types/Cargo.toml +++ b/clients/sov-celestia/types/Cargo.toml @@ -6,7 +6,7 @@ license = { workspace = true } rust-version = { workspace = true } version = { workspace = true } repository = { workspace = true } -keywords = ["rollup", "sovereign", "ibc", "light-client"] +keywords = ["sovereign-sdk", "rollup", "ibc", "light-client"] readme = "./../../README.md" description = """ Encapsulates essential `sov-celestia` light client data structures and domain types, @@ -19,9 +19,7 @@ workspace = true [dependencies] # external dependencies -bytes = { workspace = true } -hex = { version = "0.4.3" } -jmt = { workspace = true } +hex = { version = "0.4.3", optional = true } derive_more = { workspace = true } prost = { workspace = true } schemars = { workspace = true, optional = true } @@ -32,8 +30,8 @@ typed-builder = { version = "0.18.0", optional = true } ibc-core = { workspace = true } ibc-client-tendermint = { workspace = true } ibc-client-wasm-types = { workspace = true, features = ["cosmwasm"], optional = true } +sov-client-types = { path = "./../../sov-types" } sov-ibc-proto = { path = "./../../../proto" } -ics23 = { version = "0.11", default-features = false } # DA layer dependencies tendermint = { workspace = true } @@ -46,8 +44,6 @@ std = [ "ibc-core/std", "ibc-client-tendermint/std", "sov-ibc-proto/std", - "ics23/std", - "bytes/std", "prost/std", "serde/std", "tendermint/std" @@ -56,7 +52,6 @@ serde = [ "ibc-core/serde", "ibc-client-tendermint/serde", "sov-ibc-proto/serde", - "ics23/serde", "dep:serde", ] json-schema = [ @@ -65,6 +60,8 @@ json-schema = [ "dep:schemars", ] test-util = [ + "hex", "typed-builder", + "sov-client-types/test-util", "ibc-client-wasm-types" ] diff --git a/clients/sov-celestia/types/src/client_message/header.rs b/clients/sov-celestia/types/src/client_message/header.rs index 09b5d2e7..c80b76b9 100644 --- a/clients/sov-celestia/types/src/client_message/header.rs +++ b/clients/sov-celestia/types/src/client_message/header.rs @@ -8,18 +8,17 @@ use ibc_core::primitives::Timestamp; use tendermint::chain::Id as TmChainId; use tendermint_light_client_verifier::types::TrustedBlockState; -use super::aggregated_proof::AggregatedProof; use crate::consensus_state::SovTmConsensusState; -use crate::error::Error; -use crate::proto::tendermint::v1::Header as RawSovTmHeader; +use crate::proto::v1::Header as RawSovTmHeader; +use crate::sovereign::{AggregatedProof, Error}; pub const SOV_TENDERMINT_HEADER_TYPE_URL: &str = "/ibc.lightclients.sovereign.tendermint.v1.Header"; #[derive(Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Header { - pub da_header: H, pub aggregated_proof: AggregatedProof, + pub da_header: H, } impl Debug for Header { @@ -32,8 +31,8 @@ impl Display for Header { fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> { write!( f, - "Header {{ da_header: {}, aggregated_proof: {} }}", - &self.da_header, &self.aggregated_proof + "Header {{ aggregated_proof: {}, da_header: {} }}", + &self.aggregated_proof, &self.da_header ) } } @@ -49,7 +48,8 @@ impl SovTmHeader { /// Returns the height of the Sovereign-Tendermint header. pub fn height(&self) -> Height { - self.aggregated_proof.final_slot_number() + Height::new(0, self.aggregated_proof.final_slot_number()) + .expect("zero slot number rejected beforehand") } /// Returns the trusted height of the Sovereign-Tendermint header, which @@ -58,26 +58,51 @@ impl SovTmHeader { self.da_header.trusted_height } - /// Performs sanity checks and validate if the fields of the given header - /// are consistent with the trusted fields of this header. + /// Performs sanity checks on header to ensure the consistency of fields. pub fn validate_basic(&self) -> Result<(), Error> { self.da_header.validate_basic().map_err(Error::source)?; self.aggregated_proof.validate_basic()?; - if self.height() != self.da_header.height() { - return Err(Error::mismatch(format!( - "DA header height {} does not match aggregated proof height(slot number) {}", - self.da_header.height(), - self.height() - )))?; - }; + Ok(()) + } + /// Validates the height offset between the rollup and DA layer. + pub fn validate_da_height_offset( + &self, + genesis_da_height: Height, + client_latest_height: Height, + ) -> Result<(), ClientError> { + let expected_da_height = self.height().add(genesis_da_height.revision_height()); + + let given_da_height = self.da_header.height(); + + if expected_da_height != given_da_height { + return Err(ClientError::Other { + description: format!( + "The height of the DA header does not match expected height:\ + got '{given_da_height}', expected '{expected_da_height}'", + ), + }); + } + + let client_height_in_da = client_latest_height.add(genesis_da_height.revision_height()); + + let header_trusted_height = self.da_header.trusted_height; + + if client_height_in_da != header_trusted_height { + return Err(ClientError::Other { + description: format!( + "trusted DA height does not match expected height:\ + got {header_trusted_height}, expected {client_height_in_da}", + ), + }); + }; Ok(()) } - /// Transforms the header into a `TrustedBlockState` which can be used for - /// the DA header misbehaviour verification. + /// Transforms the header into a `TrustedBlockState`, used for the DA header + /// misbehaviour verification. pub fn as_trusted_da_block_state<'a>( &'a self, consensus_state: &SovTmConsensusState, diff --git a/clients/sov-celestia/types/src/client_message/misbehaviour.rs b/clients/sov-celestia/types/src/client_message/misbehaviour.rs index c9f87306..13e1b86c 100644 --- a/clients/sov-celestia/types/src/client_message/misbehaviour.rs +++ b/clients/sov-celestia/types/src/client_message/misbehaviour.rs @@ -1,6 +1,7 @@ //! Defines the misbehaviour type for the Sovereign light client use alloc::format; +use core::fmt::Debug; use ibc_client_tendermint::types::{Header as TmHeader, Misbehaviour as TmMisbehaviour}; use ibc_core::client::types::error::ClientError; @@ -8,66 +9,82 @@ use ibc_core::host::types::identifiers::ClientId; use ibc_core::primitives::proto::{Any, Protobuf}; use super::header::{Header, SovTmHeader}; -use crate::error::Error; -use crate::proto::tendermint::v1::Misbehaviour as RawSovTmMisbehaviour; +use crate::proto::v1::Misbehaviour as RawSovTmMisbehaviour; +use crate::sovereign::Error; pub const SOV_TENDERMINT_MISBEHAVIOUR_TYPE_URL: &str = "/ibc.lightclients.sovereign.tendermint.v1.Misbehaviour"; /// Sovereign light client's misbehaviour type #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(Clone, PartialEq, Eq)] pub struct Misbehaviour { client_id: ClientId, - header1: Box>, - header2: Box>, + header_1: Box>, + header_2: Box>, } -/// Misbehaviour type alias for the Sovereign SDK rollups operating on the -/// Tendermint-driven DA layer. -pub type SovTmMisbehaviour = Misbehaviour; - -impl SovTmMisbehaviour { - pub fn new(client_id: ClientId, header1: SovTmHeader, header2: SovTmHeader) -> Self { +impl Misbehaviour { + /// Creates a new misbehaviour + pub fn new(client_id: ClientId, header_1: Header, header_2: Header) -> Self { Self { client_id, - header1: header1.into(), - header2: header2.into(), + header_1: Box::new(header_1), + header_2: Box::new(header_2), } } + /// Getter for the client identifier pub fn client_id(&self) -> &ClientId { &self.client_id } - pub fn header1(&self) -> &SovTmHeader { - &self.header1 + /// Getter for the first header + pub fn header_1(&self) -> &Header { + &self.header_1 } - pub fn header2(&self) -> &SovTmHeader { - &self.header2 + /// Getter for the second header + pub fn header_2(&self) -> &Header { + &self.header_2 + } +} + +impl Debug for Misbehaviour { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "Misbehaviour {{ client_id: {:?}, header_1: {{...}}, header_2: {{...}} }}", + self.client_id, + ) } +} +/// Misbehaviour type alias for the Sovereign SDK rollups operating on the +/// Tendermint-driven DA layer. +pub type SovTmMisbehaviour = Misbehaviour; + +impl SovTmMisbehaviour { /// Protobuf decoding of the `SovTmMisbehaviour` through the `RawSovTmMisbehaviour` type. pub fn decode_thru_raw(value: Vec) -> Result { Protobuf::::decode(&mut value.as_slice()).map_err(Error::source) } pub fn validate_basic(&self) -> Result<(), Error> { - self.header1.validate_basic()?; - self.header2.validate_basic()?; + self.header_1.validate_basic()?; + self.header_2.validate_basic()?; - if self.header1.da_header.signed_header.header.chain_id - != self.header2.da_header.signed_header.header.chain_id + if self.header_1.da_header.signed_header.header.chain_id + != self.header_2.da_header.signed_header.header.chain_id { return Err(Error::invalid("headers must have identical chain_ids")); } - if self.header1.height() < self.header2.height() { + if self.header_1.height() < self.header_2.height() { return Err(Error::invalid(format!( - "header1 height is less than header2 height ({} < {})", - self.header1.height(), - self.header2.height() + "header_1 height is less than header_2 height ({} < {})", + self.header_1.height(), + self.header_2.height() ))); } @@ -77,8 +94,8 @@ impl SovTmMisbehaviour { pub fn into_tendermint_misbehaviour(&self) -> TmMisbehaviour { TmMisbehaviour::new( self.client_id.clone(), - self.header1.da_header.clone(), - self.header2.da_header.clone(), + self.header_1.da_header.clone(), + self.header_2.da_header.clone(), ) } } @@ -89,10 +106,10 @@ impl core::fmt::Display for SovTmMisbehaviour { f, "{} h1: {}-{} h2: {}-{}", self.client_id, - self.header1.height(), - self.header1.da_header, - self.header2.height(), - self.header2.da_header, + self.header_1.height(), + self.header_1.da_header, + self.header_2.height(), + self.header_2.da_header, ) } } @@ -107,21 +124,21 @@ impl TryFrom for SovTmMisbehaviour { description: "".into(), })?; - let header1: SovTmHeader = raw + let header_1: SovTmHeader = raw .header_1 .ok_or(ClientError::Other { description: "".into(), })? .try_into()?; - let header2: SovTmHeader = raw + let header_2: SovTmHeader = raw .header_2 .ok_or(ClientError::Other { description: "".into(), })? .try_into()?; - Ok(Self::new(client_id, header1, header2)) + Ok(Self::new(client_id, header_1, header_2)) } } @@ -130,8 +147,8 @@ impl From for RawSovTmMisbehaviour { #[allow(deprecated)] RawSovTmMisbehaviour { client_id: value.client_id.to_string(), - header_1: Some((*value.header1).into()), - header_2: Some((*value.header2).into()), + header_1: Some((*value.header_1).into()), + header_2: Some((*value.header_2).into()), } } } diff --git a/clients/sov-celestia/types/src/client_message/mod.rs b/clients/sov-celestia/types/src/client_message/mod.rs index db33e9b6..ee735730 100644 --- a/clients/sov-celestia/types/src/client_message/mod.rs +++ b/clients/sov-celestia/types/src/client_message/mod.rs @@ -1,11 +1,8 @@ -mod aggregated_proof; mod header; mod misbehaviour; -mod pretty; use core::fmt::Debug; -pub use aggregated_proof::*; pub use header::*; use ibc_client_tendermint::types::Header as TmHeader; use ibc_core::primitives::prelude::*; @@ -13,7 +10,7 @@ use ibc_core::primitives::proto::{Any, Protobuf}; pub use misbehaviour::*; use prost::Message; -use crate::error::Error; +use crate::sovereign::Error; /// Defines the union ClientMessage type allowing to submit all possible /// messages for updating clients or reporting misbehaviour. @@ -74,79 +71,22 @@ impl From for Any { #[cfg(feature = "test-util")] pub mod test_util { use ibc_client_tendermint::types::Header as TmHeader; - use ibc_core::client::types::Height; use super::*; use crate::client_state::test_util::HeaderConfig; - - // ------------------------------------------------------------------------- - // NOTE: Vectors default to 32-byte arrays as empty vectors aren't valid. - // ------------------------------------------------------------------------- - - #[derive(typed_builder::TypedBuilder, Debug)] - #[builder(build_method(into = AggregatedProof))] - pub struct AggregatedProofConfig { - pub public_data: PublicDataConfig, - #[builder(default = vec![0; 32].into())] - pub serialized_proof: SerializedAggregatedProof, - } - - impl From for AggregatedProof { - fn from(config: AggregatedProofConfig) -> Self { - Self { - public_data: config.public_data.into(), - serialized_proof: config.serialized_proof, - } - } - } - - #[derive(typed_builder::TypedBuilder, Debug)] - pub struct PublicDataConfig { - #[builder(default = vec![vec![0; 32].into()])] - pub validity_conditions: Vec, - pub initial_slot_number: Height, - pub final_slot_number: Height, - #[builder(default = Root::from([0; 32]))] - pub genesis_state_root: Root, - #[builder(default = Root::from([0; 32]))] - pub initial_state_root: Root, - #[builder(default = Root::from([0; 32]))] - pub final_state_root: Root, - #[builder(default = vec![0; 32])] - pub initial_slot_hash: Vec, - #[builder(default = vec![0; 32])] - pub final_slot_hash: Vec, - #[builder(default = CodeCommitment::from(vec![1; 32]))] - pub code_commitment: CodeCommitment, - } - - impl From for AggregatedProofPublicData { - fn from(config: PublicDataConfig) -> Self { - Self { - validity_conditions: config.validity_conditions, - initial_slot_number: config.initial_slot_number, - final_slot_number: config.final_slot_number, - genesis_state_root: config.genesis_state_root, - initial_state_root: config.initial_state_root, - final_state_root: config.final_state_root, - initial_slot_hash: config.initial_slot_hash, - final_slot_hash: config.final_slot_hash, - code_commitment: config.code_commitment, - } - } - } + use crate::sovereign::{AggregatedProofConfig, PublicDataConfig, Root}; pub fn dummy_sov_header( da_header: TmHeader, - initial_slot_number: Height, - final_slot_number: Height, + initial_slot_number: u64, + final_slot_number: u64, final_state_root: Root, ) -> SovTmHeader { let aggregated_proof = AggregatedProofConfig::builder() .public_data( PublicDataConfig::builder() - .initial_slot_number(initial_slot_number) - .final_slot_number(final_slot_number) + .initial_slot_number(initial_slot_number.into()) + .final_slot_number(final_slot_number.into()) .final_state_root(final_state_root) .build(), ) diff --git a/clients/sov-celestia/types/src/client_state/da_params.rs b/clients/sov-celestia/types/src/client_state/da_params.rs index 59310f16..59395f59 100644 --- a/clients/sov-celestia/types/src/client_state/da_params.rs +++ b/clients/sov-celestia/types/src/client_state/da_params.rs @@ -5,41 +5,65 @@ use ibc_client_tendermint::types::TrustThreshold; use ibc_core::host::types::identifiers::ChainId; use ibc_core::primitives::proto::Protobuf; -use crate::error::Error; -use crate::proto::tendermint::v1::TendermintClientParams as RawTmClientParams; +use crate::proto::v1::TendermintClientParams as RawTmClientParams; +use crate::sovereign::Error; /// Defines the Tendermint-specific client state parameters #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -pub struct TmClientParams { +pub struct TendermintClientParams { pub chain_id: ChainId, pub trust_level: TrustThreshold, - pub trusting_period: Duration, pub unbonding_period: Duration, pub max_clock_drift: Duration, } -impl TmClientParams { +impl TendermintClientParams { pub fn new( chain_id: ChainId, trust_level: TrustThreshold, - trusting_period: Duration, unbonding_period: Duration, max_clock_drift: Duration, ) -> Self { Self { chain_id, trust_level, - trusting_period, unbonding_period, max_clock_drift, } } + + /// Returns `true` if the respective fields of two `TendermintClientParams` + /// match for the client recovery process. + pub fn check_on_recovery(&self, substitute: &Self) -> bool { + self.trust_level == substitute.trust_level + && self.unbonding_period == substitute.unbonding_period + && self.max_clock_drift == substitute.max_clock_drift + } + + /// Updates the `TendermintClientParams` on the client recovery process with + /// the given substitute. + pub fn update_on_recovery(self, substitute: Self) -> Self { + Self { + chain_id: substitute.chain_id, + ..self + } + } + + /// Updates the respective fields of the `TendermintClientParams` on the + /// client upgrade process with the given upgraded client parameters. + pub fn update_on_upgrade(self, upgraded: Self) -> Self { + Self { + chain_id: upgraded.chain_id, + unbonding_period: upgraded.unbonding_period, + ..self + } + } } -impl Protobuf for TmClientParams {} +impl Protobuf for TendermintClientParams {} -impl TryFrom for TmClientParams { +impl TryFrom for TendermintClientParams { type Error = Error; fn try_from(raw: RawTmClientParams) -> Result { @@ -50,12 +74,6 @@ impl TryFrom for TmClientParams { TrustThreshold::new(fraction.numerator, fraction.denominator)? }; - let trusting_period = raw - .trusting_period - .ok_or(Error::missing("trusting_period"))? - .try_into() - .map_err(|_| Error::invalid("trusting_period"))?; - let unbonding_period = raw .unbonding_period .ok_or(Error::missing("unbonding_period"))? @@ -71,22 +89,20 @@ impl TryFrom for TmClientParams { Ok(Self::new( chain_id, trust_level, - trusting_period, unbonding_period, max_clock_drift, )) } } -impl From for RawTmClientParams { - fn from(value: TmClientParams) -> Self { +impl From for RawTmClientParams { + fn from(value: TendermintClientParams) -> Self { Self { chain_id: value.chain_id.to_string(), trust_level: Some(Fraction { numerator: value.trust_level.numerator(), denominator: value.trust_level.denominator(), }), - trusting_period: Some(value.trusting_period.into()), unbonding_period: Some(value.unbonding_period.into()), max_clock_drift: Some(value.max_clock_drift.into()), } diff --git a/clients/sov-celestia/types/src/client_state/definition.rs b/clients/sov-celestia/types/src/client_state/definition.rs index b2bc3f83..1cbd232e 100644 --- a/clients/sov-celestia/types/src/client_state/definition.rs +++ b/clients/sov-celestia/types/src/client_state/definition.rs @@ -1,88 +1,106 @@ use core::cmp::max; -use std::str::FromStr; +use core::time::Duration; use ibc_client_tendermint::types::{Header as TmHeader, TrustThreshold}; -use ibc_core::client::types::error::{ClientError, UpgradeClientError}; +use ibc_core::client::types::error::ClientError; use ibc_core::client::types::Height; -use ibc_core::commitment_types::commitment::CommitmentPrefix; use ibc_core::host::types::identifiers::ChainId; use ibc_core::primitives::proto::{Any, Protobuf}; use ibc_core::primitives::ZERO_DURATION; use tendermint_light_client_verifier::options::Options; -use super::TmClientParams; -use crate::client_message::{CodeCommitment, Root}; -use crate::error::Error; -use crate::proto::tendermint::v1::ClientState as RawClientState; +use super::TendermintClientParams; +use crate::proto::v1::ClientState as RawClientState; +use crate::sovereign::{CodeCommitment, Error, Root, SovereignClientParams, UpgradePath}; pub const SOV_TENDERMINT_CLIENT_STATE_TYPE_URL: &str = "/ibc.lightclients.sovereign.tendermint.v1.ClientState"; -/// Contains the core implementation of the Sovereign light client +/// Defines the `ClientState` type for the Sovereign SDK rollups. #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[derive(Clone, Debug, PartialEq)] pub struct ClientState { - pub genesis_state_root: Root, - pub code_commitment: CodeCommitment, - pub latest_height: Height, - pub frozen_height: Option, - pub upgrade_path: UpgradePath, + pub sovereign_params: SovereignClientParams, pub da_params: Da, } impl ClientState { - pub fn new( - genesis_state_root: Root, - code_commitment: CodeCommitment, - latest_height: Height, - frozen_height: Option, - upgrade_path: UpgradePath, - da_params: Da, - ) -> Self { + pub fn new(sovereign_params: SovereignClientParams, da_params: Da) -> Self { Self { - genesis_state_root, - code_commitment, - latest_height, - frozen_height, - upgrade_path, + sovereign_params, da_params, } } pub fn genesis_state_root(&self) -> &Root { - &self.genesis_state_root + &self.sovereign_params.genesis_state_root + } + + pub fn genesis_da_height(&self) -> Height { + self.sovereign_params.genesis_da_height } pub fn code_commitment(&self) -> &CodeCommitment { - &self.code_commitment + &self.sovereign_params.code_commitment } - pub fn latest_height(&self) -> Height { - self.latest_height + pub fn trusting_period(&self) -> Duration { + self.sovereign_params.trusting_period } pub fn is_frozen(&self) -> bool { - self.frozen_height.is_some() + self.sovereign_params.frozen_height.is_some() } pub fn with_frozen_height(self, h: Height) -> Self { Self { - frozen_height: Some(h), + sovereign_params: SovereignClientParams { + frozen_height: Some(h), + ..self.sovereign_params + }, ..self } } + + /// Returns latest height of the client state aligned with the rollup's + /// height (slot number). + pub fn latest_height_in_sov(&self) -> Height { + self.sovereign_params.latest_height + } + + /// Returns the latest height of the client state aligned with the DA + /// height. This function considers the DA height at which the rollup + /// started (`genesis_da_height`). + pub fn latest_height_in_da(&self) -> Height { + self.latest_height_in_sov() + .add(self.genesis_da_height().revision_height()) + } + + pub fn upgrade_path(&self) -> &UpgradePath { + &self.sovereign_params.upgrade_path + } } -pub type SovTmClientState = ClientState; +pub type SovTmClientState = ClientState; impl SovTmClientState { pub fn chain_id(&self) -> &ChainId { &self.da_params.chain_id } - pub fn with_header(self, header: TmHeader) -> Result { + pub fn with_da_header(self, da_header: TmHeader) -> Result { + let updating_height = da_header + .height() + .sub(self.genesis_da_height().revision_height()) + .map_err(Error::source)?; + + let latest_height = max(updating_height, self.latest_height_in_sov()); + Ok(Self { - latest_height: max(header.height(), self.latest_height), + sovereign_params: SovereignClientParams { + latest_height, + ..self.sovereign_params + }, ..self }) } @@ -96,15 +114,15 @@ impl SovTmClientState { .trust_level .try_into() .map_err(Error::source)?, - trusting_period: self.da_params.trusting_period, + trusting_period: self.sovereign_params.trusting_period, clock_drift: self.da_params.max_clock_drift, }) } // Resets custom fields to zero values (used in `update_client`) pub fn zero_custom_fields(&mut self) { - self.frozen_height = None; - self.da_params.trusting_period = ZERO_DURATION; + self.sovereign_params.frozen_height = None; + self.sovereign_params.trusting_period = ZERO_DURATION; self.da_params.trust_level = TrustThreshold::ZERO; self.da_params.max_clock_drift = ZERO_DURATION; } @@ -116,44 +134,24 @@ impl TryFrom for SovTmClientState { type Error = ClientError; fn try_from(raw: RawClientState) -> Result { - let genesis_state_root = raw.genesis_state_root.try_into()?; - - let code_commitment = raw - .code_commitment - .ok_or(Error::missing("code_commitment"))? - .into(); - - let latest_height = raw - .latest_height - .ok_or(Error::missing("latest_height"))? + let sovereign_params = raw + .sovereign_params + .ok_or(Error::missing("sovereign_params"))? .try_into()?; - let upgrade_path = raw.upgrade_path; - let tendermint_params = raw .tendermint_params .ok_or(Error::missing("tendermint_params"))? .try_into()?; - Ok(Self::new( - genesis_state_root, - code_commitment, - latest_height, - raw.frozen_height.map(TryInto::try_into).transpose()?, - upgrade_path.try_into()?, - tendermint_params, - )) + Ok(Self::new(sovereign_params, tendermint_params)) } } impl From for RawClientState { fn from(value: SovTmClientState) -> Self { Self { - genesis_state_root: value.genesis_state_root.into(), - code_commitment: Some(value.code_commitment.into()), - latest_height: Some(value.latest_height.into()), - frozen_height: value.frozen_height.map(|h| h.into()), - upgrade_path: value.upgrade_path.0, + sovereign_params: Some(value.sovereign_params.into()), tendermint_params: Some(value.da_params.into()), } } @@ -191,54 +189,3 @@ impl From for Any { } } } - -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -#[derive(Clone, Debug, PartialEq)] -pub struct UpgradePath(String); - -impl Default for UpgradePath { - fn default() -> Self { - Self("sov_ibc/Ibc/".to_string()) - } -} - -impl UpgradePath { - pub fn new(path: String) -> Self { - Self(path) - } - - pub fn as_str(&self) -> &str { - &self.0 - } -} - -impl TryFrom for UpgradePath { - type Error = ClientError; - - fn try_from(value: String) -> Result { - Self::from_str(&value) - } -} - -impl FromStr for UpgradePath { - type Err = ClientError; - - fn from_str(s: &str) -> Result { - if s.is_empty() { - return Err(UpgradeClientError::Other { - reason: "empty upgrade path".into(), - })?; - } - - Ok(Self(s.to_string())) - } -} - -impl TryFrom for CommitmentPrefix { - type Error = ClientError; - - fn try_from(value: UpgradePath) -> Result { - CommitmentPrefix::try_from(value.0.into_bytes()) - .map_err(ClientError::InvalidCommitmentProof) - } -} diff --git a/clients/sov-celestia/types/src/client_state/mod.rs b/clients/sov-celestia/types/src/client_state/mod.rs index 7cc34b87..3bff3367 100644 --- a/clients/sov-celestia/types/src/client_state/mod.rs +++ b/clients/sov-celestia/types/src/client_state/mod.rs @@ -9,8 +9,8 @@ use ibc_core::host::types::identifiers::ClientType; pub const SOV_CELESTIA_CLIENT_TYPE: &str = "100-sov-celestia"; -/// Returns the `ClientType` for the Sovereign SDK Rollups. -pub fn sov_client_type() -> ClientType { +/// Returns the `ClientType` for the `sov-celestia` light client. +pub fn sov_celestia_client_type() -> ClientType { ClientType::from_str(SOV_CELESTIA_CLIENT_TYPE).expect("Never fails because it's valid") } @@ -28,8 +28,10 @@ pub mod test_util { use tendermint::Hash; use super::*; - use crate::client_message::{CodeCommitment, Root}; use crate::consensus_state::{SovTmConsensusState, TmConsensusParams}; + use crate::sovereign::{ + AggregatedProof, SovereignClientParams, SovereignConsensusParams, SovereignParamsConfig, + }; pub fn mock_celestia_chain_id() -> ChainId { ChainId::new("mock-celestia-0").expect("Never fails") @@ -38,52 +40,34 @@ pub mod test_util { #[derive(typed_builder::TypedBuilder, Debug)] #[builder(build_method(into = SovTmClientState))] pub struct ClientStateConfig { - #[builder(default = Root::from([0; 32]))] - pub genesis_state_root: Root, - #[builder(default = CodeCommitment::from(vec![1; 32]))] - pub code_commitment: CodeCommitment, - pub latest_height: Height, - #[builder(default)] - pub frozen_height: Option, - #[builder(default)] - pub upgrade_path: UpgradePath, - pub tendermint_params: TmClientParams, + pub sovereign_params: SovereignClientParams, + pub tendermint_params: TendermintClientParams, } impl From for SovTmClientState { fn from(config: ClientStateConfig) -> Self { - ClientState::new( - config.genesis_state_root, - config.code_commitment, - config.latest_height, - config.frozen_height, - config.upgrade_path, - config.tendermint_params, - ) + ClientState::new(config.sovereign_params, config.tendermint_params) } } #[derive(typed_builder::TypedBuilder, Debug)] - #[builder(build_method(into = TmClientParams))] + #[builder(build_method(into = TendermintClientParams))] pub struct TendermintParamsConfig { #[builder(default = mock_celestia_chain_id())] pub chain_id: ChainId, #[builder(default = TrustThreshold::ONE_THIRD)] pub trust_level: TrustThreshold, - #[builder(default = Duration::from_secs(64000))] - pub trusting_period: Duration, #[builder(default = Duration::from_secs(128000))] pub unbonding_period: Duration, #[builder(default = Duration::from_millis(3000))] pub max_clock_drift: Duration, } - impl From for TmClientParams { + impl From for TendermintClientParams { fn from(config: TendermintParamsConfig) -> Self { Self::new( config.chain_id, config.trust_level, - config.trusting_period, config.unbonding_period, config.max_clock_drift, ) @@ -92,7 +76,7 @@ pub mod test_util { use ibc_client_tendermint::types::Header as TmHeader; - use crate::client_message::{AggregatedProof, SovTmHeader}; + use crate::client_message::SovTmHeader; #[derive(typed_builder::TypedBuilder, Debug)] #[builder(build_method(into = SovTmHeader))] pub struct HeaderConfig { @@ -110,40 +94,49 @@ pub mod test_util { } pub fn dummy_sov_client_state(chain_id: ChainId, latest_height: Height) -> SovTmClientState { + let sovereign_params = SovereignParamsConfig::builder() + .latest_height(latest_height) + .build(); + let tendermint_params = TendermintParamsConfig::builder().chain_id(chain_id).build(); ClientStateConfig::builder() - .latest_height(latest_height) + .sovereign_params(sovereign_params) .tendermint_params(tendermint_params) .build() } pub fn dummy_sov_consensus_state(timestamp: Timestamp) -> SovTmConsensusState { - SovTmConsensusState::new( - vec![0].into(), - TmConsensusParams::new( - timestamp.into_tm_time().expect("Time exists"), - // Hash of default validator set - Hash::from_str("D6B93922C33AAEBEC9043566CB4B1B48365B1358B67C7DEF986D9EE1861BC143") - .expect("Never fails"), - ), - ) + let sovereign_params = SovereignConsensusParams::new(vec![0].into()); + + let tendermint_params = TmConsensusParams::new( + timestamp.into_tm_time().expect("Time exists"), + // Hash of default validator set + Hash::from_str("D6B93922C33AAEBEC9043566CB4B1B48365B1358B67C7DEF986D9EE1861BC143") + .expect("Never fails"), + ); + + SovTmConsensusState::new(sovereign_params, tendermint_params) } pub fn dummy_wasm_client_state() -> WasmClientState { + let sovereign_params = SovereignParamsConfig::builder() + .latest_height(Height::new(0, 1).expect("Never fails")) + .build(); + let tendermint_params = TendermintParamsConfig::builder() .chain_id("test-1".parse().expect("Never fails")) .build(); let client_state = ClientStateConfig::builder() - .latest_height(Height::new(0, 1).expect("Never fails")) + .sovereign_params(sovereign_params) .tendermint_params(tendermint_params) .build(); WasmClientState { data: Any::from(client_state.clone()).value, checksum: dummy_checksum(), - latest_height: client_state.latest_height, + latest_height: client_state.latest_height_in_sov(), } } diff --git a/clients/sov-celestia/types/src/consensus_state/da_params.rs b/clients/sov-celestia/types/src/consensus_state/da_params.rs index f3da9c3b..e75b3360 100644 --- a/clients/sov-celestia/types/src/consensus_state/da_params.rs +++ b/clients/sov-celestia/types/src/consensus_state/da_params.rs @@ -3,8 +3,8 @@ use tendermint::hash::Algorithm; use tendermint::{Hash, Time}; use tendermint_proto::google::protobuf as tpb; -use crate::error::Error; -use crate::proto::tendermint::v1::TendermintConsensusParams as RawTmConsensusParams; +use crate::proto::v1::TendermintConsensusParams as RawTmConsensusParams; +use crate::sovereign::Error; /// Defines the Tendermint-specific consensus state parameters #[derive(Clone, Debug, PartialEq, Eq)] diff --git a/clients/sov-celestia/types/src/consensus_state/definition.rs b/clients/sov-celestia/types/src/consensus_state/definition.rs index f0fae308..1bc288af 100644 --- a/clients/sov-celestia/types/src/consensus_state/definition.rs +++ b/clients/sov-celestia/types/src/consensus_state/definition.rs @@ -7,24 +7,29 @@ use tendermint::Time; use super::TmConsensusParams; use crate::client_message::SovTmHeader; -use crate::proto::tendermint::v1::ConsensusState as RawConsensusState; +use crate::proto::v1::ConsensusState as RawConsensusState; +use crate::sovereign::{Error, SovereignConsensusParams}; pub const SOV_TENDERMINT_CONSENSUS_STATE_TYPE_URL: &str = "/ibc.lightclients.sovereign.tendermint.v1.ConsensusState"; -/// Defines the Sovereign light client's consensus state +/// Defines the generic `ConsensusState` type for the Sovereign SDK rollups #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[derive(Clone, Debug, PartialEq, Eq)] pub struct ConsensusState { - pub root: CommitmentRoot, + pub sovereign_params: SovereignConsensusParams, pub da_params: Da, } impl ConsensusState { - pub fn new(root: CommitmentRoot, da_params: Da) -> Self { - Self { root, da_params } + pub fn new(sovereign_params: SovereignConsensusParams, da_params: Da) -> Self { + Self { + sovereign_params, + da_params, + } } } + pub type SovTmConsensusState = ConsensusState; impl SovTmConsensusState { @@ -40,33 +45,21 @@ impl TryFrom for SovTmConsensusState { type Error = ClientError; fn try_from(raw: RawConsensusState) -> Result { - let proto_root = raw - .root - .ok_or(ClientError::Other { - description: "missing root".to_string(), - })? - .hash; - - let da_params = raw - .tendermint_params - .ok_or(ClientError::Other { - description: "missing tendermint params".to_string(), - })? - .try_into()?; - - Ok(Self { - root: proto_root.into(), - da_params, - }) + Ok(Self::new( + raw.sovereign_params + .ok_or(Error::missing("sovereign_params"))? + .try_into()?, + raw.tendermint_params + .ok_or(Error::missing("tendermint_params"))? + .try_into()?, + )) } } impl From for RawConsensusState { fn from(value: SovTmConsensusState) -> Self { RawConsensusState { - root: Some(ibc_core::commitment_types::proto::v1::MerkleRoot { - hash: value.root.into_vec(), - }), + sovereign_params: Some(value.sovereign_params.into()), tendermint_params: Some(value.da_params.into()), } } @@ -107,7 +100,7 @@ impl From for Any { impl From for SovTmConsensusState { fn from(header: tendermint::block::Header) -> Self { Self { - root: CommitmentRoot::from_bytes(header.app_hash.as_ref()), + sovereign_params: CommitmentRoot::from_bytes(header.app_hash.as_ref()).into(), da_params: TmConsensusParams::new(header.time, header.next_validators_hash), } } @@ -117,15 +110,9 @@ impl From for SovTmConsensusState { fn from(header: SovTmHeader) -> Self { let tm_header = header.da_header.signed_header.header; - Self { - root: CommitmentRoot::from_bytes( - header - .aggregated_proof - .public_data - .final_state_root - .as_ref(), - ), - da_params: TmConsensusParams::new(tm_header.time, tm_header.next_validators_hash), - } + Self::new( + CommitmentRoot::from_bytes(header.aggregated_proof.final_state_root().as_ref()).into(), + TmConsensusParams::new(tm_header.time, tm_header.next_validators_hash), + ) } } diff --git a/clients/sov-celestia/types/src/lib.rs b/clients/sov-celestia/types/src/lib.rs index 55b709c4..d944b35c 100644 --- a/clients/sov-celestia/types/src/lib.rs +++ b/clients/sov-celestia/types/src/lib.rs @@ -2,13 +2,16 @@ extern crate alloc; pub mod client_message; pub mod client_state; -pub mod codec; pub mod consensus_state; -pub mod error; + +/// Re-exports Sovereign SDK light clients types from the `sov_ibc_client_types` +/// crate. +pub mod sovereign { + pub use sov_client_types::*; +} /// Re-exports Sovereign SDK rollup light clients proto types from /// `ibc_proto-rs` pub mod proto { - pub use sov_ibc_proto::ibc::lightclients::sovereign::*; - pub use sov_ibc_proto::sovereign::*; + pub use sov_ibc_proto::ibc::lightclients::sovereign::tendermint::*; } diff --git a/clients/sov-types/Cargo.toml b/clients/sov-types/Cargo.toml new file mode 100644 index 00000000..664176ed --- /dev/null +++ b/clients/sov-types/Cargo.toml @@ -0,0 +1,53 @@ +[package] +name = "sov-client-types" +authors = { workspace = true } +edition = { workspace = true } +license = { workspace = true } +rust-version = { workspace = true } +version = { workspace = true } +repository = { workspace = true } +keywords = ["sovereign-sdk", "rollup", "ibc", "light-client"] +readme = "./../README.md" +description = """ + Encapsulates essential data structures of Sovereign SDK light clients, shared among all Sovereign SDK rollups, + regardless of the underlying Data Availability (DA) layer, designed for universal applicability to facilitate + developement and integration across diverse IBC-enabled projects. +""" + +[lints] +workspace = true + +[dependencies] +# external dependencies +derive_more = { workspace = true } +hex = { version = "0.4.3" } +jmt = { workspace = true } +prost = { workspace = true } +schemars = { workspace = true, optional = true } +serde = { workspace = true, features = ["derive"], optional = true } +typed-builder = { version = "0.18.0", optional = true } + +# ibc dependencies +ibc-core = { workspace = true } +sov-ibc-proto = { path = "./../../proto" } + +[features] +default = ["std"] +std = [ + "ibc-core/std", + "sov-ibc-proto/std", + "prost/std", + "serde/std", +] +serde = [ + "ibc-core/serde", + "sov-ibc-proto/serde", + "dep:serde", +] +json-schema = [ + "ibc-core/schema", + "dep:schemars", +] +test-util = [ + "typed-builder", +] diff --git a/clients/sov-celestia/types/src/client_message/aggregated_proof.rs b/clients/sov-types/src/aggregated_proof.rs similarity index 66% rename from clients/sov-celestia/types/src/client_message/aggregated_proof.rs rename to clients/sov-types/src/aggregated_proof.rs index d05d1cda..6e59103e 100644 --- a/clients/sov-celestia/types/src/client_message/aggregated_proof.rs +++ b/clients/sov-types/src/aggregated_proof.rs @@ -1,35 +1,35 @@ //! Defines the aggregated proof data structures, and their conversions to and //! from the raw Protobuf types for the Sovereign SDK rollups. //! -//! Note: Since Rust protobuf types currently live in `sovereign-ibc`, -//! additionally we are in the midst of development where aggregated proof -//! definitions are evolving, and want to leverage client-specific methods and -//! implementations. As a result, we're keeping a set of domain types identical -//! to those in the Sovereign SDK, at least for now. This facilitates easier -//! development and minimizes dependencies on the Sovereign SDK repository. -//! Looking ahead, we may consider merging these two into a potential shared -//! client-side library. +//! Note: Since Rust protobuf types currently live in `sovereign-ibc`, we are in +//! the midst of development where aggregated proof definitions are evolving, +//! and additionally we want to have control over client-specific methods and +//! implementations, we're currently keeping a set of domain types identical to +//! those in the Sovereign SDK. This facilitates easier development and +//! minimizes dependencies on the Sovereign SDK repository. Looking ahead, we +//! may consider merging these two into a potential shared client-side library. use core::fmt::{Display, Error as FmtError, Formatter}; -use ibc_core::client::types::Height; use ibc_core::primitives::prelude::*; use ibc_core::primitives::proto::Protobuf; +use ibc_core::primitives::utils::PrettySlice; -use crate::client_message::pretty::PrettySlice; use crate::error::Error; use crate::proto::types::v1::{ AggregatedProof as RawAggregatedProof, AggregatedProofPublicData as RawAggregatedProofPublicData, CodeCommitment as RawCodeCommitment, SerializedAggregatedProof as RawSerializedAggregatedProof, - SerializedValidityCondition as RawSerializedValidityCondition, + SerializedValidityCondition as RawSerializedValidityCondition, SlotNumber as RawSlotNumber, }; -/// Defines the aggregated proof data structure for the Sovereign SDK rollups +/// Defines the aggregated proof data structure for the Sovereign SDK rollups. #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct AggregatedProof { + /// The public data of the aggregated proof pub public_data: AggregatedProofPublicData, + /// The serialized proof pub serialized_proof: SerializedAggregatedProof, } @@ -52,12 +52,12 @@ impl AggregatedProof { &self.serialized_proof } - pub fn initial_slot_number(&self) -> Height { - self.public_data.initial_slot_number + pub fn initial_slot_number(&self) -> u64 { + self.public_data.initial_slot_number.0 } - pub fn final_slot_number(&self) -> Height { - self.public_data.final_slot_number + pub fn final_slot_number(&self) -> u64 { + self.public_data.final_slot_number.0 } pub fn genesis_state_root(&self) -> &Root { @@ -102,11 +102,11 @@ impl TryFrom for AggregatedProof { Ok(Self { public_data: raw .public_data - .ok_or(Error::missing("public data"))? + .ok_or(Error::missing("public_data"))? .try_into()?, serialized_proof: raw .serialized_proof - .ok_or(Error::missing("serialized proof"))? + .ok_or(Error::missing("serialized_proof"))? .into(), }) } @@ -122,13 +122,13 @@ impl From for RawAggregatedProof { } /// Defines the public properties of the AggregatedProof for the Sovereign SDK -/// rollups, utilized for verifying the proof. +/// rollups, utilized for the proof verification. #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct AggregatedProofPublicData { pub validity_conditions: Vec, - pub initial_slot_number: Height, - pub final_slot_number: Height, + pub initial_slot_number: SlotNumber, + pub final_slot_number: SlotNumber, pub genesis_state_root: Root, pub initial_state_root: Root, pub final_state_root: Root, @@ -140,16 +140,20 @@ pub struct AggregatedProofPublicData { impl AggregatedProofPublicData { pub fn basic_validate(&self) -> Result<(), Error> { if self.validity_conditions.is_empty() { - return Err(Error::empty("validity conditions")); + return Err(Error::empty("validity_conditions")); } self.validity_conditions.iter().try_for_each(|vc| { if vc.is_empty() { - return Err(Error::empty("validity condition")); + return Err(Error::empty("validity_condition")); } Ok(()) })?; + if self.initial_slot_number.is_zero() || self.final_slot_number.is_zero() { + return Err(Error::invalid("slot number cannot be zero")); + } + if self.initial_slot_number > self.final_slot_number { return Err(Error::invalid( "initial slot number is greater than final slot number", @@ -157,15 +161,15 @@ impl AggregatedProofPublicData { } if self.initial_slot_hash.is_empty() { - return Err(Error::empty("initial slot hash")); + return Err(Error::empty("initial_slot_hash")); } if self.final_slot_hash.is_empty() { - return Err(Error::empty("final slot hash")); + return Err(Error::empty("final_slot_hash")); } if self.code_commitment.is_empty() { - return Err(Error::empty("code commitment")); + return Err(Error::empty("code_commitment")); } Ok(()) @@ -176,7 +180,9 @@ impl Display for AggregatedProofPublicData { fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { write!( f, - "AggregatedProofPublicData {{ validity_conditions: {}, initial_slot_number: {}, final_slot_number: {}, initial_slot_hash: {}, final_slot_hash: {}, genesis_state_root: {}, initial_state_root: {}, final_state_root: {}, code_commitment: {} }}", + "AggregatedProofPublicData {{ validity_conditions: {}, initial_slot_number: {},\ + final_slot_number: {}, initial_slot_hash: {}, final_slot_hash: {}, genesis_state_root: {},\ + initial_state_root: {}, final_state_root: {}, code_commitment: {} }}", PrettySlice(&self.validity_conditions), self.initial_slot_number, self.final_slot_number, @@ -202,8 +208,14 @@ impl TryFrom for AggregatedProofPublicData { .into_iter() .map(Into::into) .collect(), - initial_slot_number: Height::new(0, raw.initial_slot_number)?, - final_slot_number: Height::new(0, raw.final_slot_number)?, + initial_slot_number: raw + .initial_slot_number + .ok_or(Error::missing("initial slot number"))? + .into(), + final_slot_number: raw + .final_slot_number + .ok_or(Error::missing("final slot number"))? + .into(), genesis_state_root: raw.genesis_state_root.try_into()?, initial_state_root: raw.initial_state_root.try_into()?, final_state_root: raw.final_state_root.try_into()?, @@ -225,8 +237,8 @@ impl From for RawAggregatedProofPublicData { .into_iter() .map(Into::into) .collect(), - initial_slot_number: value.initial_slot_number.revision_height(), - final_slot_number: value.final_slot_number.revision_height(), + initial_slot_number: Some(value.initial_slot_number.into()), + final_slot_number: Some(value.final_slot_number.into()), genesis_state_root: value.genesis_state_root.into(), initial_state_root: value.initial_state_root.into(), final_state_root: value.final_state_root.into(), @@ -237,7 +249,7 @@ impl From for RawAggregatedProofPublicData { } } -/// Defines the validity condition for each block of the aggregated proof +/// Defines the validity condition for each block of the aggregated proof. #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct ValidityCondition(Vec); @@ -287,7 +299,7 @@ impl From for RawSerializedValidityCondition { } } -/// Defines the code commitment of the aggregated proof circuit +/// Defines the code commitment of the aggregated proof circuit. #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct CodeCommitment(Vec); @@ -341,6 +353,7 @@ impl From for RawCodeCommitment { } } +/// Defines the serialized aggregated proof for the Sovereign SDK rollups. #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct SerializedAggregatedProof(Vec); @@ -390,7 +403,43 @@ impl From for RawSerializedAggregatedProof { } } -/// Defines the root hash of the aggregated proof +/// Defines the slot number for rollups which is equivalent to the height in the +/// Sovereign SDK system. +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, derive_more::Display, derive_more::From)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct SlotNumber(pub u64); + +impl SlotNumber { + pub fn new(slot_number: u64) -> Self { + Self(slot_number) + } + + pub fn value(&self) -> u64 { + self.0 + } + + pub fn is_zero(&self) -> bool { + self.0 == 0 + } +} + +impl Protobuf for SlotNumber {} + +impl From for SlotNumber { + fn from(raw: RawSlotNumber) -> Self { + Self(raw.slot_number) + } +} + +impl From for RawSlotNumber { + fn from(value: SlotNumber) -> Self { + Self { + slot_number: value.0, + } + } +} + +/// Defines the root hash of the aggregated proof. #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Root([u8; 32]); @@ -434,3 +483,65 @@ impl From for Vec { root.0.to_vec() } } + +#[cfg(feature = "test-util")] +pub mod test_util { + use super::*; + + // ------------------------------------------------------------------------- + // NOTE: Vectors default to 32-byte arrays as empty vectors aren't valid. + // ------------------------------------------------------------------------- + + #[derive(typed_builder::TypedBuilder, Debug)] + #[builder(build_method(into = AggregatedProof))] + pub struct AggregatedProofConfig { + pub public_data: PublicDataConfig, + #[builder(default = vec![0; 32].into())] + pub serialized_proof: SerializedAggregatedProof, + } + + impl From for AggregatedProof { + fn from(config: AggregatedProofConfig) -> Self { + Self { + public_data: config.public_data.into(), + serialized_proof: config.serialized_proof, + } + } + } + + #[derive(typed_builder::TypedBuilder, Debug)] + pub struct PublicDataConfig { + #[builder(default = vec![vec![0; 32].into()])] + pub validity_conditions: Vec, + pub initial_slot_number: SlotNumber, + pub final_slot_number: SlotNumber, + #[builder(default = Root::from([0; 32]))] + pub genesis_state_root: Root, + #[builder(default = Root::from([0; 32]))] + pub initial_state_root: Root, + #[builder(default = Root::from([0; 32]))] + pub final_state_root: Root, + #[builder(default = vec![0; 32])] + pub initial_slot_hash: Vec, + #[builder(default = vec![0; 32])] + pub final_slot_hash: Vec, + #[builder(default = CodeCommitment::from(vec![1; 32]))] + pub code_commitment: CodeCommitment, + } + + impl From for AggregatedProofPublicData { + fn from(config: PublicDataConfig) -> Self { + Self { + validity_conditions: config.validity_conditions, + initial_slot_number: config.initial_slot_number, + final_slot_number: config.final_slot_number, + genesis_state_root: config.genesis_state_root, + initial_state_root: config.initial_state_root, + final_state_root: config.final_state_root, + initial_slot_hash: config.initial_slot_hash, + final_slot_hash: config.final_slot_hash, + code_commitment: config.code_commitment, + } + } + } +} diff --git a/clients/sov-types/src/client_params.rs b/clients/sov-types/src/client_params.rs new file mode 100644 index 00000000..8a09db99 --- /dev/null +++ b/clients/sov-types/src/client_params.rs @@ -0,0 +1,252 @@ +use std::str::FromStr; +use std::time::Duration; + +use ibc_core::client::types::error::{ClientError, UpgradeClientError}; +use ibc_core::client::types::Height; +use ibc_core::commitment_types::commitment::CommitmentPrefix; +use ibc_core::primitives::proto::Protobuf; + +use crate::aggregated_proof::{CodeCommitment, Root}; +use crate::error::Error; +use crate::proto::SovereignClientParams as RawSovereignClientParams; + +/// Defines the Sovereign SDK rollup-specific client parameters. +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[derive(Clone, Debug, PartialEq)] +pub struct SovereignClientParams { + /// The height of the DA layer at which the rollup initialized. + pub genesis_da_height: Height, + /// The genesis state root, which is unique to each rollup. Of course + /// assuming an honest rollup that has not tampered with its software. + pub genesis_state_root: Root, + /// The code commitment of the rollup's software, which is the output + /// commitment of the ZK circuit. + pub code_commitment: CodeCommitment, + /// The trusting period is the period in which headers can be verified. + /// + /// Note: During each update, the client verifies both the Data Availability + /// (DA) header and the aggregated proof simultaneously. When setting this + /// period, consider both the DA layer and the rollup, ensuring it's the + /// maximum acceptable duration. If the rollup has a shorter trusting + /// window, it dictates when the client expires. + pub trusting_period: Duration, + /// The frozen height indicates whether the client is frozen. + /// + /// Note: When frozen, `ibc-rs` sets the height to Height::new(0, 1), + /// following the same logic as in `ibc-go`. + pub frozen_height: Option, + /// The latest height of the rollup, which corresponds to the height of the + /// last update. + /// + /// Note: The `ibc-rs` requires the use of the `Height` type. Therefore, + /// incoming height values, identified as `SlotNumber` in the Sovereign SDK + /// system and of type `u64`, should be converted to `Height` for + /// compatibility with `ibc-rs` implementation. + pub latest_height: Height, + /// The upgrade path is the path to the location on rollup where the + /// upgraded client and consensus states are stored. + pub upgrade_path: UpgradePath, +} + +impl SovereignClientParams { + pub fn new( + genesis_da_height: Height, + genesis_state_root: Root, + code_commitment: CodeCommitment, + trusting_period: Duration, + frozen_height: Option, + latest_height: Height, + upgrade_path: UpgradePath, + ) -> Self { + Self { + genesis_da_height, + genesis_state_root, + code_commitment, + trusting_period, + frozen_height, + latest_height, + upgrade_path, + } + } + + /// Returns `true` if the respective fields of two `SovereignClientParams` + /// match for the client recovery process. + pub fn check_on_recovery(&self, substitute: &Self) -> bool { + self.genesis_da_height == substitute.genesis_da_height + && self.genesis_state_root == substitute.genesis_state_root + && self.code_commitment == substitute.code_commitment + && self.upgrade_path == substitute.upgrade_path + } + + /// Updates the `SovereignClientParams` on the client recovery process with + /// the given substitute. + pub fn update_on_recovery(self, substitute: Self) -> Self { + Self { + trusting_period: substitute.trusting_period, + frozen_height: None, + latest_height: substitute.latest_height, + ..self + } + } + + /// Updates the respective fields of the `SovereignClientParams` on the + /// client upgrade process with the given upgraded client parameters. + pub fn update_on_upgrade(self, upgraded: Self) -> Self { + Self { + frozen_height: None, + code_commitment: upgraded.code_commitment, + latest_height: upgraded.latest_height, + upgrade_path: upgraded.upgrade_path, + ..self + } + } +} + +impl Protobuf for SovereignClientParams {} + +impl TryFrom for SovereignClientParams { + type Error = ClientError; + + fn try_from(raw: RawSovereignClientParams) -> Result { + let genesis_da_height = raw + .genesis_da_height + .ok_or(Error::missing("genesis_da_height"))? + .try_into()?; + + let genesis_state_root = raw.genesis_state_root.try_into()?; + + let code_commitment = raw + .code_commitment + .ok_or(Error::missing("code_commitment"))? + .into(); + + let trusting_period = raw + .trusting_period + .ok_or(Error::missing("trusting_period"))? + .try_into() + .map_err(|_| Error::invalid("trusting_period"))?; + + let frozen_height = raw.frozen_height.map(TryInto::try_into).transpose()?; + + let latest_height = raw + .latest_height + .ok_or(Error::missing("latest_height"))? + .try_into()?; + + let upgrade_path = raw.upgrade_path.try_into()?; + + Ok(Self::new( + genesis_da_height, + genesis_state_root, + code_commitment, + trusting_period, + frozen_height, + latest_height, + upgrade_path, + )) + } +} + +impl From for RawSovereignClientParams { + fn from(value: SovereignClientParams) -> Self { + RawSovereignClientParams { + genesis_state_root: value.genesis_state_root.into(), + genesis_da_height: Some(value.genesis_da_height.into()), + code_commitment: Some(value.code_commitment.into()), + trusting_period: Some(value.trusting_period.into()), + frozen_height: value.frozen_height.map(Into::into), + latest_height: Some(value.latest_height.into()), + upgrade_path: value.upgrade_path.0, + } + } +} + +/// Defines the upgrade path type for the Sovereign SDK rollup. +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[derive(Clone, Debug, PartialEq)] +pub struct UpgradePath(String); + +impl Default for UpgradePath { + fn default() -> Self { + Self("sov_ibc/Ibc/".to_string()) + } +} + +impl UpgradePath { + pub fn new(path: String) -> Self { + Self(path) + } + + pub fn as_str(&self) -> &str { + &self.0 + } +} + +impl TryFrom for UpgradePath { + type Error = ClientError; + + fn try_from(value: String) -> Result { + Self::from_str(&value) + } +} + +impl FromStr for UpgradePath { + type Err = ClientError; + + fn from_str(s: &str) -> Result { + if s.is_empty() { + return Err(UpgradeClientError::Other { + reason: "empty upgrade path".into(), + })?; + } + + Ok(Self(s.to_string())) + } +} + +impl TryFrom for CommitmentPrefix { + type Error = ClientError; + + fn try_from(value: UpgradePath) -> Result { + CommitmentPrefix::try_from(value.0.into_bytes()) + .map_err(ClientError::InvalidCommitmentProof) + } +} + +#[cfg(feature = "test-util")] +pub mod test_util { + + use super::*; + + #[derive(typed_builder::TypedBuilder, Debug)] + #[builder(build_method(into = SovereignClientParams))] + pub struct SovereignParamsConfig { + #[builder(default = Height::new(0, 3).unwrap())] + pub genesis_da_height: Height, + #[builder(default = Root::from([0; 32]))] + pub genesis_state_root: Root, + #[builder(default = CodeCommitment::from(vec![1; 32]))] + pub code_commitment: CodeCommitment, + #[builder(default = Duration::from_secs(64000))] + pub trusting_period: Duration, + #[builder(default)] + pub frozen_height: Option, + pub latest_height: Height, + #[builder(default)] + pub upgrade_path: UpgradePath, + } + + impl From for SovereignClientParams { + fn from(config: SovereignParamsConfig) -> Self { + SovereignClientParams::new( + config.genesis_da_height, + config.genesis_state_root, + config.code_commitment, + config.trusting_period, + config.frozen_height, + config.latest_height, + config.upgrade_path, + ) + } + } +} diff --git a/clients/sov-types/src/consensus_params.rs b/clients/sov-types/src/consensus_params.rs new file mode 100644 index 00000000..7bee76bd --- /dev/null +++ b/clients/sov-types/src/consensus_params.rs @@ -0,0 +1,67 @@ +use ibc_core::client::types::error::ClientError; +use ibc_core::commitment_types::commitment::CommitmentRoot; +use ibc_core::primitives::proto::Protobuf; + +use crate::proto::SovereignConsensusParams as RawSovereignConsensusParams; + +/// Defines the Sovereign SDK rollup-specific consensus parameters. +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct SovereignConsensusParams { + /// The commitment root of the rollup's final state. + /// + /// This is obtained on client updates from the `final_state_root` field of + /// the received `AggregatedProof`. + pub root: CommitmentRoot, +} + +impl SovereignConsensusParams { + pub fn new(root: CommitmentRoot) -> Self { + Self { root } + } + + pub fn as_bytes(&self) -> &[u8] { + self.root.as_bytes() + } +} + +impl From for SovereignConsensusParams { + fn from(root: CommitmentRoot) -> Self { + Self { root } + } +} + +impl From<&[u8]> for SovereignConsensusParams { + fn from(value: &[u8]) -> Self { + Self { + root: CommitmentRoot::from_bytes(value), + } + } +} + +impl Protobuf for SovereignConsensusParams {} + +impl TryFrom for SovereignConsensusParams { + type Error = ClientError; + + fn try_from(raw: RawSovereignConsensusParams) -> Result { + let root = raw + .root + .ok_or(ClientError::Other { + description: "missing root".to_string(), + })? + .hash; + + Ok(Self { root: root.into() }) + } +} + +impl From for RawSovereignConsensusParams { + fn from(value: SovereignConsensusParams) -> Self { + Self { + root: Some(ibc_core::commitment_types::proto::v1::MerkleRoot { + hash: value.root.into_vec(), + }), + } + } +} diff --git a/clients/sov-celestia/types/src/error.rs b/clients/sov-types/src/error.rs similarity index 87% rename from clients/sov-celestia/types/src/error.rs rename to clients/sov-types/src/error.rs index 3978216c..0a35d5ee 100644 --- a/clients/sov-celestia/types/src/error.rs +++ b/clients/sov-types/src/error.rs @@ -1,11 +1,8 @@ -use alloc::string::{String, ToString}; - use ibc_core::client::types::error::ClientError; use ibc_core::handler::types::error::ContextError; use ibc_core::host::types::error::IdentifierError; -use tendermint_light_client_verifier::Verdict; -/// Defines the error type for Sovereign light client. +/// Defines the error type shared among Sovereign SDK light clients. #[derive(Clone, Debug)] pub struct Error { /// Error code. @@ -182,21 +179,3 @@ impl From for Error { Self::source(err) } } - -pub trait IntoResult { - fn into_result(self) -> Result; -} - -impl IntoResult<(), ClientError> for Verdict { - fn into_result(self) -> Result<(), ClientError> { - match self { - Verdict::Success => Ok(()), - Verdict::NotEnoughTrust(reason) => Err(ClientError::Other { - description: reason.to_string(), - }), - Verdict::Invalid(detail) => Err(ClientError::Other { - description: detail.to_string(), - }), - } - } -} diff --git a/clients/sov-celestia/types/src/codec.rs b/clients/sov-types/src/helpers/codec.rs similarity index 100% rename from clients/sov-celestia/types/src/codec.rs rename to clients/sov-types/src/helpers/codec.rs diff --git a/clients/sov-types/src/helpers/mod.rs b/clients/sov-types/src/helpers/mod.rs new file mode 100644 index 00000000..7ffeffe5 --- /dev/null +++ b/clients/sov-types/src/helpers/mod.rs @@ -0,0 +1,5 @@ +mod codec; +mod pretty; + +pub use codec::*; +pub use pretty::*; diff --git a/clients/sov-celestia/types/src/client_message/pretty.rs b/clients/sov-types/src/helpers/pretty.rs similarity index 100% rename from clients/sov-celestia/types/src/client_message/pretty.rs rename to clients/sov-types/src/helpers/pretty.rs diff --git a/clients/sov-types/src/lib.rs b/clients/sov-types/src/lib.rs new file mode 100644 index 00000000..6e68d549 --- /dev/null +++ b/clients/sov-types/src/lib.rs @@ -0,0 +1,25 @@ +mod aggregated_proof; +mod client_params; +mod consensus_params; +mod error; +mod helpers; + +#[cfg(feature = "test-util")] +pub use aggregated_proof::test_util::*; +pub use aggregated_proof::{ + AggregatedProof, AggregatedProofPublicData, CodeCommitment, Root, SerializedAggregatedProof, + SlotNumber, ValidityCondition, +}; +#[cfg(feature = "test-util")] +pub use client_params::test_util::*; +pub use client_params::{SovereignClientParams, UpgradePath}; +pub use consensus_params::SovereignConsensusParams; +pub use error::*; +pub use helpers::*; + +/// Re-exports Sovereign SDK light clients proto types from `sov-ibc-proto` +/// crate. +pub mod proto { + pub use sov_ibc_proto::ibc::lightclients::sovereign::v1::*; + pub use sov_ibc_proto::sovereign::*; +} diff --git a/mocks/src/configs.rs b/mocks/src/configs.rs index 63d6a489..99575135 100644 --- a/mocks/src/configs.rs +++ b/mocks/src/configs.rs @@ -2,6 +2,7 @@ use std::fs::File; use std::io::Read; use std::path::Path; +use ibc_core::client::types::Height; use ibc_core::host::types::identifiers::ChainId; use ibc_testkit::fixtures::core::signer::dummy_bech32_account; use serde::de::DeserializeOwned; @@ -32,9 +33,9 @@ pub struct TestSetupConfig { pub da_chain_id: ChainId, /// The da service. pub da_service: Da, - /// The chain Id of the rollup. - #[builder(default = ChainId::new("mock-rollup-0").unwrap())] - pub rollup_id: ChainId, + #[builder(default = Height::new(0, 3).unwrap())] + /// The DA height at which rollup starts. + pub genesis_da_height: Height, /// The runtime configuration. #[builder(default = RollupGenesisConfig::default())] pub rollup_genesis_config: RollupGenesisConfig, diff --git a/mocks/src/cosmos/core.rs b/mocks/src/cosmos/core.rs index e22b379a..19a6ca1d 100644 --- a/mocks/src/cosmos/core.rs +++ b/mocks/src/cosmos/core.rs @@ -57,6 +57,11 @@ impl MockTendermint { self.blocks.acquire_mutex().clone() } + /// Returns the chain's height. + pub fn height(&self) -> u64 { + self.blocks().len() as u64 + } + /// Returns the list of the chain's validators. pub fn validators(&self) -> Vec { self.validators.acquire_mutex().clone() diff --git a/mocks/src/cosmos/manual.rs b/mocks/src/cosmos/manual.rs index bffe0c45..b07f8ce6 100644 --- a/mocks/src/cosmos/manual.rs +++ b/mocks/src/cosmos/manual.rs @@ -23,7 +23,7 @@ use ibc_core::host::types::path::{ use ibc_core::host::{ExecutionContext, ValidationContext}; use ibc_core::primitives::Timestamp; use sov_celestia_client::client_state::ClientState; -use sov_celestia_client::types::client_state::sov_client_type; +use sov_celestia_client::types::client_state::sov_celestia_client_type; use sov_celestia_client::types::client_state::test_util::{ dummy_sov_client_state, dummy_sov_consensus_state, }; @@ -35,7 +35,7 @@ impl MockCosmosChain { pub fn setup_client(&mut self, client_chain_id: &ChainId) -> ClientId { let client_counter = self.ibc_ctx().client_counter().unwrap(); - let client_id = sov_client_type().build_client_id(client_counter); + let client_id = sov_celestia_client_type().build_client_id(client_counter); let current_height = self.ibc_ctx().host_height().unwrap(); diff --git a/mocks/src/relayer/builder.rs b/mocks/src/relayer/builder.rs index e9564b00..0fe46ce7 100644 --- a/mocks/src/relayer/builder.rs +++ b/mocks/src/relayer/builder.rs @@ -1,7 +1,7 @@ use ibc_client_tendermint::types::client_type as tm_client_type; use ibc_core::host::types::identifiers::Sequence; use ibc_core::host::ValidationContext; -use sov_celestia_client::types::client_state::sov_client_type; +use sov_celestia_client::types::client_state::sov_celestia_client_type; #[cfg(all(feature = "celestia-da", not(feature = "mock-da")))] use sov_consensus_state_tracker::CelestiaService; use sov_consensus_state_tracker::HasConsensusState; @@ -102,6 +102,7 @@ where ); rollup.init( + self.setup_cfg.genesis_da_height, &self.setup_cfg.kernel_genesis_config(), &self.setup_cfg.runtime_genesis_config(), ); @@ -111,7 +112,7 @@ where _ => panic!("Unexpected response"), }; - let sov_client_id = sov_client_type().build_client_id(sov_client_counter); + let sov_client_id = sov_celestia_client_type().build_client_id(sov_client_counter); let mut cos_chain = CosmosBuilder::default().build(); diff --git a/mocks/src/sovereign/rollup.rs b/mocks/src/sovereign/rollup.rs index bf202612..33c3d35a 100644 --- a/mocks/src/sovereign/rollup.rs +++ b/mocks/src/sovereign/rollup.rs @@ -116,32 +116,31 @@ where pub fn obtain_ibc_header(&self, target_height: Height, trusted_height: Height) -> SovTmHeader { let blocks = self.da_core.blocks(); - let revision_height = target_height.revision_height(); + let target_revision_height = target_height.revision_height(); - if revision_height as usize > blocks.len() { + let height_offset = self.da_core.height() - target_revision_height; + + let da_height = target_revision_height + height_offset; + + if da_height as usize > blocks.len() { panic!("block index out of bounds"); } - let target_block = blocks[revision_height as usize - 1].clone(); + let target_block = blocks[da_height as usize - 1].clone(); let header = Header { signed_header: target_block.signed_header, validator_set: target_block.validators, - trusted_height, + trusted_height: trusted_height.add(height_offset), trusted_next_validator_set: target_block.next_validators, }; - let target_state_root = match self.state_root(revision_height - 1) { + let target_state_root = match self.state_root(target_revision_height - 1) { Some(root) => root.user_hash(), None => panic!("state root not found"), }; - dummy_sov_header( - header, - Height::new(0, 1).unwrap(), - Height::new(0, revision_height).unwrap(), - target_state_root.into(), - ) + dummy_sov_header(header, 1, target_revision_height, target_state_root.into()) } /// Returns the balance of a user for a given token diff --git a/mocks/src/sovereign/runner.rs b/mocks/src/sovereign/runner.rs index d26cde6a..2d707d1b 100644 --- a/mocks/src/sovereign/runner.rs +++ b/mocks/src/sovereign/runner.rs @@ -1,6 +1,7 @@ //! Contains the implementation of the Sovereign SDK rollup runner. use std::time::Duration; +use ibc_core::client::types::Height; use sov_consensus_state_tracker::HasConsensusState; use sov_kernels::basic::BasicKernelGenesisConfig; use sov_modules_api::runtime::capabilities::{Kernel, KernelSlotHooks}; @@ -29,9 +30,12 @@ where /// Initializes the chain with the genesis configuration pub fn init( &mut self, + genesis_da_height: Height, kernel_genesis_config: &BasicKernelGenesisConfig, runtime_genesis_config: &GenesisConfig, ) { + self.advance_da_block_up_to(genesis_da_height); + let mut checkpoint = StateCheckpoint::new(self.prover_storage()); let mut kernel_working_set = KernelWorkingSet::uninitialized(&mut checkpoint); @@ -49,6 +53,12 @@ where self.commit(working_set.checkpoint().0); } + pub fn advance_da_block_up_to(&mut self, height: Height) { + for _ in 0..height.revision_height() - 1 { + self.da_core.grow_blocks(vec![0; 32]); + } + } + /// Begins processing a DA block by triggering the `begin_slot_hook` pub async fn begin_slot(&mut self, mut checkpoint: StateCheckpoint) -> StateCheckpoint { let kernel_working_set = KernelWorkingSet::from_kernel(self.kernel(), &mut checkpoint); diff --git a/modules/sov-consensus-state-tracker/src/celestia_da.rs b/modules/sov-consensus-state-tracker/src/celestia_da.rs index 760e559c..29e7e2ca 100644 --- a/modules/sov-consensus-state-tracker/src/celestia_da.rs +++ b/modules/sov-consensus-state-tracker/src/celestia_da.rs @@ -6,24 +6,29 @@ use sov_celestia_client::consensus_state::ConsensusState as HostConsensusState; use sov_celestia_client::types::consensus_state::{ ConsensusState as SovConsensusState, TmConsensusParams, }; +use sov_celestia_client::types::sovereign::SovereignConsensusParams; use sov_rollup_interface::da::BlockHeaderTrait; use crate::HasConsensusState; impl HasConsensusState for CelestiaSpec { fn consensus_state(header: &CelestiaHeader) -> HostConsensusState { - let timestamp = tendermint::Time::from_unix_timestamp( - header.time().secs(), - header.time().subsec_nanos(), - ) - .expect("Could not obtain timestamp from header"); + let sovereign_params = + SovereignConsensusParams::new(CommitmentRoot::from_bytes(header.hash().as_ref())); - let next_validator_hash = tendermint::Hash::decode_vec(&header.header.next_validators_hash) - .expect("Could not decode next validator hash from header"); + let da_params = TmConsensusParams::new( + tendermint::Time::from_unix_timestamp( + header.time().secs(), + header.time().subsec_nanos(), + ) + .expect("Could not obtain timestamp from header"), + tendermint::Hash::decode_vec(&header.header.next_validators_hash) + .expect("Could not decode next validator hash from header"), + ); SovConsensusState { - root: CommitmentRoot::from_bytes(header.hash().as_ref()), - da_params: TmConsensusParams::new(timestamp, next_validator_hash), + sovereign_params, + da_params, } .into() } diff --git a/modules/sov-consensus-state-tracker/src/mock_da.rs b/modules/sov-consensus-state-tracker/src/mock_da.rs index 8e7113c5..203a9e3d 100644 --- a/modules/sov-consensus-state-tracker/src/mock_da.rs +++ b/modules/sov-consensus-state-tracker/src/mock_da.rs @@ -5,6 +5,7 @@ use sov_celestia_client::consensus_state::ConsensusState as HostConsensusState; use sov_celestia_client::types::consensus_state::{ ConsensusState as SovConsensusState, TmConsensusParams, }; +use sov_celestia_client::types::sovereign::SovereignConsensusParams; pub use sov_mock_da::{MockAddress, MockDaConfig, MockDaService, MockDaSpec}; use sov_rollup_interface::da::BlockHeaderTrait; @@ -12,19 +13,24 @@ use crate::HasConsensusState; impl HasConsensusState for MockDaSpec { fn consensus_state(header: &Self::BlockHeader) -> HostConsensusState { + let sovereign_params = + SovereignConsensusParams::new(CommitmentRoot::from_bytes(header.hash().as_ref())); + + let da_params = TmConsensusParams::new( + tendermint::Time::from_unix_timestamp( + header.time().secs(), + header.time().subsec_nanos(), + ) + .expect("time is valid"), + tendermint::Hash::from_str( + "D6B93922C33AAEBEC9043566CB4B1B48365B1358B67C7DEF986D9EE1861BC143", + ) + .expect("Never fails"), + ); + SovConsensusState { - root: CommitmentRoot::from_bytes(header.hash().as_ref()), - da_params: TmConsensusParams::new( - tendermint::Time::from_unix_timestamp( - header.time().secs(), - header.time().subsec_nanos(), - ) - .expect("time is valid"), - tendermint::Hash::from_str( - "D6B93922C33AAEBEC9043566CB4B1B48365B1358B67C7DEF986D9EE1861BC143", - ) - .expect("Never fails"), - ), + sovereign_params, + da_params, } .into() } diff --git a/proto/definitions/ibc/lightclients/sovereign/tendermint/v1/sov_tendermint.proto b/proto/definitions/ibc/lightclients/sovereign/tendermint/v1/tendermint.proto similarity index 58% rename from proto/definitions/ibc/lightclients/sovereign/tendermint/v1/sov_tendermint.proto rename to proto/definitions/ibc/lightclients/sovereign/tendermint/v1/tendermint.proto index eed36ebe..2adc5e7f 100644 --- a/proto/definitions/ibc/lightclients/sovereign/tendermint/v1/sov_tendermint.proto +++ b/proto/definitions/ibc/lightclients/sovereign/tendermint/v1/tendermint.proto @@ -5,8 +5,7 @@ package ibc.lightclients.sovereign.tendermint.v1; import "gogoproto/gogo.proto"; import "google/protobuf/duration.proto"; import "google/protobuf/timestamp.proto"; -import "ibc/core/client/v1/client.proto"; -import "ibc/core/commitment/v1/commitment.proto"; +import "ibc/lightclients/sovereign/v1/sovereign.proto"; import "ibc/lightclients/tendermint/v1/tendermint.proto"; import "sovereign/types/v1/types.proto"; @@ -15,37 +14,20 @@ import "sovereign/types/v1/types.proto"; message ClientState { option (gogoproto.goproto_getters) = false; - // the genesis state root of the rollup - bytes genesis_state_root = 1 [(gogoproto.moretags) = "yaml:\"genesis_state_root\""]; - // the code commitment of the aggregated proof circuit - .sovereign.types.v1.CodeCommitment code_commitment = 2 [ + // the Sovereign-specific client state parameters + .ibc.lightclients.sovereign.v1.SovereignClientParams sovereign_params = 1 [ (gogoproto.nullable) = false, - (gogoproto.moretags) = "yaml:\"code_commitment\"" + (gogoproto.moretags) = "yaml:\"sovereign_params\"" ]; - // the latest height the client was updated to - ibc.core.client.v1.Height latest_height = 3 [ - (gogoproto.nullable) = false, - (gogoproto.moretags) = "yaml:\"latest_height\"" - ]; - // the height when the client was frozen due to a misbehaviour - ibc.core.client.v1.Height frozen_height = 4 [ - (gogoproto.nullable) = false, - (gogoproto.moretags) = "yaml:\"frozen_height\"" - ]; - // the path at which next upgraded client will be committed. Each element - // corresponds to the key for a single CommitmentProof in the chained proof. - // NOTE: ClientState must stored under - // `{upgradePath}/{upgradeHeight}/clientState` ConsensusState must be stored - // under `{upgradepath}/{upgradeHeight}/consensusState` - string upgrade_path = 5 [(gogoproto.moretags) = "yaml:\"upgrade_path\""]; // the tendermint-specific client state parameters - TendermintClientParams tendermint_params = 6 [ + TendermintClientParams tendermint_params = 2 [ (gogoproto.nullable) = false, (gogoproto.moretags) = "yaml:\"tendermint_params\"" ]; } -// TendermintClientParams contains the data necessary to verify Tendermint headers +// TendermintClientParams contains the data necessary to verify Tendermint +// headers message TendermintClientParams { // the identifier of the chain hosting the Tendermint consensus string chain_id = 1; @@ -54,21 +36,14 @@ message TendermintClientParams { (gogoproto.nullable) = false, (gogoproto.moretags) = "yaml:\"trust_level\"" ]; - // the duration of the period since the LastestTimestamp during which the - // submitted headers are valid for upgrade - google.protobuf.Duration trusting_period = 3 [ - (gogoproto.nullable) = false, - (gogoproto.stdduration) = true, - (gogoproto.moretags) = "yaml:\"trusting_period\"" - ]; // the duration of the staking unbonding period - google.protobuf.Duration unbonding_period = 4 [ + google.protobuf.Duration unbonding_period = 3 [ (gogoproto.nullable) = false, (gogoproto.stdduration) = true, (gogoproto.moretags) = "yaml:\"unbonding_period\"" ]; // the duration of new (untrusted) header's Time can drift into the future. - google.protobuf.Duration max_clock_drift = 5 [ + google.protobuf.Duration max_clock_drift = 4 [ (gogoproto.nullable) = false, (gogoproto.stdduration) = true, (gogoproto.moretags) = "yaml:\"max_clock_drift\"" @@ -80,8 +55,11 @@ message TendermintClientParams { message ConsensusState { option (gogoproto.goproto_getters) = false; - // the state root of rollup at the ConsensusState height - ibc.core.commitment.v1.MerkleRoot root = 1 [(gogoproto.nullable) = false]; + // the Sovereign-specific consensus state parameters + .ibc.lightclients.sovereign.v1.SovereignConsensusParams sovereign_params = 1 [ + (gogoproto.nullable) = false, + (gogoproto.moretags) = "yaml:\"sovereign_params\"" + ]; // the tendermint-specific consensus state parameters TendermintConsensusParams tendermint_params = 2 [ (gogoproto.nullable) = false, @@ -106,30 +84,31 @@ message TendermintConsensusParams { } // Header defines the structure of the header for the Sovereign SDK light -// clients operating on a Tendermint-based Data Availability layer. -// It encapsulates all the information necessary to update client from a trusted +// clients operating on the Tendermint-based Data Availability layer. It +// encapsulates all the information necessary to update client from a trusted // rollup ConsensusState. -// The TrustedHeight is the height of a stored ConsensusState on the client that -// will be used to verify the new untrusted header. The Trusted ConsensusState -// must be within the unbonding period of current time in order to correctly -// verify, and the TrustedValidators must hash to -// TrustedConsensusState.NextValidatorsHash since that is the last trusted -// validator set at the TrustedHeight. + +// The `trusted_height` under the `tendermint_header` is the height of a stored +// `ConsensusState` on the client that will be used to verify the new untrusted +// header. The trusted `ConsensusState` must be within the unbonding period of +// current time in order to correctly verify, and the `trusted_validators` must +// hash to the `next_validators_hash` of trusted `ConsensusState` since that is +// the last trusted validator set at the `trusted_height`. message Header { // the Tendermint header ibc.lightclients.tendermint.v1.Header tendermint_header = 1 [ (gogoproto.nullable) = false, (gogoproto.moretags) = "yaml:\"tendermint_header\"" ]; - // the rollup aggregated proof data + // the Sovereign SDK rollup aggregated proof data .sovereign.types.v1.AggregatedProof aggregated_proof = 2 [ (gogoproto.nullable) = false, (gogoproto.moretags) = "yaml:\"aggregated_proof\"" ]; } -// Misbehaviour defines the misbehaviour for the Sovereign SDK -// rollups with Tendermint-based Data Availability layer. +// Misbehaviour defines the misbehaviour for the Sovereign SDK rollups operating +// on the Tendermint-based Data Availability layer. message Misbehaviour { option (gogoproto.goproto_getters) = false; diff --git a/proto/definitions/ibc/lightclients/sovereign/v1/sovereign.proto b/proto/definitions/ibc/lightclients/sovereign/v1/sovereign.proto new file mode 100644 index 00000000..74ba5d71 --- /dev/null +++ b/proto/definitions/ibc/lightclients/sovereign/v1/sovereign.proto @@ -0,0 +1,61 @@ +syntax = "proto3"; + +package ibc.lightclients.sovereign.v1; + +import "gogoproto/gogo.proto"; +import "google/protobuf/duration.proto"; +import "ibc/core/client/v1/client.proto"; +import "ibc/core/commitment/v1/commitment.proto"; +import "sovereign/types/v1/types.proto"; + +// SovereignClientParams structure encompasses the essential parameters shared +// among all Sovereign light clients, regardless of the underlying Data +// Availability (DA) layer, to track the client state of the rollup. +message SovereignClientParams { + option (gogoproto.goproto_getters) = false; + + // the genesis state root of the rollup + bytes genesis_state_root = 1 [(gogoproto.moretags) = "yaml:\"genesis_state_root\""]; + // the genesis DA height from which the rollup started + ibc.core.client.v1.Height genesis_da_height = 2 [ + (gogoproto.nullable) = false, + (gogoproto.moretags) = "yaml:\"genesis_da_height\"" + ]; + // the code commitment of the aggregated proof circuit + .sovereign.types.v1.CodeCommitment code_commitment = 3 [ + (gogoproto.nullable) = false, + (gogoproto.moretags) = "yaml:\"code_commitment\"" + ]; + // the duration of the period since the latest DA Timestamp during which the + // submitted headers are valid for upgrade + google.protobuf.Duration trusting_period = 4 [ + (gogoproto.nullable) = false, + (gogoproto.stdduration) = true, + (gogoproto.moretags) = "yaml:\"trusting_period\"" + ]; + // the frozen height when the client was frozen due to the misbehaviour + ibc.core.client.v1.Height frozen_height = 6 [ + (gogoproto.nullable) = false, + (gogoproto.moretags) = "yaml:\"frozen_height\"" + ]; + // the latest height (slot number) the client was updated to + ibc.core.client.v1.Height latest_height = 5 [ + (gogoproto.nullable) = false, + (gogoproto.moretags) = "yaml:\"latest_height\"" + ]; + // the path at which next upgraded client will be committed. Each element + // corresponds to the key for a single CommitmentProof in the chained proof. + // NOTE: ClientState must stored under + // `{upgradePath}/{upgradeHeight}/clientState` ConsensusState must be stored + // under `{upgradepath}/{upgradeHeight}/consensusState` + string upgrade_path = 7 [(gogoproto.moretags) = "yaml:\"upgrade_path\""]; +} + +// SovereignConsensusParams structure encompasses the essential parameters +// shared among all Sovereign light clients, regardless of the underlying Data +// Availability (DA) layer, to track the consensus state of the rollup. +message SovereignConsensusParams { + option (gogoproto.goproto_getters) = false; + // the state root of rollup at the ConsensusState height + ibc.core.commitment.v1.MerkleRoot root = 1 [(gogoproto.nullable) = false]; +} diff --git a/proto/definitions/sovereign/types/v1/types.proto b/proto/definitions/sovereign/types/v1/types.proto index 25b6c26b..9c57bedf 100644 --- a/proto/definitions/sovereign/types/v1/types.proto +++ b/proto/definitions/sovereign/types/v1/types.proto @@ -24,10 +24,16 @@ message AggregatedProofPublicData { ]; // the initial slot number of the rollup from which the proof captures the // rollup's transition from the initial state root. - uint64 initial_slot_number = 2; + SlotNumber initial_slot_number = 2 [ + (gogoproto.nullable) = false, + (gogoproto.moretags) = "yaml:\"initial_slot_number\"" + ]; // the final slot number of the rollup, up to which the proof captures the // rollup's transition to the final state root. - uint64 final_slot_number = 3; + SlotNumber final_slot_number = 3 [ + (gogoproto.nullable) = false, + (gogoproto.moretags) = "yaml:\"final_slot_number\"" + ]; // the genesis state root bytes genesis_state_root = 4; // the initial state root @@ -59,6 +65,13 @@ message SerializedValidityCondition { bytes validity_condition = 1; } +// SlotNumber defines the slot number of rollups which is the height in the +// Sovereign SDK system +message SlotNumber { + // the slot number (rollup height) + uint64 slot_number = 1; +} + // CodeCommitment defines the code commitment of the aggregated proof circuit message CodeCommitment { // the code commitment diff --git a/proto/src/lib.rs b/proto/src/lib.rs index bb78b60f..7234dd1e 100644 --- a/proto/src/lib.rs +++ b/proto/src/lib.rs @@ -21,6 +21,11 @@ macro_rules! include_proto { pub mod ibc { pub mod lightclients { pub mod sovereign { + pub mod v1 { + include_proto!("ibc.lightclients.sovereign.v1.rs"); + #[cfg(feature = "serde")] + include_proto!("ibc.lightclients.sovereign.v1.serde.rs"); + } pub mod tendermint { pub mod v1 { include_proto!("ibc.lightclients.sovereign.tendermint.v1.rs"); diff --git a/proto/src/prost/ibc.lightclients.sovereign.tendermint.v1.rs b/proto/src/prost/ibc.lightclients.sovereign.tendermint.v1.rs index 12e2e6ee..825cd122 100644 --- a/proto/src/prost/ibc.lightclients.sovereign.tendermint.v1.rs +++ b/proto/src/prost/ibc.lightclients.sovereign.tendermint.v1.rs @@ -1,47 +1,30 @@ +// This file is @generated by prost-build. /// ClientState defines the client state for the Sovereign SDK rollups operating /// on a Tendermint-based Data Availability layer. #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct ClientState { - /// the genesis state root of the rollup - #[prost(bytes = "vec", tag = "1")] - pub genesis_state_root: ::prost::alloc::vec::Vec, - /// the code commitment of the aggregated proof circuit - #[prost(message, optional, tag = "2")] - pub code_commitment: ::core::option::Option< - super::super::super::super::super::sovereign::types::v1::CodeCommitment, - >, - /// the latest height the client was updated to - #[prost(message, optional, tag = "3")] - pub latest_height: ::core::option::Option< - ::ibc_proto::ibc::core::client::v1::Height, - >, - /// the height when the client was frozen due to a misbehaviour - #[prost(message, optional, tag = "4")] - pub frozen_height: ::core::option::Option< - ::ibc_proto::ibc::core::client::v1::Height, + /// the Sovereign-specific client state parameters + #[prost(message, optional, tag = "1")] + pub sovereign_params: ::core::option::Option< + super::super::v1::SovereignClientParams, >, - /// the path at which next upgraded client will be committed. Each element - /// corresponds to the key for a single CommitmentProof in the chained proof. - /// NOTE: ClientState must stored under - /// `{upgradePath}/{upgradeHeight}/clientState` ConsensusState must be stored - /// under `{upgradepath}/{upgradeHeight}/consensusState` - #[prost(string, tag = "5")] - pub upgrade_path: ::prost::alloc::string::String, /// the tendermint-specific client state parameters - #[prost(message, optional, tag = "6")] + #[prost(message, optional, tag = "2")] pub tendermint_params: ::core::option::Option, } impl ::prost::Name for ClientState { const NAME: &'static str = "ClientState"; const PACKAGE: &'static str = "ibc.lightclients.sovereign.tendermint.v1"; fn full_name() -> ::prost::alloc::string::String { - ::prost::alloc::format!( - "ibc.lightclients.sovereign.tendermint.v1.{}", Self::NAME - ) + "ibc.lightclients.sovereign.tendermint.v1.ClientState".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/ibc.lightclients.sovereign.tendermint.v1.ClientState".into() } } -/// TendermintClientParams contains the data necessary to verify Tendermint headers +/// TendermintClientParams contains the data necessary to verify Tendermint +/// headers #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct TendermintClientParams { @@ -53,26 +36,23 @@ pub struct TendermintClientParams { pub trust_level: ::core::option::Option< ::ibc_proto::ibc::lightclients::tendermint::v1::Fraction, >, - /// the duration of the period since the LastestTimestamp during which the - /// submitted headers are valid for upgrade - #[prost(message, optional, tag = "3")] - pub trusting_period: ::core::option::Option<::ibc_proto::google::protobuf::Duration>, /// the duration of the staking unbonding period - #[prost(message, optional, tag = "4")] + #[prost(message, optional, tag = "3")] pub unbonding_period: ::core::option::Option< ::ibc_proto::google::protobuf::Duration, >, /// the duration of new (untrusted) header's Time can drift into the future. - #[prost(message, optional, tag = "5")] + #[prost(message, optional, tag = "4")] pub max_clock_drift: ::core::option::Option<::ibc_proto::google::protobuf::Duration>, } impl ::prost::Name for TendermintClientParams { const NAME: &'static str = "TendermintClientParams"; const PACKAGE: &'static str = "ibc.lightclients.sovereign.tendermint.v1"; fn full_name() -> ::prost::alloc::string::String { - ::prost::alloc::format!( - "ibc.lightclients.sovereign.tendermint.v1.{}", Self::NAME - ) + "ibc.lightclients.sovereign.tendermint.v1.TendermintClientParams".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/ibc.lightclients.sovereign.tendermint.v1.TendermintClientParams".into() } } /// ConsensusState defines the consensus state for the Sovereign SDK rollups @@ -80,9 +60,11 @@ impl ::prost::Name for TendermintClientParams { #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct ConsensusState { - /// the state root of rollup at the ConsensusState height + /// the Sovereign-specific consensus state parameters #[prost(message, optional, tag = "1")] - pub root: ::core::option::Option<::ibc_proto::ibc::core::commitment::v1::MerkleRoot>, + pub sovereign_params: ::core::option::Option< + super::super::v1::SovereignConsensusParams, + >, /// the tendermint-specific consensus state parameters #[prost(message, optional, tag = "2")] pub tendermint_params: ::core::option::Option, @@ -91,9 +73,10 @@ impl ::prost::Name for ConsensusState { const NAME: &'static str = "ConsensusState"; const PACKAGE: &'static str = "ibc.lightclients.sovereign.tendermint.v1"; fn full_name() -> ::prost::alloc::string::String { - ::prost::alloc::format!( - "ibc.lightclients.sovereign.tendermint.v1.{}", Self::NAME - ) + "ibc.lightclients.sovereign.tendermint.v1.ConsensusState".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/ibc.lightclients.sovereign.tendermint.v1.ConsensusState".into() } } /// TendermintConsensusParams contains the necessary consensus state parameters @@ -113,21 +96,18 @@ impl ::prost::Name for TendermintConsensusParams { const NAME: &'static str = "TendermintConsensusParams"; const PACKAGE: &'static str = "ibc.lightclients.sovereign.tendermint.v1"; fn full_name() -> ::prost::alloc::string::String { - ::prost::alloc::format!( - "ibc.lightclients.sovereign.tendermint.v1.{}", Self::NAME - ) + "ibc.lightclients.sovereign.tendermint.v1.TendermintConsensusParams".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/ibc.lightclients.sovereign.tendermint.v1.TendermintConsensusParams".into() } } -/// Header defines the structure of the header for the Sovereign SDK light -/// clients operating on a Tendermint-based Data Availability layer. -/// It encapsulates all the information necessary to update client from a trusted -/// rollup ConsensusState. -/// The TrustedHeight is the height of a stored ConsensusState on the client that -/// will be used to verify the new untrusted header. The Trusted ConsensusState -/// must be within the unbonding period of current time in order to correctly -/// verify, and the TrustedValidators must hash to -/// TrustedConsensusState.NextValidatorsHash since that is the last trusted -/// validator set at the TrustedHeight. +/// The `trusted_height` under the `tendermint_header` is the height of a stored +/// `ConsensusState` on the client that will be used to verify the new untrusted +/// header. The trusted `ConsensusState` must be within the unbonding period of +/// current time in order to correctly verify, and the `trusted_validators` must +/// hash to the `next_validators_hash` of trusted `ConsensusState` since that is +/// the last trusted validator set at the `trusted_height`. #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct Header { @@ -136,7 +116,7 @@ pub struct Header { pub tendermint_header: ::core::option::Option< ::ibc_proto::ibc::lightclients::tendermint::v1::Header, >, - /// the rollup aggregated proof data + /// the Sovereign SDK rollup aggregated proof data #[prost(message, optional, tag = "2")] pub aggregated_proof: ::core::option::Option< super::super::super::super::super::sovereign::types::v1::AggregatedProof, @@ -146,13 +126,14 @@ impl ::prost::Name for Header { const NAME: &'static str = "Header"; const PACKAGE: &'static str = "ibc.lightclients.sovereign.tendermint.v1"; fn full_name() -> ::prost::alloc::string::String { - ::prost::alloc::format!( - "ibc.lightclients.sovereign.tendermint.v1.{}", Self::NAME - ) + "ibc.lightclients.sovereign.tendermint.v1.Header".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/ibc.lightclients.sovereign.tendermint.v1.Header".into() } } -/// Misbehaviour defines the misbehaviour for the Sovereign SDK -/// rollups with Tendermint-based Data Availability layer. +/// Misbehaviour defines the misbehaviour for the Sovereign SDK rollups operating +/// on the Tendermint-based Data Availability layer. #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct Misbehaviour { @@ -170,8 +151,9 @@ impl ::prost::Name for Misbehaviour { const NAME: &'static str = "Misbehaviour"; const PACKAGE: &'static str = "ibc.lightclients.sovereign.tendermint.v1"; fn full_name() -> ::prost::alloc::string::String { - ::prost::alloc::format!( - "ibc.lightclients.sovereign.tendermint.v1.{}", Self::NAME - ) + "ibc.lightclients.sovereign.tendermint.v1.Misbehaviour".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/ibc.lightclients.sovereign.tendermint.v1.Misbehaviour".into() } } diff --git a/proto/src/prost/ibc.lightclients.sovereign.tendermint.v1.serde.rs b/proto/src/prost/ibc.lightclients.sovereign.tendermint.v1.serde.rs index ccebe7fa..779b6e97 100644 --- a/proto/src/prost/ibc.lightclients.sovereign.tendermint.v1.serde.rs +++ b/proto/src/prost/ibc.lightclients.sovereign.tendermint.v1.serde.rs @@ -12,34 +12,9 @@ impl serde::Serialize for ClientState { if true { len += 1; } - if true { - len += 1; - } - if true { - len += 1; - } - if true { - len += 1; - } - if true { - len += 1; - } let mut struct_ser = serializer.serialize_struct("ibc.lightclients.sovereign.tendermint.v1.ClientState", len)?; - if true { - #[allow(clippy::needless_borrow)] - struct_ser.serialize_field("genesisStateRoot", pbjson::private::base64::encode(&self.genesis_state_root).as_str())?; - } - if let Some(v) = self.code_commitment.as_ref() { - struct_ser.serialize_field("codeCommitment", v)?; - } - if let Some(v) = self.latest_height.as_ref() { - struct_ser.serialize_field("latestHeight", v)?; - } - if let Some(v) = self.frozen_height.as_ref() { - struct_ser.serialize_field("frozenHeight", v)?; - } - if true { - struct_ser.serialize_field("upgradePath", &self.upgrade_path)?; + if let Some(v) = self.sovereign_params.as_ref() { + struct_ser.serialize_field("sovereignParams", v)?; } if let Some(v) = self.tendermint_params.as_ref() { struct_ser.serialize_field("tendermintParams", v)?; @@ -54,27 +29,15 @@ impl<'de> serde::Deserialize<'de> for ClientState { D: serde::Deserializer<'de>, { const FIELDS: &[&str] = &[ - "genesis_state_root", - "genesisStateRoot", - "code_commitment", - "codeCommitment", - "latest_height", - "latestHeight", - "frozen_height", - "frozenHeight", - "upgrade_path", - "upgradePath", + "sovereign_params", + "sovereignParams", "tendermint_params", "tendermintParams", ]; #[allow(clippy::enum_variant_names)] enum GeneratedField { - GenesisStateRoot, - CodeCommitment, - LatestHeight, - FrozenHeight, - UpgradePath, + SovereignParams, TendermintParams, } impl<'de> serde::Deserialize<'de> for GeneratedField { @@ -97,11 +60,7 @@ impl<'de> serde::Deserialize<'de> for ClientState { E: serde::de::Error, { match value { - "genesisStateRoot" | "genesis_state_root" => Ok(GeneratedField::GenesisStateRoot), - "codeCommitment" | "code_commitment" => Ok(GeneratedField::CodeCommitment), - "latestHeight" | "latest_height" => Ok(GeneratedField::LatestHeight), - "frozenHeight" | "frozen_height" => Ok(GeneratedField::FrozenHeight), - "upgradePath" | "upgrade_path" => Ok(GeneratedField::UpgradePath), + "sovereignParams" | "sovereign_params" => Ok(GeneratedField::SovereignParams), "tendermintParams" | "tendermint_params" => Ok(GeneratedField::TendermintParams), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), } @@ -122,45 +81,15 @@ impl<'de> serde::Deserialize<'de> for ClientState { where V: serde::de::MapAccess<'de>, { - let mut genesis_state_root__ = None; - let mut code_commitment__ = None; - let mut latest_height__ = None; - let mut frozen_height__ = None; - let mut upgrade_path__ = None; + let mut sovereign_params__ = None; let mut tendermint_params__ = None; while let Some(k) = map_.next_key()? { match k { - GeneratedField::GenesisStateRoot => { - if genesis_state_root__.is_some() { - return Err(serde::de::Error::duplicate_field("genesisStateRoot")); - } - genesis_state_root__ = - Some(map_.next_value::<::pbjson::private::BytesDeserialize<_>>()?.0) - ; - } - GeneratedField::CodeCommitment => { - if code_commitment__.is_some() { - return Err(serde::de::Error::duplicate_field("codeCommitment")); - } - code_commitment__ = map_.next_value()?; - } - GeneratedField::LatestHeight => { - if latest_height__.is_some() { - return Err(serde::de::Error::duplicate_field("latestHeight")); - } - latest_height__ = map_.next_value()?; - } - GeneratedField::FrozenHeight => { - if frozen_height__.is_some() { - return Err(serde::de::Error::duplicate_field("frozenHeight")); + GeneratedField::SovereignParams => { + if sovereign_params__.is_some() { + return Err(serde::de::Error::duplicate_field("sovereignParams")); } - frozen_height__ = map_.next_value()?; - } - GeneratedField::UpgradePath => { - if upgrade_path__.is_some() { - return Err(serde::de::Error::duplicate_field("upgradePath")); - } - upgrade_path__ = Some(map_.next_value()?); + sovereign_params__ = map_.next_value()?; } GeneratedField::TendermintParams => { if tendermint_params__.is_some() { @@ -171,11 +100,7 @@ impl<'de> serde::Deserialize<'de> for ClientState { } } Ok(ClientState { - genesis_state_root: genesis_state_root__.unwrap_or_default(), - code_commitment: code_commitment__, - latest_height: latest_height__, - frozen_height: frozen_height__, - upgrade_path: upgrade_path__.unwrap_or_default(), + sovereign_params: sovereign_params__, tendermint_params: tendermint_params__, }) } @@ -198,8 +123,8 @@ impl serde::Serialize for ConsensusState { len += 1; } let mut struct_ser = serializer.serialize_struct("ibc.lightclients.sovereign.tendermint.v1.ConsensusState", len)?; - if let Some(v) = self.root.as_ref() { - struct_ser.serialize_field("root", v)?; + if let Some(v) = self.sovereign_params.as_ref() { + struct_ser.serialize_field("sovereignParams", v)?; } if let Some(v) = self.tendermint_params.as_ref() { struct_ser.serialize_field("tendermintParams", v)?; @@ -214,14 +139,15 @@ impl<'de> serde::Deserialize<'de> for ConsensusState { D: serde::Deserializer<'de>, { const FIELDS: &[&str] = &[ - "root", + "sovereign_params", + "sovereignParams", "tendermint_params", "tendermintParams", ]; #[allow(clippy::enum_variant_names)] enum GeneratedField { - Root, + SovereignParams, TendermintParams, } impl<'de> serde::Deserialize<'de> for GeneratedField { @@ -244,7 +170,7 @@ impl<'de> serde::Deserialize<'de> for ConsensusState { E: serde::de::Error, { match value { - "root" => Ok(GeneratedField::Root), + "sovereignParams" | "sovereign_params" => Ok(GeneratedField::SovereignParams), "tendermintParams" | "tendermint_params" => Ok(GeneratedField::TendermintParams), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), } @@ -265,15 +191,15 @@ impl<'de> serde::Deserialize<'de> for ConsensusState { where V: serde::de::MapAccess<'de>, { - let mut root__ = None; + let mut sovereign_params__ = None; let mut tendermint_params__ = None; while let Some(k) = map_.next_key()? { match k { - GeneratedField::Root => { - if root__.is_some() { - return Err(serde::de::Error::duplicate_field("root")); + GeneratedField::SovereignParams => { + if sovereign_params__.is_some() { + return Err(serde::de::Error::duplicate_field("sovereignParams")); } - root__ = map_.next_value()?; + sovereign_params__ = map_.next_value()?; } GeneratedField::TendermintParams => { if tendermint_params__.is_some() { @@ -284,7 +210,7 @@ impl<'de> serde::Deserialize<'de> for ConsensusState { } } Ok(ConsensusState { - root: root__, + sovereign_params: sovereign_params__, tendermint_params: tendermint_params__, }) } @@ -550,9 +476,6 @@ impl serde::Serialize for TendermintClientParams { if true { len += 1; } - if true { - len += 1; - } let mut struct_ser = serializer.serialize_struct("ibc.lightclients.sovereign.tendermint.v1.TendermintClientParams", len)?; if true { struct_ser.serialize_field("chainId", &self.chain_id)?; @@ -560,9 +483,6 @@ impl serde::Serialize for TendermintClientParams { if let Some(v) = self.trust_level.as_ref() { struct_ser.serialize_field("trustLevel", v)?; } - if let Some(v) = self.trusting_period.as_ref() { - struct_ser.serialize_field("trustingPeriod", v)?; - } if let Some(v) = self.unbonding_period.as_ref() { struct_ser.serialize_field("unbondingPeriod", v)?; } @@ -583,8 +503,6 @@ impl<'de> serde::Deserialize<'de> for TendermintClientParams { "chainId", "trust_level", "trustLevel", - "trusting_period", - "trustingPeriod", "unbonding_period", "unbondingPeriod", "max_clock_drift", @@ -595,7 +513,6 @@ impl<'de> serde::Deserialize<'de> for TendermintClientParams { enum GeneratedField { ChainId, TrustLevel, - TrustingPeriod, UnbondingPeriod, MaxClockDrift, } @@ -621,7 +538,6 @@ impl<'de> serde::Deserialize<'de> for TendermintClientParams { match value { "chainId" | "chain_id" => Ok(GeneratedField::ChainId), "trustLevel" | "trust_level" => Ok(GeneratedField::TrustLevel), - "trustingPeriod" | "trusting_period" => Ok(GeneratedField::TrustingPeriod), "unbondingPeriod" | "unbonding_period" => Ok(GeneratedField::UnbondingPeriod), "maxClockDrift" | "max_clock_drift" => Ok(GeneratedField::MaxClockDrift), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), @@ -645,7 +561,6 @@ impl<'de> serde::Deserialize<'de> for TendermintClientParams { { let mut chain_id__ = None; let mut trust_level__ = None; - let mut trusting_period__ = None; let mut unbonding_period__ = None; let mut max_clock_drift__ = None; while let Some(k) = map_.next_key()? { @@ -662,12 +577,6 @@ impl<'de> serde::Deserialize<'de> for TendermintClientParams { } trust_level__ = map_.next_value()?; } - GeneratedField::TrustingPeriod => { - if trusting_period__.is_some() { - return Err(serde::de::Error::duplicate_field("trustingPeriod")); - } - trusting_period__ = map_.next_value()?; - } GeneratedField::UnbondingPeriod => { if unbonding_period__.is_some() { return Err(serde::de::Error::duplicate_field("unbondingPeriod")); @@ -685,7 +594,6 @@ impl<'de> serde::Deserialize<'de> for TendermintClientParams { Ok(TendermintClientParams { chain_id: chain_id__.unwrap_or_default(), trust_level: trust_level__, - trusting_period: trusting_period__, unbonding_period: unbonding_period__, max_clock_drift: max_clock_drift__, }) diff --git a/proto/src/prost/ibc.lightclients.sovereign.v1.rs b/proto/src/prost/ibc.lightclients.sovereign.v1.rs new file mode 100644 index 00000000..922d5bfe --- /dev/null +++ b/proto/src/prost/ibc.lightclients.sovereign.v1.rs @@ -0,0 +1,72 @@ +// This file is @generated by prost-build. +/// SovereignClientParams structure encompasses the essential parameters shared +/// among all Sovereign light clients, regardless of the underlying Data +/// Availability (DA) layer, to track the client state of the rollup. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct SovereignClientParams { + /// the genesis state root of the rollup + #[prost(bytes = "vec", tag = "1")] + pub genesis_state_root: ::prost::alloc::vec::Vec, + /// the genesis DA height from which the rollup started + #[prost(message, optional, tag = "2")] + pub genesis_da_height: ::core::option::Option< + ::ibc_proto::ibc::core::client::v1::Height, + >, + /// the code commitment of the aggregated proof circuit + #[prost(message, optional, tag = "3")] + pub code_commitment: ::core::option::Option< + super::super::super::super::sovereign::types::v1::CodeCommitment, + >, + /// the duration of the period since the latest DA Timestamp during which the + /// submitted headers are valid for upgrade + #[prost(message, optional, tag = "4")] + pub trusting_period: ::core::option::Option<::ibc_proto::google::protobuf::Duration>, + /// the frozen height when the client was frozen due to the misbehaviour + #[prost(message, optional, tag = "6")] + pub frozen_height: ::core::option::Option< + ::ibc_proto::ibc::core::client::v1::Height, + >, + /// the latest height (slot number) the client was updated to + #[prost(message, optional, tag = "5")] + pub latest_height: ::core::option::Option< + ::ibc_proto::ibc::core::client::v1::Height, + >, + /// the path at which next upgraded client will be committed. Each element + /// corresponds to the key for a single CommitmentProof in the chained proof. + /// NOTE: ClientState must stored under + /// `{upgradePath}/{upgradeHeight}/clientState` ConsensusState must be stored + /// under `{upgradepath}/{upgradeHeight}/consensusState` + #[prost(string, tag = "7")] + pub upgrade_path: ::prost::alloc::string::String, +} +impl ::prost::Name for SovereignClientParams { + const NAME: &'static str = "SovereignClientParams"; + const PACKAGE: &'static str = "ibc.lightclients.sovereign.v1"; + fn full_name() -> ::prost::alloc::string::String { + "ibc.lightclients.sovereign.v1.SovereignClientParams".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/ibc.lightclients.sovereign.v1.SovereignClientParams".into() + } +} +/// SovereignConsensusParams structure encompasses the essential parameters +/// shared among all Sovereign light clients, regardless of the underlying Data +/// Availability (DA) layer, to track the consensus state of the rollup. +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct SovereignConsensusParams { + /// the state root of rollup at the ConsensusState height + #[prost(message, optional, tag = "1")] + pub root: ::core::option::Option<::ibc_proto::ibc::core::commitment::v1::MerkleRoot>, +} +impl ::prost::Name for SovereignConsensusParams { + const NAME: &'static str = "SovereignConsensusParams"; + const PACKAGE: &'static str = "ibc.lightclients.sovereign.v1"; + fn full_name() -> ::prost::alloc::string::String { + "ibc.lightclients.sovereign.v1.SovereignConsensusParams".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/ibc.lightclients.sovereign.v1.SovereignConsensusParams".into() + } +} diff --git a/proto/src/prost/ibc.lightclients.sovereign.v1.serde.rs b/proto/src/prost/ibc.lightclients.sovereign.v1.serde.rs new file mode 100644 index 00000000..de3a9cdc --- /dev/null +++ b/proto/src/prost/ibc.lightclients.sovereign.v1.serde.rs @@ -0,0 +1,294 @@ +impl serde::Serialize for SovereignClientParams { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> core::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if true { + len += 1; + } + if true { + len += 1; + } + if true { + len += 1; + } + if true { + len += 1; + } + if true { + len += 1; + } + if true { + len += 1; + } + if true { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("ibc.lightclients.sovereign.v1.SovereignClientParams", len)?; + if true { + #[allow(clippy::needless_borrow)] + struct_ser.serialize_field("genesisStateRoot", pbjson::private::base64::encode(&self.genesis_state_root).as_str())?; + } + if let Some(v) = self.genesis_da_height.as_ref() { + struct_ser.serialize_field("genesisDaHeight", v)?; + } + if let Some(v) = self.code_commitment.as_ref() { + struct_ser.serialize_field("codeCommitment", v)?; + } + if let Some(v) = self.trusting_period.as_ref() { + struct_ser.serialize_field("trustingPeriod", v)?; + } + if let Some(v) = self.frozen_height.as_ref() { + struct_ser.serialize_field("frozenHeight", v)?; + } + if let Some(v) = self.latest_height.as_ref() { + struct_ser.serialize_field("latestHeight", v)?; + } + if true { + struct_ser.serialize_field("upgradePath", &self.upgrade_path)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for SovereignClientParams { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> core::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "genesis_state_root", + "genesisStateRoot", + "genesis_da_height", + "genesisDaHeight", + "code_commitment", + "codeCommitment", + "trusting_period", + "trustingPeriod", + "frozen_height", + "frozenHeight", + "latest_height", + "latestHeight", + "upgrade_path", + "upgradePath", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + GenesisStateRoot, + GenesisDaHeight, + CodeCommitment, + TrustingPeriod, + FrozenHeight, + LatestHeight, + UpgradePath, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> core::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> core::result::Result + where + E: serde::de::Error, + { + match value { + "genesisStateRoot" | "genesis_state_root" => Ok(GeneratedField::GenesisStateRoot), + "genesisDaHeight" | "genesis_da_height" => Ok(GeneratedField::GenesisDaHeight), + "codeCommitment" | "code_commitment" => Ok(GeneratedField::CodeCommitment), + "trustingPeriod" | "trusting_period" => Ok(GeneratedField::TrustingPeriod), + "frozenHeight" | "frozen_height" => Ok(GeneratedField::FrozenHeight), + "latestHeight" | "latest_height" => Ok(GeneratedField::LatestHeight), + "upgradePath" | "upgrade_path" => Ok(GeneratedField::UpgradePath), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = SovereignClientParams; + + fn expecting(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + formatter.write_str("struct ibc.lightclients.sovereign.v1.SovereignClientParams") + } + + fn visit_map(self, mut map_: V) -> core::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut genesis_state_root__ = None; + let mut genesis_da_height__ = None; + let mut code_commitment__ = None; + let mut trusting_period__ = None; + let mut frozen_height__ = None; + let mut latest_height__ = None; + let mut upgrade_path__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::GenesisStateRoot => { + if genesis_state_root__.is_some() { + return Err(serde::de::Error::duplicate_field("genesisStateRoot")); + } + genesis_state_root__ = + Some(map_.next_value::<::pbjson::private::BytesDeserialize<_>>()?.0) + ; + } + GeneratedField::GenesisDaHeight => { + if genesis_da_height__.is_some() { + return Err(serde::de::Error::duplicate_field("genesisDaHeight")); + } + genesis_da_height__ = map_.next_value()?; + } + GeneratedField::CodeCommitment => { + if code_commitment__.is_some() { + return Err(serde::de::Error::duplicate_field("codeCommitment")); + } + code_commitment__ = map_.next_value()?; + } + GeneratedField::TrustingPeriod => { + if trusting_period__.is_some() { + return Err(serde::de::Error::duplicate_field("trustingPeriod")); + } + trusting_period__ = map_.next_value()?; + } + GeneratedField::FrozenHeight => { + if frozen_height__.is_some() { + return Err(serde::de::Error::duplicate_field("frozenHeight")); + } + frozen_height__ = map_.next_value()?; + } + GeneratedField::LatestHeight => { + if latest_height__.is_some() { + return Err(serde::de::Error::duplicate_field("latestHeight")); + } + latest_height__ = map_.next_value()?; + } + GeneratedField::UpgradePath => { + if upgrade_path__.is_some() { + return Err(serde::de::Error::duplicate_field("upgradePath")); + } + upgrade_path__ = Some(map_.next_value()?); + } + } + } + Ok(SovereignClientParams { + genesis_state_root: genesis_state_root__.unwrap_or_default(), + genesis_da_height: genesis_da_height__, + code_commitment: code_commitment__, + trusting_period: trusting_period__, + frozen_height: frozen_height__, + latest_height: latest_height__, + upgrade_path: upgrade_path__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("ibc.lightclients.sovereign.v1.SovereignClientParams", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for SovereignConsensusParams { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> core::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if true { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("ibc.lightclients.sovereign.v1.SovereignConsensusParams", len)?; + if let Some(v) = self.root.as_ref() { + struct_ser.serialize_field("root", v)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for SovereignConsensusParams { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> core::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "root", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Root, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> core::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> core::result::Result + where + E: serde::de::Error, + { + match value { + "root" => Ok(GeneratedField::Root), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = SovereignConsensusParams; + + fn expecting(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + formatter.write_str("struct ibc.lightclients.sovereign.v1.SovereignConsensusParams") + } + + fn visit_map(self, mut map_: V) -> core::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut root__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Root => { + if root__.is_some() { + return Err(serde::de::Error::duplicate_field("root")); + } + root__ = map_.next_value()?; + } + } + } + Ok(SovereignConsensusParams { + root: root__, + }) + } + } + deserializer.deserialize_struct("ibc.lightclients.sovereign.v1.SovereignConsensusParams", FIELDS, GeneratedVisitor) + } +} diff --git a/proto/src/prost/proto_descriptor.bin b/proto/src/prost/proto_descriptor.bin index 77e9b555c87866d13e121cdcd7bfd5dda54f02cd..e7b84f35bae418708ea2700ae9ae219fec8a3176 100644 GIT binary patch delta 5782 zcmbVQTWlNG5#Nk9`apoTfPd1aMOzgOP&6pe1_@BKKLrW|LBATLNZTN3nvXuv zxsP4Nj|M^XrMWwI&dl7obMElw$MwH@j$He(^3mMZt7&Cs&(=qC%CCc4@Px8;6>f&M zZaf6_iu$IHv{C;ew9)S`!i`#)H06r9O3uu$+WAstwOB2rta11@gpyF<0b>4{bww zKNF-OA%gH=OJ?jiROAN!)9 z)L=N07p0zF(jdNRxUH|#OB#vBRJC{ih2Ps%!(I3rTj)?H$g=_m0;&N$DqVgQuCE}D z;o_hRUZWu-aR9d&-C>CXh-38hI5;41x?LR5I8Im{Cw)8|+}%fao`e3uKG-2mdJ&*c z(;bPabcUq98u0eh3rxS?)mKr!-_=)9zaRB`xP4#18=)_sgTBFttM5boh!&LgeW)L4 z?;yQgA0r*2|2_wM2Zvn!I@BN1+N6FR>JN2vk}%ib5%5Oo1LvW4IO^)}K>et;N9ylD z{ixnfPH=t9&j`fnH_yX~^CPfZ>S(xQ#P1xPhC4>wqtn=yzPOW8O{8?6n^H}rbW}Y+ z$^=wAw{cH`CN4mE*SOYA77-S}6Yx&ZpI?Bb!3pUmt|91z*1=ss2|*{i40081cmwJY z&on)>3|Ds@(Rz65z0Afj`r0z|*N#aWxP~^4$<(8SHjZKH^Jqg2sP}sASM;Q@eIbmr zg*V5tjY`%s*flW3y*El1jdCfUuddt1D3`YnL9`&(IW_`~Y z%$^`Qi$VDU>KxwFzzQq{SQX7_t-KC=3~`=bUV)H_|D&~enIe=>Z(dddN@#6fZ%@^& zmrIq>82MHkiRMykBY76+T0UnLEB1)n{zf)Nw}lwr66mDK479_>DBbt6vWMQc3f=U^ zDx9K_1f%UcKGGu7lqsIz_8v6LX2GVTNjTk_CH{$ORp`#+4{gm(pV{1?FxNi4TkB$8thk= z>6;0x{Vo$4=~qnX3@np|yjijAisOlod%`q^{RwhUbv;uy(fqnu$p&}OS4|iUC)67+ zb$P-oB)A=Bsc2h8yK2iwGif-oTj~>U(X{(&y%;DCPX2nE1(;H?kZ>Dnj zTxHW3I5{0L^5&*h9yTf^qf$24F7bWBBsz^6kBN)I$}!rYb@E%|!S=NaqS(Ca zRL_p<|G?s8;uu~c4=ZUud_mt!8_&TWTF!x9^UJEnk7&j(FFs1R(T^9O5fMrnN?i|g zYGD#@`F>-Gw?GeLuqJ3#^#j~tSyINyX?ZD)i{(;5wgHw2d1Eo6a;<_Hl^_as>LzG+ zBy^{#BkD-#PSd_o&Pj-e4YVoVDjFygIrlZo2Fez=gDuEOtVeqQTWAp49S2!~8=}DJ z56;721{DxH2)z=G@nNuUzat@baQu+OW_%c&Xm_wBAGW#Jk`Hxk-cK{$^&p+9AqcB_ zg-)+S3w>i6{6t(5mLht+1gC1Kg&u@JP$Wv|L8yIDdf-J5LeZG?z>6M)M#7Ew#DMkTJiZhUIyAMLN3Cr6ukWcJf~6SM~e&dEx1JuUJL;)(IH&;`z|&OVCnN(Vt%T zG*~n4?TAQ!7$GA)N`F-Jr#IH`_@fGc`doih0l!xrBd0h#_S^^ztNJ8|m#L7%Fd#|9 z$6k*S`od!n-seMCBCac(>s?nk*SoIx(3MDx{-gjs4P)dtz~OLreCwx|;9jLxhkZOQ zS-}JB6%em)kwLLnKs+ek1o#arKCaKo4AzMd;_au%yR5fh!5{KWDf(N=b_+OhYtOn{ zcd30!dm*yF+^xHOj^=XL-hwH;y}39}e@cI0uh2u9!P|?1?PWr?7e%xeCZ5DZE3Cat z(o7kSoy7k!>yyyKbBhw1nCu;JB+T^W(6A$6rYECw^4aPU)iW8J-FoF?=e9thV{_EHHGYU`52jqacPjf3h`Gg*7^&%V#PrN`X3Xn!+SulrQjR& zIkLN2OqGgh`pyJW>(ADZ`==B53P6%=q@!u*9r+=UU2cVmIG*|cag6gg=5L9^IqA36g6{8WS1^l2=0gx^;r zZa*}u`aa$s+=HMO3J@__UHRc4uN}!*<1>zgb>*L(lWhq(OZ7j{?6f6WSUAkw%3@9G zL2{Ji;-zlIX?C^%lPShUtsn*pISisji_tMWctGx8E{6|I@XWAT5w|4zgv;*e*dtwL3!FZC)lo9VA&@@% zVTc}CheI{Sl>L&Y6ktr*-##Q^*yPwB8<8-KDf{;gIWUqb2V58sJQa~Vg~kN#AfCus zj*HA0g;7!Px_Jf`iivA_VaPJ>|^^5S#)Il5-*q{Q~6USvw1kn?jIE^8&F-=Xt zVO1Zyt(b`o!)aE`37Fv76VqEFG3!VeMq>Un&n14tFcJ%gMHo!vFP=#m23z1qHifA> z&T+9Sj>2(O-%sZYpwku``c{uh4#iW$j2)GaE0hrGsC-=?IHqEoRaG`)s~C z9xF=d!0h0>aDa(C);Z|_Tlj#zZyr!XB+el))&*Fk|E)m0w%`u3EXD;n410Nu3pfn3 zA5Tz1h=uM&2SU;Q&MZEt&hy^DzVmcGq$bE~J}d%!FeN>g6#W-oV+kLyNj?WzX*uL1 z#oL~p@G<-E!cVZepoF!Q;z ziI(i7QNYOzyNPLM`S`%Rq<@-%<^xGSG_b+VO5b77uye&V3q3b+CbtPM(!7Z?-r)rZ zwYWgyah8mc_=gI8u?j2vo%ntg236x!h0xFjq}%vqU=PKlwu}G3z@~OJ1r{|fLtiol z{rtFb6?IYrqU=$^%%`Rf^OHddPbPK55+}n%e)wzh@Yw=CnKV`(V+)nd9vOHH*@FHq zi{Qk&{eoh4_txyn%K(-tLpA$VOJ$z_;}b=ywTXAe^}BIw7gx2{q>YuJS+h>6aP+ delta 3595 zcmYLLU2Igx72Y{_c71n%wS8mEdi}SyG0QHt@gF~4V|xP#f-ORbaRNdvUhKtQu)WTD z9rNR`rZ}xjizrm-MCxN-B2}vT(AJ8gs#1TFr&g*IRjry9=Q!u@93yKkv0{(bIPE%F^kiByZP&!OMq>vQP0K)+4JX`k(87!qvsA;Y&|!*clHz@XgVbSrY$Zqo_0l#R695kvyg#s>CaBW)4@2{zJ5 zz7tU-ca#)JLmqSa%LaERv z{x%?nWc4D|%cTX1@a4kmm*njQdL(~)jz;CkBAu=LBNy9_&F6EArSVd>l#@>?=*8GI zQ8`_h$z7T*EG*JRwF;OX~dZnJLYj?xpZkRm!F+0MJ@T{6%@t~ z!&E671T`v+E5*Xi+@hz!eT|OlwAj9~G+WHV%~G~B7Y)i$L8++ofQjl-ZgD18T*xn$ za8}GNEJs5!U7$Pkp(TG-pzpCO@&^;tCr^f{pXKGV3F?>km*|wdr~o`&qCV#_6Om(u z#pT@M^2)ONwC@TU-ulIB^mR*oyhl_x!9d_UOc%PmvO*nQNf8!gp=j(tk6t3u;lO}i zf_oycSKMRBQ^4VoK&Sl43f)Ua?B|3K77u{imDC9WhOoZ#2@;{iK2Ry3(&xyr?Q~$w zF^R(-66Y8iK!Uyl8mLAB$%fQCq1mb=%~mIVPM1Xh9fQ}#vIWd>k1wA)-%9jKKc-s1Q2x{DlqD01Q2yy4IT(`LBxCzk{a z%byphR=&GRJ@TV9ia09m-FA}>8B=WQmD{e<>5g9imr-o%4OeSV(154jnw_Ep_|$*K z`{|I}xK15Y{p9A&{mlAP2h0tI8~uj|G&Y<8TYvhH*Ix~l4*31mQ0XA=5oPTHR7%q@ zkG&?VZqQEo)+A-ij1+CsC`~e1wGz1 zDvoNS;NJwDm%qP7M=ws8k|sS&O*C{G6N-Nm-90)NI71jFde6IIP@-;Sub42X4PEE2 z@K#c`g)gU3kMXqJe zbHVI?DvMY6X&pUvuAer`(_$m2XNKTPV4bnpXIw4~;`4iHordHeZenceoTCBx$vSn( zALSwbIZv%j$iLpEq)c9=HmvuTDIs4i>$SW}iEw-_yF3>!6@>iYDrLg)QgLOul$#N< z>KdhL6f;-sh@NfKOu|>`rX0LO?d4TU=zzKN$m-q!PXhMUBSZRaIK$gkhi|%XQ=$&v zbrU|dq2G1`Y3oM#xav%6ROYc(T`|SN{QSyNJUcsE%*|r(n2BS`DO`!qWaU5ZP$auX zZq{%QK-cyhG$2%f*9OuCgbMK5VA%s%J#0Rn4lBdV3-qFY(-xDDjf-n zxC>-iW;Q4)n_j271KUtIXy$x_*)>876%K!sp>86W2ZFkcTv-kFK^41ACL?#LVNj(V z8~7wPF{x^h5MgVRg&j{s_u6DTYsCe9n>nF-jP5fzb(c<;T?3c{I5s^4hyX-1d~*r| z_ZT{UrS^sxz(VbPW{E0H$U(5`@1Pm~CgXej9hD3IEylZyS8_rR7(HSypi_*$m=8z diff --git a/proto/src/prost/sovereign.types.v1.rs b/proto/src/prost/sovereign.types.v1.rs index dc905da1..c5f7ff5c 100644 --- a/proto/src/prost/sovereign.types.v1.rs +++ b/proto/src/prost/sovereign.types.v1.rs @@ -1,3 +1,4 @@ +// This file is @generated by prost-build. /// AggregatedProof is the overarching structure, encompassing public data, proof /// data information, and aggregated proof bytes. #[allow(clippy::derive_partial_eq_without_eq)] @@ -14,7 +15,10 @@ impl ::prost::Name for AggregatedProof { const NAME: &'static str = "AggregatedProof"; const PACKAGE: &'static str = "sovereign.types.v1"; fn full_name() -> ::prost::alloc::string::String { - ::prost::alloc::format!("sovereign.types.v1.{}", Self::NAME) + "sovereign.types.v1.AggregatedProof".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/sovereign.types.v1.AggregatedProof".into() } } /// AggregatedProofPublicData defines the public properties of the @@ -28,12 +32,12 @@ pub struct AggregatedProofPublicData { pub validity_conditions: ::prost::alloc::vec::Vec, /// the initial slot number of the rollup from which the proof captures the /// rollup's transition from the initial state root. - #[prost(uint64, tag = "2")] - pub initial_slot_number: u64, + #[prost(message, optional, tag = "2")] + pub initial_slot_number: ::core::option::Option, /// the final slot number of the rollup, up to which the proof captures the /// rollup's transition to the final state root. - #[prost(uint64, tag = "3")] - pub final_slot_number: u64, + #[prost(message, optional, tag = "3")] + pub final_slot_number: ::core::option::Option, /// the genesis state root #[prost(bytes = "vec", tag = "4")] pub genesis_state_root: ::prost::alloc::vec::Vec, @@ -57,7 +61,10 @@ impl ::prost::Name for AggregatedProofPublicData { const NAME: &'static str = "AggregatedProofPublicData"; const PACKAGE: &'static str = "sovereign.types.v1"; fn full_name() -> ::prost::alloc::string::String { - ::prost::alloc::format!("sovereign.types.v1.{}", Self::NAME) + "sovereign.types.v1.AggregatedProofPublicData".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/sovereign.types.v1.AggregatedProofPublicData".into() } } /// SerializedAggregatedProof defines the raw aggregated proof structure for the @@ -73,7 +80,10 @@ impl ::prost::Name for SerializedAggregatedProof { const NAME: &'static str = "SerializedAggregatedProof"; const PACKAGE: &'static str = "sovereign.types.v1"; fn full_name() -> ::prost::alloc::string::String { - ::prost::alloc::format!("sovereign.types.v1.{}", Self::NAME) + "sovereign.types.v1.SerializedAggregatedProof".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/sovereign.types.v1.SerializedAggregatedProof".into() } } /// SerializedValidityCondition defines the serialized validity condition for @@ -89,7 +99,29 @@ impl ::prost::Name for SerializedValidityCondition { const NAME: &'static str = "SerializedValidityCondition"; const PACKAGE: &'static str = "sovereign.types.v1"; fn full_name() -> ::prost::alloc::string::String { - ::prost::alloc::format!("sovereign.types.v1.{}", Self::NAME) + "sovereign.types.v1.SerializedValidityCondition".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/sovereign.types.v1.SerializedValidityCondition".into() + } +} +/// SlotNumber defines the slot number of rollups which is the height in the +/// Sovereign SDK system +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct SlotNumber { + /// the slot number (rollup height) + #[prost(uint64, tag = "1")] + pub slot_number: u64, +} +impl ::prost::Name for SlotNumber { + const NAME: &'static str = "SlotNumber"; + const PACKAGE: &'static str = "sovereign.types.v1"; + fn full_name() -> ::prost::alloc::string::String { + "sovereign.types.v1.SlotNumber".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/sovereign.types.v1.SlotNumber".into() } } /// CodeCommitment defines the code commitment of the aggregated proof circuit @@ -104,6 +136,9 @@ impl ::prost::Name for CodeCommitment { const NAME: &'static str = "CodeCommitment"; const PACKAGE: &'static str = "sovereign.types.v1"; fn full_name() -> ::prost::alloc::string::String { - ::prost::alloc::format!("sovereign.types.v1.{}", Self::NAME) + "sovereign.types.v1.CodeCommitment".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/sovereign.types.v1.CodeCommitment".into() } } diff --git a/proto/src/prost/sovereign.types.v1.serde.rs b/proto/src/prost/sovereign.types.v1.serde.rs index 291ce199..7a1a37c1 100644 --- a/proto/src/prost/sovereign.types.v1.serde.rs +++ b/proto/src/prost/sovereign.types.v1.serde.rs @@ -147,13 +147,11 @@ impl serde::Serialize for AggregatedProofPublicData { if true { struct_ser.serialize_field("validityConditions", &self.validity_conditions)?; } - if true { - #[allow(clippy::needless_borrow)] - struct_ser.serialize_field("initialSlotNumber", ::alloc::string::ToString::to_string(&self.initial_slot_number).as_str())?; + if let Some(v) = self.initial_slot_number.as_ref() { + struct_ser.serialize_field("initialSlotNumber", v)?; } - if true { - #[allow(clippy::needless_borrow)] - struct_ser.serialize_field("finalSlotNumber", ::alloc::string::ToString::to_string(&self.final_slot_number).as_str())?; + if let Some(v) = self.final_slot_number.as_ref() { + struct_ser.serialize_field("finalSlotNumber", v)?; } if true { #[allow(clippy::needless_borrow)] @@ -289,17 +287,13 @@ impl<'de> serde::Deserialize<'de> for AggregatedProofPublicData { if initial_slot_number__.is_some() { return Err(serde::de::Error::duplicate_field("initialSlotNumber")); } - initial_slot_number__ = - Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) - ; + initial_slot_number__ = map_.next_value()?; } GeneratedField::FinalSlotNumber => { if final_slot_number__.is_some() { return Err(serde::de::Error::duplicate_field("finalSlotNumber")); } - final_slot_number__ = - Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) - ; + final_slot_number__ = map_.next_value()?; } GeneratedField::GenesisStateRoot => { if genesis_state_root__.is_some() { @@ -351,8 +345,8 @@ impl<'de> serde::Deserialize<'de> for AggregatedProofPublicData { } Ok(AggregatedProofPublicData { validity_conditions: validity_conditions__.unwrap_or_default(), - initial_slot_number: initial_slot_number__.unwrap_or_default(), - final_slot_number: final_slot_number__.unwrap_or_default(), + initial_slot_number: initial_slot_number__, + final_slot_number: final_slot_number__, genesis_state_root: genesis_state_root__.unwrap_or_default(), initial_state_root: initial_state_root__.unwrap_or_default(), final_state_root: final_state_root__.unwrap_or_default(), @@ -650,3 +644,98 @@ impl<'de> serde::Deserialize<'de> for SerializedValidityCondition { deserializer.deserialize_struct("sovereign.types.v1.SerializedValidityCondition", FIELDS, GeneratedVisitor) } } +impl serde::Serialize for SlotNumber { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> core::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if true { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("sovereign.types.v1.SlotNumber", len)?; + if true { + #[allow(clippy::needless_borrow)] + struct_ser.serialize_field("slotNumber", ::alloc::string::ToString::to_string(&self.slot_number).as_str())?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for SlotNumber { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> core::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "slot_number", + "slotNumber", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + SlotNumber, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> core::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> core::result::Result + where + E: serde::de::Error, + { + match value { + "slotNumber" | "slot_number" => Ok(GeneratedField::SlotNumber), + _ => Err(serde::de::Error::unknown_field(value, FIELDS)), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = SlotNumber; + + fn expecting(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + formatter.write_str("struct sovereign.types.v1.SlotNumber") + } + + fn visit_map(self, mut map_: V) -> core::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut slot_number__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::SlotNumber => { + if slot_number__.is_some() { + return Err(serde::de::Error::duplicate_field("slotNumber")); + } + slot_number__ = + Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) + ; + } + } + } + Ok(SlotNumber { + slot_number: slot_number__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("sovereign.types.v1.SlotNumber", FIELDS, GeneratedVisitor) + } +} From 40249c88d0c0d625dc6cbfbf64151c362c75cf82 Mon Sep 17 00:00:00 2001 From: Farhad Shabani Date: Fri, 12 Apr 2024 22:43:05 -0700 Subject: [PATCH 2/6] chore: update basecoin rev --- .cargo/config.toml | 2 +- Cargo.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.cargo/config.toml b/.cargo/config.toml index 758f6275..0a5f47e2 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -17,7 +17,7 @@ ibc-primitives = { git = "https://github.com/cosmos/ibc-rs.git" ibc-query = { git = "https://github.com/cosmos/ibc-rs.git", rev = "c579628c67" } ibc-testkit = { git = "https://github.com/cosmos/ibc-rs.git", rev = "c579628c67" } -basecoin = { git = "https://github.com/informalsystems/basecoin-rs.git", rev = "75fbb86" } +basecoin = { git = "https://github.com/informalsystems/basecoin-rs.git", rev = "5af9823" } jmt = { git = "https://github.com/penumbra-zone/jmt.git", rev = "1d007e11cb68aa5ca13e9a5af4a12e6439d5f7b6" } sov-modules-api = { path = "vendor/sovereign-sdk/module-system/sov-modules-api" } diff --git a/Cargo.lock b/Cargo.lock index 3c4494ba..fa4ac261 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -569,7 +569,7 @@ checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" [[package]] name = "basecoin" version = "0.1.0" -source = "git+https://github.com/informalsystems/basecoin-rs.git?rev=75fbb86#75fbb86374d2369383aa3f819d1296bad64759b1" +source = "git+https://github.com/informalsystems/basecoin-rs.git?rev=5af9823#5af9823070163d20f20a43f0bed68e1aa2c50d56" dependencies = [ "basecoin-app", "basecoin-modules", @@ -591,7 +591,7 @@ dependencies = [ [[package]] name = "basecoin-app" version = "0.1.0" -source = "git+https://github.com/informalsystems/basecoin-rs.git?rev=75fbb86#75fbb86374d2369383aa3f819d1296bad64759b1" +source = "git+https://github.com/informalsystems/basecoin-rs.git?rev=5af9823#5af9823070163d20f20a43f0bed68e1aa2c50d56" dependencies = [ "basecoin-modules", "basecoin-store", @@ -610,7 +610,7 @@ dependencies = [ [[package]] name = "basecoin-modules" version = "0.1.0" -source = "git+https://github.com/informalsystems/basecoin-rs.git?rev=75fbb86#75fbb86374d2369383aa3f819d1296bad64759b1" +source = "git+https://github.com/informalsystems/basecoin-rs.git?rev=5af9823#5af9823070163d20f20a43f0bed68e1aa2c50d56" dependencies = [ "base64 0.21.7", "basecoin-store", @@ -637,7 +637,7 @@ dependencies = [ [[package]] name = "basecoin-store" version = "0.1.0" -source = "git+https://github.com/informalsystems/basecoin-rs.git?rev=75fbb86#75fbb86374d2369383aa3f819d1296bad64759b1" +source = "git+https://github.com/informalsystems/basecoin-rs.git?rev=5af9823#5af9823070163d20f20a43f0bed68e1aa2c50d56" dependencies = [ "displaydoc", "ics23", From 9df342aba8f94abee0c257d4da94414bf59ac926 Mon Sep 17 00:00:00 2001 From: Farhad Shabani Date: Sat, 13 Apr 2024 08:43:41 -0700 Subject: [PATCH 3/6] imp: place AnyCodec under sov-celestia-cw + reomve now unused PrettySlice + clean-ups --- .../sov-celestia-cw/src/context/client_ctx.rs | 2 +- clients/sov-celestia-cw/src/context/mod.rs | 6 +-- clients/sov-celestia-cw/src/lib.rs | 1 + clients/sov-celestia-cw/src/tests/fixture.rs | 3 +- clients/sov-celestia-cw/src/types/helper.rs | 30 +++++++++++++ clients/sov-celestia-cw/src/types/mod.rs | 4 +- clients/sov-celestia-cw/src/types/msgs.rs | 1 - clients/sov-celestia-cw/src/types/utils.rs | 43 ------------------- .../src/utils}/codec.rs | 0 clients/sov-celestia-cw/src/utils/mod.rs | 17 ++++++++ clients/sov-types/src/helpers/mod.rs | 5 --- clients/sov-types/src/helpers/pretty.rs | 18 -------- clients/sov-types/src/lib.rs | 2 - 13 files changed, 55 insertions(+), 77 deletions(-) create mode 100644 clients/sov-celestia-cw/src/types/helper.rs delete mode 100644 clients/sov-celestia-cw/src/types/utils.rs rename clients/{sov-types/src/helpers => sov-celestia-cw/src/utils}/codec.rs (100%) create mode 100644 clients/sov-celestia-cw/src/utils/mod.rs delete mode 100644 clients/sov-types/src/helpers/mod.rs delete mode 100644 clients/sov-types/src/helpers/pretty.rs diff --git a/clients/sov-celestia-cw/src/context/client_ctx.rs b/clients/sov-celestia-cw/src/context/client_ctx.rs index a04d0373..df6714a9 100644 --- a/clients/sov-celestia-cw/src/context/client_ctx.rs +++ b/clients/sov-celestia-cw/src/context/client_ctx.rs @@ -8,10 +8,10 @@ use ibc_core::host::types::identifiers::ClientId; use ibc_core::host::types::path::{iteration_key, ClientConsensusStatePath, ClientStatePath}; use ibc_core::primitives::proto::{Any, Protobuf}; use ibc_core::primitives::Timestamp; -use sov_celestia_client::types::sovereign::AnyCodec; use super::Context; use crate::types::ClientType; +use crate::utils::AnyCodec; impl<'a, C: ClientType<'a>> ClientValidationContext for Context<'a, C> { type ClientStateRef = C::ClientState; diff --git a/clients/sov-celestia-cw/src/context/mod.rs b/clients/sov-celestia-cw/src/context/mod.rs index 2252e829..d44f15ec 100644 --- a/clients/sov-celestia-cw/src/context/mod.rs +++ b/clients/sov-celestia-cw/src/context/mod.rs @@ -15,11 +15,9 @@ use ibc_core::host::types::path::{ }; use ibc_core::primitives::proto::{Any, Protobuf}; use prost::Message; -use sov_celestia_client::types::sovereign::AnyCodec; -use crate::types::{ - parse_height, ClientType, ContractError, GenesisMetadata, HeightTravel, MigrationPrefix, -}; +use crate::types::{ClientType, ContractError, GenesisMetadata, HeightTravel, MigrationPrefix}; +use crate::utils::{parse_height, AnyCodec}; type Checksum = Vec; diff --git a/clients/sov-celestia-cw/src/lib.rs b/clients/sov-celestia-cw/src/lib.rs index 5eb3ae92..91de4b6b 100644 --- a/clients/sov-celestia-cw/src/lib.rs +++ b/clients/sov-celestia-cw/src/lib.rs @@ -15,6 +15,7 @@ pub mod context; pub mod entrypoints; pub mod handlers; pub mod types; +pub mod utils; #[cfg(test)] pub mod tests; diff --git a/clients/sov-celestia-cw/src/tests/fixture.rs b/clients/sov-celestia-cw/src/tests/fixture.rs index 76a0cf40..8faaca95 100644 --- a/clients/sov-celestia-cw/src/tests/fixture.rs +++ b/clients/sov-celestia-cw/src/tests/fixture.rs @@ -15,7 +15,7 @@ use sov_celestia_client::types::client_state::test_util::{ }; use sov_celestia_client::types::client_state::SovTmClientState; use sov_celestia_client::types::consensus_state::SovTmConsensusState; -use sov_celestia_client::types::sovereign::{AnyCodec, Root, SovereignParamsConfig}; +use sov_celestia_client::types::sovereign::{Root, SovereignParamsConfig}; use tendermint_testgen::{Generator, Validator}; use crate::entrypoints::SovTmContext; @@ -23,6 +23,7 @@ use crate::types::{ CheckForMisbehaviourMsgRaw, ExportMetadataMsg, GenesisMetadata, InstantiateMsg, QueryMsg, QueryResponse, StatusMsg, VerifyClientMessageRaw, }; +use crate::utils::AnyCodec; /// Test fixture #[derive(Clone, Debug)] diff --git a/clients/sov-celestia-cw/src/types/helper.rs b/clients/sov-celestia-cw/src/types/helper.rs new file mode 100644 index 00000000..104dda6f --- /dev/null +++ b/clients/sov-celestia-cw/src/types/helper.rs @@ -0,0 +1,30 @@ +use ibc_client_wasm_types::{SUBJECT_PREFIX, SUBSTITUTE_PREFIX}; + +/// The MigrationPrefix enumerates the prefix type used during migration mode. +/// The migration mode is activated when there is an incoming +/// `MigrateClientStore` message. It specifies the prefix key for either the +/// subject or substitute store, or none if the migration is not active. +#[derive(Clone, Debug)] +pub enum MigrationPrefix { + Subject, + Substitute, + None, +} + +impl MigrationPrefix { + pub fn key(&self) -> &[u8] { + match self { + MigrationPrefix::Subject => SUBJECT_PREFIX, + MigrationPrefix::Substitute => SUBSTITUTE_PREFIX, + MigrationPrefix::None => b"", + } + } +} + +/// Travel is an enum to represent the direction of travel in the context of +/// height. +#[derive(Clone, Debug)] +pub enum HeightTravel { + Next, + Prev, +} diff --git a/clients/sov-celestia-cw/src/types/mod.rs b/clients/sov-celestia-cw/src/types/mod.rs index 71f5f712..9a5de9ae 100644 --- a/clients/sov-celestia-cw/src/types/mod.rs +++ b/clients/sov-celestia-cw/src/types/mod.rs @@ -1,11 +1,11 @@ mod client_type; mod error; +mod helper; mod msgs; mod response; -mod utils; pub use client_type::*; pub use error::*; +pub use helper::*; pub use msgs::*; pub use response::*; -pub use utils::*; diff --git a/clients/sov-celestia-cw/src/types/msgs.rs b/clients/sov-celestia-cw/src/types/msgs.rs index e9ff9dce..32fd4db5 100644 --- a/clients/sov-celestia-cw/src/types/msgs.rs +++ b/clients/sov-celestia-cw/src/types/msgs.rs @@ -1,5 +1,4 @@ //! Contains the definition of the messages that can be sent to the CosmWasm contract. - use std::str::FromStr; use cosmwasm_schema::cw_serde; diff --git a/clients/sov-celestia-cw/src/types/utils.rs b/clients/sov-celestia-cw/src/types/utils.rs deleted file mode 100644 index e2514f3b..00000000 --- a/clients/sov-celestia-cw/src/types/utils.rs +++ /dev/null @@ -1,43 +0,0 @@ -use ibc_client_wasm_types::{SUBJECT_PREFIX, SUBSTITUTE_PREFIX}; -use ibc_core::client::types::error::ClientError; -use ibc_core::client::types::Height; - -/// The MigrationPrefix field indicates whether the recovery mode has been -/// activated if there is an incoming `MigrateClientStore` message. If so, it -/// specifies the prefix key for either the subject or substitute storage index. -#[derive(Clone, Debug)] -pub enum MigrationPrefix { - Subject, - Substitute, - None, -} - -impl MigrationPrefix { - pub fn key(&self) -> &[u8] { - match self { - MigrationPrefix::Subject => SUBJECT_PREFIX, - MigrationPrefix::Substitute => SUBSTITUTE_PREFIX, - MigrationPrefix::None => b"", - } - } -} - -/// Travel is an enum to represent the direction of travel in the context of -/// height. -#[derive(Clone, Debug)] -pub enum HeightTravel { - Next, - Prev, -} - -/// Decodes a `Height` from a UTF-8 encoded byte array. -pub fn parse_height(encoded_height: Vec) -> Result { - let height_str = - alloc::str::from_utf8(encoded_height.as_slice()).map_err(|e| ClientError::Other { - description: e.to_string(), - })?; - - Height::try_from(height_str).map_err(|e| ClientError::Other { - description: e.to_string(), - }) -} diff --git a/clients/sov-types/src/helpers/codec.rs b/clients/sov-celestia-cw/src/utils/codec.rs similarity index 100% rename from clients/sov-types/src/helpers/codec.rs rename to clients/sov-celestia-cw/src/utils/codec.rs diff --git a/clients/sov-celestia-cw/src/utils/mod.rs b/clients/sov-celestia-cw/src/utils/mod.rs new file mode 100644 index 00000000..31d99d61 --- /dev/null +++ b/clients/sov-celestia-cw/src/utils/mod.rs @@ -0,0 +1,17 @@ +mod codec; + +pub use codec::*; +use ibc_core::client::types::error::ClientError; +use ibc_core::client::types::Height; + +/// Decodes a `Height` from a UTF-8 encoded byte array. +pub fn parse_height(encoded_height: Vec) -> Result { + let height_str = + alloc::str::from_utf8(encoded_height.as_slice()).map_err(|e| ClientError::Other { + description: e.to_string(), + })?; + + Height::try_from(height_str).map_err(|e| ClientError::Other { + description: e.to_string(), + }) +} diff --git a/clients/sov-types/src/helpers/mod.rs b/clients/sov-types/src/helpers/mod.rs deleted file mode 100644 index 7ffeffe5..00000000 --- a/clients/sov-types/src/helpers/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -mod codec; -mod pretty; - -pub use codec::*; -pub use pretty::*; diff --git a/clients/sov-types/src/helpers/pretty.rs b/clients/sov-types/src/helpers/pretty.rs deleted file mode 100644 index 71ad90b0..00000000 --- a/clients/sov-types/src/helpers/pretty.rs +++ /dev/null @@ -1,18 +0,0 @@ -use core::fmt::{Display, Error as FmtError, Formatter}; - -pub struct PrettySlice<'a, T>(pub &'a [T]); - -impl<'a, T: Display> Display for PrettySlice<'a, T> { - fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> { - write!(f, "[ ")?; - let mut vec_iterator = self.0.iter().peekable(); - while let Some(element) = vec_iterator.next() { - write!(f, "{element}")?; - // If it is not the last element, add separator. - if vec_iterator.peek().is_some() { - write!(f, ", ")?; - } - } - write!(f, " ]") - } -} diff --git a/clients/sov-types/src/lib.rs b/clients/sov-types/src/lib.rs index 6e68d549..e0ea7198 100644 --- a/clients/sov-types/src/lib.rs +++ b/clients/sov-types/src/lib.rs @@ -2,7 +2,6 @@ mod aggregated_proof; mod client_params; mod consensus_params; mod error; -mod helpers; #[cfg(feature = "test-util")] pub use aggregated_proof::test_util::*; @@ -15,7 +14,6 @@ pub use client_params::test_util::*; pub use client_params::{SovereignClientParams, UpgradePath}; pub use consensus_params::SovereignConsensusParams; pub use error::*; -pub use helpers::*; /// Re-exports Sovereign SDK light clients proto types from `sov-ibc-proto` /// crate. From 5bfd3bd6d5c1396bd7b34685fb123e736953fe50 Mon Sep 17 00:00:00 2001 From: Farhad Shabani Date: Sat, 13 Apr 2024 08:51:33 -0700 Subject: [PATCH 4/6] imp: pass entire setup_cfg to MockRollup::init() --- mocks/src/relayer/builder.rs | 6 +----- mocks/src/sovereign/runner.rs | 17 ++++++----------- 2 files changed, 7 insertions(+), 16 deletions(-) diff --git a/mocks/src/relayer/builder.rs b/mocks/src/relayer/builder.rs index 0fe46ce7..11058f70 100644 --- a/mocks/src/relayer/builder.rs +++ b/mocks/src/relayer/builder.rs @@ -101,11 +101,7 @@ where self.setup_cfg.da_service.clone(), ); - rollup.init( - self.setup_cfg.genesis_da_height, - &self.setup_cfg.kernel_genesis_config(), - &self.setup_cfg.runtime_genesis_config(), - ); + rollup.init(&self.setup_cfg); let sov_client_counter = match rollup.query(QueryReq::ClientCounter).await { QueryResp::ClientCounter(counter) => counter, diff --git a/mocks/src/sovereign/runner.rs b/mocks/src/sovereign/runner.rs index 2d707d1b..9c420b2c 100644 --- a/mocks/src/sovereign/runner.rs +++ b/mocks/src/sovereign/runner.rs @@ -3,7 +3,6 @@ use std::time::Duration; use ibc_core::client::types::Height; use sov_consensus_state_tracker::HasConsensusState; -use sov_kernels::basic::BasicKernelGenesisConfig; use sov_modules_api::runtime::capabilities::{Kernel, KernelSlotHooks}; use sov_modules_api::{ CallResponse, DispatchCall, Gas, GasMeter, Genesis, KernelWorkingSet, SlotData, Spec, @@ -16,7 +15,8 @@ use sov_state::{MerkleProofSpec, ProverStorage, Storage}; use tokio::task::JoinHandle; use tracing::{debug, info}; -use super::{GenesisConfig, MockRollup}; +use super::MockRollup; +use crate::configs::TestSetupConfig; use crate::utils::{wait_for_block, MutexUtil}; impl MockRollup @@ -28,26 +28,21 @@ where

::Hasher: Send, { /// Initializes the chain with the genesis configuration - pub fn init( - &mut self, - genesis_da_height: Height, - kernel_genesis_config: &BasicKernelGenesisConfig, - runtime_genesis_config: &GenesisConfig, - ) { - self.advance_da_block_up_to(genesis_da_height); + pub fn init(&mut self, setup_cfg: &TestSetupConfig) { + self.advance_da_block_up_to(setup_cfg.genesis_da_height); let mut checkpoint = StateCheckpoint::new(self.prover_storage()); let mut kernel_working_set = KernelWorkingSet::uninitialized(&mut checkpoint); self.kernel() - .genesis(kernel_genesis_config, &mut kernel_working_set) + .genesis(&setup_cfg.kernel_genesis_config(), &mut kernel_working_set) .unwrap(); let mut working_set = checkpoint.to_revertable(Default::default()); self.runtime() - .genesis(runtime_genesis_config, &mut working_set) + .genesis(&setup_cfg.runtime_genesis_config(), &mut working_set) .unwrap(); self.commit(working_set.checkpoint().0); From 169ed3829823056b52946580eb56d69ec4d3771b Mon Sep 17 00:00:00 2001 From: Farhad Shabani Date: Sat, 13 Apr 2024 09:02:12 -0700 Subject: [PATCH 5/6] nit --- clients/sov-types/src/client_params.rs | 8 ++++---- mocks/src/cosmos/core.rs | 7 +++++++ mocks/src/sovereign/runner.rs | 10 ++-------- modules/sov-consensus-state-tracker/src/celestia_da.rs | 4 +--- modules/sov-consensus-state-tracker/src/mock_da.rs | 4 +--- 5 files changed, 15 insertions(+), 18 deletions(-) diff --git a/clients/sov-types/src/client_params.rs b/clients/sov-types/src/client_params.rs index 8a09db99..6831e4f6 100644 --- a/clients/sov-types/src/client_params.rs +++ b/clients/sov-types/src/client_params.rs @@ -24,10 +24,10 @@ pub struct SovereignClientParams { pub code_commitment: CodeCommitment, /// The trusting period is the period in which headers can be verified. /// - /// Note: During each update, the client verifies both the Data Availability - /// (DA) header and the aggregated proof simultaneously. When setting this - /// period, consider both the DA layer and the rollup, ensuring it's the - /// maximum acceptable duration. If the rollup has a shorter trusting + /// Note: During each update, the client verifies both the core header of DA + /// and the aggregated proof simultaneously. When setting this period, + /// consider both the DA layer and the rollup, ensuring it is the maximum + /// acceptable duration. If the rollup should have a shorter trusting /// window, it dictates when the client expires. pub trusting_period: Duration, /// The frozen height indicates whether the client is frozen. diff --git a/mocks/src/cosmos/core.rs b/mocks/src/cosmos/core.rs index 19a6ca1d..9d830b10 100644 --- a/mocks/src/cosmos/core.rs +++ b/mocks/src/cosmos/core.rs @@ -1,6 +1,7 @@ use std::str::FromStr; use std::sync::{Arc, Mutex}; +use ibc_core::client::types::Height; use ibc_core::host::types::identifiers::ChainId; use tendermint::{AppHash, Time}; use tendermint_testgen::light_block::TmLightBlock; @@ -92,4 +93,10 @@ impl MockTendermint { self.blocks.acquire_mutex().push(light_block); } + + pub fn advance_da_block_up_to(&mut self, height: Height) { + for _ in 0..height.revision_height() - 1 { + self.grow_blocks(vec![0; 32]); + } + } } diff --git a/mocks/src/sovereign/runner.rs b/mocks/src/sovereign/runner.rs index 9c420b2c..0bf6c123 100644 --- a/mocks/src/sovereign/runner.rs +++ b/mocks/src/sovereign/runner.rs @@ -1,7 +1,6 @@ //! Contains the implementation of the Sovereign SDK rollup runner. use std::time::Duration; -use ibc_core::client::types::Height; use sov_consensus_state_tracker::HasConsensusState; use sov_modules_api::runtime::capabilities::{Kernel, KernelSlotHooks}; use sov_modules_api::{ @@ -29,7 +28,8 @@ where { /// Initializes the chain with the genesis configuration pub fn init(&mut self, setup_cfg: &TestSetupConfig) { - self.advance_da_block_up_to(setup_cfg.genesis_da_height); + self.da_core + .advance_da_block_up_to(setup_cfg.genesis_da_height); let mut checkpoint = StateCheckpoint::new(self.prover_storage()); @@ -48,12 +48,6 @@ where self.commit(working_set.checkpoint().0); } - pub fn advance_da_block_up_to(&mut self, height: Height) { - for _ in 0..height.revision_height() - 1 { - self.da_core.grow_blocks(vec![0; 32]); - } - } - /// Begins processing a DA block by triggering the `begin_slot_hook` pub async fn begin_slot(&mut self, mut checkpoint: StateCheckpoint) -> StateCheckpoint { let kernel_working_set = KernelWorkingSet::from_kernel(self.kernel(), &mut checkpoint); diff --git a/modules/sov-consensus-state-tracker/src/celestia_da.rs b/modules/sov-consensus-state-tracker/src/celestia_da.rs index 29e7e2ca..895ee11c 100644 --- a/modules/sov-consensus-state-tracker/src/celestia_da.rs +++ b/modules/sov-consensus-state-tracker/src/celestia_da.rs @@ -6,15 +6,13 @@ use sov_celestia_client::consensus_state::ConsensusState as HostConsensusState; use sov_celestia_client::types::consensus_state::{ ConsensusState as SovConsensusState, TmConsensusParams, }; -use sov_celestia_client::types::sovereign::SovereignConsensusParams; use sov_rollup_interface::da::BlockHeaderTrait; use crate::HasConsensusState; impl HasConsensusState for CelestiaSpec { fn consensus_state(header: &CelestiaHeader) -> HostConsensusState { - let sovereign_params = - SovereignConsensusParams::new(CommitmentRoot::from_bytes(header.hash().as_ref())); + let sovereign_params = CommitmentRoot::from_bytes(header.hash().as_ref()).into(); let da_params = TmConsensusParams::new( tendermint::Time::from_unix_timestamp( diff --git a/modules/sov-consensus-state-tracker/src/mock_da.rs b/modules/sov-consensus-state-tracker/src/mock_da.rs index 203a9e3d..61af1b5f 100644 --- a/modules/sov-consensus-state-tracker/src/mock_da.rs +++ b/modules/sov-consensus-state-tracker/src/mock_da.rs @@ -5,7 +5,6 @@ use sov_celestia_client::consensus_state::ConsensusState as HostConsensusState; use sov_celestia_client::types::consensus_state::{ ConsensusState as SovConsensusState, TmConsensusParams, }; -use sov_celestia_client::types::sovereign::SovereignConsensusParams; pub use sov_mock_da::{MockAddress, MockDaConfig, MockDaService, MockDaSpec}; use sov_rollup_interface::da::BlockHeaderTrait; @@ -13,8 +12,7 @@ use crate::HasConsensusState; impl HasConsensusState for MockDaSpec { fn consensus_state(header: &Self::BlockHeader) -> HostConsensusState { - let sovereign_params = - SovereignConsensusParams::new(CommitmentRoot::from_bytes(header.hash().as_ref())); + let sovereign_params = CommitmentRoot::from_bytes(header.hash().as_ref()).into(); let da_params = TmConsensusParams::new( tendermint::Time::from_unix_timestamp( From 6075f870f6d553e089240d249d7d3e370772b393 Mon Sep 17 00:00:00 2001 From: Farhad Shabani Date: Sat, 13 Apr 2024 10:20:03 -0700 Subject: [PATCH 6/6] chore: update basecoin rev --- .cargo/config.toml | 2 +- Cargo.lock | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/.cargo/config.toml b/.cargo/config.toml index 0a5f47e2..9fd88696 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -17,7 +17,7 @@ ibc-primitives = { git = "https://github.com/cosmos/ibc-rs.git" ibc-query = { git = "https://github.com/cosmos/ibc-rs.git", rev = "c579628c67" } ibc-testkit = { git = "https://github.com/cosmos/ibc-rs.git", rev = "c579628c67" } -basecoin = { git = "https://github.com/informalsystems/basecoin-rs.git", rev = "5af9823" } +basecoin = { git = "https://github.com/informalsystems/basecoin-rs.git", rev = "c996c41" } jmt = { git = "https://github.com/penumbra-zone/jmt.git", rev = "1d007e11cb68aa5ca13e9a5af4a12e6439d5f7b6" } sov-modules-api = { path = "vendor/sovereign-sdk/module-system/sov-modules-api" } diff --git a/Cargo.lock b/Cargo.lock index fa4ac261..b5b0d787 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -569,7 +569,7 @@ checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" [[package]] name = "basecoin" version = "0.1.0" -source = "git+https://github.com/informalsystems/basecoin-rs.git?rev=5af9823#5af9823070163d20f20a43f0bed68e1aa2c50d56" +source = "git+https://github.com/informalsystems/basecoin-rs.git?rev=c996c41#c996c41b990b544dcdcea6d3cc4f67637105f283" dependencies = [ "basecoin-app", "basecoin-modules", @@ -591,7 +591,7 @@ dependencies = [ [[package]] name = "basecoin-app" version = "0.1.0" -source = "git+https://github.com/informalsystems/basecoin-rs.git?rev=5af9823#5af9823070163d20f20a43f0bed68e1aa2c50d56" +source = "git+https://github.com/informalsystems/basecoin-rs.git?rev=c996c41#c996c41b990b544dcdcea6d3cc4f67637105f283" dependencies = [ "basecoin-modules", "basecoin-store", @@ -610,7 +610,7 @@ dependencies = [ [[package]] name = "basecoin-modules" version = "0.1.0" -source = "git+https://github.com/informalsystems/basecoin-rs.git?rev=5af9823#5af9823070163d20f20a43f0bed68e1aa2c50d56" +source = "git+https://github.com/informalsystems/basecoin-rs.git?rev=c996c41#c996c41b990b544dcdcea6d3cc4f67637105f283" dependencies = [ "base64 0.21.7", "basecoin-store", @@ -637,7 +637,7 @@ dependencies = [ [[package]] name = "basecoin-store" version = "0.1.0" -source = "git+https://github.com/informalsystems/basecoin-rs.git?rev=5af9823#5af9823070163d20f20a43f0bed68e1aa2c50d56" +source = "git+https://github.com/informalsystems/basecoin-rs.git?rev=c996c41#c996c41b990b544dcdcea6d3cc4f67637105f283" dependencies = [ "displaydoc", "ics23", @@ -2627,6 +2627,7 @@ name = "ibc-client-tendermint-types" version = "0.51.0" source = "git+https://github.com/cosmos/ibc-rs.git?rev=c579628c67#c579628c672bdb384ae4ef3cb02a7455c9d03386" dependencies = [ + "borsh", "displaydoc", "ibc-core-client-types", "ibc-core-commitment-types", @@ -2879,6 +2880,7 @@ name = "ibc-core-host-cosmos" version = "0.51.0" source = "git+https://github.com/cosmos/ibc-rs.git?rev=c579628c67#c579628c672bdb384ae4ef3cb02a7455c9d03386" dependencies = [ + "borsh", "derive_more", "displaydoc", "ibc-app-transfer-types",