Skip to content

Commit

Permalink
chore: fix cometbls ethabi encodings
Browse files Browse the repository at this point in the history
  • Loading branch information
benluelo committed Dec 4, 2024
1 parent d73ca08 commit 67448b9
Show file tree
Hide file tree
Showing 6 changed files with 214 additions and 48 deletions.
4 changes: 1 addition & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -144,9 +144,7 @@ members = [

"drip",

# "cosmwasm/union-ibc/light-clients/movement",
"cosmwasm/union-ibc/light-clients/movement/types",
"lib/aptos-verifier",
# "lib/aptos-verifier",

"lib/reconnecting-jsonrpc-ws-client",
"lib/voyager-core",
Expand Down
8 changes: 4 additions & 4 deletions cosmwasm/union-ibc/light-clients/cometbls/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,13 +214,13 @@ fn verify_header<T: ZkpVerifier>(
.into());
}

Ok(T::verify_zkp(
T::verify_zkp(
&client_state.chain_id,
trusted_validators_hash.into_encoding(),
&header.signed_header,
&header.zero_knowledge_proof,
)
.map_err(Error::InvalidZKP)?)
.map_err(Error::InvalidZKP)
}

fn verify_misbehaviour<T: ZkpVerifier>(
Expand All @@ -231,7 +231,7 @@ fn verify_misbehaviour<T: ZkpVerifier>(
misbehaviour: Misbehaviour,
) -> Result<(), Error> {
if misbehaviour.header_a.signed_header.height < misbehaviour.header_b.signed_header.height {
return Err(Error::InvalidMisbehaviourHeaderSequence.into());
return Err(Error::InvalidMisbehaviourHeaderSequence);
}

verify_header(ctx, client_state, consensus_state_a, &misbehaviour.header_a)?;
Expand All @@ -247,7 +247,7 @@ fn verify_misbehaviour<T: ZkpVerifier>(
return Ok(());
}

Err(Error::MisbehaviourNotFound.into())
Err(Error::MisbehaviourNotFound)
}

fn update_state(
Expand Down
63 changes: 63 additions & 0 deletions lib/cometbls-light-client-types/src/client_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,66 @@ pub mod proto {
}
}
}

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

use alloy::sol_types::SolValue;
use unionlabs::{
encoding::{Decode, Encode, EthAbi},
ibc::core::client::height::Height,
TryFromEthAbiBytesErrorAlloy,
};

use crate::{ChainId, ClientState};

alloy::sol! {
struct SolClientState {
bytes31 chainId;
uint64 trustingPeriod;
uint64 maxClockDrift;
uint64 frozenHeight;
uint64 latestHeight;
bytes32 contractAddress;
}
}

impl Encode<EthAbi> for ClientState {
fn encode(self) -> Vec<u8> {
SolClientState {
chainId: self.chain_id.into_fixed_bytes(),
trustingPeriod: self.trusting_period,
maxClockDrift: self.max_clock_drift,
frozenHeight: self.frozen_height.height(),
latestHeight: self.latest_height.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(bytes, true)?;

Ok(Self {
chain_id: ChainId::try_from_fixed_bytes(client_state.chainId)
.map_err(|err| TryFromEthAbiBytesErrorAlloy::Convert(Error::ChainId(err)))?,
trusting_period: client_state.trustingPeriod,
max_clock_drift: client_state.maxClockDrift,
frozen_height: Height::new(client_state.frozenHeight),
latest_height: Height::new(client_state.latestHeight),
contract_address: client_state.contractAddress.into(),
})
}
}

#[derive(Debug, Clone, PartialEq, thiserror::Error)]
pub enum Error {
#[error("invalid chain_id")]
ChainId(#[from] FromUtf8Error),
}
}
80 changes: 40 additions & 40 deletions lib/cometbls-light-client-types/src/consensus_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,46 +11,6 @@ pub struct ConsensusState {
pub next_validators_hash: H256<HexUnprefixed>,
}

#[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 app_hash;
bytes32 next_validators_hash;
}
}

impl From<ConsensusState> for SolConsensusState {
fn from(value: ConsensusState) -> Self {
Self {
timestamp: value.timestamp,
app_hash: value.app_hash.hash.get().into(),
next_validators_hash: value.next_validators_hash.get().into(),
}
}
}

impl From<SolConsensusState> for ConsensusState {
fn from(value: SolConsensusState) -> Self {
Self {
timestamp: value.timestamp,
app_hash: MerkleRoot {
hash: H256::new(value.app_hash.0),
},
next_validators_hash: H256::new(value.next_validators_hash.0),
}
}
}
}

#[cfg(feature = "proto")]
pub mod proto {
use unionlabs::{
Expand Down Expand Up @@ -100,3 +60,43 @@ pub mod proto {
}
}
}

#[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 app_hash;
bytes32 next_validators_hash;
}
}

