Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix to generate commitment in verify_membership #31

Merged
merged 1 commit into from
Nov 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions crates/ibc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ ssz-rs = { git = "https://github.com/bluele/ssz_rs", branch = "serde-no-std", de
hex = { version = "0.4.3", default-features = false }

ethereum-ibc-proto = { path = "../../proto", default-features = false }
ethereum-consensus = { git = "https://github.com/datachainlab/ethereum-light-client-rs", rev = "v0.1.6", default-features = false }
ethereum-light-client-verifier = { git = "https://github.com/datachainlab/ethereum-light-client-rs", rev = "v0.1.6", default-features = false }
ethereum-consensus = { git = "https://github.com/datachainlab/ethereum-light-client-rs", rev = "v0.1.7", default-features = false }
ethereum-light-client-verifier = { git = "https://github.com/datachainlab/ethereum-light-client-rs", rev = "v0.1.7", default-features = false }

[dev-dependencies]
time = { version = "0.3", default-features = false, features = ["macros", "parsing"] }
hex-literal = "0.4.1"
ethereum-light-client-verifier = { git = "https://github.com/datachainlab/ethereum-light-client-rs", rev = "v0.1.6", default-features = false, features = ["test-utils"] }
ethereum-light-client-verifier = { git = "https://github.com/datachainlab/ethereum-light-client-rs", rev = "v0.1.7", default-features = false, features = ["test-utils"] }
83 changes: 82 additions & 1 deletion crates/ibc/src/client_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ use ibc_proto::google::protobuf::Any;
use ibc_proto::protobuf::Protobuf;
use prost::Message;
use serde::{Deserialize, Serialize};
use tiny_keccak::{Hasher, Keccak};

/// The revision number for the Ethereum light client is always 0.
///
Expand Down Expand Up @@ -204,11 +205,12 @@ impl<const SYNC_COMMITTEE_SIZE: usize> ClientState<SYNC_COMMITTEE_SIZE> {
}
let key =
calculate_ibc_commitment_storage_location(&self.ibc_commitments_slot, path.clone());
let commitment = Self::keccak256(&value);
self.execution_verifier
.verify_membership(
root,
key.as_bytes(),
rlp::encode(&trim_left_zero(&value)).as_ref(),
rlp::encode(&trim_left_zero(commitment.as_bytes())).as_ref(),
proof.clone(),
)
.map_err(|e| ClientError::ClientSpecific {
Expand Down Expand Up @@ -314,6 +316,14 @@ impl<const SYNC_COMMITTEE_SIZE: usize> ClientState<SYNC_COMMITTEE_SIZE> {
Ok(())
}
}

fn keccak256(bz: &[u8]) -> H256 {
let mut hasher = Keccak::v256();
let mut output = [0u8; 32];
hasher.update(bz);
hasher.finalize(&mut output);
H256::from_slice(&output)
}
}

impl<const SYNC_COMMITTEE_SIZE: usize> Ics2ClientState for ClientState<SYNC_COMMITTEE_SIZE> {
Expand Down Expand Up @@ -1018,6 +1028,7 @@ fn verify_delay_passed(
#[cfg(test)]
mod tests {
use super::*;
use core::str::FromStr;
use ethereum_consensus::fork::{
altair::ALTAIR_FORK_SPEC, bellatrix::BELLATRIX_FORK_SPEC, capella::CAPELLA_FORK_SPEC,
deneb::DENEB_FORK_SPEC,
Expand Down Expand Up @@ -1124,6 +1135,76 @@ mod tests {
assert!(res.is_ok(), "{:?}", res);
}

#[test]
fn test_verify_membership() {
let client_state =
ClientState::<{ ethereum_consensus::preset::minimal::PRESET.SYNC_COMMITTEE_SIZE }> {
ibc_address: Address(hex!("a7f733a4fEA1071f58114b203F57444969b86524")),
ibc_commitments_slot: H256(hex!(
"1ee222554989dda120e26ecacf756fe1235cd8d726706b57517715dde4f0c900"
)),
latest_execution_block_number: 1.into(),
..Default::default()
};
let root = hex!("27cd08827e6bf1e435832f4b2660107beb562314287b3fa534f3b189574c0cca")
.to_vec()
.into();
let (path, proof, value) = get_membership_proof();
let proof_height = Height::new(ETHEREUM_CLIENT_REVISION_NUMBER, 1).unwrap();
let res = client_state.verify_membership(
proof_height,
&Default::default(),
&proof.try_into().unwrap(),
&root,
Path::from_str(&path).unwrap(),
value,
);
assert!(res.is_ok(), "{:?}", res);
}

#[test]
fn test_verify_non_membership() {
let client_state =
ClientState::<{ ethereum_consensus::preset::minimal::PRESET.SYNC_COMMITTEE_SIZE }> {
ibc_address: Address(hex!("a7f733a4fEA1071f58114b203F57444969b86524")),
ibc_commitments_slot: H256(hex!(
"1ee222554989dda120e26ecacf756fe1235cd8d726706b57517715dde4f0c900"
)),
latest_execution_block_number: 1.into(),
..Default::default()
};
let root = hex!("27cd08827e6bf1e435832f4b2660107beb562314287b3fa534f3b189574c0cca")
.to_vec()
.into();
let (path, proof) = get_non_membership_proof();
let proof_height = Height::new(ETHEREUM_CLIENT_REVISION_NUMBER, 1).unwrap();
let res = client_state.verify_non_membership(
proof_height,
&Default::default(),
&proof.try_into().unwrap(),
&root,
Path::from_str(&path).unwrap(),
);
assert!(res.is_ok(), "{:?}", res);
}

// returns: (path, proof, value)
fn get_membership_proof() -> (String, Vec<u8>, Vec<u8>) {
(
"clients/lcp-client-0/clientState".to_string(),
hex!("f90159f901118080a0143145e818eeff83817419a6632ea193fd1acaa4f791eb17282f623f38117f56a0e6ee0a993a7254ee9253d766ea005aec74eb1e11656961f0fb11323f4f91075580808080a01efae04adc2e970b4af3517581f41ce2ba4ff60492d33696c1e2a5ab70cb55bba03bac3f5124774e41fb6efdd7219530846f9f6441045c4666d2855c6598cfca00a020d7122ffc86cb37228940b5a9441e9fd272a3450245c9130ca3ab00bc1cd6ef80a0047f255205a0f2b0e7d29d490abf02bfb62c3ed201c338bc7f0088fa9c5d77eda069fecc766fcb2df04eb3a834b1f4ba134df2be114479e251d9cc9b6ba493077b80a094c3ed6a7ef63a6a67e46cc9876b9b1882eeba3d28e6d61bb15cdfb207d077e180f843a03e077f3dfd0489e70c68282ced0126c62fcef50acdcb7f57aa4552b87b456b11a1a05dc044e92e82db28c96fd98edd502949612b06e8da6dd74664a43a5ed857b298").to_vec(),
hex!("0a242f6962632e6c69676874636c69656e74732e6c63702e76312e436c69656e74537461746512ed010a208083673c69fe3f098ea79a799d9dbb99c39b4b4f17a1a79ef58bdf8ae86299951080f524220310fb012a1353575f48415244454e494e475f4e45454445442a1147524f55505f4f55545f4f465f44415445320e494e54454c2d53412d3030323139320e494e54454c2d53412d3030323839320e494e54454c2d53412d3030333334320e494e54454c2d53412d3030343737320e494e54454c2d53412d3030363134320e494e54454c2d53412d3030363135320e494e54454c2d53412d3030363137320e494e54454c2d53412d30303832383a14cb96f8d6c2d543102184d679d7829b39434e4eec48015001").to_vec()
)
}

// returns: (path, proof)
fn get_non_membership_proof() -> (String, Vec<u8>) {
(
"clients/lcp-client-1/clientState".to_string(),
hex!("f90114f901118080a0143145e818eeff83817419a6632ea193fd1acaa4f791eb17282f623f38117f56a0e6ee0a993a7254ee9253d766ea005aec74eb1e11656961f0fb11323f4f91075580808080a01efae04adc2e970b4af3517581f41ce2ba4ff60492d33696c1e2a5ab70cb55bba03bac3f5124774e41fb6efdd7219530846f9f6441045c4666d2855c6598cfca00a020d7122ffc86cb37228940b5a9441e9fd272a3450245c9130ca3ab00bc1cd6ef80a0047f255205a0f2b0e7d29d490abf02bfb62c3ed201c338bc7f0088fa9c5d77eda069fecc766fcb2df04eb3a834b1f4ba134df2be114479e251d9cc9b6ba493077b80a094c3ed6a7ef63a6a67e46cc9876b9b1882eeba3d28e6d61bb15cdfb207d077e180").to_vec()
)
}

#[test]
fn test_trusting_period_validation() {
{
Expand Down
2 changes: 2 additions & 0 deletions crates/ibc/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ pub enum Error {
ContextError(ContextError),
/// zero timestamp error
ZeroTimestampError,
/// zero block number error
ZeroBlockNumberError,
/// timestamp overflow error: `{0}`
TimestampOverflowError(TimestampOverflowError),
/// parse timestamp error: `{0}`
Expand Down
18 changes: 14 additions & 4 deletions crates/ibc/src/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use crate::types::{
use bytes::Buf;
use ethereum_consensus::compute::compute_timestamp_at_slot;
use ethereum_consensus::context::ChainContext;
use ethereum_consensus::types::U64;
use ethereum_ibc_proto::ibc::lightclients::ethereum::v1::Header as RawHeader;
use ethereum_light_client_verifier::updates::ConsensusUpdate;
use ibc::core::ics02_client::error::ClientError;
Expand Down Expand Up @@ -86,6 +87,9 @@ impl<const SYNC_COMMITTEE_SIZE: usize> Header<SYNC_COMMITTEE_SIZE> {
if self.timestamp.into_tm_time().is_none() {
return Err(Error::ZeroTimestampError);
}
if self.execution_update.block_number == U64(0) {
return Err(Error::ZeroBlockNumberError);
}
let header_timestamp_nanos = self
.timestamp
.into_tm_time()
Expand Down Expand Up @@ -237,7 +241,7 @@ mod tests {
let dummy_execution_block_number = 1;

for b in [false, true] {
let update = gen_light_client_update_with_params::<32, _>(
let (update, _) = gen_light_client_update_with_params::<32, _>(
&ctx,
base_signature_slot,
base_attested_slot,
Expand All @@ -257,7 +261,10 @@ mod tests {
is_next: true,
},
consensus_update: update.clone(),
execution_update: ExecutionUpdateInfo::default(),
execution_update: ExecutionUpdateInfo {
block_number: U64(2),
..Default::default()
},
account_update: AccountUpdateInfo::default(),
timestamp: Timestamp::from_nanoseconds(
compute_timestamp_at_slot(&ctx, update.finalized_beacon_header().slot).0
Expand All @@ -278,7 +285,10 @@ mod tests {
is_next: true,
},
consensus_update: update,
execution_update: ExecutionUpdateInfo::default(),
execution_update: ExecutionUpdateInfo {
block_number: U64(2),
..Default::default()
},
account_update: AccountUpdateInfo::default(),
timestamp: Timestamp::from_nanoseconds(0).unwrap(),
};
Expand All @@ -287,7 +297,7 @@ mod tests {
assert!(res.is_err(), "header with zero timestamp should fail");
}

let update = gen_light_client_update_with_params::<32, _>(
let (update, _) = gen_light_client_update_with_params::<32, _>(
&ctx,
base_signature_slot,
base_attested_slot,
Expand Down
6 changes: 3 additions & 3 deletions crates/ibc/src/misbehaviour.rs
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ mod tests {
let dummy_execution_state_root = [1u8; 32].into();
let dummy_execution_block_number = 1;

let update_1 = gen_light_client_update_with_params::<32, _>(
let (update_1, _) = gen_light_client_update_with_params::<32, _>(
&ctx,
base_signature_slot,
base_attested_slot,
Expand All @@ -257,7 +257,7 @@ mod tests {
true,
32,
);
let update_2 = gen_light_client_update_with_params::<32, _>(
let (update_2, _) = gen_light_client_update_with_params::<32, _>(
&ctx,
base_signature_slot,
base_attested_slot,
Expand Down Expand Up @@ -288,7 +288,7 @@ mod tests {
assert_eq!(misbehaviour, decoded);

let different_dummy_execution_state_root = [2u8; 32].into();
let update_3 = gen_light_client_update_with_params::<32, _>(
let (update_3, _) = gen_light_client_update_with_params::<32, _>(
&ctx,
base_signature_slot,
base_attested_slot,
Expand Down
20 changes: 12 additions & 8 deletions crates/ibc/src/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ mod tests {

{
// store_period == finalized_period == attested_period == signature_period
let update = to_consensus_update_info(gen_light_client_update_with_params::<32, _>(
let (update, _) = gen_light_client_update_with_params::<32, _>(
&ctx,
base_signature_slot,
base_attested_slot,
Expand All @@ -188,7 +188,8 @@ mod tests {
scm.get_committee(base_store_period + 1),
true,
32,
));
);
let update = to_consensus_update_info(update);
let new_block_number = 2.into();
let res = apply_updates(
&ctx,
Expand Down Expand Up @@ -226,7 +227,7 @@ mod tests {
}
{
// store_period + 1 == finalized_period == attested_period == signature_period
let update = to_consensus_update_info(gen_light_client_update_with_params::<32, _>(
let (update, _) = gen_light_client_update_with_params::<32, _>(
&ctx,
base_signature_slot + slots_per_period,
base_attested_slot + slots_per_period,
Expand All @@ -237,7 +238,8 @@ mod tests {
scm.get_committee(base_store_period + 2),
true,
32,
));
);
let update = to_consensus_update_info(update);
let new_block_number = 2.into();
let res = apply_updates(
&ctx,
Expand Down Expand Up @@ -276,7 +278,7 @@ mod tests {
{
// store_period + 1 == finalized_period == attested_period == signature_period
// but the update has no next sync committee
let update = to_consensus_update_info(gen_light_client_update_with_params::<32, _>(
let (update, _) = gen_light_client_update_with_params::<32, _>(
&ctx,
base_signature_slot + slots_per_period,
base_attested_slot + slots_per_period,
Expand All @@ -287,7 +289,8 @@ mod tests {
scm.get_committee(base_store_period + 2),
false,
32,
));
);
let update = to_consensus_update_info(update);
let new_block_number = 2.into();
let res = apply_updates(
&ctx,
Expand All @@ -314,7 +317,7 @@ mod tests {
}
{
// finalized_period - 1 == store_period == attested_period == signature_period
let update = to_consensus_update_info(gen_light_client_update_with_params::<32, _>(
let (update, _) = gen_light_client_update_with_params::<32, _>(
&ctx,
base_signature_slot,
base_attested_slot,
Expand All @@ -325,7 +328,8 @@ mod tests {
scm.get_committee(base_store_period),
true,
32,
));
);
let update = to_consensus_update_info(update);
let new_block_number = 2.into();
let res = apply_updates(
&ctx,
Expand Down