Skip to content

Commit

Permalink
generic state lens client state type (#3574)
Browse files Browse the repository at this point in the history
  • Loading branch information
benluelo authored Jan 17, 2025
2 parents 0543024 + ddcb0f1 commit 2ba0e29
Show file tree
Hide file tree
Showing 24 changed files with 817 additions and 465 deletions.
12 changes: 12 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,7 @@ tendermint-rpc = { git = "https://github.com/unionlabs/tendermint-rs", branch =

alloy = { version = "0.6", default-features = false }
alloy-primitives = { version = "0.8.16", default-features = false }
alloy-sol-types = { version = "0.8.12", default-features = true }

# https://github.com/aptos-labs/aptos-core/pull/12636
aptos-crypto = { git = "https://github.com/unionlabs/aptos-core" }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,17 +133,17 @@ impl IbcClient for StateLensIcs23MptLightClient {

let l2_timestamp = extract_uint64(
&header.l2_consensus_state,
client_state.timestamp_offset as usize,
client_state.extra.timestamp_offset as usize,
);

let l2_state_root = extract_bytes32(
&header.l2_consensus_state,
client_state.state_root_offset as usize,
client_state.extra.state_root_offset as usize,
);

let l2_storage_root = extract_bytes32(
&header.l2_consensus_state,
client_state.storage_root_offset as usize,
client_state.extra.storage_root_offset as usize,
);

if client_state.l2_latest_height < header.l2_height.height() {
Expand Down
2 changes: 1 addition & 1 deletion lib/create3/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ version = "0.1.0"

[dependencies]
alloy-primitives = { workspace = true }
alloy-sol-types = "0.8.12"
alloy-sol-types = { workspace = true }
sha3.workspace = true

[lints]
Expand Down
78 changes: 76 additions & 2 deletions lib/macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ use syn::{
punctuated::Punctuated,
spanned::Spanned,
Attribute, Data, DeriveInput, Expr, ExprPath, Field, Fields, GenericParam, Generics, Ident,
Item, ItemEnum, ItemStruct, LitStr, MacroDelimiter, Meta, MetaList, Path, Token, Type, Variant,
WhereClause, WherePredicate,
Index, Item, ItemEnum, ItemStruct, LitStr, MacroDelimiter, Meta, MetaList, Path, Token, Type,
Variant, WhereClause, WherePredicate,
};

#[proc_macro_attribute]
Expand Down Expand Up @@ -1107,3 +1107,77 @@ fn parse_ibc_path(path: LitStr) -> Vec<Segment> {
})
.collect()
}

#[proc_macro_derive(AsTuple)]
pub fn as_tuple(ts: TokenStream) -> TokenStream {
derive_as_tuple(parse_macro_input!(ts as DeriveInput))
// .inspect(|x| println!("{x}"))
.map_err(|e| e.into_compile_error())
.unwrap_or_else(convert::identity)
.into()
}

fn derive_as_tuple(
DeriveInput {
ident,
generics,
data,
..
}: DeriveInput,
) -> Result<proc_macro2::TokenStream, syn::Error> {
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();

let Data::Struct(data_struct) = data else {
return Err(syn::Error::new(
Span::call_site(),
"only structs are supported",
));
};

let (into_tuple_fields, as_tuple_fields, from_tuple_fields) = (
data_struct.fields.members(),
data_struct.fields.members(),
data_struct.fields.members(),
);

let field_types = data_struct.fields.iter().map(|f| &f.ty);

let from_tuple_tuple_idxs = data_struct
.fields
.members()
.enumerate()
.map(|(idx, _)| Index::from(idx));

Ok(quote! {
const _: () = {
#[automatically_derived]
impl #impl_generics ::unionlabs::tuple::AsTuple for #ident #ty_generics #where_clause {
type Tuple = (#(#field_types,)*);

fn as_tuple(&self) -> <Self::Tuple as ::unionlabs::tuple::Tuple>::Ref<'_> {
(
#(
&self.#as_tuple_fields,
)*
)
}

fn into_tuple(self) -> Self::Tuple {
(
#(
self.#into_tuple_fields,
)*
)
}

fn from_tuple(tuple: Self::Tuple) -> Self {
Self {
#(
#from_tuple_fields: tuple.#from_tuple_tuple_idxs,
)*
}
}
}
};
})
}
16 changes: 9 additions & 7 deletions lib/state-lens-ics23-ics23-light-client-types/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,18 @@ name = "state-lens-ics23-ics23-light-client-types"
version = "0.1.0"

