Skip to content
Closed
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
7 changes: 4 additions & 3 deletions crates/ibc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@ 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.2.0", default-features = false }
ethereum-light-client-verifier = { git = "https://github.com/datachainlab/ethereum-light-client-rs", rev = "v0.2.0", default-features = false }
ethereum-consensus = { git = "https://github.com/yoshidan/ethereum-light-client-rs", branch = "feature/verify_block_hash", default-features = false }
ethereum-light-client-verifier = { git = "https://github.com/yoshidan/ethereum-light-client-rs", branch = "feature/verify_block_hash", 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.2.0", default-features = false, features = ["test-utils"] }
ethereum-light-client-verifier = { git = "https://github.com/yoshidan/ethereum-light-client-rs", branch = "feature/verify_block_hash", default-features = false, features = ["test-utils"] }

125 changes: 70 additions & 55 deletions crates/ibc/src/client_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,60 +125,12 @@ impl<const SYNC_COMMITTEE_SIZE: usize> ClientState<SYNC_COMMITTEE_SIZE> {
state_root: H256,
account_update: &AccountUpdateInfo,
) -> Result<(), Error> {
match self
.execution_verifier
.verify_account(
state_root,
&self.ibc_address,
account_update.account_proof.clone(),
)
.map_err(|e| {
Error::MPTVerificationError(
e,
state_root,
hex::encode(self.ibc_address.0),
account_update
.account_proof
.iter()
.map(hex::encode)
.collect(),
)
})? {
Some(account) => {
if account_update.account_storage_root == account.storage_root {
Ok(())
} else {
Err(Error::AccountStorageRootMismatch(
account_update.account_storage_root,
account.storage_root,
state_root,
hex::encode(self.ibc_address.0),
account_update
.account_proof
.iter()
.map(hex::encode)
.collect(),
))
}
}
None => {
if account_update.account_storage_root.is_zero() {
Ok(())
} else {
Err(Error::AccountStorageRootMismatch(
account_update.account_storage_root,
H256::default(),
state_root,
hex::encode(self.ibc_address.0),
account_update
.account_proof
.iter()
.map(hex::encode)
.collect(),
))
}
}
}
verify_account_storage(
&self.ibc_address,
&self.execution_verifier,
state_root,
account_update,
)
}

pub fn verify_membership(
Expand Down Expand Up @@ -770,6 +722,7 @@ impl<const SYNC_COMMITTEE_SIZE: usize> TryFrom<RawClientState>
execution_payload_state_root_gindex: spec.execution_payload_state_root_gindex,
execution_payload_block_number_gindex: spec
.execution_payload_block_number_gindex,
execution_payload_block_hash_gindex: spec.execution_payload_block_hash_gindex,
})
} else {
Err(Error::proto_missing(&format!("forks[{}].spec", idx)))
Expand Down Expand Up @@ -852,6 +805,7 @@ impl<const SYNC_COMMITTEE_SIZE: usize> From<ClientState<SYNC_COMMITTEE_SIZE>> fo
execution_payload_state_root_gindex: spec.execution_payload_state_root_gindex,
execution_payload_block_number_gindex: spec
.execution_payload_block_number_gindex,
execution_payload_block_hash_gindex: spec.execution_payload_block_hash_gindex,
}),
}
}
Expand Down Expand Up @@ -963,7 +917,7 @@ fn maybe_consensus_state(
}
}

