Skip to content

Commit

Permalink
feat(cosmwasm): sibling eth lc (#2676)
Browse files Browse the repository at this point in the history
towards #2659 

in this PR:
- we introduce an evm light client derived from an L1 light client for
direct access to eth from cosmos chains
- we refactor the ABCI custom query to be reusable
  • Loading branch information
hussein-aitlahcen authored Aug 6, 2024
2 parents 515f5b7 + 9d78051 commit c744138
Show file tree
Hide file tree
Showing 22 changed files with 829 additions and 60 deletions.
13 changes: 13 additions & 0 deletions Cargo.lock

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

76 changes: 39 additions & 37 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ members = [
"light-clients/berachain-light-client",
"light-clients/cometbls-light-client",
"light-clients/ethereum-light-client",
"light-clients/evm-in-cosmos-light-client",
"light-clients/scroll-light-client",
"light-clients/tendermint-light-client",
"light-clients/linea-light-client",
Expand Down Expand Up @@ -93,43 +94,44 @@ opt-level = 3
strip = true

[workspace.dependencies]
arbitrum-verifier = { path = "lib/arbitrum-verifier", default-features = false }
beacon-api = { path = "lib/beacon-api", default-features = false }
block-message = { path = "lib/block-message", default-features = false }
chain-utils = { path = "lib/chain-utils", default-features = false }
cometbft-rpc = { path = "lib/cometbft-rpc", default-features = false }
cometbls-groth16-verifier = { path = "lib/cometbls-groth16-verifier", default-features = false }
contracts = { path = "generated/rust/contracts", default-features = false }
ethereum-light-client = { path = "light-clients/ethereum-light-client", default-features = false }
ethereum-verifier = { path = "lib/ethereum-verifier", default-features = false }
gnark-key-parser = { path = "lib/gnark-key-parser", default-features = false }
gnark-mimc = { path = "lib/gnark-mimc", default-features = false }
ibc-vm-rs = { path = "lib/ibc-vm-rs", default-features = false }
ics008-wasm-client = { path = "lib/ics-008-wasm-client", default-features = false }
ics23 = { path = "lib/ics23", default-features = false }
linea-verifier = { path = "lib/linea-verifier", default-features = false }
linea-zktrie = { path = "lib/linea-zktrie", default-features = false }
macros = { path = "lib/macros", default-features = false }
pg-queue = { path = "lib/pg-queue", default-features = false }
poseidon-rs = { path = "lib/poseidon-rs", default-features = false }
protos = { path = "generated/rust/protos", default-features = false }
queue-msg = { path = "lib/queue-msg", default-features = false }
queue-msg-macro = { path = "lib/queue-msg-macro", default-features = false }
relay-message = { path = "lib/relay-message", default-features = false }
scroll-api = { path = "lib/scroll-api", default-features = false }
scroll-codec = { path = "lib/scroll-codec", default-features = false }
scroll-rpc = { path = "lib/scroll-rpc", default-features = false }
scroll-verifier = { path = "lib/scroll-verifier", default-features = false }
serde-utils = { path = "lib/serde-utils", default-features = false }
ssz = { path = "lib/ssz", default-features = false }
ssz-derive = { path = "lib/ssz-derive", default-features = false }
tendermint-light-client = { path = "light-clients/tendermint-light-client", default-features = false }
tendermint-verifier = { path = "lib/tendermint-verifier", default-features = false }
token-factory-api = { path = "cosmwasm/token-factory-api", default-features = false }
ucs01-relay-api = { path = "cosmwasm/ucs01-relay-api", default-features = false }
unionlabs = { path = "lib/unionlabs", default-features = false }
voyager-message = { path = "lib/voyager-message", default-features = false }
zktrie = { path = "lib/zktrie-rs", default-features = false }
arbitrum-verifier = { path = "lib/arbitrum-verifier", default-features = false }
beacon-api = { path = "lib/beacon-api", default-features = false }
block-message = { path = "lib/block-message", default-features = false }
chain-utils = { path = "lib/chain-utils", default-features = false }
cometbft-rpc = { path = "lib/cometbft-rpc", default-features = false }
cometbls-groth16-verifier = { path = "lib/cometbls-groth16-verifier", default-features = false }
contracts = { path = "generated/rust/contracts", default-features = false }
ethereum-light-client = { path = "light-clients/ethereum-light-client", default-features = false }
ethereum-verifier = { path = "lib/ethereum-verifier", default-features = false }
evm-in-cosmos-light-client = { path = "light-clients/evm-in-cosmos-light-client", default-features = false }
gnark-key-parser = { path = "lib/gnark-key-parser", default-features = false }
gnark-mimc = { path = "lib/gnark-mimc", default-features = false }
ibc-vm-rs = { path = "lib/ibc-vm-rs", default-features = false }
ics008-wasm-client = { path = "lib/ics-008-wasm-client", default-features = false }
ics23 = { path = "lib/ics23", default-features = false }
linea-verifier = { path = "lib/linea-verifier", default-features = false }
linea-zktrie = { path = "lib/linea-zktrie", default-features = false }
macros = { path = "lib/macros", default-features = false }
pg-queue = { path = "lib/pg-queue", default-features = false }
poseidon-rs = { path = "lib/poseidon-rs", default-features = false }
protos = { path = "generated/rust/protos", default-features = false }
queue-msg = { path = "lib/queue-msg", default-features = false }
queue-msg-macro = { path = "lib/queue-msg-macro", default-features = false }
relay-message = { path = "lib/relay-message", default-features = false }
scroll-api = { path = "lib/scroll-api", default-features = false }
scroll-codec = { path = "lib/scroll-codec", default-features = false }
scroll-rpc = { path = "lib/scroll-rpc", default-features = false }
scroll-verifier = { path = "lib/scroll-verifier", default-features = false }
serde-utils = { path = "lib/serde-utils", default-features = false }
ssz = { path = "lib/ssz", default-features = false }
ssz-derive = { path = "lib/ssz-derive", default-features = false }
tendermint-light-client = { path = "light-clients/tendermint-light-client", default-features = false }
tendermint-verifier = { path = "lib/tendermint-verifier", default-features = false }
token-factory-api = { path = "cosmwasm/token-factory-api", default-features = false }
ucs01-relay-api = { path = "cosmwasm/ucs01-relay-api", default-features = false }
unionlabs = { path = "lib/unionlabs", default-features = false }
voyager-message = { path = "lib/voyager-message", default-features = false }
zktrie = { path = "lib/zktrie-rs", default-features = false }

# external dependencies
milagro_bls = { git = "https://github.com/Snowfork/milagro_bls", rev = "bc2b5b5e8d48b7e2e1bfaa56dc2d93e13cb32095", default-features = false }
Expand Down
1 change: 1 addition & 0 deletions dictionary.txt
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,7 @@ ethevent
ethkey
evidencekeeper
evidencetypes
evmincosmos
evmos
extldflags
extralight
Expand Down
1 change: 1 addition & 0 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,7 @@
./light-clients/arbitrum-light-client/arbitrum-light-client.nix
./light-clients/linea-light-client/linea-light-client.nix
./light-clients/berachain-light-client/berachain-light-client.nix
./light-clients/evm-in-cosmos-light-client/evm-in-cosmos-light-client.nix
./lib/cometbls-groth16-verifier/default.nix
./lib/linea-verifier/default.nix
./lib/linea-zktrie/default.nix
Expand Down
6 changes: 6 additions & 0 deletions generated/rust/protos/Cargo.toml

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

8 changes: 8 additions & 0 deletions generated/rust/protos/src/lib.rs

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

67 changes: 67 additions & 0 deletions generated/rust/protos/src/union.ibc.lightclients.evmincosmos.v1.rs

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

3 changes: 3 additions & 0 deletions hubble/src/chain_id_query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,9 @@ pub async fn tx(db: PgPool, indexers: Indexers) {

cs.chain_id().to_string()
}
WasmClientType::EvmInCosmos => {
todo!()
}
};

datas.push(Data {
Expand Down
89 changes: 66 additions & 23 deletions lib/unionlabs/src/cosmwasm/wasm/union/custom_query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use core::fmt::Debug;

use cosmwasm_std::{Binary, Deps, QueryRequest};

use crate::bls::BlsPublicKey;
use crate::{bls::BlsPublicKey, ibc::core::client::height::Height, ics24::Path};

#[derive(thiserror::Error, Debug, PartialEq, Clone)]
pub enum Error {
Expand All @@ -13,8 +13,11 @@ pub enum Error {
AggregatePublicKeys(String),
#[error("invalid public key is returned from `aggregate_public_key`")]
InvalidAggregatePublicKey,
#[error("error while running `consensus_state` query ({0})")]
ConsensusState(String),
#[error("abci query for {path} failed: {err}")]
ABCI {
path: Path<String, Height>,
err: String,
},
}

#[derive(serde::Serialize, serde::Deserialize, Clone)]
Expand Down Expand Up @@ -73,8 +76,8 @@ use {
crate::{
encoding::{Decode, DecodeAs, Proto},
google::protobuf::any::Any,
ibc::core::client::height::Height,
ics24::ClientConsensusStatePath,
ics24::{ClientConsensusStatePath, ClientStatePath},
traits::Id,
},
cosmwasm_std::{to_json_vec, ContractResult, Env, SystemResult},
prost::Message,
Expand All @@ -83,20 +86,16 @@ use {

#[allow(clippy::missing_panics_doc)]
#[cfg(feature = "stargate")]
pub fn query_consensus_state<T>(
pub fn query_ibc_abci<T>(
deps: Deps<UnionCustomQuery>,
env: &Env,
// TODO: Use ClientId here
client_id: String,
height: Height,
path: Path<String, Height>,
) -> Result<T, Error>
where
Any<T>: Decode<Proto>,
{
let query = protos::cosmos::base::tendermint::v1beta1::AbciQueryRequest {
data: ClientConsensusStatePath { client_id, height }
.to_string()
.into_bytes(),
data: path.clone().to_string().into_bytes(),
path: "store/ibc/key".to_string(),
height: env
.block
Expand All @@ -110,19 +109,63 @@ where
path: "/cosmos.base.tendermint.v1beta1.Service/ABCIQuery".into(),
data: query.encode_to_vec().into(),
})
.map_err(|e| Error::ConsensusState(format!("{e:?}")))?;
.map_err(|e| Error::ABCI {
path: path.clone(),
err: format!("{e:?}"),
})?;
let abci_response_data = match deps.querier.raw_query(&raw) {
SystemResult::Err(system_err) => Err(Error::ConsensusState(format!(
"Querier system error: {system_err}"
))),
SystemResult::Ok(ContractResult::Err(contract_err)) => Err(Error::ConsensusState(format!(
"Querier contract error: {contract_err}"
))),
SystemResult::Err(system_err) => Err(Error::ABCI {
path: path.clone(),
err: format!("Querier system error: {system_err}"),
}),
SystemResult::Ok(ContractResult::Err(contract_err)) => Err(Error::ABCI {
path: path.clone(),
err: format!("Querier contract error: {contract_err}"),
}),
SystemResult::Ok(ContractResult::Ok(value)) => Ok(value),
}?;
let abci_response = AbciQueryResponse::decode(abci_response_data.as_ref())
.map_err(|e| Error::ConsensusState(format!("{e:?}")))?;
let Any(value) = Any::<T>::decode_as::<Proto>(&abci_response.value)
.map_err(|e| Error::ConsensusState(format!("{e:?}")))?;
let abci_response =
AbciQueryResponse::decode(abci_response_data.as_ref()).map_err(|e| Error::ABCI {
path: path.clone(),
err: format!("AbciQueryResponse decoding: {e:?}"),
})?;
let Any(value) =
Any::<T>::decode_as::<Proto>(&abci_response.value).map_err(|e| Error::ABCI {
path,
err: format!("AnyProto decoding: {e:?}"),
})?;
Ok(value)
}

#[allow(clippy::missing_panics_doc)]
#[cfg(feature = "stargate")]
pub fn query_consensus_state<T>(
deps: Deps<UnionCustomQuery>,
env: &Env,
// TODO: Use ClientId here
client_id: String,
height: Height,
) -> Result<T, Error>
where
Any<T>: Decode<Proto>,
{
query_ibc_abci::<T>(
deps,
env,
Path::ClientConsensusState(ClientConsensusStatePath { client_id, height }),
)
}

#[allow(clippy::missing_panics_doc)]
#[cfg(feature = "stargate")]
pub fn query_client_state<T>(
deps: Deps<UnionCustomQuery>,
env: &Env,
// TODO: Use ClientId here
client_id: String,
) -> Result<T, Error>
where
Any<T>: Decode<Proto>,
{
query_ibc_abci::<T>(deps, env, Path::ClientState(ClientStatePath { client_id }))
}
1 change: 1 addition & 0 deletions lib/unionlabs/src/ibc/lightclients.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ pub mod arbitrum;
pub mod berachain;
pub mod cometbls;
pub mod ethereum;
pub mod evm_in_cosmos;
pub mod linea;
pub mod scroll;
pub mod tendermint;
Expand Down
3 changes: 3 additions & 0 deletions lib/unionlabs/src/ibc/lightclients/evm_in_cosmos.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub mod client_state;
pub mod consensus_state;
pub mod header;
Loading

0 comments on commit c744138

Please sign in to comment.