From 3bd8077eee5e7e217ed9d05d56b35de83ff3020a Mon Sep 17 00:00:00 2001 From: aeryz Date: Mon, 20 Jan 2025 11:50:47 +0300 Subject: [PATCH 01/15] feat: add state lens move client types Signed-off-by: aeryz --- Cargo.lock | 14 ++++++ Cargo.toml | 2 + .../Cargo.toml | 23 ++++++++++ .../src/client_state.rs | 15 ++++++ .../src/consensus_state.rs | 46 +++++++++++++++++++ .../src/lib.rs | 4 ++ 6 files changed, 104 insertions(+) create mode 100644 lib/state-lens-ics23-move-light-client-types/Cargo.toml create mode 100644 lib/state-lens-ics23-move-light-client-types/src/client_state.rs create mode 100644 lib/state-lens-ics23-move-light-client-types/src/consensus_state.rs create mode 100644 lib/state-lens-ics23-move-light-client-types/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 795ecdf3cd..cc230f8a46 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11280,6 +11280,20 @@ dependencies = [ "unionlabs", ] +[[package]] +name = "state-lens-ics23-move-light-client-types" +version = "0.1.0" +dependencies = [ + "alloy", + "bincode 2.0.0-rc.3", + "hex-literal", + "protos", + "serde", + "state-lens-light-client-types", + "thiserror", + "unionlabs", +] + [[package]] name = "state-lens-ics23-mpt-light-client" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 584c365a7a..77f26838ac 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -79,6 +79,7 @@ members = [ "lib/state-lens-ics23-mpt-light-client-types", "lib/state-lens-ics23-mpt-light-client-types", "lib/state-lens-ics23-ics23-light-client-types", + "lib/state-lens-ics23-move-light-client-types", # these will all be re enabled and updated once ethereum-light-client is updated @@ -224,6 +225,7 @@ scroll-rpc = { path = "lib/scroll-rpc", default-features = fal state-lens-ics23-ics23-light-client-types = { path = "lib/state-lens-ics23-ics23-light-client-types", default-features = false } state-lens-ics23-mpt-light-client-types = { path = "lib/state-lens-ics23-mpt-light-client-types", default-features = false } +state-lens-ics23-move-light-client-types = { path = "lib/state-lens-ics23-move-light-client-types", default-features = false } tendermint-light-client = { path = "cosmwasm/ibc-union/light-clients/tendermint", default-features = false } tendermint-light-client-types = { path = "lib/tendermint-light-client-types", default-features = false } diff --git a/lib/state-lens-ics23-move-light-client-types/Cargo.toml b/lib/state-lens-ics23-move-light-client-types/Cargo.toml new file mode 100644 index 0000000000..a0f4fea05c --- /dev/null +++ b/lib/state-lens-ics23-move-light-client-types/Cargo.toml @@ -0,0 +1,23 @@ +[package] +edition = "2021" +name = "state-lens-ics23-move-light-client-types" +version = "0.1.0" + +[dependencies] +alloy = { workspace = true, optional = true, features = ["sol-types"] } +bincode = { workspace = true, optional = true, features = ["alloc", "derive"] } +protos = { workspace = true, optional = true, features = ["proto_full", "serde"] } +serde = { workspace = true, optional = true, features = ["derive"] } +state-lens-light-client-types = { workspace = true } +thiserror = { workspace = true } +unionlabs = { workspace = true, features = ["ethabi", "proto"] } + +[dev-dependencies] +hex-literal = { workspace = true } + +[features] +default = [] + +bincode = ["dep:bincode", "unionlabs/bincode", "state-lens-light-client-types/bincode"] +ethabi = ["unionlabs/ethabi", "dep:alloy", "dep:protos", "state-lens-light-client-types/ethabi"] +serde = ["dep:serde", "state-lens-light-client-types/serde"] diff --git a/lib/state-lens-ics23-move-light-client-types/src/client_state.rs b/lib/state-lens-ics23-move-light-client-types/src/client_state.rs new file mode 100644 index 0000000000..7309d7627c --- /dev/null +++ b/lib/state-lens-ics23-move-light-client-types/src/client_state.rs @@ -0,0 +1,15 @@ +use unionlabs::tuple::AsTuple; + +pub type ClientState = state_lens_light_client_types::ClientState; + +#[derive(Debug, Clone, PartialEq, AsTuple)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "bincode", derive(bincode::Encode, bincode::Decode))] +pub struct Extra { + /// the offset at which we extract the u64 timestamp from the l2 consensus state + /// timestamp = consensus_state[timestamp_offset:timestamp_offset+8] + pub timestamp_offset: u16, + /// the offset at which we extract the bytes32 storage root (of the ibc contract on the l2) from the l2 consensus state + /// storage_root = consensus_state[storage_root_offset:storage_root_offset+32] + pub storage_root_offset: u16, +} diff --git a/lib/state-lens-ics23-move-light-client-types/src/consensus_state.rs b/lib/state-lens-ics23-move-light-client-types/src/consensus_state.rs new file mode 100644 index 0000000000..1168e75ef0 --- /dev/null +++ b/lib/state-lens-ics23-move-light-client-types/src/consensus_state.rs @@ -0,0 +1,46 @@ +use unionlabs::primitives::H256; + +#[derive(Debug, Clone, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "bincode", derive(bincode::Encode, bincode::Decode))] +pub struct ConsensusState { + /// Timestamp of the execution layer. + pub timestamp: u64, + /// State root of the execution layer. + pub state_root: H256, +} + +#[cfg(feature = "ethabi")] +pub mod ethabi { + use alloy::sol_types::SolValue; + use unionlabs::impl_ethabi_via_try_from_into; + + use super::*; + + impl_ethabi_via_try_from_into!(ConsensusState => SolConsensusState); + + alloy::sol! { + struct SolConsensusState { + uint64 timestamp; + bytes32 stateRoot; + } + } + + impl From for SolConsensusState { + fn from(value: ConsensusState) -> Self { + Self { + timestamp: value.timestamp, + stateRoot: value.state_root.get().into(), + } + } + } + + impl From for ConsensusState { + fn from(value: SolConsensusState) -> Self { + Self { + timestamp: value.timestamp, + state_root: H256::new(value.stateRoot.0), + } + } + } +} diff --git a/lib/state-lens-ics23-move-light-client-types/src/lib.rs b/lib/state-lens-ics23-move-light-client-types/src/lib.rs new file mode 100644 index 0000000000..491b00f903 --- /dev/null +++ b/lib/state-lens-ics23-move-light-client-types/src/lib.rs @@ -0,0 +1,4 @@ +pub mod client_state; +pub mod consensus_state; + +pub use crate::{client_state::ClientState, consensus_state::ConsensusState}; From 25a7f5fe909ee8e21eeaba96983fd039b145372b Mon Sep 17 00:00:00 2001 From: aeryz Date: Mon, 20 Jan 2025 12:52:02 +0300 Subject: [PATCH 02/15] feat(aptos): state lens ics23-mpt client impl Signed-off-by: aeryz --- move/README.md | 1 + move/move-ibc/sources/bcs_utils.move | 6 + move/move-ibc/sources/cometbls_lc.move | 1 - move/move-ibc/sources/state_lens_lc.move | 237 ++++++++++++++++++++++- 4 files changed, 234 insertions(+), 11 deletions(-) diff --git a/move/README.md b/move/README.md index 9e35beb0bc..6e1027a760 100644 --- a/move/README.md +++ b/move/README.md @@ -5,4 +5,5 @@ N thousand specifies a new namespace: - IBC: 35xxx - Cometbls light client: 351xx + - State lens light client: 352xx - UCS01 Relay: 36xxx diff --git a/move/move-ibc/sources/bcs_utils.move b/move/move-ibc/sources/bcs_utils.move index ec795f1bda..13a237855e 100644 --- a/move/move-ibc/sources/bcs_utils.move +++ b/move/move-ibc/sources/bcs_utils.move @@ -52,6 +52,12 @@ module ibc::bcs_utils { length } + /// Peel a u16 + public fun peel_u16(buf: &mut BcsBuf): u16 { + buf.cursor = buf.cursor + 2; + from_bcs::to_u16(vector::slice(&buf.inner, buf.cursor - 2, buf.cursor)) + } + /// Peel a u32 public fun peel_u32(buf: &mut BcsBuf): u32 { buf.cursor = buf.cursor + 4; diff --git a/move/move-ibc/sources/cometbls_lc.move b/move/move-ibc/sources/cometbls_lc.move index 2126879ca9..018e9724d3 100644 --- a/move/move-ibc/sources/cometbls_lc.move +++ b/move/move-ibc/sources/cometbls_lc.move @@ -108,7 +108,6 @@ module ibc::cometbls_lc { } public fun latest_height(client_id: u32): u64 acquires State { - // Return error code, 0 for success let state = borrow_global(get_client_address(client_id)); height::get_revision_height(&state.client_state.latest_height) } diff --git a/move/move-ibc/sources/state_lens_lc.move b/move/move-ibc/sources/state_lens_lc.move index ee3a9ec16f..691274704d 100644 --- a/move/move-ibc/sources/state_lens_lc.move +++ b/move/move-ibc/sources/state_lens_lc.move @@ -1,23 +1,166 @@ module ibc::statelens_lc { use std::vector; + use std::string::String; + + use aptos_std::smart_table::{Self, SmartTable}; + use aptos_std::aptos_hash::keccak256; + use aptos_std::from_bcs; + use aptos_std::bcs; + use aptos_std::object; + + use ibc::ics23; + use ibc::height::{Self, Height}; + use ibc::ethabi; + use ibc::bcs_utils; + use ibc::commitment; + use ibc::cometbls_lc; + + const E_INVALID_CLIENT_STATE: u64 = 35200; + const E_CONSENSUS_STATE_TIMESTAMP_ZERO: u64 = 35201; + const E_SIGNED_HEADER_HEIGHT_NOT_MORE_RECENT: u64 = 35202; + const E_SIGNED_HEADER_TIMESTAMP_NOT_MORE_RECENT: u64 = 35203; + const E_HEADER_EXCEEDED_TRUSTING_PERIOD: u64 = 35204; + const E_HEADER_EXCEEDED_MAX_CLOCK_DRIFT: u64 = 35205; + const E_VALIDATORS_HASH_MISMATCH: u64 = 35206; + const E_INVALID_ZKP: u64 = 35207; + const E_FROZEN_CLIENT: u64 = 35208; + const E_INVALID_MISBEHAVIOUR: u64 = 35209; + const E_L2_CONSENSUS_STATE_PROOF_VERIFICATION: u64 = 35210; + const E_UNIMPLEMENTED: u64 = 35299; + + struct State has key, store { + client_state: ClientState, + consensus_states: SmartTable + } + + struct ClientState has copy, drop, store { + /// L2 chain ID. This is the same as the ID of the chain being tracked by `self.l2_client_id`. + /// + /// ("C") + l2_chain_id: String, + + /// L1 client ID. This is the ID of the L1 client running on A that is used to check the L2 + /// inclusion proof against. + /// + /// ("B" on "A") + l1_client_id: u32, + + /// L2 client ID. This is the ID of the L2 client running on B (L1) tracking the C (L2). + /// + /// ("C" on "B") + l2_client_id: u32, + + /// L2 latest height + l2_latest_height: u64, + + /// the offset at which we extract the u64 timestamp from the l2 consensus state + /// timestamp = consensus_state[timestamp_offset:timestamp_offset+8] + timestamp_offset: u16, + /// the offset at which we extract the bytes32 state root from the l2 consensus state + /// state_root = consensus_state[state_root_offset:state_root_offset+32] + state_root_offset: u16, + /// the offset at which we extract the bytes32 storage root (of the ibc contract on the l2) from the l2 consensus state + /// storage_root = consensus_state[storage_root_offset:storage_root_offset+32] + storage_root_offset: u16, + } + + struct ConsensusState has copy, drop, store { + /// Timestamp of the execution layer. + timestamp: u64, + /// State root of the execution layer. + state_root: vector, + /// Storage root of the ibc contract extracted from the state root. + storage_root: vector, + + } + + struct Header has copy, drop { + l1_height: Height, + l2_height: Height, + /// Proof of the L2 consensus state as stored in the state of the L1. + l2_consensus_state_proof: vector, + l2_consensus_state: vector, + } public fun create_client( - _ibc_signer: &signer, - _client_id: u32, - _client_state_bytes: vector, - _consensus_state_bytes: vector + ibc_signer: &signer, + client_id: u32, + client_state_bytes: vector, + consensus_state_bytes: vector ): (vector, vector) { - (vector::empty(), vector::empty()) + let client_state = decode_client_state(client_state_bytes); + let consensus_state = decode_consensus_state(consensus_state_bytes); + + assert!( + client_state.l2_latest_height != 0 + && consensus_state.timestamp != 0, + E_INVALID_CLIENT_STATE + ); + + let consensus_states = smart_table::new(); + smart_table::upsert( + &mut consensus_states, + client_state.l2_latest_height, + consensus_state + ); + + let state = State { client_state: client_state, consensus_states: consensus_states }; + + let store_constructor = + object::create_named_object(ibc_signer, bcs::to_bytes(&client_id)); + let client_signer = object::generate_signer(&store_constructor); + + move_to(&client_signer, state); + + (client_state_bytes, consensus_state_bytes) } - public fun latest_height(_client_id: u32): u64 { - 0 + public fun latest_height(client_id: u32): u64 acquires State { + let state = borrow_global(get_client_address(client_id)); + state.client_state.l2_latest_height } public fun update_client( - _client_id: u32, _client_msg: vector - ): (vector, vector>, vector) { - (vector::empty(), vector::empty(), vector::empty()) + client_id: u32, client_msg: vector + ): (vector, vector>, vector) acquires State { + let header = decode_header(client_msg); + + let state = borrow_global_mut(get_client_address(client_id)); + + assert!(cometbls_lc::verify_membership( + state.client_state.l1_client_id, + height::get_revision_height(&header.l1_height), + commitment::consensus_state_path( + state.client_state.l2_client_id, + height::get_revision_height(&header.l2_height) + ), + header.l2_consensus_state_proof, + keccak256(header.l2_consensus_state) + ) == 0, E_L2_CONSENSUS_STATE_PROOF_VERIFICATION); + + let l2_timestamp = extract_uint64(vector::slice(&header.l2_consensus_state, (state.client_state.timestamp_offset as u64), ((state.client_state.timestamp_offset + 8) as u64))); + let l2_state_root = vector::slice(&header.l2_consensus_state, (state.client_state.state_root_offset as u64), ((state.client_state.state_root_offset + 32) as u64)); + let l2_storage_root = vector::slice(&header.l2_consensus_state, (state.client_state.storage_root_offset as u64), ((state.client_state.storage_root_offset + 32) as u64)); + + let new_height = height::get_revision_height(&header.l2_height); + + if ((state.client_state.l2_latest_height as u64) < new_height) { + state.client_state.l2_latest_height = new_height; + }; + + let consensus_state = ConsensusState { + timestamp: l2_timestamp, + state_root: l2_state_root, + storage_root: l2_storage_root + }; + + smart_table::upsert(&mut state.consensus_states, new_height, consensus_state); + + ( + bcs::to_bytes(&state.client_state), + vector[encode_consensus_state(&consensus_state)], + vector[new_height] + ) } public fun report_misbehaviour( @@ -64,4 +207,78 @@ module ibc::statelens_lc { ): bool { false } + + fun decode_client_state(buf: vector): ClientState { + let buf = bcs_utils::new(buf); + + let l2_chain_id = bcs_utils::peel_string(&mut buf); + let l1_client_id = bcs_utils::peel_u32(&mut buf); + let l2_client_id = bcs_utils::peel_u32(&mut buf); + let l2_latest_height = bcs_utils::peel_u64(&mut buf); + let timestamp_offset = bcs_utils::peel_u16(&mut buf); + let state_root_offset = bcs_utils::peel_u16(&mut buf); + let storage_root_offset = bcs_utils::peel_u16(&mut buf); + + ClientState { + l2_chain_id, + l1_client_id, + l2_client_id, + l2_latest_height, + timestamp_offset, + state_root_offset, + storage_root_offset + } + } + + fun decode_consensus_state(buf: vector): ConsensusState { + let buf = bcs_utils::new(buf); + + let timestamp = bcs_utils::peel_u64(&mut buf); + let state_root = bcs_utils::peel_fixed_bytes(&mut buf, 32); + let storage_root = bcs_utils::peel_fixed_bytes(&mut buf, 32); + + ConsensusState { + timestamp, + state_root, + storage_root + } + } + + fun decode_header(buf: vector): Header { + let buf = bcs_utils::new(buf); + + let l1_height = height::decode_bcs(&mut buf); + let l2_height = height::decode_bcs(&mut buf); + let l2_consensus_state_proof = bcs_utils::peel_bytes(&mut buf); + let l2_consensus_state = bcs_utils::peel_bytes(&mut buf); + + Header { + l1_height, + l2_height, + l2_consensus_state_proof, + l2_consensus_state + } + } + + fun encode_consensus_state(cs: &ConsensusState): vector { + let buf = vector::empty(); + + ethabi::encode_uint(&mut buf, cs.timestamp); + + vector::append(&mut buf, cs.state_root); + vector::append(&mut buf, cs.storage_root); + + buf + } + + fun extract_uint64(buf: vector): u64 { + vector::reverse(&mut buf); + from_bcs::to_u64(buf) + } + + fun get_client_address(client_id: u32): address { + let vault_addr = object::create_object_address(&@ibc, b"IBC_VAULT_SEED"); + + object::create_object_address(&vault_addr, bcs::to_bytes(&client_id)) + } } From 10cab6d625639dea618c8fc59a3dbdc0dff27244 Mon Sep 17 00:00:00 2001 From: aeryz Date: Mon, 20 Jan 2025 15:24:10 +0300 Subject: [PATCH 03/15] chore: client_id_to_type mapping Signed-off-by: aeryz --- move/move-ibc/sources/ibc.move | 26 +++++++--- move/move-ibc/sources/state_lens_lc.move | 64 ++++++++++++++---------- 2 files changed, 56 insertions(+), 34 deletions(-) diff --git a/move/move-ibc/sources/ibc.move b/move/move-ibc/sources/ibc.move index 1cc2780433..8201454209 100644 --- a/move/move-ibc/sources/ibc.move +++ b/move/move-ibc/sources/ibc.move @@ -219,7 +219,8 @@ module ibc::ibc { commitments: Table, vector>, connections: SmartTable, channels: SmartTable, - channel_to_module: SmartTable + channel_to_module: SmartTable, + client_id_to_type: SmartTable } struct SignerRef has key { @@ -280,6 +281,8 @@ module ibc::ibc { consensus_state ); + smart_table::upsert(&mut store.client_id_to_type, client_id, client_type); + // TODO(aeryz): fetch these status from proper exported consts assert!(light_client::status(client_type, client_id) == 0, E_CLIENT_NOT_ACTIVE); @@ -1143,7 +1146,8 @@ module ibc::ibc { commitments: table::new(), connections: smart_table::new(), channels: smart_table::new(), - channel_to_module: smart_table::new() + channel_to_module: smart_table::new(), + client_id_to_type: smart_table::new() }; move_to(vault_signer, store); @@ -1163,15 +1167,21 @@ module ibc::ibc { } #[view] - public fun client_state(client_type: String, client_id: u32): vector { - light_client::get_client_state(client_type, client_id) + public fun client_state(client_id: u32): vector acquires IBCStore { + let store = borrow_global(get_vault_addr()); + light_client::get_client_state( + *smart_table::borrow(&store.client_id_to_type, client_id), client_id + ) } #[view] - public fun consensus_state( - client_type: String, client_id: u32, revision_height: u64 - ): vector { - light_client::get_consensus_state(client_type, client_id, revision_height) + public fun consensus_state(client_id: u32, revision_height: u64): vector acquires IBCStore { + let store = borrow_global(get_vault_addr()); + light_client::get_consensus_state( + *smart_table::borrow(&store.client_id_to_type, client_id), + client_id, + revision_height + ) } #[view] diff --git a/move/move-ibc/sources/state_lens_lc.move b/move/move-ibc/sources/state_lens_lc.move index 691274704d..5bb39196f8 100644 --- a/move/move-ibc/sources/state_lens_lc.move +++ b/move/move-ibc/sources/state_lens_lc.move @@ -61,7 +61,7 @@ module ibc::statelens_lc { state_root_offset: u16, /// the offset at which we extract the bytes32 storage root (of the ibc contract on the l2) from the l2 consensus state /// storage_root = consensus_state[storage_root_offset:storage_root_offset+32] - storage_root_offset: u16, + storage_root_offset: u16 } struct ConsensusState has copy, drop, store { @@ -70,8 +70,7 @@ module ibc::statelens_lc { /// State root of the execution layer. state_root: vector, /// Storage root of the ibc contract extracted from the state root. - storage_root: vector, - + storage_root: vector } struct Header has copy, drop { @@ -79,7 +78,7 @@ module ibc::statelens_lc { l2_height: Height, /// Proof of the L2 consensus state as stored in the state of the L1. l2_consensus_state_proof: vector, - l2_consensus_state: vector, + l2_consensus_state: vector } public fun create_client( @@ -92,8 +91,7 @@ module ibc::statelens_lc { let consensus_state = decode_consensus_state(consensus_state_bytes); assert!( - client_state.l2_latest_height != 0 - && consensus_state.timestamp != 0, + client_state.l2_latest_height != 0 && consensus_state.timestamp != 0, E_INVALID_CLIENT_STATE ); @@ -127,23 +125,41 @@ module ibc::statelens_lc { let state = borrow_global_mut(get_client_address(client_id)); - assert!(cometbls_lc::verify_membership( - state.client_state.l1_client_id, - height::get_revision_height(&header.l1_height), - commitment::consensus_state_path( - state.client_state.l2_client_id, - height::get_revision_height(&header.l2_height) - ), - header.l2_consensus_state_proof, - keccak256(header.l2_consensus_state) - ) == 0, E_L2_CONSENSUS_STATE_PROOF_VERIFICATION); - - let l2_timestamp = extract_uint64(vector::slice(&header.l2_consensus_state, (state.client_state.timestamp_offset as u64), ((state.client_state.timestamp_offset + 8) as u64))); - let l2_state_root = vector::slice(&header.l2_consensus_state, (state.client_state.state_root_offset as u64), ((state.client_state.state_root_offset + 32) as u64)); - let l2_storage_root = vector::slice(&header.l2_consensus_state, (state.client_state.storage_root_offset as u64), ((state.client_state.storage_root_offset + 32) as u64)); + assert!( + cometbls_lc::verify_membership( + state.client_state.l1_client_id, + height::get_revision_height(&header.l1_height), + commitment::consensus_state_path( + state.client_state.l2_client_id, + height::get_revision_height(&header.l2_height) + ), + header.l2_consensus_state_proof, + keccak256(header.l2_consensus_state) + ) == 0, + E_L2_CONSENSUS_STATE_PROOF_VERIFICATION + ); + + let l2_timestamp = + extract_uint64( + vector::slice( + &header.l2_consensus_state, + (state.client_state.timestamp_offset as u64), + ((state.client_state.timestamp_offset + 8) as u64) + ) + ); + let l2_state_root = vector::slice( + &header.l2_consensus_state, + (state.client_state.state_root_offset as u64), + ((state.client_state.state_root_offset + 32) as u64) + ); + let l2_storage_root = vector::slice( + &header.l2_consensus_state, + (state.client_state.storage_root_offset as u64), + ((state.client_state.storage_root_offset + 32) as u64) + ); let new_height = height::get_revision_height(&header.l2_height); - + if ((state.client_state.l2_latest_height as u64) < new_height) { state.client_state.l2_latest_height = new_height; }; @@ -237,11 +253,7 @@ module ibc::statelens_lc { let state_root = bcs_utils::peel_fixed_bytes(&mut buf, 32); let storage_root = bcs_utils::peel_fixed_bytes(&mut buf, 32); - ConsensusState { - timestamp, - state_root, - storage_root - } + ConsensusState { timestamp, state_root, storage_root } } fun decode_header(buf: vector): Header { From 9535e452ac5edb7cb37becb9fd28b8d8f455c48b Mon Sep 17 00:00:00 2001 From: aeryz Date: Mon, 20 Jan 2025 15:41:33 +0300 Subject: [PATCH 04/15] chore(move): fix client type check Signed-off-by: aeryz --- move/move-ibc/sources/ibc.move | 2 -- move/move-ibc/sources/light_client.move | 22 +++++++++++----------- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/move/move-ibc/sources/ibc.move b/move/move-ibc/sources/ibc.move index 8201454209..f2253065dc 100644 --- a/move/move-ibc/sources/ibc.move +++ b/move/move-ibc/sources/ibc.move @@ -267,8 +267,6 @@ module ibc::ibc { public entry fun create_client( client_type: String, client_state: vector, consensus_state: vector ) acquires IBCStore, SignerRef { - assert!(string::bytes(&client_type) == &b"cometbls", E_UNKNOWN_CLIENT_TYPE); - let client_id = generate_client_identifier(); let store = borrow_global_mut(get_vault_addr()); diff --git a/move/move-ibc/sources/light_client.move b/move/move-ibc/sources/light_client.move index ef9677dd23..2d812a25d3 100644 --- a/move/move-ibc/sources/light_client.move +++ b/move/move-ibc/sources/light_client.move @@ -21,7 +21,7 @@ module ibc::light_client { consensus_state_bytes ); return (client_state, consensus_state) - } else if (string::bytes(&client_type) == &b"statelens") { + } else if (string::bytes(&client_type) == &b"state-lens/ics23/mpt") { let (client_state, consensus_state) = statelens_lc::create_client( ibc_signer, @@ -38,7 +38,7 @@ module ibc::light_client { public fun status(client_type: String, client_id: u32): u64 { if (string::bytes(&client_type) == &b"cometbls") { return cometbls_lc::status(client_id) - } else if (string::bytes(&client_type) == &b"statelens") { + } else if (string::bytes(&client_type) == &b"state-lens/ics23/mpt") { return statelens_lc::status(client_id) }; abort E_UNKNOWN_CLIENT_TYPE @@ -48,7 +48,7 @@ module ibc::light_client { public fun latest_height(client_type: String, client_id: u32): u64 { if (string::bytes(&client_type) == &b"cometbls") { return cometbls_lc::latest_height(client_id) - } else if (string::bytes(&client_type) == &b"statelens") { + } else if (string::bytes(&client_type) == &b"state-lens/ics23/mpt") { return statelens_lc::latest_height(client_id) }; abort E_UNKNOWN_CLIENT_TYPE @@ -59,7 +59,7 @@ module ibc::light_client { ): bool { if (string::bytes(&client_type) == &b"cometbls") { return cometbls_lc::check_for_misbehaviour(client_id, header) - } else if (string::bytes(&client_type) == &b"statelens") { + } else if (string::bytes(&client_type) == &b"state-lens/ics23/mpt") { return statelens_lc::check_for_misbehaviour(client_id, header) }; abort E_UNKNOWN_CLIENT_TYPE @@ -70,7 +70,7 @@ module ibc::light_client { ): (vector, vector>, vector) { if (string::bytes(&client_type) == &b"cometbls") { return cometbls_lc::update_client(client_id, client_msg) - } else if (string::bytes(&client_type) == &b"statelens") { + } else if (string::bytes(&client_type) == &b"state-lens/ics23/mpt") { return statelens_lc::update_client(client_id, client_msg) }; abort E_UNKNOWN_CLIENT_TYPE @@ -81,7 +81,7 @@ module ibc::light_client { ) { if (string::bytes(&client_type) == &b"cometbls") { cometbls_lc::report_misbehaviour(client_id, misbehaviour) - } else if (string::bytes(&client_type) == &b"statelens") { + } else if (string::bytes(&client_type) == &b"state-lens/ics23/mpt") { statelens_lc::report_misbehaviour(client_id, misbehaviour) }; abort E_UNKNOWN_CLIENT_TYPE @@ -92,7 +92,7 @@ module ibc::light_client { ): u64 { if (string::bytes(&client_type) == &b"cometbls") { return cometbls_lc::get_timestamp_at_height(client_id, height) - } else if (string::bytes(&client_type) == &b"statelens") { + } else if (string::bytes(&client_type) == &b"state-lens/ics23/mpt") { return statelens_lc::get_timestamp_at_height(client_id, height) }; abort E_UNKNOWN_CLIENT_TYPE @@ -101,7 +101,7 @@ module ibc::light_client { public fun get_client_state(client_type: String, client_id: u32): vector { if (string::bytes(&client_type) == &b"cometbls") { return cometbls_lc::get_client_state(client_id) - } else if (string::bytes(&client_type) == &b"statelens") { + } else if (string::bytes(&client_type) == &b"state-lens/ics23/mpt") { return statelens_lc::get_client_state(client_id) }; abort E_UNKNOWN_CLIENT_TYPE @@ -112,7 +112,7 @@ module ibc::light_client { ): vector { if (string::bytes(&client_type) == &b"cometbls") { return cometbls_lc::get_consensus_state(client_id, height) - } else if (string::bytes(&client_type) == &b"statelens") { + } else if (string::bytes(&client_type) == &b"state-lens/ics23/mpt") { return statelens_lc::get_consensus_state(client_id, height) }; abort E_UNKNOWN_CLIENT_TYPE @@ -128,7 +128,7 @@ module ibc::light_client { ): u64 { if (string::bytes(&client_type) == &b"cometbls") { return cometbls_lc::verify_membership(client_id, height, proof, key, value) - } else if (string::bytes(&client_type) == &b"statelens") { + } else if (string::bytes(&client_type) == &b"state-lens/ics23/mpt") { return statelens_lc::verify_membership(client_id, height, proof, key, value) }; abort E_UNKNOWN_CLIENT_TYPE @@ -143,7 +143,7 @@ module ibc::light_client { ): u64 { if (string::bytes(&client_type) == &b"cometbls") { return cometbls_lc::verify_non_membership(client_id, height, proof, path) - } else if (string::bytes(&client_type) == &b"statelens") { + } else if (string::bytes(&client_type) == &b"state-lens/ics23/mpt") { return statelens_lc::verify_non_membership(client_id, height, proof, path) }; abort E_UNKNOWN_CLIENT_TYPE From c7ce63b054fb8e74df76e6cba5730cfbf0abfbc5 Mon Sep 17 00:00:00 2001 From: aeryz Date: Tue, 21 Jan 2025 15:46:36 +0300 Subject: [PATCH 05/15] chore(aptos-move): use saved client_type based on the client id Signed-off-by: aeryz --- move/move-ibc/sources/acknowledge_packet.move | 3 - move/move-ibc/sources/channel_handshake.move | 13 +--- move/move-ibc/sources/ibc.move | 71 ++++++++++++------- move/move-ibc/sources/ibc_commitment.move | 4 +- move/move-ibc/sources/ics23.move | 10 +++ move/move-ibc/sources/mpt_verifier.move | 15 ++-- move/move-ibc/sources/recv_packet.move | 12 +--- move/move-ibc/sources/state_lens_lc.move | 36 ++++++---- move/move-ibc/sources/timeout_packet.move | 3 - 9 files changed, 91 insertions(+), 76 deletions(-) diff --git a/move/move-ibc/sources/acknowledge_packet.move b/move/move-ibc/sources/acknowledge_packet.move index 83a217cb25..d67bd1c827 100644 --- a/move/move-ibc/sources/acknowledge_packet.move +++ b/move/move-ibc/sources/acknowledge_packet.move @@ -1,7 +1,6 @@ module ibc::acknowledge_packet { use ibc::packet::{Self, Packet}; - use std::string::{String}; use ibc::channel; use ibc::engine; use ibc::commitment; @@ -12,7 +11,6 @@ module ibc::acknowledge_packet { use std::vector; public entry fun acknowledge_packet( - client_type: String, port_id: address, packet_source_channels: vector, packet_destination_channels: vector, @@ -68,7 +66,6 @@ module ibc::acknowledge_packet { let err = ibc::verify_commitment( - client_type, client_id, proof_height, proof, diff --git a/move/move-ibc/sources/channel_handshake.move b/move/move-ibc/sources/channel_handshake.move index 44571c2636..9b83668469 100644 --- a/move/move-ibc/sources/channel_handshake.move +++ b/move/move-ibc/sources/channel_handshake.move @@ -27,7 +27,6 @@ module ibc::channel_handshake { } public entry fun channel_open_try( - client_type: String, port_id: address, connection_id: u32, counterparty_channel_id: u32, @@ -39,7 +38,6 @@ module ibc::channel_handshake { ) { let channel_id = ibc::channel_open_try( - client_type, port_id, connection_id, counterparty_channel_id, @@ -58,7 +56,6 @@ module ibc::channel_handshake { } public entry fun channel_open_ack( - client_type: String, port_id: address, channel_id: u32, counterparty_version: String, @@ -67,7 +64,6 @@ module ibc::channel_handshake { proof_height: u64 ) { ibc::channel_open_ack( - client_type, port_id, channel_id, counterparty_version, @@ -88,19 +84,12 @@ module ibc::channel_handshake { } public entry fun channel_open_confirm( - client_type: String, port_id: address, channel_id: u32, proof_ack: vector, proof_height: u64 ) { - ibc::channel_open_confirm( - client_type, - port_id, - channel_id, - proof_ack, - proof_height - ); + ibc::channel_open_confirm(port_id, channel_id, proof_ack, proof_height); engine::dispatch(helpers::pack_channel_open_confirm_params(channel_id)); diff --git a/move/move-ibc/sources/ibc.move b/move/move-ibc/sources/ibc.move index f2253065dc..cea4077f1b 100644 --- a/move/move-ibc/sources/ibc.move +++ b/move/move-ibc/sources/ibc.move @@ -9,7 +9,7 @@ module ibc::ibc { use std::event; use std::bcs; use std::object; - use std::string::{Self, String}; + use std::string::{String}; use std::hash; use std::option::{Self, Option}; use std::string_utils; @@ -261,7 +261,7 @@ module ibc::ibc { /// Create a client with an initial client and consensus state. /// - /// * `client_type`: Strictly "cometbls" for now. + /// * `client_type`: "cometbls" or "state-lens/ics23/mpt". /// * `client_state`: The initial state of the client. The encoding is defined by the underlying client implementation. /// * `consensus_state`: The consensus state at an initial height. The encoding is defined by the underlying client implementation. public entry fun create_client( @@ -346,13 +346,13 @@ module ibc::ibc { /// by the light client (`client_id`). /// * `proof_height`: The height at when `proof_init` was generated. public entry fun connection_open_try( - client_type: String, counterparty_client_id: u32, counterparty_connection_id: u32, client_id: u32, proof_init: vector, proof_height: u64 ) acquires IBCStore { + let client_type = client_id_to_type(client_id); let connection_id = generate_connection_identifier(); let store = borrow_global_mut(get_vault_addr()); @@ -412,12 +412,20 @@ module ibc::ibc { /// by the light client (`client_id`). /// * `proof_height`: The height at when `proof_try` was generated. public entry fun connection_open_ack( - client_type: String, connection_id: u32, counterparty_connection_id: u32, proof_try: vector, proof_height: u64 ) acquires IBCStore { + let client_type = + client_id_to_type( + connection_end::client_id( + smart_table::borrow( + &borrow_global(get_vault_addr()).connections, + connection_id + ) + ) + ); let store = borrow_global_mut(get_vault_addr()); assert!( @@ -481,18 +489,19 @@ module ibc::ibc { /// by the light client (`client_id`). /// * `proof_height`: The height at when `proof_ack` was generated. public entry fun connection_open_confirm( - client_type: String, - connection_id: u32, - proof_ack: vector, - proof_height: u64 + connection_id: u32, proof_ack: vector, proof_height: u64 ) acquires IBCStore { + let client_type = + client_id_to_type( + connection_end::client_id( + smart_table::borrow( + &borrow_global(get_vault_addr()).connections, + connection_id + ) + ) + ); let store = borrow_global_mut(get_vault_addr()); - assert!( - smart_table::contains(&store.connections, connection_id), - E_CONNECTION_DOES_NOT_EXIST - ); - let connection = smart_table::borrow_mut(&mut store.connections, connection_id); assert!( connection_end::state(connection) == CONN_STATE_TRYOPEN, @@ -545,8 +554,9 @@ module ibc::ibc { /// the client update data. The light client just needs to make sure altering this data can NEVER make it /// transition to an invalid state. public entry fun update_client( - client_type: String, client_id: u32, client_message: vector + client_id: u32, client_message: vector ) acquires IBCStore { + let client_type = client_id_to_type(client_id); let store = borrow_global_mut(get_vault_addr()); assert!( @@ -590,7 +600,7 @@ module ibc::ibc { hash::sha2_256(*vector::borrow(&consensus_states, i)) ); - event::emit(ClientUpdated { client_id, client_type: client_type, height }); + event::emit(ClientUpdated { client_id, client_type, height }); i = i + 1; }; @@ -605,7 +615,7 @@ module ibc::ibc { /// * `misbehaviour`: Light client defined misbehaviour data. It's the responsibility of the caller to gather and encode /// the correct data. The light client MUST detect any invalid misbehaviors and ignore those. public entry fun submit_misbehaviour( - client_type: String, client_id: u32, misbehaviour: vector + client_id: u32, misbehaviour: vector ) acquires IBCStore { let store = borrow_global_mut(get_vault_addr()); @@ -617,9 +627,11 @@ module ibc::ibc { E_CLIENT_NOT_FOUND ); + let client_type = client_id_to_type(client_id); + light_client::report_misbehaviour(client_type, client_id, misbehaviour); - event::emit(SubmitMisbehaviour { client_id, client_type: client_type }); + event::emit(SubmitMisbehaviour { client_id, client_type }); } /// Execute the init phase of the channel handshake. `T` is the witness type of the target module that is @@ -706,7 +718,6 @@ module ibc::ibc { /// by the light client (`client_id`). /// * `proof_height`: The height at when `proof_init` was generated. public fun channel_open_try( - client_type: String, port_id: address, connection_id: u32, counterparty_channel_id: u32, @@ -721,6 +732,8 @@ module ibc::ibc { let client_id = ensure_connection_state(connection_id); + let client_type = client_id_to_type(client_id); + let expected_channel = channel::new( CHAN_STATE_INIT, @@ -816,7 +829,6 @@ module ibc::ibc { /// by the light client (`client_id`). /// * `proof_height`: The height at when `proof_try` was generated. public fun channel_open_ack( - client_type: String, port_id: address, channel_id: u32, counterparty_version: String, @@ -850,6 +862,8 @@ module ibc::ibc { counterparty_version ); + let client_type = client_id_to_type(client_id); + let err = verify_channel_state( client_type, @@ -892,7 +906,6 @@ module ibc::ibc { /// by the light client (`client_id`). /// * `proof_height`: The height at when `proof_ack` was generated. public fun channel_open_confirm( - client_type: String, port_id: address, channel_id: u32, proof_ack: vector, @@ -923,6 +936,8 @@ module ibc::ibc { *channel::version(&chan) ); + let client_type = client_id_to_type(client_id); + let err = verify_channel_state( client_type, @@ -1058,7 +1073,6 @@ module ibc::ibc { } public(friend) fun timeout_packet( - client_type: String, port_id: address, packet_source_channel: u32, packet_destination_channel: u32, @@ -1085,6 +1099,7 @@ module ibc::ibc { let destination_channel = packet::destination_channel(&packet); let channel = ensure_channel_state(source_channel); let client_id = ensure_connection_state(channel::connection_id(&channel)); + let client_type = client_id_to_type(client_id); let proof_timestamp = light_client::get_timestamp_at_height(client_type, client_id, proof_height); @@ -1158,6 +1173,12 @@ module ibc::ibc { // ========= UTILS and VIEW functions ========= // + #[view] + public fun client_id_to_type(client_id: u32): String acquires IBCStore { + let store = borrow_global(get_vault_addr()); + *smart_table::borrow(&store.client_id_to_type, client_id) + } + #[view] public fun get_module(channel_id: u32): address acquires IBCStore { let store = borrow_global(get_vault_addr()); @@ -1348,13 +1369,13 @@ module ibc::ibc { } public fun verify_commitment( - client_type: String, client_id: u32, height: u64, proof: vector, path: vector, commitment: vector - ): u64 { + ): u64 acquires IBCStore { + let client_type = client_id_to_type(client_id); light_client::verify_membership( client_type, client_id, @@ -1490,12 +1511,12 @@ module ibc::ibc { fun verify_absent_commitment( client_type: String, - clientId: u32, + client_id: u32, height: u64, proof: vector, path: vector ): u64 { - light_client::verify_non_membership(client_type, clientId, height, proof, path) + light_client::verify_non_membership(client_type, client_id, height, proof, path) } fun address_to_string(addr: address): String { diff --git a/move/move-ibc/sources/ibc_commitment.move b/move/move-ibc/sources/ibc_commitment.move index dab1ff2b1b..bd77ef5462 100644 --- a/move/move-ibc/sources/ibc_commitment.move +++ b/move/move-ibc/sources/ibc_commitment.move @@ -179,13 +179,13 @@ module ibc::commitment { } public fun client_state_commitment_key(channel_id: u32): vector { - client_state_path(channel_id) + keccak256(client_state_path(channel_id)) } public fun consensus_state_commitment_key( channel_id: u32, height: u64 ): vector { - consensus_state_path(channel_id, height) + keccak256(consensus_state_path(channel_id, height)) } public fun connection_commitment_key(channel_id: u32): vector { diff --git a/move/move-ibc/sources/ics23.move b/move/move-ibc/sources/ics23.move index 5a32f75155..574d948dc8 100644 --- a/move/move-ibc/sources/ics23.move +++ b/move/move-ibc/sources/ics23.move @@ -308,4 +308,14 @@ module ibc::ics23 { // ) // ); // } + + #[test] + fun test_decode() { + let mem_proof = + decode_membership_proof( + x"4103f64b1e5af826603673cac212ceedb720fb845c66aa7ce71ca304905ad66b6e518f45ebee8d9b85345cea31097b92cbe2ad1bdf6f28edb6d678edc90beb33a45f20c157348fc7d075310f7d6c66f776051837111fda874a1dd3028d1194bc0b84d0060002b691e7020c070204b691e7022021202e60f5d93b1af14ad194d1d178ef53a7c52a101f441d23be54545ec1d96c011b280408b691e702202474ff5887b23d801a16c134c792f21ff3ce9251de3bd3c7a625b76fe3a9b6582000070610b691e702202120464094ac3afa7acaf1b44f50c789b7317cb2562054e1825833d206e68be2dce8070816b691e7022021207a543411b7ab4cdc2c61d08600d81e0b6847b7f9e3af92458b970ce1b0d11098070a2eb691e702202120b6c279988f0719237378323464860c08b562866b18c9d6867fdf727061aa3f01070e66b691e702202120a060f1df88ed45d0933ff584fb79db0118a81695d4a1f221b07965c209479ec22910d401b691e70220b3c357c7c3f497292320aa40d8fdfea78a04c7014b3ecaa401d06a78e280a04820000812d203b691e7022021202f751293c3774c7b9851a9659b59814a10accecd2466c319ea80ad894c62dcd229148006b691e7022065b3fe92c7d5951d8d020fce65f3d752fe654e1b718989ee7ea2f5dc130165e6200029168e0cb691e70220919a75b56ea1cd4ade3fa2a5abf5f532d1a60a7373426e65f1d99403bc97dd6c2000081aaa1ab691e7022021205eb5a5643abe553a8d412f00434bbd2a478f8b09ce6e34598ad81a258522b999291cb63bb691e70220cebfbcee54dc4bc8e5c9f92883f68fd9f61aaa598053d10acdcf011e6b5043e82000047761736d20c72e21ec48b1a939c2e222550a28351efc670e599748959ad2c048c23bcf8d2d01000221012d4d7964d98298ac3383588a55b5464f8633ef52c99a2e6b35ccf97228db77a3002101e30f8d11d327eee46be8cd501e84c9a96e9b35baccd92a81999fdf5915a1dd4200" + ); + std::debug::print(&vector::is_empty(&mem_proof.sub_proof.leaf_prefix)); + std::debug::print(&vector::is_empty(&mem_proof.top_level_proof.leaf_prefix)); + } } diff --git a/move/move-ibc/sources/mpt_verifier.move b/move/move-ibc/sources/mpt_verifier.move index 96aec08a74..391e37a7bd 100644 --- a/move/move-ibc/sources/mpt_verifier.move +++ b/move/move-ibc/sources/mpt_verifier.move @@ -1,7 +1,6 @@ module ibc::mpt_verifier { use aptos_std::vector; - use std::string; use std::bcs; use aptos_std::aptos_hash::keccak256; @@ -533,9 +532,9 @@ module ibc::mpt_verifier { let key = keccak256(slot); let (is_exists, value) = verify_trie_value(&proofChain, &key, storage_root); - std::debug::print(&string::utf8(b"is_exists:")); + std::debug::print(&std::string::utf8(b"is_exists:")); std::debug::print(&is_exists); - std::debug::print(&string::utf8(b"value:")); + std::debug::print(&std::string::utf8(b"value:")); std::debug::print(&value); assert!(!is_exists, 1001); } @@ -572,9 +571,9 @@ module ibc::mpt_verifier { let key = keccak256(slot); let (is_exists, value) = verify_trie_value(&proofChain, &key, storage_root); - std::debug::print(&string::utf8(b"is_exists:")); + std::debug::print(&std::string::utf8(b"is_exists:")); std::debug::print(&is_exists); - std::debug::print(&string::utf8(b"value:")); + std::debug::print(&std::string::utf8(b"value:")); std::debug::print(&value); assert!(is_exists, 1001); assert!(value == x"01", 1002); @@ -605,9 +604,9 @@ module ibc::mpt_verifier { let key = keccak256(keccak256(slot)); let (is_exists, value) = verify_trie_value(&proofChain, &key, storage_root); - std::debug::print(&string::utf8(b"is_exists:")); + std::debug::print(&std::string::utf8(b"is_exists:")); std::debug::print(&is_exists); - std::debug::print(&string::utf8(b"value:")); + std::debug::print(&std::string::utf8(b"value:")); std::debug::print(&value); assert!(is_exists, 1001); assert!(value == expected_valude, 1002); @@ -685,7 +684,7 @@ module ibc::mpt_verifier { let buf: vector = x"f90211a0b51ceda38c7c0d96cee1d651d8c9001299aae0a56dd4778366faccf8c89802f0a011e1adf2007c6afdc9300271c03ad104cf9ed625a3cca7050416449175f7ef21a0e4187606d7baba63b37fd6978f264374e8d7289da084c4a56170ce1e438ff0f0a061869b1b76c51cc75983fc4792b3fc9c1c5e366a76149979920143afd2899770a0ae2ffd634be69d00ca955e55ad4bb4c1065d40938f82f56d678a87180087d2aba0dcfab65101c9968d7891a91ffc1d6c8bcda2773458d802feca923a7d938f7695a0c62fdc1d9731b77b5310a9a9e1bc9edb79976637f6f29c13ce49459ef7cdb7d5a0fce12c4968e940f0f7dbe888d359b81425bde60f261761608465fd74fa390828a04f77e522f007df2b5c6090006e531d113647900ef01ce8ddad6b6b908e786ce9a04beb43119c19f9f2b94738830b8ca07ce2cb40a2fc60e51567810deda9719527a05085bfa24339e17ba1305a8d7c93468ab8414fde3b1b0ce77ea3f196e16217eaa0071e1a46d2a544b7cc24d3153619887ab88606501aea6f30f03e084dab9da01aa0a27d98ca7583cd6f303c41747e5109978c3399cb632283a9a6d5300366bfc97ca0c38268688069ddd9ec101532ea6f0253025f9df93c6d5e916968221232f8da00a0654ec1fadfb6c2d7849b96c26a1373e111cc6fd30c408ee833e0e2a89c4828f7a04a1eba1371dffabf57cd6f2a1774d2d464968546390a9f4dd78a76444cfce53580"; let result = parse_nodes(&buf); - std::debug::print(&string::utf8(b"result: ")); + std::debug::print(&std::string::utf8(b"result: ")); std::debug::print(&result); } diff --git a/move/move-ibc/sources/recv_packet.move b/move/move-ibc/sources/recv_packet.move index 90d8146892..ca14aaee41 100644 --- a/move/move-ibc/sources/recv_packet.move +++ b/move/move-ibc/sources/recv_packet.move @@ -1,6 +1,5 @@ module ibc::recv_packet { use ibc::packet::{Self, Packet}; - use std::string::{String}; use ibc::channel; use ibc::engine; use ibc::commitment; @@ -19,7 +18,6 @@ module ibc::recv_packet { /// Note that any sanity check failures will result in this function to be aborted in order for caller's /// storage to be reverted. This will result in acks won't be able to written. public entry fun recv_packet( - client_type: String, port_id: address, packet_source_channels: vector, packet_destination_channels: vector, @@ -48,17 +46,10 @@ module ibc::recv_packet { i = i + 1; }; - process_receive( - client_type, - packets, - proof_height, - proof, - false - ); + process_receive(packets, proof_height, proof, false); } public fun process_receive( - client_type: String, packets: vector, proof_height: u64, proof: vector, @@ -92,7 +83,6 @@ module ibc::recv_packet { let err = ibc::verify_commitment( - client_type, client_id, proof_height, proof, diff --git a/move/move-ibc/sources/state_lens_lc.move b/move/move-ibc/sources/state_lens_lc.move index 5bb39196f8..df01713c58 100644 --- a/move/move-ibc/sources/state_lens_lc.move +++ b/move/move-ibc/sources/state_lens_lc.move @@ -8,7 +8,6 @@ module ibc::statelens_lc { use aptos_std::bcs; use aptos_std::object; - use ibc::ics23; use ibc::height::{Self, Height}; use ibc::ethabi; use ibc::bcs_utils; @@ -129,11 +128,11 @@ module ibc::statelens_lc { cometbls_lc::verify_membership( state.client_state.l1_client_id, height::get_revision_height(&header.l1_height), - commitment::consensus_state_path( + header.l2_consensus_state_proof, + commitment::consensus_state_commitment_key( state.client_state.l2_client_id, height::get_revision_height(&header.l2_height) ), - header.l2_consensus_state_proof, keccak256(header.l2_consensus_state) ) == 0, E_L2_CONSENSUS_STATE_PROOF_VERIFICATION @@ -210,12 +209,15 @@ module ibc::statelens_lc { 0 } - public fun get_client_state(_client_id: u32): vector { - vector::empty() + public fun get_client_state(client_id: u32): vector acquires State { + let state = borrow_global(get_client_address(client_id)); + bcs::to_bytes(&state.client_state) } - public fun get_consensus_state(_client_id: u32, _height: u64): vector { - vector::empty() + public fun get_consensus_state(client_id: u32, height: u64): vector acquires State { + let state = borrow_global(get_client_address(client_id)); + let consensus_state = smart_table::borrow(&state.consensus_states, height); + encode_consensus_state(consensus_state) } public fun check_for_misbehaviour( @@ -247,11 +249,10 @@ module ibc::statelens_lc { } fun decode_consensus_state(buf: vector): ConsensusState { - let buf = bcs_utils::new(buf); - - let timestamp = bcs_utils::peel_u64(&mut buf); - let state_root = bcs_utils::peel_fixed_bytes(&mut buf, 32); - let storage_root = bcs_utils::peel_fixed_bytes(&mut buf, 32); + let index = 0; + let timestamp = (ethabi::decode_uint(&buf, &mut index) as u64); + let state_root = vector::slice(&buf, 32, 64); + let storage_root = vector::slice(&buf, 64, 96); ConsensusState { timestamp, state_root, storage_root } } @@ -293,4 +294,15 @@ module ibc::statelens_lc { object::create_object_address(&vault_addr, bcs::to_bytes(&client_id)) } + + #[test] + fun decode_test() { + let client_state = x"0531373030300100000013000000e898300000000000000020004000"; + let client_state = decode_client_state(client_state); + let consensus_state = + x"000000000000000000000000000000000000000000000000181c75935aab8000f5c411575dae56d013ca1b7626896a9e96b457c14043091768d3d021fd5ebf333a42f6ef5bdc9ebe38b19ba1b8578f6e20e2a552bba787951c185159c721a165"; + let consensus_state = decode_consensus_state(consensus_state); + std::debug::print(&client_state); + std::debug::print(&consensus_state); + } } diff --git a/move/move-ibc/sources/timeout_packet.move b/move/move-ibc/sources/timeout_packet.move index a702c12f00..ac82e3371a 100644 --- a/move/move-ibc/sources/timeout_packet.move +++ b/move/move-ibc/sources/timeout_packet.move @@ -4,10 +4,8 @@ module ibc::timeout_packet { use ibc::dispatcher; use ibc::helpers; use ibc::ibc; - use std::string::{String}; public entry fun timeout_packet( - client_type: String, port_id: address, packet_source_channel: u32, packet_destination_channel: u32, @@ -20,7 +18,6 @@ module ibc::timeout_packet { ) { let packet = ibc::timeout_packet( - client_type, port_id, packet_source_channel, packet_destination_channel, From cc624a93de5013da5687befc98a5438a5cc742c8 Mon Sep 17 00:00:00 2001 From: aeryz Date: Wed, 22 Jan 2025 09:12:31 +0300 Subject: [PATCH 06/15] chore: add migrate entrypoints to cw contracts Signed-off-by: aeryz --- .../ibc-union/light-clients/berachain/Cargo.toml | 1 + .../light-clients/berachain/src/contract.rs | 12 ++++++++++++ .../ibc-union/light-clients/movement/src/contract.rs | 12 ++++++++++++ 3 files changed, 25 insertions(+) diff --git a/cosmwasm/ibc-union/light-clients/berachain/Cargo.toml b/cosmwasm/ibc-union/light-clients/berachain/Cargo.toml index f2d2eed812..4f5d9ad25a 100644 --- a/cosmwasm/ibc-union/light-clients/berachain/Cargo.toml +++ b/cosmwasm/ibc-union/light-clients/berachain/Cargo.toml @@ -19,6 +19,7 @@ crate-type = ["cdylib", "rlib"] beacon-api-types = { workspace = true, features = ["ssz"] } cosmwasm-std = { workspace = true, features = ["abort", "cosmwasm_2_1"] } ethereum-light-client = { workspace = true, features = ["library"] } +serde = { workspace = true, features = ["derive"] } thiserror = { workspace = true } berachain-light-client-types = { workspace = true, features = ["serde", "ethabi", "bincode"] } diff --git a/cosmwasm/ibc-union/light-clients/berachain/src/contract.rs b/cosmwasm/ibc-union/light-clients/berachain/src/contract.rs index 45da400982..375cdcc89c 100644 --- a/cosmwasm/ibc-union/light-clients/berachain/src/contract.rs +++ b/cosmwasm/ibc-union/light-clients/berachain/src/contract.rs @@ -20,3 +20,15 @@ pub fn instantiate( pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { ibc_union_light_client::query::(deps, env, msg).map_err(Into::into) } + +#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] +pub struct MigrateMsg {} + +#[entry_point] +pub fn migrate( + _deps: DepsMut, + _env: Env, + _msg: MigrateMsg, +) -> Result> { + Ok(Response::new()) +} diff --git a/cosmwasm/ibc-union/light-clients/movement/src/contract.rs b/cosmwasm/ibc-union/light-clients/movement/src/contract.rs index 35c97caa7b..4ad86c0fec 100644 --- a/cosmwasm/ibc-union/light-clients/movement/src/contract.rs +++ b/cosmwasm/ibc-union/light-clients/movement/src/contract.rs @@ -20,3 +20,15 @@ pub fn instantiate( pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { ibc_union_light_client::query::(deps, env, msg).map_err(Into::into) } + +#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] +pub struct MigrateMsg {} + +#[entry_point] +pub fn migrate( + _deps: DepsMut, + _env: Env, + _msg: MigrateMsg, +) -> Result> { + Ok(Response::new()) +} From 590f0fbeda5fb035fb83b5639f5083f572d7af43 Mon Sep 17 00:00:00 2001 From: aeryz Date: Wed, 22 Jan 2025 09:14:00 +0300 Subject: [PATCH 07/15] chore(evm): fix encoding and add ics23smt to deployments --- .../clients/StateLensIcs23MptClient.sol | 16 +- ...Client.sol => StateLensIcs23SmtClient.sol} | 60 ++--- evm/evm.nix | 22 ++ evm/scripts/Deploy.s.sol | 176 ++++++++++++++ ...nt.t.sol => StateLensIcs23SmtClient.t.sol} | 221 +++++++----------- 5 files changed, 334 insertions(+), 161 deletions(-) rename evm/contracts/clients/{StateLensIcs23MoveClient.sol => StateLensIcs23SmtClient.sol} (85%) rename evm/tests/src/02-client/{StateLensIcs23MoveClient.t.sol => StateLensIcs23SmtClient.t.sol} (61%) diff --git a/evm/contracts/clients/StateLensIcs23MptClient.sol b/evm/contracts/clients/StateLensIcs23MptClient.sol index 42922a2453..b47adfba0e 100644 --- a/evm/contracts/clients/StateLensIcs23MptClient.sol +++ b/evm/contracts/clients/StateLensIcs23MptClient.sol @@ -52,13 +52,25 @@ library StateLensIcs23MptLib { function encode( ConsensusState memory consensusState ) internal pure returns (bytes memory) { - return abi.encode(consensusState); + return abi.encode( + consensusState.timestamp, + consensusState.stateRoot, + consensusState.storageRoot + ); } function encode( ClientState memory clientState ) internal pure returns (bytes memory) { - return abi.encode(clientState); + return abi.encode( + clientState.l2ChainId, + clientState.l1ClientId, + clientState.l2ClientId, + clientState.l2LatestHeight, + clientState.timestampOffset, + clientState.stateRootOffset, + clientState.storageRootOffset + ); } function commit( diff --git a/evm/contracts/clients/StateLensIcs23MoveClient.sol b/evm/contracts/clients/StateLensIcs23SmtClient.sol similarity index 85% rename from evm/contracts/clients/StateLensIcs23MoveClient.sol rename to evm/contracts/clients/StateLensIcs23SmtClient.sol index 501cef6f7a..7e67be6b12 100644 --- a/evm/contracts/clients/StateLensIcs23MoveClient.sol +++ b/evm/contracts/clients/StateLensIcs23SmtClient.sol @@ -32,7 +32,7 @@ struct ConsensusState { bytes32 stateRoot; } -library StateLensIcs23MoveLib { +library StateLensIcs23SmtLib { uint256 public constant EVM_IBC_COMMITMENT_SLOT = 0; event CreateLensClient( @@ -48,14 +48,21 @@ library StateLensIcs23MoveLib { function encode( ConsensusState memory consensusState - ) internal pure returns (bytes memory) { - return abi.encode(consensusState); + ) public pure returns (bytes memory) { + return abi.encode(consensusState.timestamp, consensusState.stateRoot); } function encode( ClientState memory clientState - ) internal pure returns (bytes memory) { - return abi.encode(clientState); + ) public pure returns (bytes memory) { + return abi.encode( + clientState.l2ChainId, + clientState.l1ClientId, + clientState.l2ClientId, + clientState.l2LatestHeight, + clientState.timestampOffset, + clientState.stateRootOffset + ); } function commit( @@ -91,14 +98,14 @@ library StateLensIcs23MoveLib { } } -contract StateLensIcs23MoveClient is +contract StateLensIcs23SmtClient is ILightClient, Initializable, UUPSUpgradeable, OwnableUpgradeable, PausableUpgradeable { - using StateLensIcs23MoveLib for *; + using StateLensIcs23SmtLib for *; address private ibcHandler; @@ -130,26 +137,22 @@ contract StateLensIcs23MoveClient is string memory counterpartyChainId ) { - // ClientState calldata clientState; - // assembly { - // clientState := clientStateBytes.offset - // } - // ConsensusState calldata consensusState; - // assembly { - // consensusState := consensusStateBytes.offset - // } - ClientState memory clientState = - abi.decode(clientStateBytes, (ClientState)); - ConsensusState memory consensusState = - abi.decode(consensusStateBytes, (ConsensusState)); + ClientState calldata clientState; + assembly { + clientState := clientStateBytes.offset + } + ConsensusState calldata consensusState; + assembly { + consensusState := consensusStateBytes.offset + } if (clientState.l2LatestHeight == 0 || consensusState.timestamp == 0) { - revert StateLensIcs23MoveLib.ErrInvalidInitialConsensusState(); + revert StateLensIcs23SmtLib.ErrInvalidInitialConsensusState(); } clientStates[clientId] = clientState; consensusStates[clientId][clientState.l2LatestHeight] = consensusState; - emit StateLensIcs23MoveLib.CreateLensClient( + emit StateLensIcs23SmtLib.CreateLensClient( clientId, clientState.l1ClientId, clientState.l2ClientId, @@ -174,7 +177,10 @@ contract StateLensIcs23MoveClient is uint32 clientId, bytes calldata clientMessageBytes ) external override onlyIBC returns (ConsensusStateUpdate memory) { - Header memory header = abi.decode(clientMessageBytes, (Header)); + Header calldata header; + assembly { + header := clientMessageBytes.offset + } ClientState storage clientState = clientStates[clientId]; ILightClient l1Client = @@ -193,18 +199,18 @@ contract StateLensIcs23MoveClient is abi.encodePacked(keccak256(header.l2ConsensusState)) ) ) { - revert StateLensIcs23MoveLib.ErrInvalidL1Proof(); + revert StateLensIcs23SmtLib.ErrInvalidL1Proof(); } bytes memory rawL2ConsensusState = header.l2ConsensusState; uint64 l2Timestamp = uint64( uint256( - StateLensIcs23MoveLib.extractMemory( + StateLensIcs23SmtLib.extractMemory( rawL2ConsensusState, clientState.timestampOffset ) ) ); - bytes32 l2StateRoot = StateLensIcs23MoveLib.extractMemory( + bytes32 l2StateRoot = StateLensIcs23SmtLib.extractMemory( rawL2ConsensusState, clientState.stateRootOffset ); @@ -231,7 +237,7 @@ contract StateLensIcs23MoveClient is uint32 clientId, bytes calldata clientMessageBytes ) external override onlyIBC { - revert StateLensIcs23MoveLib.ErrUnsupported(); + revert StateLensIcs23SmtLib.ErrUnsupported(); } function verifyMembership( @@ -300,7 +306,7 @@ contract StateLensIcs23MoveClient is function _onlyIBC() internal view { if (msg.sender != ibcHandler) { - revert StateLensIcs23MoveLib.ErrNotIBC(); + revert StateLensIcs23SmtLib.ErrNotIBC(); } } diff --git a/evm/evm.nix b/evm/evm.nix index 949724b595..c62faaad57 100644 --- a/evm/evm.nix +++ b/evm/evm.nix @@ -605,6 +605,10 @@ _: { jq --compact-output --slurp 'map(.abi) | add' \ ${contracts}/out/StateLensIcs23Ics23Client.sol/StateLensIcs23Ics23Client.json \ ${contracts}/out/StateLensIcs23Ics23Client.sol/StateLensIcs23Ics23Lib.json > state-lens-ics23-ics23-client.json + + jq --compact-output --slurp 'map(.abi) | add' \ + ${contracts}/out/StateLensIcs23SmtClient.sol/StateLensIcs23SmtClient.json \ + ${contracts}/out/StateLensIcs23SmtClient.sol/StateLensIcs23SmtLib.json > state-lens-ics23-smt-client.json '' ); @@ -713,6 +717,12 @@ _: { value = eth-deploy-single ({ kind = "StateLensIcs23Ics23Client"; } // args); }) networks ) + // builtins.listToAttrs ( + builtins.map (args: { + name = "eth-deploy-${args.network}-state-lens-ics23-smt-client"; + value = eth-deploy-single ({ kind = "StateLensIcs23SmtClient"; } // args); + }) networks + ) // builtins.listToAttrs ( builtins.map (args: { name = "eth-deploy-${args.network}-ucs03"; @@ -785,6 +795,18 @@ _: { ); }) networks ) + // builtins.listToAttrs ( + builtins.map (args: { + name = "eth-upgrade-${args.network}-state-lens-ics23-smt-client"; + value = eth-upgrade ( + { + dry = false; + protocol = "StateLensIcs23SmtClient"; + } + // args + ); + }) networks + ) // builtins.listToAttrs ( builtins.map (args: { name = "eth-dryupgrade-${args.network}-ibc"; diff --git a/evm/scripts/Deploy.s.sol b/evm/scripts/Deploy.s.sol index 58bbd6e1f1..5a6ccda390 100644 --- a/evm/scripts/Deploy.s.sol +++ b/evm/scripts/Deploy.s.sol @@ -18,6 +18,8 @@ import {StateLensIcs23Ics23Client} from "../contracts/clients/StateLensIcs23Ics23Client.sol"; import {StateLensIcs23MptClient} from "../contracts/clients/StateLensIcs23MptClient.sol"; +import {StateLensIcs23SmtClient} from + "../contracts/clients/StateLensIcs23SmtClient.sol"; import "../contracts/apps/ucs/00-pingpong/PingPong.sol"; import "../contracts/apps/ucs/01-relay/Relay.sol"; import "../contracts/apps/ucs/02-nft/NFT.sol"; @@ -46,6 +48,7 @@ library LightClients { string constant COMETBLS = "cometbls"; string constant STATE_LENS_ICS23_MPT = "state-lens/ics23/mpt"; string constant STATE_LENS_ICS23_ICS23 = "state-lens/ics23/ics23"; + string constant STATE_LENS_ICS23_SMT = "state-lens/ics23/smt"; function make( string memory lightClient @@ -146,6 +149,24 @@ abstract contract UnionScript is UnionBase { ); } + function deployStateLensIcs23SmtClient( + IBCHandler handler, + address owner + ) internal returns (StateLensIcs23SmtClient) { + return StateLensIcs23SmtClient( + deploy( + LightClients.make(LightClients.STATE_LENS_ICS23_SMT), + abi.encode( + address(new StateLensIcs23SmtClient()), + abi.encodeCall( + StateLensIcs23SmtClient.initialize, + (address(handler), owner) + ) + ) + ) + ); + } + function deployCometbls( IBCHandler handler, address owner @@ -235,6 +256,7 @@ abstract contract UnionScript is UnionBase { CometblsClient, StateLensIcs23MptClient, StateLensIcs23Ics23Client, + StateLensIcs23SmtClient, PingPong, UCS01Relay, UCS02NFT, @@ -247,6 +269,8 @@ abstract contract UnionScript is UnionBase { deployStateLensIcs23MptClient(handler, owner); StateLensIcs23Ics23Client stateLensIcs23Ics23Client = deployStateLensIcs23Ics23Client(handler, owner); + StateLensIcs23SmtClient stateLensIcs23SmtClient = + deployStateLensIcs23SmtClient(handler, owner); PingPong pingpong = deployUCS00(handler, owner, 100000000000000); UCS01Relay relay = deployUCS01(handler, owner); UCS02NFT nft = deployUCS02(handler, owner); @@ -256,6 +280,7 @@ abstract contract UnionScript is UnionBase { cometblsClient, stateLensIcs23MptClient, stateLensIcs23Ics23Client, + stateLensIcs23SmtClient, pingpong, relay, nft, @@ -425,6 +450,76 @@ contract DeployStateLensIcs23Ics23Client is UnionScript { } } +contract DeployStateLensIcs23SmtClient is UnionScript { + using LibString for *; + + address immutable deployer; + address immutable sender; + + constructor() { + deployer = vm.envAddress("DEPLOYER"); + sender = vm.envAddress("SENDER"); + } + + function getDeployer() internal view override returns (Deployer) { + return Deployer(deployer); + } + + function getDeployed( + string memory salt + ) internal view returns (address) { + return CREATE3.predictDeterministicAddress( + keccak256(abi.encodePacked(sender.toHexString(), "/", salt)), + deployer + ); + } + + function run() public { + uint256 privateKey = vm.envUint("PRIVATE_KEY"); + + address owner = vm.addr(privateKey); + + address handler = getDeployed(IBC.BASED); + + vm.startBroadcast(privateKey); + + StateLensIcs23SmtClient stateLensIcs23SmtClient = + deployStateLensIcs23SmtClient(IBCHandler(handler), owner); + + vm.stopBroadcast(); + + console.log( + "StateLensIcs23SmtClient: ", address(stateLensIcs23SmtClient) + ); + } +} + +contract RegisterIcs23SmtClient is Script { + using LibString for *; + + address immutable handler; + address immutable client; + + constructor() { + handler = vm.envAddress("IBC_HANDLER"); + client = vm.envAddress("CLIENT"); + } + + function run() public { + uint256 privateKey = vm.envUint("PRIVATE_KEY"); + + address owner = vm.addr(privateKey); + + vm.startBroadcast(privateKey); + + IBCHandler(handler).registerClient( + LightClients.STATE_LENS_ICS23_SMT, StateLensIcs23SmtClient(client) + ); + + vm.stopBroadcast(); + } +} + contract DeployIBC is UnionScript { Deployer immutable deployer; @@ -445,6 +540,7 @@ contract DeployIBC is UnionScript { CometblsClient cometblsClient, StateLensIcs23MptClient stateLensIcs23MptClient, StateLensIcs23Ics23Client stateLensIcs23Ics23Client, + StateLensIcs23SmtClient stateLensIcs23SmtClient, PingPong pingpong, UCS01Relay relay, UCS02NFT nft, @@ -457,6 +553,9 @@ contract DeployIBC is UnionScript { handler.registerClient( LightClients.STATE_LENS_ICS23_ICS23, stateLensIcs23Ics23Client ); + handler.registerClient( + LightClients.STATE_LENS_ICS23_SMT, stateLensIcs23SmtClient + ); vm.stopBroadcast(); @@ -470,6 +569,9 @@ contract DeployIBC is UnionScript { console.log( "StateLensIcs23Ics23Client: ", address(stateLensIcs23Ics23Client) ); + console.log( + "StateLensIcs23SmtClient: ", address(stateLensIcs23SmtClient) + ); console.log("UCS00: ", address(pingpong)); console.log("UCS01: ", address(relay)); console.log("UCS02: ", address(nft)); @@ -496,6 +598,7 @@ contract DeployDeployerAndIBC is UnionScript { CometblsClient cometblsClient, StateLensIcs23MptClient stateLensIcs23MptClient, StateLensIcs23Ics23Client stateLensIcs23Ics23Client, + StateLensIcs23SmtClient stateLensIcs23SmtClient, PingPong pingpong, UCS01Relay relay, UCS02NFT nft, @@ -508,6 +611,9 @@ contract DeployDeployerAndIBC is UnionScript { handler.registerClient( LightClients.STATE_LENS_ICS23_ICS23, stateLensIcs23Ics23Client ); + handler.registerClient( + LightClients.STATE_LENS_ICS23_SMT, stateLensIcs23SmtClient + ); vm.stopBroadcast(); @@ -521,6 +627,9 @@ contract DeployDeployerAndIBC is UnionScript { console.log( "StateLensIcs23Ics23Client: ", address(stateLensIcs23Ics23Client) ); + console.log( + "StateLensIcs23SmtClient: ", address(stateLensIcs23SmtClient) + ); console.log("UCS00: ", address(pingpong)); console.log("UCS01: ", address(relay)); console.log("UCS02: ", address(nft)); @@ -565,6 +674,8 @@ contract GetDeployed is Script { getDeployed(LightClients.make(LightClients.STATE_LENS_ICS23_MPT)); address stateLensIcs23Ics23Client = getDeployed(LightClients.make(LightClients.STATE_LENS_ICS23_ICS23)); + address stateLensIcs23SmtClient = + getDeployed(LightClients.make(LightClients.STATE_LENS_ICS23_SMT)); address ucs00 = getDeployed(Protocols.make(Protocols.UCS00)); address ucs01 = getDeployed(Protocols.make(Protocols.UCS01)); address ucs02 = getDeployed(Protocols.make(Protocols.UCS02)); @@ -599,6 +710,14 @@ contract GetDeployed is Script { ) ) ); + console.log( + string( + abi.encodePacked( + "StateLensIcs23SmtClient: ", + stateLensIcs23SmtClient.toHexString() + ) + ) + ); console.log(string(abi.encodePacked("UCS00: ", ucs00.toHexString()))); console.log(string(abi.encodePacked("UCS01: ", ucs01.toHexString()))); console.log(string(abi.encodePacked("UCS02: ", ucs02.toHexString()))); @@ -784,6 +903,21 @@ contract GetDeployed is Script { implStateLensIcs23Ics23Client ); + string memory implStateLensIcs23SmtClient = + "implStateLensIcs23SmtClient"; + implStateLensIcs23SmtClient.serialize( + "contract", + string( + "contracts/clients/StateLensIcs23SmtClient.sol:StateLensIcs23SmtClient" + ) + ); + implStateLensIcs23SmtClient = + implStateLensIcs23SmtClient.serialize("args", bytes(hex"")); + impls.serialize( + implOf(stateLensIcs23SmtClient).toHexString(), + implStateLensIcs23SmtClient + ); + string memory implUCS00 = "implUCS00"; implUCS00.serialize( "contract", @@ -1182,3 +1316,45 @@ contract UpgradeStateLensIcs23Ics23Client is Script { vm.stopBroadcast(); } } + +contract UpgradeStateLensIcs23SmtClient is Script { + using LibString for *; + + address immutable deployer; + address immutable sender; + uint256 immutable privateKey; + + constructor() { + deployer = vm.envAddress("DEPLOYER"); + sender = vm.envAddress("SENDER"); + privateKey = vm.envUint("PRIVATE_KEY"); + } + + function getDeployed( + string memory salt + ) internal view returns (address) { + return CREATE3.predictDeterministicAddress( + keccak256(abi.encodePacked(sender.toHexString(), "/", salt)), + deployer + ); + } + + function run() public { + address stateLensIcs23SmtClient = + getDeployed(LightClients.make(LightClients.STATE_LENS_ICS23_SMT)); + console.log( + string( + abi.encodePacked( + "StateLensIcs23SmtClient: ", + stateLensIcs23SmtClient.toHexString() + ) + ) + ); + vm.startBroadcast(privateKey); + address newImplementation = address(new StateLensIcs23SmtClient()); + StateLensIcs23SmtClient(stateLensIcs23SmtClient).upgradeToAndCall( + newImplementation, new bytes(0) + ); + vm.stopBroadcast(); + } +} diff --git a/evm/tests/src/02-client/StateLensIcs23MoveClient.t.sol b/evm/tests/src/02-client/StateLensIcs23SmtClient.t.sol similarity index 61% rename from evm/tests/src/02-client/StateLensIcs23MoveClient.t.sol rename to evm/tests/src/02-client/StateLensIcs23SmtClient.t.sol index 763efecfa5..9923ffba79 100644 --- a/evm/tests/src/02-client/StateLensIcs23MoveClient.t.sol +++ b/evm/tests/src/02-client/StateLensIcs23SmtClient.t.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.27; import "forge-std/Test.sol"; -import "../../../contracts/clients/StateLensIcs23MoveClient.sol"; +import "../../../contracts/clients/StateLensIcs23SmtClient.sol"; import "@openzeppelin/proxy/ERC1967/ERC1967Proxy.sol"; /*////////////////////////////////////////////////////////////// @@ -146,8 +146,8 @@ contract MockIBCStore { TEST CONTRACT //////////////////////////////////////////////////////////////*/ -contract StateLensIcs23MoveClientTest is Test { - StateLensIcs23MoveClient client; +contract StateLensIcs23SmtClientTest is Test { + StateLensIcs23SmtClient client; MockIBCStore ibcStore; MockLightClient lightClient; address ibcHandler; @@ -158,16 +158,16 @@ contract StateLensIcs23MoveClientTest is Test { ibcHandler = address(ibcStore); // Deploy the implementation - StateLensIcs23MoveClient implementation = new StateLensIcs23MoveClient(); + StateLensIcs23SmtClient implementation = new StateLensIcs23SmtClient(); // Deploy proxy ERC1967Proxy proxy = new ERC1967Proxy( address(implementation), abi.encodeWithSelector( - StateLensIcs23MoveClient.initialize.selector, ibcHandler, admin + StateLensIcs23SmtClient.initialize.selector, ibcHandler, admin ) ); // Cast proxy -> client - client = StateLensIcs23MoveClient(address(proxy)); + client = StateLensIcs23SmtClient(address(proxy)); // Create our mock L1 client and store it in the mock IBCStore lightClient = new MockLightClient(); @@ -189,13 +189,13 @@ contract StateLensIcs23MoveClientTest is Test { timestampOffset: 0, stateRootOffset: 32 }); - bytes memory clientStateBytes = abi.encode(cState); + bytes memory clientStateBytes = StateLensIcs23SmtLib.encode(cState); ConsensusState memory consState = ConsensusState({ timestamp: 12345, stateRoot: keccak256("fake-root") }); - bytes memory consStateBytes = abi.encode(consState); + bytes memory consStateBytes = StateLensIcs23SmtLib.encode(consState); vm.prank(ibcHandler); @@ -227,39 +227,39 @@ contract StateLensIcs23MoveClientTest is Test { timestampOffset: 0, stateRootOffset: 32 }); - bytes memory cStateBytes = abi.encode(cState); + bytes memory cStateBytes = StateLensIcs23SmtLib.encode(cState); ConsensusState memory consState = ConsensusState({timestamp: 1234, stateRoot: keccak256("x")}); - bytes memory consStateBytes = abi.encode(consState); + bytes memory consStateBytes = StateLensIcs23SmtLib.encode(consState); vm.prank(ibcHandler); vm.expectRevert( abi.encodeWithSelector( - StateLensIcs23MoveLib.ErrInvalidInitialConsensusState.selector + StateLensIcs23SmtLib.ErrInvalidInitialConsensusState.selector ) ); client.createClient(clientId, cStateBytes, consStateBytes); } function test_updateClient_success() public { - { - ClientState memory cState = ClientState({ - l2ChainId: "fake-l2", - l1ClientId: 10, - l2ClientId: 20, - l2LatestHeight: 100, - timestampOffset: 0, - stateRootOffset: 32 - }); - ConsensusState memory cs = ConsensusState({ - timestamp: 9999, - stateRoot: keccak256("old-root") - }); - - vm.prank(ibcHandler); - client.createClient(1, abi.encode(cState), abi.encode(cs)); - } + ClientState memory cState = ClientState({ + l2ChainId: "fake-l2", + l1ClientId: 10, + l2ClientId: 20, + l2LatestHeight: 100, + timestampOffset: 0, + stateRootOffset: 32 + }); + ConsensusState memory cs = + ConsensusState({timestamp: 9999, stateRoot: keccak256("old-root")}); + + vm.startPrank(ibcHandler); + client.createClient( + 1, + StateLensIcs23SmtLib.encode(cState), + StateLensIcs23SmtLib.encode(cs) + ); Header memory header = Header({ l1Height: 500, @@ -269,38 +269,44 @@ contract StateLensIcs23MoveClientTest is Test { uint64(8888), keccak256("new-root"), keccak256("new-storage") ) }); - bytes memory headerBytes = abi.encode(header); + bytes memory headerBytes = abi.encode( + header.l1Height, + header.l2Height, + header.l2InclusionProof, + header.l2ConsensusState + ); lightClient.setVerifyMembershipReturn(true); - vm.prank(ibcHandler); client.updateClient(1, headerBytes); bytes memory stored = client.getConsensusState(1, 101); - ConsensusState memory dec = abi.decode(stored, (ConsensusState)); + ConsensusState memory dec = decodeConsensusState(stored); assertEq(dec.timestamp, 8888, "timestamp mismatch"); assertEq(dec.stateRoot, keccak256("new-root"), "stateRoot mismatch"); + + vm.stopPrank(); } function test_updateClient_revert_invalidProof() public { - { - ClientState memory cState = ClientState({ - l2ChainId: "fake-l2", - l1ClientId: 10, - l2ClientId: 20, - l2LatestHeight: 100, - timestampOffset: 0, - stateRootOffset: 32 - }); - ConsensusState memory cs = ConsensusState({ - timestamp: 9999, - stateRoot: keccak256("old-root") - }); - - vm.prank(ibcHandler); - client.createClient(123, abi.encode(cState), abi.encode(cs)); - } + ClientState memory cState = ClientState({ + l2ChainId: "fake-l2", + l1ClientId: 10, + l2ClientId: 20, + l2LatestHeight: 100, + timestampOffset: 0, + stateRootOffset: 32 + }); + ConsensusState memory cs = + ConsensusState({timestamp: 9999, stateRoot: keccak256("old-root")}); + + vm.startPrank(ibcHandler); + client.createClient( + 123, + StateLensIcs23SmtLib.encode(cState), + StateLensIcs23SmtLib.encode(cs) + ); Header memory header = Header({ l1Height: 500, @@ -310,114 +316,65 @@ contract StateLensIcs23MoveClientTest is Test { uint64(8888), keccak256("new-root"), keccak256("new-storage") ) }); - bytes memory headerBytes = abi.encode(header); + bytes memory headerBytes = abi.encode( + header.l1Height, + header.l2Height, + header.l2InclusionProof, + header.l2ConsensusState + ); lightClient.setVerifyMembershipReturn(false); - vm.prank(ibcHandler); vm.expectRevert( abi.encodeWithSelector( - StateLensIcs23MoveLib.ErrInvalidL1Proof.selector + StateLensIcs23SmtLib.ErrInvalidL1Proof.selector ) ); client.updateClient(123, headerBytes); + vm.stopPrank(); } function test_misbehaviour_reverts() public { vm.prank(ibcHandler); vm.expectRevert( - abi.encodeWithSelector( - StateLensIcs23MoveLib.ErrUnsupported.selector - ) + abi.encodeWithSelector(StateLensIcs23SmtLib.ErrUnsupported.selector) ); client.misbehaviour(1, bytes("")); } function test_isFrozenImpl() public { - { - ClientState memory cState = ClientState({ - l2ChainId: "fake-l2", - l1ClientId: 10, - l2ClientId: 20, - l2LatestHeight: 100, - timestampOffset: 0, - stateRootOffset: 32 - }); - ConsensusState memory cs = ConsensusState({ - timestamp: 9999, - stateRoot: keccak256("old-root") - }); - vm.prank(ibcHandler); - client.createClient(999, abi.encode(cState), abi.encode(cs)); - } + ClientState memory cState = ClientState({ + l2ChainId: "fake-l2", + l1ClientId: 10, + l2ClientId: 20, + l2LatestHeight: 100, + timestampOffset: 0, + stateRootOffset: 32 + }); + ConsensusState memory cs = + ConsensusState({timestamp: 9999, stateRoot: keccak256("old-root")}); + vm.startPrank(ibcHandler); + client.createClient( + 999, + StateLensIcs23SmtLib.encode(cState), + StateLensIcs23SmtLib.encode(cs) + ); lightClient.setIsFrozenReturn(true); - // TODO: verifymembership is returning true automatically, so this test will revert anyway bool frozen = client.isFrozen(999); assertTrue(frozen, "expected client to be frozen"); + vm.stopPrank(); } - function test_verifyMembership_isFrozen() public { - { - ClientState memory cState = ClientState({ - l2ChainId: "fake-l2", - l1ClientId: 10, - l2ClientId: 20, - l2LatestHeight: 100, - timestampOffset: 0, - stateRootOffset: 32 - }); - ConsensusState memory cs = ConsensusState({ - timestamp: 9999, - stateRoot: keccak256("old-root") - }); - vm.prank(ibcHandler); - client.createClient(2, abi.encode(cState), abi.encode(cs)); - } - - lightClient.setIsFrozenReturn(true); - // TODO: verifymembership is returning true automatically, so this test will revert anyway - - // vm.prank(ibcHandler); - // vm.expectRevert( - // abi.encodeWithSelector( - // StateLensIcs23MoveLib.ErrClientFrozen.selector - // ) - // ); - - client.verifyMembership( - 2, 100, bytes("proof"), bytes("path"), bytes("value") - ); - } - - function test_verifyNonMembership_isFrozen() public { - { - ClientState memory cState = ClientState({ - l2ChainId: "fake-l2", - l1ClientId: 10, - l2ClientId: 20, - l2LatestHeight: 100, - timestampOffset: 0, - stateRootOffset: 32 - }); - ConsensusState memory cs = ConsensusState({ - timestamp: 9999, - stateRoot: keccak256("old-root") - }); - vm.prank(ibcHandler); - client.createClient(3, abi.encode(cState), abi.encode(cs)); - } - - lightClient.setIsFrozenReturn(true); - // TODO: verifymembership is returning true automatically, so this test will revert anyway - - // vm.prank(ibcHandler); - // vm.expectRevert( - // abi.encodeWithSelector( - // StateLensIcs23MoveLib.ErrClientFrozen.selector - // ) - // ); - // client.verifyNonMembership(3, 100, bytes("proof"), bytes("path")); + function decodeConsensusState( + bytes memory bz + ) internal pure returns (ConsensusState memory) { + ConsensusState memory consensusState; + (uint64 timestamp, bytes32 stateRoot) = + abi.decode(bz, (uint64, bytes32)); + consensusState.timestamp = timestamp; + consensusState.stateRoot = stateRoot; + return consensusState; } } From 94dca4439337515db0ce7e626bba8d520d8712e7 Mon Sep 17 00:00:00 2001 From: aeryz Date: Wed, 22 Jan 2025 09:17:56 +0300 Subject: [PATCH 08/15] chore(aptos-move): regen types and rename ics23move to ics23smt --- generated/rust/aptos-move-ibc/src/lib.rs | 587 +++++++++++------- .../Cargo.toml | 2 +- .../src/client_state.rs | 4 +- .../src/consensus_state.rs | 0 .../src/lib.rs | 0 5 files changed, 351 insertions(+), 242 deletions(-) rename lib/{state-lens-ics23-move-light-client-types => state-lens-ics23-smt-light-client-types}/Cargo.toml (94%) rename lib/{state-lens-ics23-move-light-client-types => state-lens-ics23-smt-light-client-types}/src/client_state.rs (84%) rename lib/{state-lens-ics23-move-light-client-types => state-lens-ics23-smt-light-client-types}/src/consensus_state.rs (100%) rename lib/{state-lens-ics23-move-light-client-types => state-lens-ics23-smt-light-client-types}/src/lib.rs (100%) diff --git a/generated/rust/aptos-move-ibc/src/lib.rs b/generated/rust/aptos-move-ibc/src/lib.rs index dab411d383..98a80286be 100644 --- a/generated/rust/aptos-move-ibc/src/lib.rs +++ b/generated/rust/aptos-move-ibc/src/lib.rs @@ -8,19 +8,146 @@ clippy::too_many_arguments )] -pub mod recv_packet { +pub mod channel_handshake { pub trait ClientExt { fn client(&self) -> &::move_bindgen::aptos_rest_client::Client; - fn recv_packet( + fn channel_open_ack( + &self, + contract_address: ::move_bindgen::aptos_types::account_address::AccountAddress, + (_0, _1, _2, _3, _4, _5): ( + ::move_bindgen::aptos_types::account_address::AccountAddress, + u32, + String, + u32, + Vec, + u64, + ), + (t0,): (impl Into<::move_bindgen::move_core_types::language_storage::TypeTag>,), + ) -> ::move_bindgen::aptos_types::transaction::EntryFunction { + ::move_bindgen::aptos_types::transaction::EntryFunction::new( + ::move_bindgen::aptos_rest_client::aptos_api_types::MoveModuleId { + address: contract_address.into(), + name: stringify!(channel_handshake).parse().unwrap(), + } + .into(), + stringify!(channel_open_ack).parse().unwrap(), + vec![t0.into().into()], + vec![ + ::move_bindgen::bcs::to_bytes(&_0).unwrap(), + ::move_bindgen::bcs::to_bytes(&_1).unwrap(), + ::move_bindgen::bcs::to_bytes(&_2).unwrap(), + ::move_bindgen::bcs::to_bytes(&_3).unwrap(), + ::move_bindgen::bcs::to_bytes(&_4).unwrap(), + ::move_bindgen::bcs::to_bytes(&_5).unwrap(), + ], + ) + } + fn channel_open_confirm( + &self, + contract_address: ::move_bindgen::aptos_types::account_address::AccountAddress, + (_0, _1, _2, _3): ( + ::move_bindgen::aptos_types::account_address::AccountAddress, + u32, + Vec, + u64, + ), + (t0,): (impl Into<::move_bindgen::move_core_types::language_storage::TypeTag>,), + ) -> ::move_bindgen::aptos_types::transaction::EntryFunction { + ::move_bindgen::aptos_types::transaction::EntryFunction::new( + ::move_bindgen::aptos_rest_client::aptos_api_types::MoveModuleId { + address: contract_address.into(), + name: stringify!(channel_handshake).parse().unwrap(), + } + .into(), + stringify!(channel_open_confirm).parse().unwrap(), + vec![t0.into().into()], + vec![ + ::move_bindgen::bcs::to_bytes(&_0).unwrap(), + ::move_bindgen::bcs::to_bytes(&_1).unwrap(), + ::move_bindgen::bcs::to_bytes(&_2).unwrap(), + ::move_bindgen::bcs::to_bytes(&_3).unwrap(), + ], + ) + } + fn channel_open_init( + &self, + contract_address: ::move_bindgen::aptos_types::account_address::AccountAddress, + (_0, _1, _2, _3): ( + ::move_bindgen::aptos_types::account_address::AccountAddress, + Vec, + u32, + String, + ), + (t0,): (impl Into<::move_bindgen::move_core_types::language_storage::TypeTag>,), + ) -> ::move_bindgen::aptos_types::transaction::EntryFunction { + ::move_bindgen::aptos_types::transaction::EntryFunction::new( + ::move_bindgen::aptos_rest_client::aptos_api_types::MoveModuleId { + address: contract_address.into(), + name: stringify!(channel_handshake).parse().unwrap(), + } + .into(), + stringify!(channel_open_init).parse().unwrap(), + vec![t0.into().into()], + vec![ + ::move_bindgen::bcs::to_bytes(&_0).unwrap(), + ::move_bindgen::bcs::to_bytes(&_1).unwrap(), + ::move_bindgen::bcs::to_bytes(&_2).unwrap(), + ::move_bindgen::bcs::to_bytes(&_3).unwrap(), + ], + ) + } + fn channel_open_try( &self, contract_address: ::move_bindgen::aptos_types::account_address::AccountAddress, (_0, _1, _2, _3, _4, _5, _6, _7): ( + ::move_bindgen::aptos_types::account_address::AccountAddress, + u32, + u32, + Vec, + String, + String, + Vec, + u64, + ), + (t0,): (impl Into<::move_bindgen::move_core_types::language_storage::TypeTag>,), + ) -> ::move_bindgen::aptos_types::transaction::EntryFunction { + ::move_bindgen::aptos_types::transaction::EntryFunction::new( + ::move_bindgen::aptos_rest_client::aptos_api_types::MoveModuleId { + address: contract_address.into(), + name: stringify!(channel_handshake).parse().unwrap(), + } + .into(), + stringify!(channel_open_try).parse().unwrap(), + vec![t0.into().into()], + vec![ + ::move_bindgen::bcs::to_bytes(&_0).unwrap(), + ::move_bindgen::bcs::to_bytes(&_1).unwrap(), + ::move_bindgen::bcs::to_bytes(&_2).unwrap(), + ::move_bindgen::bcs::to_bytes(&_3).unwrap(), + ::move_bindgen::bcs::to_bytes(&_4).unwrap(), + ::move_bindgen::bcs::to_bytes(&_5).unwrap(), + ::move_bindgen::bcs::to_bytes(&_6).unwrap(), + ::move_bindgen::bcs::to_bytes(&_7).unwrap(), + ], + ) + } + } +} + +pub mod acknowledge_packet { + pub trait ClientExt { + fn client(&self) -> &::move_bindgen::aptos_rest_client::Client; + fn acknowledge_packet( + &self, + contract_address: ::move_bindgen::aptos_types::account_address::AccountAddress, + (_0, _1, _2, _3, _4, _5, _6, _7, _8): ( ::move_bindgen::aptos_types::account_address::AccountAddress, Vec, Vec, Vec>, Vec, Vec, + Vec>, Vec, u64, ), @@ -29,10 +156,10 @@ pub mod recv_packet { ::move_bindgen::aptos_types::transaction::EntryFunction::new( ::move_bindgen::aptos_rest_client::aptos_api_types::MoveModuleId { address: contract_address.into(), - name: stringify!(recv_packet).parse().unwrap(), + name: stringify!(acknowledge_packet).parse().unwrap(), } .into(), - stringify!(recv_packet).parse().unwrap(), + stringify!(acknowledge_packet).parse().unwrap(), vec![t0.into().into()], vec![ ::move_bindgen::bcs::to_bytes(&_0).unwrap(), @@ -43,13 +170,63 @@ pub mod recv_packet { ::move_bindgen::bcs::to_bytes(&_5).unwrap(), ::move_bindgen::bcs::to_bytes(&_6).unwrap(), ::move_bindgen::bcs::to_bytes(&_7).unwrap(), + ::move_bindgen::bcs::to_bytes(&_8).unwrap(), ], ) } } } -pub mod channel { +pub mod move_in_cosmos_client { + pub trait ClientExt { + fn client(&self) -> &::move_bindgen::aptos_rest_client::Client; + #[::move_bindgen::tracing::instrument( + skip_all, + fields(%contract_address, ?ledger_version, ) + )] + async fn get_vault_addr( + &self, + contract_address: ::move_bindgen::aptos_types::account_address::AccountAddress, + ledger_version: Option, + ) -> ::core::result::Result< + ::move_bindgen::aptos_rest_client::aptos_api_types::Address, + ::move_bindgen::aptos_rest_client::error::RestError, + > { + let response = self + .client() + .view( + &::move_bindgen::aptos_rest_client::aptos_api_types::ViewRequest { + function: ::move_bindgen::aptos_rest_client::aptos_api_types::EntryFunctionId { + module: ::move_bindgen::aptos_rest_client::aptos_api_types::MoveModuleId { + address: contract_address.into(), + name: stringify!(move_in_cosmos_client).parse().unwrap(), + }, + name: stringify!(get_vault_addr).parse().unwrap(), + }, + type_arguments: vec![], + arguments: vec![], + }, + ledger_version, + ) + .await? + .into_inner(); + let value = ::move_bindgen::serde_json::Value::from(response); + ::move_bindgen::tracing::debug!(% value, "fetched response"); + let (ret_0,) = ::move_bindgen::serde_json::from_value::< + ( + <::move_bindgen::aptos_rest_client::aptos_api_types::Address as ::move_bindgen::MoveOutputType>::Raw, + ), + >(value)?; + Ok( + ( + <::move_bindgen::aptos_rest_client::aptos_api_types::Address as ::move_bindgen::MoveOutputType>::from_raw( + ret_0, + ), + ) + .0, + ) + } + } #[derive( Debug, Clone, @@ -62,16 +239,15 @@ pub mod channel { ::move_bindgen::MoveOutputType, )] #[serde(crate = "::move_bindgen::serde")] - pub struct Channel { - pub state: u8, - pub connection_id: u32, - pub counterparty_channel_id: u32, - pub counterparty_port_id: Vec, - pub version: String, + pub struct CreateLensClient { + pub client_id: u32, + pub l1_client_id: u32, + pub l2_client_id: u32, + pub l2_chain_id: String, } } -pub mod packet { +pub mod channel { #[derive( Debug, Clone, @@ -84,12 +260,12 @@ pub mod packet { ::move_bindgen::MoveOutputType, )] #[serde(crate = "::move_bindgen::serde")] - pub struct Packet { - pub source_channel: u32, - pub destination_channel: u32, - pub data: Vec, - pub timeout_height: u64, - pub timeout_timestamp: u64, + pub struct Channel { + pub state: u8, + pub connection_id: u32, + pub counterparty_channel_id: u32, + pub counterparty_port_id: Vec, + pub version: String, } } @@ -145,17 +321,19 @@ pub mod dispatcher { } } -pub mod channel_handshake { +pub mod recv_packet { pub trait ClientExt { fn client(&self) -> &::move_bindgen::aptos_rest_client::Client; - fn channel_open_ack( + fn recv_packet( &self, contract_address: ::move_bindgen::aptos_types::account_address::AccountAddress, - (_0, _1, _2, _3, _4, _5): ( + (_0, _1, _2, _3, _4, _5, _6, _7): ( ::move_bindgen::aptos_types::account_address::AccountAddress, - u32, - String, - u32, + Vec, + Vec, + Vec>, + Vec, + Vec, Vec, u64, ), @@ -164,10 +342,10 @@ pub mod channel_handshake { ::move_bindgen::aptos_types::transaction::EntryFunction::new( ::move_bindgen::aptos_rest_client::aptos_api_types::MoveModuleId { address: contract_address.into(), - name: stringify!(channel_handshake).parse().unwrap(), + name: stringify!(recv_packet).parse().unwrap(), } .into(), - stringify!(channel_open_ack).parse().unwrap(), + stringify!(recv_packet).parse().unwrap(), vec![t0.into().into()], vec![ ::move_bindgen::bcs::to_bytes(&_0).unwrap(), @@ -176,85 +354,40 @@ pub mod channel_handshake { ::move_bindgen::bcs::to_bytes(&_3).unwrap(), ::move_bindgen::bcs::to_bytes(&_4).unwrap(), ::move_bindgen::bcs::to_bytes(&_5).unwrap(), + ::move_bindgen::bcs::to_bytes(&_6).unwrap(), + ::move_bindgen::bcs::to_bytes(&_7).unwrap(), ], ) } - fn channel_open_confirm( - &self, - contract_address: ::move_bindgen::aptos_types::account_address::AccountAddress, - (_0, _1, _2, _3): ( - ::move_bindgen::aptos_types::account_address::AccountAddress, - u32, - Vec, - u64, - ), - (t0,): (impl Into<::move_bindgen::move_core_types::language_storage::TypeTag>,), - ) -> ::move_bindgen::aptos_types::transaction::EntryFunction { - ::move_bindgen::aptos_types::transaction::EntryFunction::new( - ::move_bindgen::aptos_rest_client::aptos_api_types::MoveModuleId { - address: contract_address.into(), - name: stringify!(channel_handshake).parse().unwrap(), - } - .into(), - stringify!(channel_open_confirm).parse().unwrap(), - vec![t0.into().into()], - vec![ - ::move_bindgen::bcs::to_bytes(&_0).unwrap(), - ::move_bindgen::bcs::to_bytes(&_1).unwrap(), - ::move_bindgen::bcs::to_bytes(&_2).unwrap(), - ::move_bindgen::bcs::to_bytes(&_3).unwrap(), - ], - ) - } - fn channel_open_init( - &self, - contract_address: ::move_bindgen::aptos_types::account_address::AccountAddress, - (_0, _1, _2, _3): ( - ::move_bindgen::aptos_types::account_address::AccountAddress, - Vec, - u32, - String, - ), - (t0,): (impl Into<::move_bindgen::move_core_types::language_storage::TypeTag>,), - ) -> ::move_bindgen::aptos_types::transaction::EntryFunction { - ::move_bindgen::aptos_types::transaction::EntryFunction::new( - ::move_bindgen::aptos_rest_client::aptos_api_types::MoveModuleId { - address: contract_address.into(), - name: stringify!(channel_handshake).parse().unwrap(), - } - .into(), - stringify!(channel_open_init).parse().unwrap(), - vec![t0.into().into()], - vec![ - ::move_bindgen::bcs::to_bytes(&_0).unwrap(), - ::move_bindgen::bcs::to_bytes(&_1).unwrap(), - ::move_bindgen::bcs::to_bytes(&_2).unwrap(), - ::move_bindgen::bcs::to_bytes(&_3).unwrap(), - ], - ) - } - fn channel_open_try( + } +} + +pub mod timeout_packet { + pub trait ClientExt { + fn client(&self) -> &::move_bindgen::aptos_rest_client::Client; + fn timeout_packet( &self, contract_address: ::move_bindgen::aptos_types::account_address::AccountAddress, - (_0, _1, _2, _3, _4, _5, _6, _7): ( + (_0, _1, _2, _3, _4, _5, _6, _7, _8): ( ::move_bindgen::aptos_types::account_address::AccountAddress, u32, u32, Vec, - String, - String, + u64, + u64, Vec, u64, + u64, ), (t0,): (impl Into<::move_bindgen::move_core_types::language_storage::TypeTag>,), ) -> ::move_bindgen::aptos_types::transaction::EntryFunction { ::move_bindgen::aptos_types::transaction::EntryFunction::new( ::move_bindgen::aptos_rest_client::aptos_api_types::MoveModuleId { address: contract_address.into(), - name: stringify!(channel_handshake).parse().unwrap(), + name: stringify!(timeout_packet).parse().unwrap(), } .into(), - stringify!(channel_open_try).parse().unwrap(), + stringify!(timeout_packet).parse().unwrap(), vec![t0.into().into()], vec![ ::move_bindgen::bcs::to_bytes(&_0).unwrap(), @@ -265,12 +398,34 @@ pub mod channel_handshake { ::move_bindgen::bcs::to_bytes(&_5).unwrap(), ::move_bindgen::bcs::to_bytes(&_6).unwrap(), ::move_bindgen::bcs::to_bytes(&_7).unwrap(), + ::move_bindgen::bcs::to_bytes(&_8).unwrap(), ], ) } } } +pub mod connection_end { + #[derive( + Debug, + Clone, + PartialEq, + Eq, + PartialOrd, + Ord, + ::move_bindgen::serde::Serialize, + ::move_bindgen::serde::Deserialize, + ::move_bindgen::MoveOutputType, + )] + #[serde(crate = "::move_bindgen::serde")] + pub struct ConnectionEnd { + pub state: u64, + pub client_id: u32, + pub counterparty_client_id: u32, + pub counterparty_connection_id: u32, + } +} + pub mod ibc { pub trait ClientExt { fn client(&self) -> &::move_bindgen::aptos_rest_client::Client; @@ -278,6 +433,45 @@ pub mod ibc { skip_all, fields(%contract_address, ?ledger_version, ?_0, ) )] + async fn client_id_to_type( + &self, + contract_address: ::move_bindgen::aptos_types::account_address::AccountAddress, + ledger_version: Option, + (_0,): (u32,), + ) -> ::core::result::Result + { + let response = self + .client() + .view( + &::move_bindgen::aptos_rest_client::aptos_api_types::ViewRequest { + function: ::move_bindgen::aptos_rest_client::aptos_api_types::EntryFunctionId { + module: ::move_bindgen::aptos_rest_client::aptos_api_types::MoveModuleId { + address: contract_address.into(), + name: stringify!(ibc).parse().unwrap(), + }, + name: stringify!(client_id_to_type).parse().unwrap(), + }, + type_arguments: vec![], + arguments: vec![ + ::move_bindgen::serde_json::to_value(& < u32 as + ::move_bindgen::MoveOutputType > ::into_raw(_0)).unwrap(), + ], + }, + ledger_version, + ) + .await? + .into_inner(); + let value = ::move_bindgen::serde_json::Value::from(response); + ::move_bindgen::tracing::debug!(% value, "fetched response"); + let (ret_0,) = ::move_bindgen::serde_json::from_value::<( + ::Raw, + )>(value)?; + Ok((::from_raw(ret_0),).0) + } + #[::move_bindgen::tracing::instrument( + skip_all, + fields(%contract_address, ?ledger_version, ?_0, ) + )] async fn client_state( &self, contract_address: ::move_bindgen::aptos_types::account_address::AccountAddress, @@ -816,9 +1010,10 @@ pub mod ibc { ::move_bindgen::MoveOutputType, )] #[serde(crate = "::move_bindgen::serde")] - pub struct AcknowledgePacket { - pub packet: super::packet::Packet, - pub acknowledgement: Vec, + pub struct ClientCreatedEvent { + pub client_id: u32, + pub client_type: String, + pub consensus_height: u64, } #[derive( Debug, @@ -832,13 +1027,12 @@ pub mod ibc { ::move_bindgen::MoveOutputType, )] #[serde(crate = "::move_bindgen::serde")] - pub struct ChannelOpenTry { + pub struct ChannelOpenAck { pub port_id: String, pub channel_id: u32, pub counterparty_port_id: Vec, pub counterparty_channel_id: u32, pub connection_id: u32, - pub version: String, } #[derive( Debug, @@ -852,10 +1046,9 @@ pub mod ibc { ::move_bindgen::MoveOutputType, )] #[serde(crate = "::move_bindgen::serde")] - pub struct ClientCreatedEvent { - pub client_id: u32, - pub client_type: String, - pub consensus_height: u64, + pub struct WriteAcknowledgement { + pub packet: super::packet::Packet, + pub acknowledgement: Vec, } #[derive( Debug, @@ -869,11 +1062,12 @@ pub mod ibc { ::move_bindgen::MoveOutputType, )] #[serde(crate = "::move_bindgen::serde")] - pub struct ConnectionOpenAck { - pub connection_id: u32, - pub client_id: u32, - pub counterparty_client_id: u32, - pub counterparty_connection_id: u32, + pub struct SendPacket { + pub source_channel: u32, + pub destination_channel: u32, + pub data: Vec, + pub timeout_height: u64, + pub timeout_timestamp: u64, } #[derive( Debug, @@ -887,8 +1081,10 @@ pub mod ibc { ::move_bindgen::MoveOutputType, )] #[serde(crate = "::move_bindgen::serde")] - pub struct RecvPacket { - pub packet: super::packet::Packet, + pub struct ClientUpdated { + pub client_id: u32, + pub client_type: String, + pub height: u64, } #[derive( Debug, @@ -902,12 +1098,11 @@ pub mod ibc { ::move_bindgen::MoveOutputType, )] #[serde(crate = "::move_bindgen::serde")] - pub struct ChannelOpenAck { - pub port_id: String, - pub channel_id: u32, - pub counterparty_port_id: Vec, - pub counterparty_channel_id: u32, + pub struct ConnectionOpenTry { pub connection_id: u32, + pub client_id: u32, + pub counterparty_client_id: u32, + pub counterparty_connection_id: u32, } #[derive( Debug, @@ -921,11 +1116,13 @@ pub mod ibc { ::move_bindgen::MoveOutputType, )] #[serde(crate = "::move_bindgen::serde")] - pub struct ConnectionOpenConfirm { + pub struct ChannelOpenTry { + pub port_id: String, + pub channel_id: u32, + pub counterparty_port_id: Vec, + pub counterparty_channel_id: u32, pub connection_id: u32, - pub client_id: u32, - pub counterparty_client_id: u32, - pub counterparty_connection_id: u32, + pub version: String, } #[derive( Debug, @@ -939,7 +1136,7 @@ pub mod ibc { ::move_bindgen::MoveOutputType, )] #[serde(crate = "::move_bindgen::serde")] - pub struct TimeoutPacket { + pub struct RecvPacket { pub packet: super::packet::Packet, } #[derive( @@ -954,10 +1151,8 @@ pub mod ibc { ::move_bindgen::MoveOutputType, )] #[serde(crate = "::move_bindgen::serde")] - pub struct ConnectionOpenInit { - pub connection_id: u32, - pub client_id: u32, - pub counterparty_client_id: u32, + pub struct RecvIntentPacket { + pub packet: super::packet::Packet, } #[derive( Debug, @@ -971,11 +1166,9 @@ pub mod ibc { ::move_bindgen::MoveOutputType, )] #[serde(crate = "::move_bindgen::serde")] - pub struct ConnectionOpenTry { - pub connection_id: u32, - pub client_id: u32, - pub counterparty_client_id: u32, - pub counterparty_connection_id: u32, + pub struct AcknowledgePacket { + pub packet: super::packet::Packet, + pub acknowledgement: Vec, } #[derive( Debug, @@ -989,12 +1182,8 @@ pub mod ibc { ::move_bindgen::MoveOutputType, )] #[serde(crate = "::move_bindgen::serde")] - pub struct ChannelOpenConfirm { - pub port_id: String, - pub channel_id: u32, - pub counterparty_port_id: Vec, - pub counterparty_channel_id: u32, - pub connection_id: u32, + pub struct TimeoutPacket { + pub packet: super::packet::Packet, } #[derive( Debug, @@ -1008,10 +1197,9 @@ pub mod ibc { ::move_bindgen::MoveOutputType, )] #[serde(crate = "::move_bindgen::serde")] - pub struct ClientUpdated { + pub struct SubmitMisbehaviour { pub client_id: u32, pub client_type: String, - pub height: u64, } #[derive( Debug, @@ -1025,8 +1213,12 @@ pub mod ibc { ::move_bindgen::MoveOutputType, )] #[serde(crate = "::move_bindgen::serde")] - pub struct RecvIntentPacket { - pub packet: super::packet::Packet, + pub struct ChannelOpenInit { + pub port_id: String, + pub channel_id: u32, + pub counterparty_port_id: Vec, + pub connection_id: u32, + pub version: String, } #[derive( Debug, @@ -1040,9 +1232,11 @@ pub mod ibc { ::move_bindgen::MoveOutputType, )] #[serde(crate = "::move_bindgen::serde")] - pub struct SubmitMisbehaviour { + pub struct ConnectionOpenAck { + pub connection_id: u32, pub client_id: u32, - pub client_type: String, + pub counterparty_client_id: u32, + pub counterparty_connection_id: u32, } #[derive( Debug, @@ -1056,12 +1250,12 @@ pub mod ibc { ::move_bindgen::MoveOutputType, )] #[serde(crate = "::move_bindgen::serde")] - pub struct SendPacket { - pub source_channel: u32, - pub destination_channel: u32, - pub data: Vec, - pub timeout_height: u64, - pub timeout_timestamp: u64, + pub struct ChannelOpenConfirm { + pub port_id: String, + pub channel_id: u32, + pub counterparty_port_id: Vec, + pub counterparty_channel_id: u32, + pub connection_id: u32, } #[derive( Debug, @@ -1075,9 +1269,11 @@ pub mod ibc { ::move_bindgen::MoveOutputType, )] #[serde(crate = "::move_bindgen::serde")] - pub struct WriteAcknowledgement { - pub packet: super::packet::Packet, - pub acknowledgement: Vec, + pub struct ConnectionOpenConfirm { + pub connection_id: u32, + pub client_id: u32, + pub counterparty_client_id: u32, + pub counterparty_connection_id: u32, } #[derive( Debug, @@ -1091,102 +1287,14 @@ pub mod ibc { ::move_bindgen::MoveOutputType, )] #[serde(crate = "::move_bindgen::serde")] - pub struct ChannelOpenInit { - pub port_id: String, - pub channel_id: u32, - pub counterparty_port_id: Vec, + pub struct ConnectionOpenInit { pub connection_id: u32, - pub version: String, - } -} - -pub mod acknowledge_packet { - pub trait ClientExt { - fn client(&self) -> &::move_bindgen::aptos_rest_client::Client; - fn acknowledge_packet( - &self, - contract_address: ::move_bindgen::aptos_types::account_address::AccountAddress, - (_0, _1, _2, _3, _4, _5, _6, _7, _8): ( - ::move_bindgen::aptos_types::account_address::AccountAddress, - Vec, - Vec, - Vec>, - Vec, - Vec, - Vec>, - Vec, - u64, - ), - (t0,): (impl Into<::move_bindgen::move_core_types::language_storage::TypeTag>,), - ) -> ::move_bindgen::aptos_types::transaction::EntryFunction { - ::move_bindgen::aptos_types::transaction::EntryFunction::new( - ::move_bindgen::aptos_rest_client::aptos_api_types::MoveModuleId { - address: contract_address.into(), - name: stringify!(acknowledge_packet).parse().unwrap(), - } - .into(), - stringify!(acknowledge_packet).parse().unwrap(), - vec![t0.into().into()], - vec![ - ::move_bindgen::bcs::to_bytes(&_0).unwrap(), - ::move_bindgen::bcs::to_bytes(&_1).unwrap(), - ::move_bindgen::bcs::to_bytes(&_2).unwrap(), - ::move_bindgen::bcs::to_bytes(&_3).unwrap(), - ::move_bindgen::bcs::to_bytes(&_4).unwrap(), - ::move_bindgen::bcs::to_bytes(&_5).unwrap(), - ::move_bindgen::bcs::to_bytes(&_6).unwrap(), - ::move_bindgen::bcs::to_bytes(&_7).unwrap(), - ::move_bindgen::bcs::to_bytes(&_8).unwrap(), - ], - ) - } - } -} - -pub mod timeout_packet { - pub trait ClientExt { - fn client(&self) -> &::move_bindgen::aptos_rest_client::Client; - fn timeout_packet( - &self, - contract_address: ::move_bindgen::aptos_types::account_address::AccountAddress, - (_0, _1, _2, _3, _4, _5, _6, _7, _8): ( - ::move_bindgen::aptos_types::account_address::AccountAddress, - u32, - u32, - Vec, - u64, - u64, - Vec, - u64, - u64, - ), - (t0,): (impl Into<::move_bindgen::move_core_types::language_storage::TypeTag>,), - ) -> ::move_bindgen::aptos_types::transaction::EntryFunction { - ::move_bindgen::aptos_types::transaction::EntryFunction::new( - ::move_bindgen::aptos_rest_client::aptos_api_types::MoveModuleId { - address: contract_address.into(), - name: stringify!(timeout_packet).parse().unwrap(), - } - .into(), - stringify!(timeout_packet).parse().unwrap(), - vec![t0.into().into()], - vec![ - ::move_bindgen::bcs::to_bytes(&_0).unwrap(), - ::move_bindgen::bcs::to_bytes(&_1).unwrap(), - ::move_bindgen::bcs::to_bytes(&_2).unwrap(), - ::move_bindgen::bcs::to_bytes(&_3).unwrap(), - ::move_bindgen::bcs::to_bytes(&_4).unwrap(), - ::move_bindgen::bcs::to_bytes(&_5).unwrap(), - ::move_bindgen::bcs::to_bytes(&_6).unwrap(), - ::move_bindgen::bcs::to_bytes(&_7).unwrap(), - ::move_bindgen::bcs::to_bytes(&_8).unwrap(), - ], - ) - } + pub client_id: u32, + pub counterparty_client_id: u32, } } -pub mod connection_end { +pub mod packet { #[derive( Debug, Clone, @@ -1199,10 +1307,11 @@ pub mod connection_end { ::move_bindgen::MoveOutputType, )] #[serde(crate = "::move_bindgen::serde")] - pub struct ConnectionEnd { - pub state: u64, - pub client_id: u32, - pub counterparty_client_id: u32, - pub counterparty_connection_id: u32, + pub struct Packet { + pub source_channel: u32, + pub destination_channel: u32, + pub data: Vec, + pub timeout_height: u64, + pub timeout_timestamp: u64, } } diff --git a/lib/state-lens-ics23-move-light-client-types/Cargo.toml b/lib/state-lens-ics23-smt-light-client-types/Cargo.toml similarity index 94% rename from lib/state-lens-ics23-move-light-client-types/Cargo.toml rename to lib/state-lens-ics23-smt-light-client-types/Cargo.toml index a0f4fea05c..328f3b394b 100644 --- a/lib/state-lens-ics23-move-light-client-types/Cargo.toml +++ b/lib/state-lens-ics23-smt-light-client-types/Cargo.toml @@ -1,6 +1,6 @@ [package] edition = "2021" -name = "state-lens-ics23-move-light-client-types" +name = "state-lens-ics23-smt-light-client-types" version = "0.1.0" [dependencies] diff --git a/lib/state-lens-ics23-move-light-client-types/src/client_state.rs b/lib/state-lens-ics23-smt-light-client-types/src/client_state.rs similarity index 84% rename from lib/state-lens-ics23-move-light-client-types/src/client_state.rs rename to lib/state-lens-ics23-smt-light-client-types/src/client_state.rs index 7309d7627c..c4610175dc 100644 --- a/lib/state-lens-ics23-move-light-client-types/src/client_state.rs +++ b/lib/state-lens-ics23-smt-light-client-types/src/client_state.rs @@ -10,6 +10,6 @@ pub struct Extra { /// timestamp = consensus_state[timestamp_offset:timestamp_offset+8] pub timestamp_offset: u16, /// the offset at which we extract the bytes32 storage root (of the ibc contract on the l2) from the l2 consensus state - /// storage_root = consensus_state[storage_root_offset:storage_root_offset+32] - pub storage_root_offset: u16, + /// state_root = consensus_state[state_root_offset:state_root_offset+32] + pub state_root_offset: u16, } diff --git a/lib/state-lens-ics23-move-light-client-types/src/consensus_state.rs b/lib/state-lens-ics23-smt-light-client-types/src/consensus_state.rs similarity index 100% rename from lib/state-lens-ics23-move-light-client-types/src/consensus_state.rs rename to lib/state-lens-ics23-smt-light-client-types/src/consensus_state.rs diff --git a/lib/state-lens-ics23-move-light-client-types/src/lib.rs b/lib/state-lens-ics23-smt-light-client-types/src/lib.rs similarity index 100% rename from lib/state-lens-ics23-move-light-client-types/src/lib.rs rename to lib/state-lens-ics23-smt-light-client-types/src/lib.rs From cf50555576d5ec152a2ebf060a4f88a4b1016eb0 Mon Sep 17 00:00:00 2001 From: aeryz Date: Wed, 22 Jan 2025 09:18:33 +0300 Subject: [PATCH 09/15] chore(voyager): ics23smt client module and ics23mpt aptos support --- lib/voyager-core/src/lib.rs | 7 + .../client/state-lens/ics23-mpt/src/main.rs | 19 +- .../client/state-lens/ics23-smt/Cargo.toml | 26 ++ .../client/state-lens/ics23-smt/src/main.rs | 271 ++++++++++++++++++ 4 files changed, 321 insertions(+), 2 deletions(-) create mode 100644 voyager/modules/client/state-lens/ics23-smt/Cargo.toml create mode 100644 voyager/modules/client/state-lens/ics23-smt/src/main.rs diff --git a/lib/voyager-core/src/lib.rs b/lib/voyager-core/src/lib.rs index 0634fb11bc..5abe55a392 100644 --- a/lib/voyager-core/src/lib.rs +++ b/lib/voyager-core/src/lib.rs @@ -127,6 +127,13 @@ impl ClientType { /// [ICS23]: https://github.com/cosmos/ics23 pub const STATE_LENS_ICS23_ICS23: &'static str = "state-lens/ics23/ics23"; + /// A client tracking a [Aptos] chain, verified through that chain's consensus as + /// settled on an intermediary [ICS-23] chain. + /// + /// [ICS23]: https://github.com/cosmos/ics23 + /// [Aptos]: https://github.com/aptos-labs/aptos-core + pub const STATE_LENS_ICS23_SMT: &'static str = "state-lens/ics23/smt"; + // lots more to come - near, linea, polygon - stay tuned } diff --git a/voyager/modules/client/state-lens/ics23-mpt/src/main.rs b/voyager/modules/client/state-lens/ics23-mpt/src/main.rs index a505a0e126..788819f486 100644 --- a/voyager/modules/client/state-lens/ics23-mpt/src/main.rs +++ b/voyager/modules/client/state-lens/ics23-mpt/src/main.rs @@ -12,7 +12,7 @@ use state_lens_light_client_types::Header; use tracing::instrument; use unionlabs::{ self, - encoding::{Bincode, DecodeAs, EncodeAs, EthAbi}, + encoding::{Bcs, Bincode, DecodeAs, EncodeAs, EthAbi}, ibc::core::client::height::Height, primitives::Bytes, }; @@ -37,6 +37,7 @@ async fn main() { pub enum SupportedIbcInterface { IbcSolidity, IbcCosmwasm, + IbcMoveAptos, } impl TryFrom for SupportedIbcInterface { @@ -47,6 +48,7 @@ impl TryFrom for SupportedIbcInterface { match &*value { IbcInterface::IBC_SOLIDITY => Ok(SupportedIbcInterface::IbcSolidity), IbcInterface::IBC_COSMWASM => Ok(SupportedIbcInterface::IbcCosmwasm), + IbcInterface::IBC_MOVE_APTOS => Ok(SupportedIbcInterface::IbcMoveAptos), _ => Err(format!("unsupported IBC interface: `{value}`")), } } @@ -57,6 +59,7 @@ impl SupportedIbcInterface { match self { SupportedIbcInterface::IbcSolidity => IbcInterface::IBC_SOLIDITY, SupportedIbcInterface::IbcCosmwasm => IbcInterface::IBC_COSMWASM, + SupportedIbcInterface::IbcMoveAptos => IbcInterface::IBC_MOVE_APTOS, } } } @@ -83,7 +86,8 @@ impl ClientModule for Module { info.ensure_client_type(ClientType::STATE_LENS_ICS23_MPT)?; info.ensure_consensus_type(ConsensusType::ETHEREUM)?; info.ensure_ibc_interface(IbcInterface::IBC_SOLIDITY) - .or(info.ensure_ibc_interface(IbcInterface::IBC_COSMWASM))?; + .or(info.ensure_ibc_interface(IbcInterface::IBC_COSMWASM)) + .or(info.ensure_ibc_interface(IbcInterface::IBC_MOVE_APTOS))?; Ok(Self { ibc_interface: SupportedIbcInterface::try_from(info.ibc_interface.to_string())?, @@ -121,6 +125,14 @@ impl Module { None::<()>, ) }), + SupportedIbcInterface::IbcMoveAptos => ClientState::decode_as::(client_state) + .map_err(|err| { + ErrorObject::owned( + FATAL_JSONRPC_ERROR_CODE, + format!("unable to decode client state: {err}"), + None::<()>, + ) + }), } } @@ -203,6 +215,7 @@ impl ClientModuleServer for Module { .map(|cs| match self.ibc_interface { SupportedIbcInterface::IbcSolidity => cs.abi_encode_params(), SupportedIbcInterface::IbcCosmwasm => cs.encode_as::(), + SupportedIbcInterface::IbcMoveAptos => cs.encode_as::(), }) .map(Into::into) } @@ -238,6 +251,7 @@ impl ClientModuleServer for Module { .map(|header| match self.ibc_interface { SupportedIbcInterface::IbcSolidity => header.encode_as::(), SupportedIbcInterface::IbcCosmwasm => header.encode_as::(), + SupportedIbcInterface::IbcMoveAptos => header.encode_as::(), }) .map(Into::into) } @@ -256,6 +270,7 @@ impl ClientModuleServer for Module { // the solidity MPT verifier expects the proof RLP nodes to be serialized in sequence SupportedIbcInterface::IbcSolidity => Ok(proof.proof.into_iter().flatten().collect()), SupportedIbcInterface::IbcCosmwasm => Ok(proof.encode_as::().into()), + SupportedIbcInterface::IbcMoveAptos => Ok(proof.encode_as::().into()), } } } diff --git a/voyager/modules/client/state-lens/ics23-smt/Cargo.toml b/voyager/modules/client/state-lens/ics23-smt/Cargo.toml new file mode 100644 index 0000000000..d5c722c7d8 --- /dev/null +++ b/voyager/modules/client/state-lens/ics23-smt/Cargo.toml @@ -0,0 +1,26 @@ +[package] +edition = "2021" +name = "voyager-client-module-state-lens-ics23-smt" +version = "0.1.0" + +[dependencies] +beacon-api-types = { workspace = true, features = ["serde"] } +chain-utils = { workspace = true } +enumorph = { workspace = true } +ethereum-light-client-types = { workspace = true, features = ["serde", "ethabi", "bincode"] } +futures = { workspace = true } +jsonrpsee = { workspace = true, features = ["macros", "server", "tracing"] } +macros = { workspace = true } +prost = { workspace = true } +serde = { workspace = true, features = ["derive"] } +serde-utils = { workspace = true } +serde_json = { workspace = true } +state-lens-ics23-smt-light-client-types = { workspace = true, features = ["serde", "ethabi", "bincode"] } +state-lens-light-client-types = { workspace = true, features = ["serde", "ethabi", "bincode"] } +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/modules/client/state-lens/ics23-smt/src/main.rs b/voyager/modules/client/state-lens/ics23-smt/src/main.rs new file mode 100644 index 0000000000..267bf0a7a0 --- /dev/null +++ b/voyager/modules/client/state-lens/ics23-smt/src/main.rs @@ -0,0 +1,271 @@ +use ethereum_light_client_types::StorageProof; +use jsonrpsee::{ + core::{async_trait, RpcResult}, + types::ErrorObject, + Extensions, +}; +use serde::{Deserialize, Serialize}; +use serde_json::{json, Value}; +use state_lens_ics23_move_light_client_types::{ClientState, ConsensusState}; +use state_lens_light_client_types::Header; +use tracing::instrument; +use unionlabs::{ + self, + encoding::{Bincode, DecodeAs, EncodeAs, EthAbi}, + ibc::core::client::height::Height, + primitives::Bytes, +}; +use voyager_message::{ + core::{ + ChainId, ClientStateMeta, ClientType, ConsensusStateMeta, ConsensusType, IbcInterface, + Timestamp, + }, + into_value, + module::{ClientModuleInfo, ClientModuleServer}, + ClientModule, FATAL_JSONRPC_ERROR_CODE, +}; +use voyager_vm::BoxDynError; + +#[tokio::main(flavor = "multi_thread")] +async fn main() { + Module::run().await +} + +#[derive(Debug, Clone, PartialEq, Copy, serde::Serialize, serde::Deserialize)] +#[serde(try_from = "String", into = "String")] +pub enum SupportedIbcInterface { + IbcSolidity, + IbcCosmwasm, +} + +impl TryFrom for SupportedIbcInterface { + // TODO: Better error type here + type Error = String; + + fn try_from(value: String) -> Result { + match &*value { + IbcInterface::IBC_SOLIDITY => Ok(SupportedIbcInterface::IbcSolidity), + IbcInterface::IBC_COSMWASM => Ok(SupportedIbcInterface::IbcCosmwasm), + _ => Err(format!("unsupported IBC interface: `{value}`")), + } + } +} + +impl SupportedIbcInterface { + fn as_str(&self) -> &'static str { + match self { + SupportedIbcInterface::IbcSolidity => IbcInterface::IBC_SOLIDITY, + SupportedIbcInterface::IbcCosmwasm => IbcInterface::IBC_COSMWASM, + } + } +} + +impl From for String { + fn from(value: SupportedIbcInterface) -> Self { + value.as_str().to_owned() + } +} + +#[derive(Debug, Clone)] +pub struct Module { + pub ibc_interface: SupportedIbcInterface, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct Config {} + +impl ClientModule for Module { + type Config = Config; + + async fn new(_: Self::Config, info: ClientModuleInfo) -> Result { + info.ensure_client_type(ClientType::STATE_LENS_ICS23_SMT)?; + info.ensure_consensus_type(ConsensusType::MOVEMENT)?; + info.ensure_ibc_interface(IbcInterface::IBC_SOLIDITY) + .or(info.ensure_ibc_interface(IbcInterface::IBC_COSMWASM))?; + + Ok(Self { + ibc_interface: SupportedIbcInterface::try_from(info.ibc_interface.to_string())?, + }) + } +} + +type SelfConsensusState = ConsensusState; +type SelfClientState = ClientState; + +impl Module { + pub fn decode_consensus_state(consensus_state: &[u8]) -> RpcResult { + SelfConsensusState::decode_as::(consensus_state).map_err(|err| { + ErrorObject::owned( + FATAL_JSONRPC_ERROR_CODE, + format!("unable to decode consensus state: {err}"), + None::<()>, + ) + }) + } + + pub fn decode_client_state(&self, client_state: &[u8]) -> RpcResult { + println!( + "client_state: {:?}?", + ::decode_as::(client_state).unwrap() + ); + match self.ibc_interface { + SupportedIbcInterface::IbcSolidity => { + ::decode_as::(client_state).map_err(|err| { + ErrorObject::owned( + FATAL_JSONRPC_ERROR_CODE, + format!("unable to decode client state: {err}"), + None::<()>, + ) + }) + } + SupportedIbcInterface::IbcCosmwasm => { + ::decode_as::(client_state).map_err(|err| { + ErrorObject::owned( + FATAL_JSONRPC_ERROR_CODE, + format!("unable to decode client state: {err}"), + None::<()>, + ) + }) + } + } + } + + pub fn make_height(revision_height: u64) -> Height { + Height::new(revision_height) + } +} + +#[async_trait] +impl ClientModuleServer for Module { + #[instrument] + async fn decode_client_state_meta( + &self, + _: &Extensions, + client_state: Bytes, + ) -> RpcResult { + let cs = self.decode_client_state(&client_state)?; + + Ok(ClientStateMeta { + chain_id: ChainId::new(cs.l2_chain_id.to_string()), + counterparty_height: Module::make_height(cs.l2_latest_height), + }) + } + + #[instrument] + async fn decode_consensus_state_meta( + &self, + _: &Extensions, + consensus_state: Bytes, + ) -> RpcResult { + let cs = Module::decode_consensus_state(&consensus_state)?; + + Ok(ConsensusStateMeta { + timestamp_nanos: Timestamp::from_nanos(cs.timestamp), + }) + } + + #[instrument] + async fn decode_client_state(&self, _: &Extensions, client_state: Bytes) -> RpcResult { + Ok(into_value(self.decode_client_state(&client_state)?)) + } + + #[instrument] + async fn decode_consensus_state( + &self, + _: &Extensions, + consensus_state: Bytes, + ) -> RpcResult { + Ok(into_value(Module::decode_consensus_state( + &consensus_state, + )?)) + } + + #[instrument] + async fn encode_client_state( + &self, + _: &Extensions, + client_state: Value, + metadata: Value, + ) -> RpcResult { + if !metadata.is_null() { + return Err(ErrorObject::owned( + FATAL_JSONRPC_ERROR_CODE, + "metadata was provided, but this client type does not require \ + metadata for client state encoding", + Some(json!({ + "provided_metadata": metadata, + })), + )); + } + + serde_json::from_value::(client_state) + .map_err(|err| { + ErrorObject::owned( + FATAL_JSONRPC_ERROR_CODE, + format!("unable to deserialize client state: {err}"), + None::<()>, + ) + }) + .map(|cs| match self.ibc_interface { + SupportedIbcInterface::IbcSolidity => cs.encode_as::(), + SupportedIbcInterface::IbcCosmwasm => cs.encode_as::(), + }) + .map(Into::into) + } + + #[instrument] + async fn encode_consensus_state( + &self, + _: &Extensions, + consensus_state: Value, + ) -> RpcResult { + serde_json::from_value::(consensus_state) + .map_err(|err| { + ErrorObject::owned( + FATAL_JSONRPC_ERROR_CODE, + format!("unable to deserialize consensus state: {err}"), + None::<()>, + ) + }) + .map(|cs| cs.encode_as::()) + .map(Into::into) + } + + #[instrument] + async fn encode_header(&self, _: &Extensions, header: Value) -> RpcResult { + serde_json::from_value::
(header) + .map_err(|err| { + ErrorObject::owned( + FATAL_JSONRPC_ERROR_CODE, + format!("unable to deserialize header: {err}"), + None::<()>, + ) + }) + .map(|header| match self.ibc_interface { + SupportedIbcInterface::IbcSolidity => header.encode_as::(), + SupportedIbcInterface::IbcCosmwasm => header.encode_as::(), + }) + .map(Into::into) + } + + #[instrument] + async fn encode_proof(&self, _: &Extensions, _proof: Value) -> RpcResult { + // TODO(aeryz): we cannot verify the proofs on evm yet, this will be mock until we have cw + // impl. + Ok(vec![].into()) + // let proof = serde_json::from_value::(proof).map_err(|err| { + // ErrorObject::owned( + // FATAL_JSONRPC_ERROR_CODE, + // format!("unable to deserialize proof: {err}"), + // None::<()>, + // ) + // })?; + // match self.ibc_interface { + // // TODO: extract to unionlabs? this is MPT proofs encoding for EVM + // // the solidity MPT verifier expects the proof RLP nodes to be serialized in sequence + // SupportedIbcInterface::IbcSolidity => Ok(proof.proof.into_iter().flatten().collect()), + // SupportedIbcInterface::IbcCosmwasm => Ok(proof.encode_as::().into()), + // } + } +} From 28e29ca0bd3e1fddcf87b1fddf9d717094487957 Mon Sep 17 00:00:00 2001 From: aeryz Date: Wed, 22 Jan 2025 09:19:02 +0300 Subject: [PATCH 10/15] chore(voyager): movement add whitelisted relayer support --- voyager/modules/client-bootstrap/movement/Cargo.toml | 1 + .../modules/client-bootstrap/movement/src/main.rs | 12 +++++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/voyager/modules/client-bootstrap/movement/Cargo.toml b/voyager/modules/client-bootstrap/movement/Cargo.toml index f6dada2dd5..a35a2f9f15 100644 --- a/voyager/modules/client-bootstrap/movement/Cargo.toml +++ b/voyager/modules/client-bootstrap/movement/Cargo.toml @@ -7,6 +7,7 @@ version = "0.1.0" aptos-move-ibc = { workspace = true } aptos-rest-client = { workspace = true } chain-utils = { workspace = true } +cosmwasm-std = { workspace = true } jsonrpsee = { workspace = true, features = ["macros", "server", "tracing"] } movement-light-client-types = { workspace = true, features = ["serde"] } serde = { workspace = true, features = ["derive"] } diff --git a/voyager/modules/client-bootstrap/movement/src/main.rs b/voyager/modules/client-bootstrap/movement/src/main.rs index 43816bb052..5a8f4fa28d 100644 --- a/voyager/modules/client-bootstrap/movement/src/main.rs +++ b/voyager/modules/client-bootstrap/movement/src/main.rs @@ -49,6 +49,8 @@ pub struct Module { pub aptos_client: aptos_rest_client::Client, pub movement_rest_url: String, + + pub whitelisted_relayers: Vec, } impl ClientBootstrapModule for Module { @@ -72,6 +74,11 @@ impl ClientBootstrapModule for Module { l1_settlement_address: config.l1_settlement_address, l1_client_id: config.l1_client_id, movement_rest_url: config.movement_rest_url, + whitelisted_relayers: config + .whitelisted_relayers + .into_iter() + .map(Into::into) + .collect(), }) } } @@ -99,6 +106,9 @@ pub struct Config { /// The RPC endpoint for custom movement apis. pub movement_rest_url: String, + + /// The relayers that are allowed to modify this light client + pub whitelisted_relayers: Vec, } impl Module { @@ -165,7 +175,7 @@ impl ClientBootstrapModuleServer for Module { )), frozen_height: Height::new(0), latest_block_num: height.height(), - whitelisted_relayers: vec![], + whitelisted_relayers: self.whitelisted_relayers.clone(), }) .expect("infallible")) } From 87db3352c0300eb9733f14e2481736b34f980138 Mon Sep 17 00:00:00 2001 From: aeryz Date: Wed, 22 Jan 2025 09:19:22 +0300 Subject: [PATCH 11/15] chore(voyager): ics23smt client bootstrap module --- .../state-lens/ics23-smt/Cargo.toml | 24 +++++ .../state-lens/ics23-smt/src/main.rs | 94 +++++++++++++++++++ 2 files changed, 118 insertions(+) create mode 100644 voyager/modules/client-bootstrap/state-lens/ics23-smt/Cargo.toml create mode 100644 voyager/modules/client-bootstrap/state-lens/ics23-smt/src/main.rs diff --git a/voyager/modules/client-bootstrap/state-lens/ics23-smt/Cargo.toml b/voyager/modules/client-bootstrap/state-lens/ics23-smt/Cargo.toml new file mode 100644 index 0000000000..850252ee5e --- /dev/null +++ b/voyager/modules/client-bootstrap/state-lens/ics23-smt/Cargo.toml @@ -0,0 +1,24 @@ +[package] +edition = "2021" +name = "voyager-client-bootstrap-module-state-lens-ics23-smt" +version = "0.1.0" + +[dependencies] +alloy = { workspace = true, features = ["rpc", "rpc-types", "transports", "transport-http", "transport-ws", "reqwest", "provider-ws"] } +beacon-api = { workspace = true } +beacon-api-types = { workspace = true, features = ["serde"] } +cometbft-rpc = { workspace = true } +movement-light-client-types = { workspace = true, features = ["serde"] } +ibc-union-spec.workspace = true +jsonrpsee = { workspace = true, features = ["macros", "server", "tracing"] } +serde = { workspace = true, features = ["derive"] } +serde_json = { workspace = true } +state-lens-ics23-smt-light-client-types = { workspace = true, features = ["serde"] } +tokio = { workspace = true } +tracing = { workspace = true } +unionlabs = { workspace = true } +voyager-message = { workspace = true } +voyager-vm = { workspace = true } + +[dev-dependencies] +tokio = { workspace = true, features = ["full"] } diff --git a/voyager/modules/client-bootstrap/state-lens/ics23-smt/src/main.rs b/voyager/modules/client-bootstrap/state-lens/ics23-smt/src/main.rs new file mode 100644 index 0000000000..7e498178da --- /dev/null +++ b/voyager/modules/client-bootstrap/state-lens/ics23-smt/src/main.rs @@ -0,0 +1,94 @@ +use jsonrpsee::{ + core::{async_trait, RpcResult}, + Extensions, +}; +use movement_light_client_types::ConsensusState as MovementConsensusState; +use serde::{Deserialize, Serialize}; +use serde_json::Value; +use state_lens_ics23_move_light_client_types::{client_state::Extra, ClientState, ConsensusState}; +use tracing::instrument; +use unionlabs::ibc::core::client::height::Height; +use voyager_message::{ + core::{ChainId, ClientType, QueryHeight}, + into_value, + module::{ClientBootstrapModuleInfo, ClientBootstrapModuleServer}, + ClientBootstrapModule, ExtensionsExt, VoyagerClient, +}; +use voyager_vm::BoxDynError; + +#[tokio::main(flavor = "multi_thread")] +async fn main() { + Module::run().await +} + +#[derive(Debug, Clone)] +pub struct Module { + pub l2_chain_id: ChainId, + pub l1_client_id: u32, + pub l2_client_id: u32, + pub timestamp_offset: u16, + pub state_root_offset: u16, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct Config { + pub l1_client_id: u32, + pub l2_client_id: u32, + pub timestamp_offset: u16, + pub state_root_offset: u16, +} + +impl ClientBootstrapModule for Module { + type Config = Config; + + async fn new( + config: Self::Config, + info: ClientBootstrapModuleInfo, + ) -> Result { + Ok(Self { + l2_chain_id: info.chain_id, + l1_client_id: config.l1_client_id, + l2_client_id: config.l2_client_id, + timestamp_offset: config.timestamp_offset, + state_root_offset: config.state_root_offset, + }) + } +} + +#[async_trait] +impl ClientBootstrapModuleServer for Module { + #[instrument(skip_all, fields(chain_id = %self.l2_chain_id))] + async fn self_client_state(&self, _: &Extensions, height: Height) -> RpcResult { + Ok(into_value(ClientState { + l1_client_id: self.l1_client_id, + l2_chain_id: self.l2_chain_id.to_string(), + l2_client_id: self.l2_client_id, + l2_latest_height: height.height(), + extra: Extra { + timestamp_offset: self.timestamp_offset, + state_root_offset: self.state_root_offset, + }, + })) + } + + /// The consensus state on this chain at the specified `Height`. + #[instrument(skip_all, fields(chain_id = %self.l2_chain_id))] + async fn self_consensus_state(&self, ext: &Extensions, height: Height) -> RpcResult { + let voy_client = ext.try_get::()?; + let state = voy_client + .self_consensus_state( + self.l2_chain_id.clone(), + ClientType::new(ClientType::MOVEMENT), + QueryHeight::Specific(height), + ) + .await? + .state; + let consensus_state = + serde_json::from_value::(state).expect("big trouble"); + Ok(into_value(&ConsensusState { + timestamp: consensus_state.timestamp, + state_root: consensus_state.state_root, + })) + } +} From 321e4ec4d1f219a457d9915dc188d16deaaae651 Mon Sep 17 00:00:00 2001 From: aeryz Date: Wed, 22 Jan 2025 09:19:57 +0300 Subject: [PATCH 12/15] fix(voyager): don't send batch transactions in aptos --- voyager/plugins/transaction/aptos/src/main.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/voyager/plugins/transaction/aptos/src/main.rs b/voyager/plugins/transaction/aptos/src/main.rs index 51d72eb5dc..4400f8cb10 100644 --- a/voyager/plugins/transaction/aptos/src/main.rs +++ b/voyager/plugins/transaction/aptos/src/main.rs @@ -236,16 +236,16 @@ impl PluginServer for Module { let signed_tx = raw.sign(pk, pk.public_key()).unwrap(); dbg!(&signed_tx); + let res = self + .aptos_client + .submit(&signed_tx.clone().into_inner()) + .await + .unwrap(); + dbg!(&res); txs.push(signed_tx.into_inner()); } - dbg!(&txs); - - let res = self.aptos_client.submit_batch(&txs).await.unwrap(); - - dbg!(&res); - // res.into_inner().transaction_failures Ok(noop()) From 7fe84ae973203ed861c5e7de24aba1f0b76f8fe4 Mon Sep 17 00:00:00 2001 From: aeryz Date: Wed, 22 Jan 2025 09:20:31 +0300 Subject: [PATCH 13/15] chore(voyager): support multiple client types for movement --- Cargo.lock | 77 ++++++++++++++++++---- Cargo.toml | 6 +- voyager/modules/state/movement/src/main.rs | 8 ++- 3 files changed, 73 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cc230f8a46..615f5f34d7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2233,6 +2233,7 @@ dependencies = [ "ibc-union-msg", "ics23", "lazy_static", + "serde", "serde_json", "tendermint-light-client", "tendermint-verifier", @@ -11280,20 +11281,6 @@ dependencies = [ "unionlabs", ] -[[package]] -name = "state-lens-ics23-move-light-client-types" -version = "0.1.0" -dependencies = [ - "alloy", - "bincode 2.0.0-rc.3", - "hex-literal", - "protos", - "serde", - "state-lens-light-client-types", - "thiserror", - "unionlabs", -] - [[package]] name = "state-lens-ics23-mpt-light-client" version = "0.1.0" @@ -11330,6 +11317,20 @@ dependencies = [ "unionlabs", ] +[[package]] +name = "state-lens-ics23-smt-light-client-types" +version = "0.1.0" +dependencies = [ + "alloy", + "bincode 2.0.0-rc.3", + "hex-literal", + "protos", + "serde", + "state-lens-light-client-types", + "thiserror", + "unionlabs", +] + [[package]] name = "state-lens-light-client-types" version = "0.1.0" @@ -13019,6 +13020,7 @@ dependencies = [ "aptos-move-ibc", "aptos-rest-client", "chain-utils", + "cosmwasm-std 2.1.4", "jsonrpsee", "movement-light-client-types", "serde", @@ -13072,6 +13074,27 @@ dependencies = [ "voyager-vm", ] +[[package]] +name = "voyager-client-bootstrap-module-state-lens-ics23-smt" +version = "0.1.0" +dependencies = [ + "alloy", + "beacon-api", + "beacon-api-types", + "cometbft-rpc", + "ibc-union-spec", + "jsonrpsee", + "movement-light-client-types", + "serde", + "serde_json", + "state-lens-ics23-smt-light-client-types", + "tokio", + "tracing", + "unionlabs", + "voyager-message", + "voyager-vm", +] + [[package]] name = "voyager-client-bootstrap-module-tendermint" version = "0.1.0" @@ -13196,6 +13219,32 @@ dependencies = [ "voyager-vm", ] +[[package]] +name = "voyager-client-module-state-lens-ics23-smt" +version = "0.1.0" +dependencies = [ + "beacon-api-types", + "chain-utils", + "enumorph", + "ethereum-light-client-types", + "futures", + "jsonrpsee", + "macros", + "prost 0.12.6", + "serde", + "serde-utils", + "serde_json", + "state-lens-ics23-smt-light-client-types", + "state-lens-light-client-types", + "thiserror", + "tokio", + "tracing", + "tracing-subscriber 0.3.18", + "unionlabs", + "voyager-message", + "voyager-vm", +] + [[package]] name = "voyager-client-module-tendermint" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 77f26838ac..1893721905 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -79,7 +79,7 @@ members = [ "lib/state-lens-ics23-mpt-light-client-types", "lib/state-lens-ics23-mpt-light-client-types", "lib/state-lens-ics23-ics23-light-client-types", - "lib/state-lens-ics23-move-light-client-types", + "lib/state-lens-ics23-smt-light-client-types", # these will all be re enabled and updated once ethereum-light-client is updated @@ -120,12 +120,14 @@ members = [ "voyager/modules/client/tendermint", "voyager/modules/client/state-lens/ics23-mpt", "voyager/modules/client/state-lens/ics23-ics23", + "voyager/modules/client/state-lens/ics23-smt", "voyager/modules/client-bootstrap/cometbls", "voyager/modules/client-bootstrap/ethereum", "voyager/modules/client-bootstrap/movement", "voyager/modules/client-bootstrap/tendermint", "voyager/modules/client-bootstrap/state-lens/ics23-mpt", + "voyager/modules/client-bootstrap/state-lens/ics23-smt", "voyager/modules/client-bootstrap/state-lens/ics23-ics23", "voyager/modules/consensus/berachain", @@ -225,7 +227,7 @@ scroll-rpc = { path = "lib/scroll-rpc", default-features = fal state-lens-ics23-ics23-light-client-types = { path = "lib/state-lens-ics23-ics23-light-client-types", default-features = false } state-lens-ics23-mpt-light-client-types = { path = "lib/state-lens-ics23-mpt-light-client-types", default-features = false } -state-lens-ics23-move-light-client-types = { path = "lib/state-lens-ics23-move-light-client-types", default-features = false } +state-lens-ics23-smt-light-client-types = { path = "lib/state-lens-ics23-smt-light-client-types", default-features = false } tendermint-light-client = { path = "cosmwasm/ibc-union/light-clients/tendermint", default-features = false } tendermint-light-client-types = { path = "lib/tendermint-light-client-types", default-features = false } diff --git a/voyager/modules/state/movement/src/main.rs b/voyager/modules/state/movement/src/main.rs index 09b3a9eda8..0926b6d78f 100644 --- a/voyager/modules/state/movement/src/main.rs +++ b/voyager/modules/state/movement/src/main.rs @@ -163,9 +163,13 @@ impl Module { #[async_trait] impl StateModuleServer for Module { #[instrument(skip_all, fields(chain_id = %self.chain_id))] - async fn client_info(&self, _: &Extensions, _client_id: u32) -> RpcResult { + async fn client_info(&self, _: &Extensions, client_id: u32) -> RpcResult { + let client_type = self + .client_id_to_type(self.ibc_handler_address.into(), None, (client_id,)) + .await + .map_err(rest_error_to_rpc_error)?; Ok(ClientInfo { - client_type: ClientType::new(ClientType::COMETBLS_GROTH16), + client_type: ClientType::new(client_type), ibc_interface: IbcInterface::new(IbcInterface::IBC_MOVE_APTOS), metadata: Default::default(), }) From dfb054af553e727b74dc04f659d76791d05f821d Mon Sep 17 00:00:00 2001 From: aeryz Date: Wed, 22 Jan 2025 09:32:06 +0300 Subject: [PATCH 14/15] chore(voyager): fix encode/decode issues after rebase Signed-off-by: aeryz --- Cargo.lock | 2 +- .../src/client_state.rs | 58 +++++++++++++++++++ .../state-lens/ics23-smt/Cargo.toml | 2 +- .../state-lens/ics23-smt/src/main.rs | 2 +- .../client/state-lens/ics23-smt/Cargo.toml | 2 +- .../client/state-lens/ics23-smt/src/main.rs | 12 ++-- 6 files changed, 66 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 615f5f34d7..3d3cf124e7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13223,7 +13223,7 @@ dependencies = [ name = "voyager-client-module-state-lens-ics23-smt" version = "0.1.0" dependencies = [ - "beacon-api-types", + "alloy", "chain-utils", "enumorph", "ethereum-light-client-types", diff --git a/lib/state-lens-ics23-smt-light-client-types/src/client_state.rs b/lib/state-lens-ics23-smt-light-client-types/src/client_state.rs index c4610175dc..2a61181368 100644 --- a/lib/state-lens-ics23-smt-light-client-types/src/client_state.rs +++ b/lib/state-lens-ics23-smt-light-client-types/src/client_state.rs @@ -13,3 +13,61 @@ pub struct Extra { /// state_root = consensus_state[state_root_offset:state_root_offset+32] pub state_root_offset: u16, } + +#[cfg(feature = "ethabi")] +mod ethabi { + use alloy::{ + dyn_abi::SolType, + sol_types::{private::SolTypeValue, SolValue}, + }; + + use super::*; + + impl SolType for Extra { + type RustType = Self; + + type Token<'a> = <<::Tuple as SolValue>::SolType as SolType>::Token<'a>; + + const SOL_NAME: &'static str = "Extra"; + + const ENCODED_SIZE: Option = None; + + const PACKED_ENCODED_SIZE: Option = None; + + fn valid_token(_token: &Self::Token<'_>) -> bool { + true + } + + fn detokenize((timestamp_offset, state_root_offset): Self::Token<'_>) -> Self::RustType { + Self { + timestamp_offset: <::SolType as SolType>::detokenize( + timestamp_offset, + ), + state_root_offset: <::SolType as SolType>::detokenize( + state_root_offset, + ), + } + } + } + + impl SolValue for Extra { + type SolType = Self; + } + + impl SolTypeValue for Extra { + fn stv_to_tokens(&self) -> ::Token<'_> { + ( + <::SolType as SolType>::tokenize(&self.timestamp_offset), + <::SolType as SolType>::tokenize(&self.state_root_offset), + ) + } + + fn stv_abi_encode_packed_to(&self, _out: &mut Vec) { + todo!() + } + + fn stv_eip712_data_word(&self) -> alloy::sol_types::Word { + todo!() + } + } +} diff --git a/voyager/modules/client-bootstrap/state-lens/ics23-smt/Cargo.toml b/voyager/modules/client-bootstrap/state-lens/ics23-smt/Cargo.toml index 850252ee5e..0cbfe594ff 100644 --- a/voyager/modules/client-bootstrap/state-lens/ics23-smt/Cargo.toml +++ b/voyager/modules/client-bootstrap/state-lens/ics23-smt/Cargo.toml @@ -8,9 +8,9 @@ alloy = { workspace = true, features = ["rpc", beacon-api = { workspace = true } beacon-api-types = { workspace = true, features = ["serde"] } cometbft-rpc = { workspace = true } -movement-light-client-types = { workspace = true, features = ["serde"] } ibc-union-spec.workspace = true jsonrpsee = { workspace = true, features = ["macros", "server", "tracing"] } +movement-light-client-types = { workspace = true, features = ["serde"] } serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } state-lens-ics23-smt-light-client-types = { workspace = true, features = ["serde"] } diff --git a/voyager/modules/client-bootstrap/state-lens/ics23-smt/src/main.rs b/voyager/modules/client-bootstrap/state-lens/ics23-smt/src/main.rs index 7e498178da..17a5f03423 100644 --- a/voyager/modules/client-bootstrap/state-lens/ics23-smt/src/main.rs +++ b/voyager/modules/client-bootstrap/state-lens/ics23-smt/src/main.rs @@ -5,7 +5,7 @@ use jsonrpsee::{ use movement_light_client_types::ConsensusState as MovementConsensusState; use serde::{Deserialize, Serialize}; use serde_json::Value; -use state_lens_ics23_move_light_client_types::{client_state::Extra, ClientState, ConsensusState}; +use state_lens_ics23_smt_light_client_types::{client_state::Extra, ClientState, ConsensusState}; use tracing::instrument; use unionlabs::ibc::core::client::height::Height; use voyager_message::{ diff --git a/voyager/modules/client/state-lens/ics23-smt/Cargo.toml b/voyager/modules/client/state-lens/ics23-smt/Cargo.toml index d5c722c7d8..03712afc0a 100644 --- a/voyager/modules/client/state-lens/ics23-smt/Cargo.toml +++ b/voyager/modules/client/state-lens/ics23-smt/Cargo.toml @@ -4,7 +4,7 @@ name = "voyager-client-module-state-lens-ics23-smt" version = "0.1.0" [dependencies] -beacon-api-types = { workspace = true, features = ["serde"] } +alloy = { workspace = true, features = ["sol-types"] } chain-utils = { workspace = true } enumorph = { workspace = true } ethereum-light-client-types = { workspace = true, features = ["serde", "ethabi", "bincode"] } diff --git a/voyager/modules/client/state-lens/ics23-smt/src/main.rs b/voyager/modules/client/state-lens/ics23-smt/src/main.rs index 267bf0a7a0..87fcc8b6d4 100644 --- a/voyager/modules/client/state-lens/ics23-smt/src/main.rs +++ b/voyager/modules/client/state-lens/ics23-smt/src/main.rs @@ -1,4 +1,4 @@ -use ethereum_light_client_types::StorageProof; +use alloy::sol_types::SolValue; use jsonrpsee::{ core::{async_trait, RpcResult}, types::ErrorObject, @@ -6,7 +6,7 @@ use jsonrpsee::{ }; use serde::{Deserialize, Serialize}; use serde_json::{json, Value}; -use state_lens_ics23_move_light_client_types::{ClientState, ConsensusState}; +use state_lens_ics23_smt_light_client_types::{ClientState, ConsensusState}; use state_lens_light_client_types::Header; use tracing::instrument; use unionlabs::{ @@ -105,13 +105,9 @@ impl Module { } pub fn decode_client_state(&self, client_state: &[u8]) -> RpcResult { - println!( - "client_state: {:?}?", - ::decode_as::(client_state).unwrap() - ); match self.ibc_interface { SupportedIbcInterface::IbcSolidity => { - ::decode_as::(client_state).map_err(|err| { + ClientState::abi_decode_params(client_state, true).map_err(|err| { ErrorObject::owned( FATAL_JSONRPC_ERROR_CODE, format!("unable to decode client state: {err}"), @@ -208,7 +204,7 @@ impl ClientModuleServer for Module { ) }) .map(|cs| match self.ibc_interface { - SupportedIbcInterface::IbcSolidity => cs.encode_as::(), + SupportedIbcInterface::IbcSolidity => cs.abi_encode_params(), SupportedIbcInterface::IbcCosmwasm => cs.encode_as::(), }) .map(Into::into) From cf67d42082b8dfe6c49d68838baac53b6fe50b09 Mon Sep 17 00:00:00 2001 From: aeryz Date: Wed, 22 Jan 2025 11:21:07 +0300 Subject: [PATCH 15/15] chore: pr fixes Signed-off-by: aeryz --- evm/scripts/Deploy.s.sol | 26 ----------- lib/voyager-core/src/lib.rs | 2 +- move/move-ibc/sources/ics23.move | 10 ---- move/move-ibc/sources/light_client.move | 46 ++++++++++--------- move/move-ibc/sources/state_lens_lc.move | 11 ----- .../client-bootstrap/movement/src/main.rs | 6 +++ .../client/state-lens/ics23-smt/src/main.rs | 16 +++---- voyager/plugins/transaction/aptos/src/main.rs | 2 + 8 files changed, 39 insertions(+), 80 deletions(-) diff --git a/evm/scripts/Deploy.s.sol b/evm/scripts/Deploy.s.sol index 5a6ccda390..7397b0c154 100644 --- a/evm/scripts/Deploy.s.sol +++ b/evm/scripts/Deploy.s.sol @@ -494,32 +494,6 @@ contract DeployStateLensIcs23SmtClient is UnionScript { } } -contract RegisterIcs23SmtClient is Script { - using LibString for *; - - address immutable handler; - address immutable client; - - constructor() { - handler = vm.envAddress("IBC_HANDLER"); - client = vm.envAddress("CLIENT"); - } - - function run() public { - uint256 privateKey = vm.envUint("PRIVATE_KEY"); - - address owner = vm.addr(privateKey); - - vm.startBroadcast(privateKey); - - IBCHandler(handler).registerClient( - LightClients.STATE_LENS_ICS23_SMT, StateLensIcs23SmtClient(client) - ); - - vm.stopBroadcast(); - } -} - contract DeployIBC is UnionScript { Deployer immutable deployer; diff --git a/lib/voyager-core/src/lib.rs b/lib/voyager-core/src/lib.rs index 5abe55a392..ba673af98c 100644 --- a/lib/voyager-core/src/lib.rs +++ b/lib/voyager-core/src/lib.rs @@ -127,7 +127,7 @@ impl ClientType { /// [ICS23]: https://github.com/cosmos/ics23 pub const STATE_LENS_ICS23_ICS23: &'static str = "state-lens/ics23/ics23"; - /// A client tracking a [Aptos] chain, verified through that chain's consensus as + /// A client tracking an [Aptos] chain, verified through that chain's consensus as /// settled on an intermediary [ICS-23] chain. /// /// [ICS23]: https://github.com/cosmos/ics23 diff --git a/move/move-ibc/sources/ics23.move b/move/move-ibc/sources/ics23.move index 574d948dc8..5a32f75155 100644 --- a/move/move-ibc/sources/ics23.move +++ b/move/move-ibc/sources/ics23.move @@ -308,14 +308,4 @@ module ibc::ics23 { // ) // ); // } - - #[test] - fun test_decode() { - let mem_proof = - decode_membership_proof( - x"4103f64b1e5af826603673cac212ceedb720fb845c66aa7ce71ca304905ad66b6e518f45ebee8d9b85345cea31097b92cbe2ad1bdf6f28edb6d678edc90beb33a45f20c157348fc7d075310f7d6c66f776051837111fda874a1dd3028d1194bc0b84d0060002b691e7020c070204b691e7022021202e60f5d93b1af14ad194d1d178ef53a7c52a101f441d23be54545ec1d96c011b280408b691e702202474ff5887b23d801a16c134c792f21ff3ce9251de3bd3c7a625b76fe3a9b6582000070610b691e702202120464094ac3afa7acaf1b44f50c789b7317cb2562054e1825833d206e68be2dce8070816b691e7022021207a543411b7ab4cdc2c61d08600d81e0b6847b7f9e3af92458b970ce1b0d11098070a2eb691e702202120b6c279988f0719237378323464860c08b562866b18c9d6867fdf727061aa3f01070e66b691e702202120a060f1df88ed45d0933ff584fb79db0118a81695d4a1f221b07965c209479ec22910d401b691e70220b3c357c7c3f497292320aa40d8fdfea78a04c7014b3ecaa401d06a78e280a04820000812d203b691e7022021202f751293c3774c7b9851a9659b59814a10accecd2466c319ea80ad894c62dcd229148006b691e7022065b3fe92c7d5951d8d020fce65f3d752fe654e1b718989ee7ea2f5dc130165e6200029168e0cb691e70220919a75b56ea1cd4ade3fa2a5abf5f532d1a60a7373426e65f1d99403bc97dd6c2000081aaa1ab691e7022021205eb5a5643abe553a8d412f00434bbd2a478f8b09ce6e34598ad81a258522b999291cb63bb691e70220cebfbcee54dc4bc8e5c9f92883f68fd9f61aaa598053d10acdcf011e6b5043e82000047761736d20c72e21ec48b1a939c2e222550a28351efc670e599748959ad2c048c23bcf8d2d01000221012d4d7964d98298ac3383588a55b5464f8633ef52c99a2e6b35ccf97228db77a3002101e30f8d11d327eee46be8cd501e84c9a96e9b35baccd92a81999fdf5915a1dd4200" - ); - std::debug::print(&vector::is_empty(&mem_proof.sub_proof.leaf_prefix)); - std::debug::print(&vector::is_empty(&mem_proof.top_level_proof.leaf_prefix)); - } } diff --git a/move/move-ibc/sources/light_client.move b/move/move-ibc/sources/light_client.move index 2d812a25d3..6eec8618dd 100644 --- a/move/move-ibc/sources/light_client.move +++ b/move/move-ibc/sources/light_client.move @@ -4,6 +4,8 @@ module ibc::light_client { use std::string::{Self, String}; const E_UNKNOWN_CLIENT_TYPE: u64 = 1; + const CLIENT_TYPE_STATE_LENS_ICS23_MPT: vector = b"state-lens/ics23/mpt"; + const CLIENT_TYPE_COMETBLS: vector = b"cometbls"; public fun create_client( client_type: String, @@ -12,7 +14,7 @@ module ibc::light_client { client_state_bytes: vector, consensus_state_bytes: vector ): (vector, vector) { - if (string::bytes(&client_type) == &b"cometbls") { + if (string::bytes(&client_type) == &CLIENT_TYPE_COMETBLS) { let (client_state, consensus_state) = cometbls_lc::create_client( ibc_signer, @@ -21,7 +23,7 @@ module ibc::light_client { consensus_state_bytes ); return (client_state, consensus_state) - } else if (string::bytes(&client_type) == &b"state-lens/ics23/mpt") { + } else if (string::bytes(&client_type) == &CLIENT_TYPE_STATE_LENS_ICS23_MPT) { let (client_state, consensus_state) = statelens_lc::create_client( ibc_signer, @@ -36,9 +38,9 @@ module ibc::light_client { } public fun status(client_type: String, client_id: u32): u64 { - if (string::bytes(&client_type) == &b"cometbls") { + if (string::bytes(&client_type) == &CLIENT_TYPE_COMETBLS) { return cometbls_lc::status(client_id) - } else if (string::bytes(&client_type) == &b"state-lens/ics23/mpt") { + } else if (string::bytes(&client_type) == &CLIENT_TYPE_STATE_LENS_ICS23_MPT) { return statelens_lc::status(client_id) }; abort E_UNKNOWN_CLIENT_TYPE @@ -46,9 +48,9 @@ module ibc::light_client { } public fun latest_height(client_type: String, client_id: u32): u64 { - if (string::bytes(&client_type) == &b"cometbls") { + if (string::bytes(&client_type) == &CLIENT_TYPE_COMETBLS) { return cometbls_lc::latest_height(client_id) - } else if (string::bytes(&client_type) == &b"state-lens/ics23/mpt") { + } else if (string::bytes(&client_type) == &CLIENT_TYPE_STATE_LENS_ICS23_MPT) { return statelens_lc::latest_height(client_id) }; abort E_UNKNOWN_CLIENT_TYPE @@ -57,9 +59,9 @@ module ibc::light_client { public fun check_for_misbehaviour( client_type: String, client_id: u32, header: vector ): bool { - if (string::bytes(&client_type) == &b"cometbls") { + if (string::bytes(&client_type) == &CLIENT_TYPE_COMETBLS) { return cometbls_lc::check_for_misbehaviour(client_id, header) - } else if (string::bytes(&client_type) == &b"state-lens/ics23/mpt") { + } else if (string::bytes(&client_type) == &CLIENT_TYPE_STATE_LENS_ICS23_MPT) { return statelens_lc::check_for_misbehaviour(client_id, header) }; abort E_UNKNOWN_CLIENT_TYPE @@ -68,9 +70,9 @@ module ibc::light_client { public fun update_client( client_type: String, client_id: u32, client_msg: vector ): (vector, vector>, vector) { - if (string::bytes(&client_type) == &b"cometbls") { + if (string::bytes(&client_type) == &CLIENT_TYPE_COMETBLS) { return cometbls_lc::update_client(client_id, client_msg) - } else if (string::bytes(&client_type) == &b"state-lens/ics23/mpt") { + } else if (string::bytes(&client_type) == &CLIENT_TYPE_STATE_LENS_ICS23_MPT) { return statelens_lc::update_client(client_id, client_msg) }; abort E_UNKNOWN_CLIENT_TYPE @@ -79,9 +81,9 @@ module ibc::light_client { public fun report_misbehaviour( client_type: String, client_id: u32, misbehaviour: vector ) { - if (string::bytes(&client_type) == &b"cometbls") { + if (string::bytes(&client_type) == &CLIENT_TYPE_COMETBLS) { cometbls_lc::report_misbehaviour(client_id, misbehaviour) - } else if (string::bytes(&client_type) == &b"state-lens/ics23/mpt") { + } else if (string::bytes(&client_type) == &CLIENT_TYPE_STATE_LENS_ICS23_MPT) { statelens_lc::report_misbehaviour(client_id, misbehaviour) }; abort E_UNKNOWN_CLIENT_TYPE @@ -90,18 +92,18 @@ module ibc::light_client { public fun get_timestamp_at_height( client_type: String, client_id: u32, height: u64 ): u64 { - if (string::bytes(&client_type) == &b"cometbls") { + if (string::bytes(&client_type) == &CLIENT_TYPE_COMETBLS) { return cometbls_lc::get_timestamp_at_height(client_id, height) - } else if (string::bytes(&client_type) == &b"state-lens/ics23/mpt") { + } else if (string::bytes(&client_type) == &CLIENT_TYPE_STATE_LENS_ICS23_MPT) { return statelens_lc::get_timestamp_at_height(client_id, height) }; abort E_UNKNOWN_CLIENT_TYPE } public fun get_client_state(client_type: String, client_id: u32): vector { - if (string::bytes(&client_type) == &b"cometbls") { + if (string::bytes(&client_type) == &CLIENT_TYPE_COMETBLS) { return cometbls_lc::get_client_state(client_id) - } else if (string::bytes(&client_type) == &b"state-lens/ics23/mpt") { + } else if (string::bytes(&client_type) == &CLIENT_TYPE_STATE_LENS_ICS23_MPT) { return statelens_lc::get_client_state(client_id) }; abort E_UNKNOWN_CLIENT_TYPE @@ -110,9 +112,9 @@ module ibc::light_client { public fun get_consensus_state( client_type: String, client_id: u32, height: u64 ): vector { - if (string::bytes(&client_type) == &b"cometbls") { + if (string::bytes(&client_type) == &CLIENT_TYPE_COMETBLS) { return cometbls_lc::get_consensus_state(client_id, height) - } else if (string::bytes(&client_type) == &b"state-lens/ics23/mpt") { + } else if (string::bytes(&client_type) == &CLIENT_TYPE_STATE_LENS_ICS23_MPT) { return statelens_lc::get_consensus_state(client_id, height) }; abort E_UNKNOWN_CLIENT_TYPE @@ -126,9 +128,9 @@ module ibc::light_client { key: vector, value: vector ): u64 { - if (string::bytes(&client_type) == &b"cometbls") { + if (string::bytes(&client_type) == &CLIENT_TYPE_COMETBLS) { return cometbls_lc::verify_membership(client_id, height, proof, key, value) - } else if (string::bytes(&client_type) == &b"state-lens/ics23/mpt") { + } else if (string::bytes(&client_type) == &CLIENT_TYPE_STATE_LENS_ICS23_MPT) { return statelens_lc::verify_membership(client_id, height, proof, key, value) }; abort E_UNKNOWN_CLIENT_TYPE @@ -141,9 +143,9 @@ module ibc::light_client { proof: vector, path: vector ): u64 { - if (string::bytes(&client_type) == &b"cometbls") { + if (string::bytes(&client_type) == &CLIENT_TYPE_COMETBLS) { return cometbls_lc::verify_non_membership(client_id, height, proof, path) - } else if (string::bytes(&client_type) == &b"state-lens/ics23/mpt") { + } else if (string::bytes(&client_type) == &CLIENT_TYPE_STATE_LENS_ICS23_MPT) { return statelens_lc::verify_non_membership(client_id, height, proof, path) }; abort E_UNKNOWN_CLIENT_TYPE diff --git a/move/move-ibc/sources/state_lens_lc.move b/move/move-ibc/sources/state_lens_lc.move index df01713c58..b3d6f5385d 100644 --- a/move/move-ibc/sources/state_lens_lc.move +++ b/move/move-ibc/sources/state_lens_lc.move @@ -294,15 +294,4 @@ module ibc::statelens_lc { object::create_object_address(&vault_addr, bcs::to_bytes(&client_id)) } - - #[test] - fun decode_test() { - let client_state = x"0531373030300100000013000000e898300000000000000020004000"; - let client_state = decode_client_state(client_state); - let consensus_state = - x"000000000000000000000000000000000000000000000000181c75935aab8000f5c411575dae56d013ca1b7626896a9e96b457c14043091768d3d021fd5ebf333a42f6ef5bdc9ebe38b19ba1b8578f6e20e2a552bba787951c185159c721a165"; - let consensus_state = decode_consensus_state(consensus_state); - std::debug::print(&client_state); - std::debug::print(&consensus_state); - } } diff --git a/voyager/modules/client-bootstrap/movement/src/main.rs b/voyager/modules/client-bootstrap/movement/src/main.rs index 5a8f4fa28d..4de477a2e9 100644 --- a/voyager/modules/client-bootstrap/movement/src/main.rs +++ b/voyager/modules/client-bootstrap/movement/src/main.rs @@ -108,6 +108,12 @@ pub struct Config { pub movement_rest_url: String, /// The relayers that are allowed to modify this light client + /// + /// Note that the light client had to be permissioned for now since + /// we are waiting for our [PR] to be merged so that we can fetch + /// the necessary proofs. + /// + /// [PR]: https://github.com/movementlabsxyz/movement/pull/645 pub whitelisted_relayers: Vec, } diff --git a/voyager/modules/client/state-lens/ics23-smt/src/main.rs b/voyager/modules/client/state-lens/ics23-smt/src/main.rs index 87fcc8b6d4..ff0323d305 100644 --- a/voyager/modules/client/state-lens/ics23-smt/src/main.rs +++ b/voyager/modules/client/state-lens/ics23-smt/src/main.rs @@ -90,12 +90,9 @@ impl ClientModule for Module { } } -type SelfConsensusState = ConsensusState; -type SelfClientState = ClientState; - impl Module { - pub fn decode_consensus_state(consensus_state: &[u8]) -> RpcResult { - SelfConsensusState::decode_as::(consensus_state).map_err(|err| { + pub fn decode_consensus_state(consensus_state: &[u8]) -> RpcResult { + ConsensusState::decode_as::(consensus_state).map_err(|err| { ErrorObject::owned( FATAL_JSONRPC_ERROR_CODE, format!("unable to decode consensus state: {err}"), @@ -104,7 +101,7 @@ impl Module { }) } - pub fn decode_client_state(&self, client_state: &[u8]) -> RpcResult { + pub fn decode_client_state(&self, client_state: &[u8]) -> RpcResult { match self.ibc_interface { SupportedIbcInterface::IbcSolidity => { ClientState::abi_decode_params(client_state, true).map_err(|err| { @@ -115,15 +112,14 @@ impl Module { ) }) } - SupportedIbcInterface::IbcCosmwasm => { - ::decode_as::(client_state).map_err(|err| { + SupportedIbcInterface::IbcCosmwasm => ::decode_as::(client_state) + .map_err(|err| { ErrorObject::owned( FATAL_JSONRPC_ERROR_CODE, format!("unable to decode client state: {err}"), None::<()>, ) - }) - } + }), } } diff --git a/voyager/plugins/transaction/aptos/src/main.rs b/voyager/plugins/transaction/aptos/src/main.rs index 4400f8cb10..13e9f9c3cd 100644 --- a/voyager/plugins/transaction/aptos/src/main.rs +++ b/voyager/plugins/transaction/aptos/src/main.rs @@ -235,6 +235,8 @@ impl PluginServer for Module { let signed_tx = raw.sign(pk, pk.public_key()).unwrap(); + // TODO(aeryz): we normally should've send a batch transaction but + // movement don't allow it now. dbg!(&signed_tx); let res = self .aptos_client