[dependencies]
alloy = { workspace = true, features = ["sol-types"], optional = true }
protos = { workspace = true, optional = true, features = ["proto_full", "serde"] }
serde = { workspace = true, optional = true, features = ["derive"] }
thiserror = { workspace = true }
unionlabs = { workspace = true, features = ["ethabi", "proto"] }
alloy = { workspace = true, optional = true, features = ["sol-types"] }
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 }

[dev-dependencies]
hex-literal = { workspace = true }

[features]
default = []
ethabi = ["unionlabs/ethabi", "dep:alloy", "dep:protos"]
serde = ["dep:serde"]

ethabi = ["unionlabs/ethabi", "dep:alloy", "dep:protos", "state-lens-light-client-types/ethabi"]
serde = ["dep:serde", "state-lens-light-client-types/serde"]
89 changes: 5 additions & 84 deletions lib/state-lens-ics23-ics23-light-client-types/src/client_state.rs
Original file line number Diff line number Diff line change
@@ -1,89 +1,10 @@
use unionlabs::primitives::H256;
use unionlabs::{primitives::H256, tuple::AsTuple};

#[derive(Debug, Clone, PartialEq)]
pub type ClientState = state_lens_light_client_types::ClientState<Extra>;

#[derive(Debug, Clone, PartialEq, AsTuple)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct ClientState {
/// l2 chain id
pub l2_chain_id: String,
/// l1 client id used to check the l2 inclusion proof against
pub l1_client_id: u32,
/// l2 client id
pub l2_client_id: u32,
/// l2 latest height
pub l2_latest_height: u64,
pub struct Extra {
/// ibc contract that is running on l2
pub contract_address: H256,
}

#[cfg(feature = "ethabi")]
pub mod ethabi {
use core::str;
use std::string::FromUtf8Error;

use alloy::sol_types::SolValue;
use unionlabs::{
encoding::{Decode, Encode, EthAbi},
TryFromEthAbiBytesErrorAlloy,
};

use crate::ClientState;

alloy::sol! {
struct SolClientState {
string l2ChainId;
uint32 l1ClientId;
uint32 l2ClientId;
uint64 l2LatestHeight;
bytes32 contractAddress;
}
}

impl Encode<EthAbi> for ClientState {
fn encode(self) -> Vec<u8> {
SolClientState {
l2ChainId: self.l2_chain_id,
l1ClientId: self.l1_client_id,
l2ClientId: self.l2_client_id,
l2LatestHeight: self.l2_latest_height,
contractAddress: self.contract_address.into(),
}
.abi_encode_params()
}
}

impl Decode<EthAbi> for ClientState {
type Error = TryFromEthAbiBytesErrorAlloy<Error>;

fn decode(bytes: &[u8]) -> Result<Self, Self::Error> {
let client_state = SolClientState::abi_decode_params(bytes, true)?;

Ok(Self {
l2_chain_id: String::from_utf8(client_state.l2ChainId.into_bytes())
.map_err(|err| TryFromEthAbiBytesErrorAlloy::Convert(Error::ChainId(err)))?,
l1_client_id: client_state.l1ClientId,
l2_client_id: client_state.l2ClientId,
l2_latest_height: client_state.l2LatestHeight,
contract_address: client_state.contractAddress.into(),
})
}
}

#[derive(Debug, Clone, PartialEq, thiserror::Error)]
pub enum Error {
#[error("invalid chain_id")]
ChainId(#[from] FromUtf8Error),
}

#[cfg(test)]
mod test {
#[test]
fn test_decode() {
// TODO(aeryz): impl
}

#[test]
fn test_encode() {
// TODO(aeryz): impl
}
}
}
Loading

0 comments on commit 2ba0e29

Please sign in to comment.