diff --git a/Cargo.lock b/Cargo.lock index e08588e2f4..ed3ff9fd40 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11344,6 +11344,18 @@ dependencies = [ "unionlabs", ] +[[package]] +name = "state-lens-light-client-types" +version = "0.1.0" +dependencies = [ + "alloy", + "bincode 2.0.0-rc.3", + "protos", + "serde", + "thiserror", + "unionlabs", +] + [[package]] name = "static_assertions" version = "1.1.0" @@ -13341,55 +13353,19 @@ dependencies = [ ] [[package]] -name = "voyager-client-update-plugin-state-lens-evm" +name = "voyager-client-update-plugin-state-lens" version = "0.1.0" dependencies = [ "alloy", - "cometbft-rpc", - "cometbft-types", - "dashmap 5.5.3", "enumorph", - "futures", "ibc-union-spec", "ics23", "jsonrpsee", "macros", - "num-bigint 0.4.6", - "prost 0.12.6", "protos", "serde", "serde_json", - "state-lens-ics23-mpt-light-client-types", - "thiserror", - "tokio", - "tracing", - "tracing-subscriber 0.3.18", - "unionlabs", - "voyager-message", - "voyager-vm", -] - -[[package]] -name = "voyager-client-update-plugin-state-lens-ics23-ics23" -version = "0.1.0" -dependencies = [ - "alloy", - "cometbft-rpc", - "cometbft-types", - "dashmap 5.5.3", - "enumorph", - "futures", - "ibc-union-spec", - "ics23", - "jsonrpsee", - "macros", - "num-bigint 0.4.6", - "prost 0.12.6", - "protos", - "serde", - "serde_json", - "state-lens-ics23-ics23-light-client-types", - "thiserror", + "state-lens-light-client-types", "tokio", "tracing", "tracing-subscriber 0.3.18", diff --git a/Cargo.toml b/Cargo.toml index 8624fcc77c..2a58d11cd0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -139,8 +139,7 @@ members = [ "voyager/plugins/client-update/ethereum", "voyager/plugins/client-update/movement", "voyager/plugins/client-update/tendermint", - "voyager/plugins/client-update/state-lens/evm", - "voyager/plugins/client-update/state-lens/ics23-ics23", + "voyager/plugins/client-update/state-lens", "voyager/plugins/periodic-client-update", @@ -172,6 +171,7 @@ members = [ "lib/ibc-union-spec", "lib/ibc-classic-spec", + "lib/state-lens-light-client-types", ] [workspace.package] @@ -200,6 +200,8 @@ chain-utils = { path = "lib/chain-utils", default-features = false } cometbft-rpc = { path = "lib/cometbft-rpc", default-features = false } cometbft-types = { path = "lib/cometbft-types", default-features = false } +state-lens-light-client-types = { path = "lib/state-lens-light-client-types", default-features = false } + arbitrum-light-client-types = { path = "lib/arbitrum-light-client-types", default-features = false } arbitrum-verifier = { path = "lib/arbitrum-verifier", default-features = false } diff --git a/lib/state-lens-light-client-types/Cargo.toml b/lib/state-lens-light-client-types/Cargo.toml new file mode 100644 index 0000000000..6d50cc8ebe --- /dev/null +++ b/lib/state-lens-light-client-types/Cargo.toml @@ -0,0 +1,23 @@ +[package] +edition.workspace = true +license-file.workspace = true +name = "state-lens-light-client-types" +repository.workspace = true +version = "0.1.0" + +[dependencies] +alloy = { workspace = true, features = ["sol-types"], optional = true } +bincode = { workspace = true, features = ["alloc", "derive"], optional = true } +protos = { workspace = true, optional = true, features = ["proto_full", "serde"] } +serde = { workspace = true, optional = true, features = ["derive"] } +thiserror = { workspace = true } +unionlabs = { workspace = true, features = ["ethabi", "proto"] } + +[features] +bincode = ["dep:bincode", "unionlabs/bincode"] +default = [] +ethabi = ["unionlabs/ethabi", "dep:alloy", "dep:protos"] +serde = ["dep:serde"] + +[lints] +workspace = true diff --git a/lib/state-lens-light-client-types/src/header.rs b/lib/state-lens-light-client-types/src/header.rs new file mode 100644 index 0000000000..1fa0fd1deb --- /dev/null +++ b/lib/state-lens-light-client-types/src/header.rs @@ -0,0 +1,52 @@ +use unionlabs::{ibc::core::client::height::Height, primitives::Bytes}; + +#[derive(Debug, Clone, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "bincode", derive(bincode::Encode, bincode::Decode))] +pub struct Header { + pub l1_height: Height, + pub l2_height: Height, + /// Proof of the L2 consensus state as stored in the state of the L1. + pub l2_consensus_state_proof: Bytes, + pub l2_consensus_state: Bytes, +} + +#[cfg(feature = "ethabi")] +pub mod ethabi { + use alloy::sol_types::SolValue; + use unionlabs::{ + encoding::{Encode, EthAbi}, + impl_ethabi_via_try_from_into, + union::ics23, + }; + + use crate::Header; + + impl_ethabi_via_try_from_into!(Header => SolHeader); + + impl Encode for Header { + fn encode(self) -> Vec { + Into::::into(self).abi_encode_params() + } + } + + alloy::sol! { + struct SolHeader { + uint64 l1Height; + uint64 l2Height; + bytes l2InclusionProof; + bytes l2ConsensusState; + } + } + + impl From
for SolHeader { + fn from(value: Header) -> Self { + Self { + l1Height: value.l1_height.height(), + l2Height: value.l2_height.height(), + l2InclusionProof: value.l2_consensus_state_proof.into(), + l2ConsensusState: value.l2_consensus_state.into(), + } + } + } +} diff --git a/lib/state-lens-light-client-types/src/lib.rs b/lib/state-lens-light-client-types/src/lib.rs new file mode 100644 index 0000000000..193c80e3a9 --- /dev/null +++ b/lib/state-lens-light-client-types/src/lib.rs @@ -0,0 +1,3 @@ +mod header; + +pub use header::Header; diff --git a/voyager/plugins/client-update/state-lens/Cargo.toml b/voyager/plugins/client-update/state-lens/Cargo.toml new file mode 100644 index 0000000000..8f4a300953 --- /dev/null +++ b/voyager/plugins/client-update/state-lens/Cargo.toml @@ -0,0 +1,22 @@ +[package] +edition = "2021" +name = "voyager-client-update-plugin-state-lens" +version = "0.1.0" + +[dependencies] +alloy = { workspace = true, features = ["rpc", "rpc-types", "transports", "transport-http", "transport-ws", "reqwest", "provider-ws"] } +enumorph = { workspace = true } +ibc-union-spec = { workspace = true } +ics23 = { workspace = true } +jsonrpsee = { workspace = true, features = ["macros", "server", "tracing"] } +macros = { workspace = true } +protos = { workspace = true } +serde = { workspace = true, features = ["derive"] } +serde_json = { workspace = true } +state-lens-light-client-types = { workspace = true, features = ["serde"] } +tokio = { workspace = true } +tracing = { workspace = true } +tracing-subscriber = { workspace = true } +unionlabs = { workspace = true } +voyager-message = { workspace = true } +voyager-vm = { workspace = true } diff --git a/voyager/plugins/client-update/state-lens/evm/Cargo.toml b/voyager/plugins/client-update/state-lens/evm/Cargo.toml deleted file mode 100644 index da8598a618..0000000000 --- a/voyager/plugins/client-update/state-lens/evm/Cargo.toml +++ /dev/null @@ -1,29 +0,0 @@ -[package] -edition = "2021" -name = "voyager-client-update-plugin-state-lens-evm" -version = "0.1.0" - -[dependencies] -alloy = { workspace = true, features = ["rpc", "rpc-types", "transports", "transport-http", "transport-ws", "reqwest", "provider-ws"] } -cometbft-rpc = { workspace = true } -cometbft-types.workspace = true -dashmap = { workspace = true } -enumorph = { workspace = true } -futures = { workspace = true } -ibc-union-spec.workspace = true -ics23 = { workspace = true } -jsonrpsee = { workspace = true, features = ["macros", "server", "tracing"] } -macros = { workspace = true } -num-bigint = { workspace = true } -prost = { workspace = true } -protos = { workspace = true } -serde = { workspace = true, features = ["derive"] } -serde_json = { workspace = true } -state-lens-ics23-mpt-light-client-types = { workspace = true, features = ["serde"] } -thiserror = { workspace = true } -tokio = { workspace = true } -tracing = { workspace = true } -tracing-subscriber = { workspace = true } -unionlabs = { workspace = true } -voyager-message = { workspace = true } -voyager-vm = { workspace = true } diff --git a/voyager/plugins/client-update/state-lens/evm/src/main.rs b/voyager/plugins/client-update/state-lens/evm/src/main.rs deleted file mode 100644 index d91325a96b..0000000000 --- a/voyager/plugins/client-update/state-lens/evm/src/main.rs +++ /dev/null @@ -1,341 +0,0 @@ -use std::{collections::VecDeque, fmt::Debug}; - -use alloy::{ - providers::{Provider, ProviderBuilder, RootProvider}, - transports::BoxTransport, -}; -use call::FetchUpdateAfterL1Update; -use ibc_union_spec::{ConsensusStatePath, IbcUnion}; -use jsonrpsee::{ - core::{async_trait, RpcResult}, - Extensions, -}; -use serde::{Deserialize, Serialize}; -use state_lens_ics23_mpt_light_client_types::Header; -use tracing::{debug, instrument}; -use unionlabs::ibc::core::commitment::merkle_proof::MerkleProof; -use voyager_message::{ - call::{Call, FetchUpdateHeaders, WaitForTrustedHeight}, - callback::AggregateMsgUpdateClientsFromOrderedHeaders, - core::{ChainId, ClientType, IbcSpec, QueryHeight}, - data::{Data, DecodedHeaderMeta, OrderedHeaders}, - hook::UpdateHook, - into_value, - module::{PluginInfo, PluginServer}, - DefaultCmd, ExtensionsExt, Plugin, PluginMessage, RawClientId, VoyagerClient, VoyagerMessage, -}; -use voyager_vm::{call, conc, data, pass::PassResult, promise, seq, BoxDynError, Op, Visit}; - -use crate::{ - call::{FetchUpdate, ModuleCall}, - callback::ModuleCallback, -}; - -pub mod call; -pub mod callback; - -#[tokio::main(flavor = "multi_thread")] -async fn main() { - Module::run().await -} - -#[derive(Debug, Clone)] -pub struct Module { - pub l0_client_id: u32, - pub l1_client_id: u32, - pub l1_chain_id: ChainId, - pub l2_chain_id: ChainId, - - pub l2_eth_provider: RootProvider, - pub l1_tm_client: cometbft_rpc::Client, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct Config { - pub l0_client_id: u32, - pub l1_client_id: u32, - pub l1_chain_id: ChainId, - pub l2_chain_id: ChainId, - - pub l1_ws_url: String, - pub l2_rpc_url: String, -} - -impl Plugin for Module { - type Call = ModuleCall; - type Callback = ModuleCallback; - - type Config = Config; - type Cmd = DefaultCmd; - - async fn new(config: Self::Config) -> Result { - let l1_tm_client = cometbft_rpc::Client::new(config.l1_ws_url).await?; - - let l1_chain_id = l1_tm_client.status().await?.node_info.network.to_string(); - - if l1_chain_id != config.l1_chain_id.as_str() { - return Err(format!( - "incorrect chain id: expected `{}`, but found `{}`", - config.l1_chain_id, l1_chain_id - ) - .into()); - } - - let l2_eth_provider = ProviderBuilder::new() - .on_builtin(&config.l2_rpc_url) - .await?; - - let l2_chain_id = ChainId::new(l2_eth_provider.get_chain_id().await?.to_string()); - - Ok(Self { - l0_client_id: config.l0_client_id, - l1_client_id: config.l1_client_id, - l1_chain_id: ChainId::new(l1_chain_id), - l2_chain_id, - l1_tm_client, - l2_eth_provider, - }) - } - - fn info(config: Self::Config) -> PluginInfo { - PluginInfo { - name: plugin_name(&config.l2_chain_id), - interest_filter: UpdateHook::filter( - &config.l2_chain_id, - &ClientType::new(ClientType::STATE_LENS_ICS23_MPT), - ), - } - } - - async fn cmd(_config: Self::Config, cmd: Self::Cmd) { - match cmd {} - } -} - -fn plugin_name(chain_id: &ChainId) -> String { - pub const PLUGIN_NAME: &str = env!("CARGO_PKG_NAME"); - - format!("{PLUGIN_NAME}/{}", chain_id) -} - -impl Module { - fn plugin_name(&self) -> String { - plugin_name(&self.l2_chain_id) - } -} - -#[async_trait] -impl PluginServer for Module { - #[instrument(skip_all, fields(chain_id = %self.l2_chain_id))] - async fn run_pass( - &self, - _: &Extensions, - msgs: Vec>, - ) -> RpcResult> { - Ok(PassResult { - optimize_further: vec![], - ready: msgs - .into_iter() - .map(|mut op| { - UpdateHook::new( - &self.l2_chain_id, - &ClientType::new(ClientType::STATE_LENS_ICS23_MPT), - |fetch| { - Call::Plugin(PluginMessage::new( - self.plugin_name(), - ModuleCall::from(FetchUpdate { - counterparty_chain_id: fetch.counterparty_chain_id.clone(), - update_from: fetch.update_from, - update_to: fetch.update_to, - }), - )) - }, - ) - .visit_op(&mut op); - - op - }) - .enumerate() - .map(|(i, op)| (vec![i], op)) - .collect(), - }) - } - - #[instrument(skip_all, fields(chain_id = %self.l2_chain_id))] - async fn call(&self, ext: &Extensions, msg: ModuleCall) -> RpcResult> { - match msg { - ModuleCall::FetchUpdate(FetchUpdate { - counterparty_chain_id, - update_from, - update_to, - }) => { - let voy_client = ext.try_get::()?; - let l1_latest_height = voy_client - .query_latest_height(self.l1_chain_id.clone(), true) - .await?; - let l2_consensus_state_proof = serde_json::from_value::( - voy_client - .query_ibc_proof( - self.l1_chain_id.clone(), - QueryHeight::Specific(l1_latest_height), - ConsensusStatePath { - client_id: self.l1_client_id, - height: update_to.height(), - }, - ) - .await - .expect("big trouble") - .proof, - ) - .expect("impossible"); - let l2_merkle_proof = unionlabs::union::ics23::merkle_proof::MerkleProof::try_from( - protos::ibc::core::commitment::v1::MerkleProof::from(l2_consensus_state_proof), - ) - .expect("impossible"); - let continuation = call(PluginMessage::new( - self.plugin_name(), - ModuleCall::from(FetchUpdateAfterL1Update { - counterparty_chain_id, - update_from, - update_to, - }), - )); - // If the L2 consensus proof exists on the L1, we don't have to update the L2 on the L1. - match l2_merkle_proof { - unionlabs::union::ics23::merkle_proof::MerkleProof::Membership(_, _) => { - Ok(continuation) - } - _ => Ok(conc([ - // Update the L2 (eth) client on L1 (union) and then dispatch the continuation - promise( - [call(FetchUpdateHeaders { - client_type: ClientType::new(ClientType::ETHEREUM), - chain_id: self.l2_chain_id.clone(), - counterparty_chain_id: self.l1_chain_id.clone(), - update_from, - update_to, - })], - [], - AggregateMsgUpdateClientsFromOrderedHeaders { - ibc_spec_id: IbcUnion::ID, - chain_id: self.l1_chain_id.clone(), - client_id: RawClientId::new(self.l1_client_id), - }, - ), - seq([ - call(WaitForTrustedHeight { - chain_id: self.l1_chain_id.clone(), - ibc_spec_id: IbcUnion::ID, - client_id: RawClientId::new(self.l1_client_id), - height: update_to, - finalized: true, - }), - continuation, - ]), - ])), - } - } - ModuleCall::FetchUpdateAfterL1Update(FetchUpdateAfterL1Update { - counterparty_chain_id, - .. - }) => { - let voy_client = ext.try_get::()?; - let l1_latest_height = voy_client - .query_latest_height(self.l1_chain_id.clone(), false) - .await?; - debug!("l1 latest height {}", l1_latest_height); - let l0_client_meta = voy_client - .client_meta::( - counterparty_chain_id.clone(), - QueryHeight::Latest, - self.l0_client_id, - ) - .await?; - let l1_client_meta = voy_client - .client_meta::( - self.l1_chain_id.clone(), - QueryHeight::Specific(l1_latest_height), - self.l1_client_id, - ) - .await?; - // The client has been updated to at least update_to - let update_to = l1_client_meta.counterparty_height; - debug!("l0 client meta {:#?}", l0_client_meta); - let l2_consensus_state_path = ConsensusStatePath { - client_id: self.l1_client_id, - height: update_to.height(), - }; - let l2_consensus_state = voy_client - .query_ibc_state( - self.l1_chain_id.clone(), - QueryHeight::Specific(l1_latest_height), - l2_consensus_state_path.clone(), - ) - .await? - .state; - debug!("l2 consensus state {:#?}", l2_consensus_state); - let l2_consensus_state_proof = serde_json::from_value::( - voy_client - .query_ibc_proof( - self.l1_chain_id.clone(), - QueryHeight::Specific(l1_latest_height), - l2_consensus_state_path, - ) - .await - .expect("big trouble") - .proof, - ) - .expect("impossible"); - debug!("l2 consensus state proof {:#?}", l2_consensus_state_proof); - // Dispatch an update for the L1 on the destination, then dispatch the L2 update on the destination - Ok(conc([ - promise( - [call(FetchUpdateHeaders { - client_type: ClientType::new(ClientType::COMETBLS), - chain_id: self.l1_chain_id.clone(), - counterparty_chain_id: counterparty_chain_id.clone(), - update_from: l0_client_meta.counterparty_height, - update_to: l1_latest_height, - })], - [], - AggregateMsgUpdateClientsFromOrderedHeaders { - ibc_spec_id: IbcUnion::ID, - chain_id: counterparty_chain_id.clone(), - client_id: RawClientId::new(self.l0_client_id), - }, - ), - seq([ - call(WaitForTrustedHeight { - chain_id: counterparty_chain_id, - ibc_spec_id: IbcUnion::ID, - client_id: RawClientId::new(self.l0_client_id), - height: l1_latest_height, - finalized: false, - }), - data(OrderedHeaders { - headers: vec![( - DecodedHeaderMeta { height: update_to }, - into_value(Header { - l1_height: l1_latest_height, - l2_height: update_to, - l2_consensus_state_proof, - l2_consensus_state, - }), - )], - }), - ]), - ])) - } - } - } - - #[instrument(skip_all, fields(chain_id = %self.l2_chain_id))] - async fn callback( - &self, - _: &Extensions, - callback: ModuleCallback, - _data: VecDeque, - ) -> RpcResult> { - match callback {} - } -} diff --git a/voyager/plugins/client-update/state-lens/ics23-ics23/Cargo.toml b/voyager/plugins/client-update/state-lens/ics23-ics23/Cargo.toml deleted file mode 100644 index 8827b42c43..0000000000 --- a/voyager/plugins/client-update/state-lens/ics23-ics23/Cargo.toml +++ /dev/null @@ -1,29 +0,0 @@ -[package] -edition = "2021" -name = "voyager-client-update-plugin-state-lens-ics23-ics23" -version = "0.1.0" - -[dependencies] -alloy = { workspace = true, features = ["rpc", "rpc-types", "transports", "transport-http", "transport-ws", "reqwest", "provider-ws"] } -cometbft-rpc = { workspace = true } -cometbft-types.workspace = true -dashmap = { workspace = true } -enumorph = { workspace = true } -futures = { workspace = true } -ibc-union-spec.workspace = true -ics23 = { workspace = true } -jsonrpsee = { workspace = true, features = ["macros", "server", "tracing"] } -macros = { workspace = true } -num-bigint = { workspace = true } -prost = { workspace = true } -protos = { workspace = true } -serde = { workspace = true, features = ["derive"] } -serde_json = { workspace = true } -state-lens-ics23-ics23-light-client-types = { workspace = true, features = ["serde"] } -thiserror = { workspace = true } -tokio = { workspace = true } -tracing = { workspace = true } -tracing-subscriber = { workspace = true } -unionlabs = { workspace = true } -voyager-message = { workspace = true } -voyager-vm = { workspace = true } diff --git a/voyager/plugins/client-update/state-lens/ics23-ics23/src/call.rs b/voyager/plugins/client-update/state-lens/ics23-ics23/src/call.rs deleted file mode 100644 index 3d9897aafd..0000000000 --- a/voyager/plugins/client-update/state-lens/ics23-ics23/src/call.rs +++ /dev/null @@ -1,25 +0,0 @@ -use enumorph::Enumorph; -use macros::model; -use unionlabs::ibc::core::client::height::Height; -use voyager_message::core::ChainId; - -#[model] -#[derive(Enumorph)] -pub enum ModuleCall { - FetchUpdate(FetchUpdate), - FetchUpdateAfterL1Update(FetchUpdateAfterL1Update), -} - -#[model] -pub struct FetchUpdate { - pub counterparty_chain_id: ChainId, - pub update_from: Height, - pub update_to: Height, -} - -#[model] -pub struct FetchUpdateAfterL1Update { - pub counterparty_chain_id: ChainId, - pub update_from: Height, - pub update_to: Height, -} diff --git a/voyager/plugins/client-update/state-lens/ics23-ics23/src/callback.rs b/voyager/plugins/client-update/state-lens/ics23-ics23/src/callback.rs deleted file mode 100644 index a332e95f9a..0000000000 --- a/voyager/plugins/client-update/state-lens/ics23-ics23/src/callback.rs +++ /dev/null @@ -1,6 +0,0 @@ -use enumorph::Enumorph; -use macros::model; - -#[model] -#[derive(Enumorph)] -pub enum ModuleCallback {} diff --git a/voyager/plugins/client-update/state-lens/ics23-ics23/src/data.rs b/voyager/plugins/client-update/state-lens/ics23-ics23/src/data.rs deleted file mode 100644 index f52f66d6b6..0000000000 --- a/voyager/plugins/client-update/state-lens/ics23-ics23/src/data.rs +++ /dev/null @@ -1,4 +0,0 @@ -use macros::model; - -#[model] -pub enum ModuleData {} diff --git a/voyager/plugins/client-update/state-lens/evm/src/call.rs b/voyager/plugins/client-update/state-lens/src/call.rs similarity index 100% rename from voyager/plugins/client-update/state-lens/evm/src/call.rs rename to voyager/plugins/client-update/state-lens/src/call.rs diff --git a/voyager/plugins/client-update/state-lens/evm/src/callback.rs b/voyager/plugins/client-update/state-lens/src/callback.rs similarity index 100% rename from voyager/plugins/client-update/state-lens/evm/src/callback.rs rename to voyager/plugins/client-update/state-lens/src/callback.rs diff --git a/voyager/plugins/client-update/state-lens/evm/src/data.rs b/voyager/plugins/client-update/state-lens/src/data.rs similarity index 100% rename from voyager/plugins/client-update/state-lens/evm/src/data.rs rename to voyager/plugins/client-update/state-lens/src/data.rs diff --git a/voyager/plugins/client-update/state-lens/ics23-ics23/src/main.rs b/voyager/plugins/client-update/state-lens/src/main.rs similarity index 81% rename from voyager/plugins/client-update/state-lens/ics23-ics23/src/main.rs rename to voyager/plugins/client-update/state-lens/src/main.rs index 1bf6c303cf..f92d3cc06c 100644 --- a/voyager/plugins/client-update/state-lens/ics23-ics23/src/main.rs +++ b/voyager/plugins/client-update/state-lens/src/main.rs @@ -7,7 +7,7 @@ use jsonrpsee::{ Extensions, }; use serde::{Deserialize, Serialize}; -use state_lens_ics23_ics23_light_client_types::Header; +use state_lens_light_client_types::Header; use tracing::{debug, instrument}; use unionlabs::ibc::core::commitment::merkle_proof::MerkleProof; use voyager_message::{ @@ -41,6 +41,8 @@ pub struct Module { pub l1_client_id: u32, pub l1_chain_id: ChainId, pub l2_chain_id: ChainId, + pub l2_client_type: String, + pub state_lens_client_type: ClientType, } #[derive(Debug, Clone, Serialize, Deserialize)] @@ -49,6 +51,8 @@ pub struct Config { pub l1_client_id: u32, pub l1_chain_id: ChainId, pub l2_chain_id: ChainId, + pub l2_client_type: String, + pub state_lens_client_type: ClientType, } impl Plugin for Module { @@ -64,6 +68,8 @@ impl Plugin for Module { l1_client_id: config.l1_client_id, l1_chain_id: config.l1_chain_id, l2_chain_id: config.l2_chain_id, + l2_client_type: config.l2_client_type, + state_lens_client_type: config.state_lens_client_type, }) } @@ -72,7 +78,7 @@ impl Plugin for Module { name: plugin_name(&config.l2_chain_id), interest_filter: UpdateHook::filter( &config.l2_chain_id, - &ClientType::new(ClientType::STATE_LENS_ICS23_ICS23), + &config.state_lens_client_type, ), } } @@ -107,20 +113,16 @@ impl PluginServer for Module { ready: msgs .into_iter() .map(|mut op| { - UpdateHook::new( - &self.l2_chain_id, - &ClientType::new(ClientType::STATE_LENS_ICS23_ICS23), - |fetch| { - Call::Plugin(PluginMessage::new( - self.plugin_name(), - ModuleCall::from(FetchUpdate { - counterparty_chain_id: fetch.counterparty_chain_id.clone(), - update_from: fetch.update_from, - update_to: fetch.update_to, - }), - )) - }, - ) + UpdateHook::new(&self.l2_chain_id, &self.state_lens_client_type, |fetch| { + Call::Plugin(PluginMessage::new( + self.plugin_name(), + ModuleCall::from(FetchUpdate { + counterparty_chain_id: fetch.counterparty_chain_id.clone(), + update_from: fetch.update_from, + update_to: fetch.update_to, + }), + )) + }) .visit_op(&mut op); op @@ -176,10 +178,10 @@ impl PluginServer for Module { Ok(continuation) } _ => Ok(conc([ - // Update the L2 (tm) client on L1 (union) and then dispatch the continuation + // Update the L2 (eth) client on L1 (union) and then dispatch the continuation promise( [call(FetchUpdateHeaders { - client_type: ClientType::new(ClientType::TENDERMINT), + client_type: ClientType::new(self.l2_client_type.clone()), chain_id: self.l2_chain_id.clone(), counterparty_chain_id: self.l1_chain_id.clone(), update_from, @@ -230,11 +232,13 @@ impl PluginServer for Module { .await?; // The client has been updated to at least update_to let update_to = l1_client_meta.counterparty_height; - debug!("l0 client meta {:#?}", l0_client_meta); + debug!("l0 client meta {:?}", l0_client_meta); + let l2_consensus_state_path = ConsensusStatePath { client_id: self.l1_client_id, height: update_to.height(), }; + let l2_consensus_state = voy_client .query_ibc_state( self.l1_chain_id.clone(), @@ -243,20 +247,33 @@ impl PluginServer for Module { ) .await? .state; - debug!("l2 consensus state {:#?}", l2_consensus_state); - let l2_consensus_state_proof = serde_json::from_value::( - voy_client - .query_ibc_proof( - self.l1_chain_id.clone(), - QueryHeight::Specific(l1_latest_height), - l2_consensus_state_path, - ) - .await - .expect("big trouble") - .proof, - ) - .expect("impossible"); - debug!("l2 consensus state proof {:#?}", l2_consensus_state_proof); + + debug!("l2 consensus state {:?}", l2_consensus_state); + + let l2_consensus_state_proof = voy_client + .query_ibc_proof( + self.l1_chain_id.clone(), + QueryHeight::Specific(l1_latest_height), + l2_consensus_state_path, + ) + .await + .expect("big trouble") + .proof; + + let state_lens_client = voy_client + .client_info::(counterparty_chain_id.clone(), self.l0_client_id) + .await?; + + debug!("l2 consensus state proof {:?}", l2_consensus_state_proof); + + let l2_consensus_state_proof_bytes = voy_client + .encode_proof::( + self.state_lens_client_type.clone(), + state_lens_client.ibc_interface, + l2_consensus_state_proof, + ) + .await?; + // Dispatch an update for the L1 on the destination, then dispatch the L2 update on the destination Ok(conc([ promise( @@ -288,7 +305,7 @@ impl PluginServer for Module { into_value(Header { l1_height: l1_latest_height, l2_height: update_to, - l2_consensus_state_proof, + l2_consensus_state_proof: l2_consensus_state_proof_bytes, l2_consensus_state, }), )],