impl From<ConsensusState> for SolConsensusState {
fn from(value: ConsensusState) -> Self {
Self {
timestamp: value.timestamp,
app_hash: value.app_hash.hash.get().into(),
next_validators_hash: value.next_validators_hash.get().into(),
}
}
}

impl From<SolConsensusState> for ConsensusState {
fn from(value: SolConsensusState) -> Self {
Self {
timestamp: value.timestamp,
app_hash: MerkleRoot {
hash: H256::new(value.app_hash.0),
},
next_validators_hash: H256::new(value.next_validators_hash.0),
}
}
}
}
105 changes: 105 additions & 0 deletions lib/cometbls-light-client-types/src/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,111 @@ pub mod proto {
}
}

#[cfg(feature = "ethabi")]
pub mod ethabi {
use alloy::sol_types::SolValue;
use unionlabs::{
bounded::{BoundedI32, BoundedI64, BoundedIntError},
google::protobuf::timestamp::Timestamp,
ibc::core::client::height::Height,
impl_ethabi_via_try_from_into, TryFromEthAbiBytesErrorAlloy,
};

use crate::{Header, LightHeader};

impl_ethabi_via_try_from_into!(Header => SolHeader);

alloy::sol! {
struct SolSignedHeader {
uint64 height;
uint64 secs;
uint64 nanos;
bytes32 validatorsHash;
bytes32 nextValidatorsHash;
bytes32 appHash;
}

struct SolHeader {
SolSignedHeader signedHeader;
uint64 trustedHeight;
bytes zeroKnowledgeProof;
}
}

impl From<Header> for SolHeader {
fn from(value: Header) -> Self {
SolHeader {
signedHeader: SolSignedHeader {
height: value
.signed_header
.height
.inner()
.try_into()
.expect("value is >= 0 and <= i64::MAX; qed;"),
secs: value
.signed_header
.time
.seconds
.inner()
// TODO: Figure out a better way to represent these types other than by saturating
.clamp(0, i64::MAX)
.try_into()
.expect("value is >= 0 and <= i64::MAX; qed;"),
nanos: value
.signed_header
.time
.nanos
.inner()
.try_into()
.expect("value is >= 0 and <= i32::MAX; qed;"),
validatorsHash: value.signed_header.validators_hash.into(),
nextValidatorsHash: value.signed_header.next_validators_hash.into(),
appHash: value.signed_header.app_hash.into(),
},
trustedHeight: value.trusted_height.height(),
zeroKnowledgeProof: value.zero_knowledge_proof.into(),
}
}
}

impl TryFrom<SolHeader> for Header {
type Error = TryFromEthAbiBytesErrorAlloy<Error>;

fn try_from(value: SolHeader) -> Result<Self, Self::Error> {
Ok(Self {
signed_header: LightHeader {
height: BoundedI64::new(value.signedHeader.height)
.map_err(Error::Height)
.map_err(TryFromEthAbiBytesErrorAlloy::Convert)?,
time: Timestamp {
seconds: BoundedI64::new(value.signedHeader.secs)
.map_err(Error::Secs)
.map_err(TryFromEthAbiBytesErrorAlloy::Convert)?,
nanos: BoundedI32::new(value.signedHeader.nanos)
.map_err(Error::Nanos)
.map_err(TryFromEthAbiBytesErrorAlloy::Convert)?,
},
validators_hash: value.signedHeader.validatorsHash.into(),
next_validators_hash: value.signedHeader.nextValidatorsHash.into(),
app_hash: value.signedHeader.appHash.into(),
},
trusted_height: Height::new(value.trustedHeight),
zero_knowledge_proof: value.zeroKnowledgeProof.into(),
})
}
}

#[derive(Debug, Clone, PartialEq, thiserror::Error)]
pub enum Error {
#[error("invalid height")]
Height(#[source] BoundedIntError<i64, u64>),
#[error("invalid secs")]
Secs(#[source] BoundedIntError<i64, u64>),
#[error("invalid nanos")]
Nanos(#[source] BoundedIntError<i32, u64>),
}
}

#[cfg(test)]
mod tests {
use hex_literal::hex;
Expand Down
2 changes: 1 addition & 1 deletion voyager/modules/client/cometbls/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ ark-bn254 = { version = "0.4", default-features = false, featu
ark-serialize = "0.4.2"
clap = { workspace = true, features = ["default", "derive", "env", "error-context"] }
cometbft-rpc = { workspace = true }
cometbls-light-client-types = { workspace = true, features = ["proto", "ethabi"] }
cometbls-light-client-types = { workspace = true, features = ["proto", "ethabi", "serde"] }
dashmap = { workspace = true }
enumorph = { workspace = true }
futures = { workspace = true }
Expand Down

0 comments on commit 67448b9

Please sign in to comment.