Skip to content

Commit

Permalink
Merge pull request #31 from datachainlab/fix-membership-value
Browse files Browse the repository at this point in the history
Fix to generate commitment in `verify_membership`

Signed-off-by: Jun Kimura <[email protected]>
  • Loading branch information
bluele authored Nov 17, 2024
2 parents 80ea9cc + b13451d commit 06864ca
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 19 deletions.
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

0 comments on commit 06864ca

Please sign in to comment.