fn trim_left_zero(value: &[u8]) -> &[u8] {
pub fn trim_left_zero(value: &[u8]) -> &[u8] {
let mut pos = 0;
for v in value {
if *v != 0 {
Expand Down Expand Up @@ -1026,6 +980,67 @@ fn verify_delay_passed(
Ok(())
}

pub fn verify_account_storage(
ibc_address: &Address,
execution_verifier: &ExecutionVerifier,
state_root: H256,
account_update: &AccountUpdateInfo,
) -> Result<(), Error> {
match execution_verifier
.verify_account(
state_root,
ibc_address,
account_update.account_proof.clone(),
)
.map_err(|e| {
Error::MPTVerificationError(
e,
state_root,
hex::encode(ibc_address.0),
account_update
.account_proof
.iter()
.map(hex::encode)
.collect(),
)
})? {
Some(account) => {
if account_update.account_storage_root == account.storage_root {
Ok(())
} else {
Err(Error::AccountStorageRootMismatch(
account_update.account_storage_root,
account.storage_root,
state_root,
hex::encode(ibc_address.0),
account_update
.account_proof
.iter()
.map(hex::encode)
.collect(),
))
}
}
None => {
if account_update.account_storage_root.is_zero() {
Ok(())
} else {
Err(Error::AccountStorageRootMismatch(
account_update.account_storage_root,
H256::default(),
state_root,
hex::encode(ibc_address.0),
account_update
.account_proof
.iter()
.map(hex::encode)
.collect(),
))
}
}
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
3 changes: 3 additions & 0 deletions crates/ibc/src/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ mod tests {
let base_finalized_epoch = base_attested_slot / ctx.slots_per_epoch();
let dummy_execution_state_root = [1u8; 32].into();
let dummy_execution_block_number = 1;
let dummy_execution_block_hash = [1u8; 32].into();

for b in [false, true] {
let (update, _) = gen_light_client_update_with_params::<32, _>(
Expand All @@ -248,6 +249,7 @@ mod tests {
base_finalized_epoch,
dummy_execution_state_root,
dummy_execution_block_number.into(),
dummy_execution_block_hash,
current_sync_committee,
scm.get_committee(2),
b,
Expand Down Expand Up @@ -304,6 +306,7 @@ mod tests {
base_finalized_epoch,
dummy_execution_state_root,
dummy_execution_block_number.into(),
dummy_execution_block_hash,
current_sync_committee,
scm.get_committee(2),
true,
Expand Down
4 changes: 4 additions & 0 deletions crates/ibc/src/misbehaviour.rs
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@ mod tests {
let base_finalized_epoch = base_attested_slot / ctx.slots_per_epoch();
let dummy_execution_state_root = [1u8; 32].into();
let dummy_execution_block_number = 1;
let dummy_execution_block_hash = [1u8; 32].into();

let (update_1, _) = gen_light_client_update_with_params::<32, _>(
&ctx,
Expand All @@ -252,6 +253,7 @@ mod tests {
base_finalized_epoch,
dummy_execution_state_root,
dummy_execution_block_number.into(),
dummy_execution_block_hash,
current_sync_committee,
scm.get_committee(2),
true,
Expand All @@ -264,6 +266,7 @@ mod tests {
base_finalized_epoch,
dummy_execution_state_root,
dummy_execution_block_number.into(),
dummy_execution_block_hash,
current_sync_committee,
scm.get_committee(3),
true,
Expand Down Expand Up @@ -295,6 +298,7 @@ mod tests {
base_finalized_epoch,
different_dummy_execution_state_root,
dummy_execution_block_number.into(),
dummy_execution_block_hash,
current_sync_committee,
scm.get_committee(2),
true,
Expand Down
89 changes: 50 additions & 39 deletions crates/ibc/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ pub struct ExecutionUpdateInfo {
pub block_number: U64,
/// Branch indicating the block number in the tree corresponding to the execution payload
pub block_number_branch: Vec<H256>,
/// Block hash of the execution payload
pub block_hash: H256,
/// Branch indicating the block hash in the tree corresponding to the execution payload
pub block_hash_branch: Vec<H256>,
}

impl ExecutionUpdate for ExecutionUpdateInfo {
Expand All @@ -99,6 +103,14 @@ impl ExecutionUpdate for ExecutionUpdateInfo {
fn block_number_branch(&self) -> Vec<H256> {
self.block_number_branch.clone()
}

fn block_hash(&self) -> H256 {
self.block_hash
}

fn block_hash_branch(&self) -> Vec<H256> {
self.block_hash_branch.clone()
}
}

#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
Expand Down Expand Up @@ -139,25 +151,7 @@ impl<const SYNC_COMMITTEE_SIZE: usize> TryFrom<ProtoTrustedSyncCommittee>
trusted_height.revision_number,
trusted_height.revision_height,
)?,
sync_committee: SyncCommittee {
pubkeys: Vector::<PublicKey, SYNC_COMMITTEE_SIZE>::from_iter(
value
.sync_committee
.as_ref()
.ok_or(Error::proto_missing("sync_committee"))?
.pubkeys
.clone()
.into_iter()
.map(|pk| pk.try_into())
.collect::<Result<Vec<PublicKey>, _>>()?,
),
aggregate_pubkey: PublicKey::try_from(
value
.sync_committee
.ok_or(Error::proto_missing("sync_committee"))?
.aggregate_pubkey,
)?,
},
sync_committee: convert_proto_to_sync_committee(value.sync_committee)?,
is_next: value.is_next,
})
}
Expand Down Expand Up @@ -243,7 +237,7 @@ pub(crate) fn convert_header_to_proto(header: &BeaconBlockHeader) -> ProtoBeacon
}
}

pub(crate) fn convert_proto_to_execution_update(
pub fn convert_proto_to_execution_update(
execution_update: ProtoExecutionUpdate,
) -> ExecutionUpdateInfo {
ExecutionUpdateInfo {
Expand All @@ -259,6 +253,12 @@ pub(crate) fn convert_proto_to_execution_update(
.into_iter()
.map(|n| H256::from_slice(&n))
.collect(),
block_hash: H256::from_slice(&execution_update.block_hash),
block_hash_branch: execution_update
.block_hash_branch
.into_iter()
.map(|n| H256::from_slice(&n))
.collect(),
}
}

Expand All @@ -278,6 +278,12 @@ pub(crate) fn convert_execution_update_to_proto(
.into_iter()
.map(|n| n.as_bytes().to_vec())
.collect(),
block_hash: execution_update.block_hash.as_bytes().into(),
block_hash_branch: execution_update
.block_hash_branch
.into_iter()
.map(|n| n.as_bytes().to_vec())
.collect(),
}
}

Expand Down Expand Up @@ -346,7 +352,7 @@ pub(crate) fn convert_consensus_update_to_proto<const SYNC_COMMITTEE_SIZE: usize
}
}

pub(crate) fn convert_proto_to_consensus_update<const SYNC_COMMITTEE_SIZE: usize>(
pub fn convert_proto_to_consensus_update<const SYNC_COMMITTEE_SIZE: usize>(
consensus_update: ProtoConsensusUpdate,
) -> Result<ConsensusUpdateInfo<SYNC_COMMITTEE_SIZE>, Error> {
let attested_header = convert_proto_to_header(
Expand Down Expand Up @@ -381,24 +387,7 @@ pub(crate) fn convert_proto_to_consensus_update<const SYNC_COMMITTEE_SIZE: usize
None
} else {
Some((
SyncCommittee {
pubkeys: Vector::<PublicKey, SYNC_COMMITTEE_SIZE>::from_iter(
consensus_update
.next_sync_committee
.clone()
.ok_or(Error::proto_missing("next_sync_committee"))?
.pubkeys
.into_iter()
.map(|pk| pk.try_into())
.collect::<Result<Vec<PublicKey>, _>>()?,
),
aggregate_pubkey: PublicKey::try_from(
consensus_update
.next_sync_committee
.ok_or(Error::proto_missing("next_sync_committee"))?
.aggregate_pubkey,
)?,
},
convert_proto_to_sync_committee(consensus_update.next_sync_committee)?,
decode_branch(consensus_update.next_sync_committee_branch),
))
},
Expand All @@ -418,6 +407,28 @@ pub(crate) fn convert_proto_to_consensus_update<const SYNC_COMMITTEE_SIZE: usize
Ok(consensus_update)
}

pub fn convert_proto_to_sync_committee<const SYNC_COMMITTEE_SIZE: usize>(
sync_committee: Option<ProtoSyncCommittee>,
) -> Result<SyncCommittee<SYNC_COMMITTEE_SIZE>, Error> {
let sync_committee = SyncCommittee {
pubkeys: Vector::<PublicKey, SYNC_COMMITTEE_SIZE>::from_iter(
sync_committee
.clone()
.ok_or(Error::proto_missing("next_sync_committee"))?
.pubkeys
.into_iter()
.map(|pk| pk.try_into())
.collect::<Result<Vec<PublicKey>, _>>()?,
),
aggregate_pubkey: PublicKey::try_from(
sync_committee
.ok_or(Error::proto_missing("next_sync_committee"))?
.aggregate_pubkey,
)?,
};
Ok(sync_committee)
}

pub(crate) fn decode_branch(bz: Vec<Vec<u8>>) -> Vec<H256> {
bz.into_iter().map(|b| H256::from_slice(&b)).collect()
}
Loading
Loading