Skip to content

Commit

Permalink
implement submit_misbehaviour for lcp-client
Browse files Browse the repository at this point in the history
Signed-off-by: Jun Kimura <[email protected]>
  • Loading branch information
bluele committed Feb 2, 2024
1 parent 7c81810 commit 71b2178
Show file tree
Hide file tree
Showing 6 changed files with 155 additions and 40 deletions.
53 changes: 47 additions & 6 deletions modules/lcp-client/src/client_def.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ use crate::client_state::ClientState;
use crate::consensus_state::ConsensusState;
use crate::errors::Error;
use crate::message::{
ClientMessage, ELCMessageReader, RegisterEnclaveKeyMessage, UpdateClientMessage,
ClientMessage, ELCMessageReader, MisbehaviourMessage, RegisterEnclaveKeyMessage,
UpdateClientMessage,
};
use attestation_report::EndorsedAttestationVerificationReport;
use crypto::{verify_signature_address, Address, Keccak256};
Expand Down Expand Up @@ -56,11 +57,14 @@ impl LCPClient {
) -> Result<(), Error> {
let client_state = ctx.client_state(&client_id)?.try_into()?;
match message {
ClientMessage::UpdateClient(header) => {
self.update_client(ctx, client_id, client_state, header)
ClientMessage::UpdateClient(msg) => {
self.update_client(ctx, client_id, client_state, msg)
}
ClientMessage::RegisterEnclaveKey(header) => {
self.register_enclave_key(ctx, client_id, client_state, header)
ClientMessage::RegisterEnclaveKey(msg) => {
self.register_enclave_key(ctx, client_id, client_state, msg)
}
ClientMessage::Misbehaviour(msg) => {
self.submit_misbehaviour(ctx, client_id, client_state, msg)
}
}
}
Expand All @@ -72,8 +76,11 @@ impl LCPClient {
client_state: ClientState,
message: UpdateClientMessage,
) -> Result<(), Error> {
message.elc_message.validate()?;
// TODO return an error instead of assertion

assert!(!client_state.frozen);

if client_state.latest_height.is_zero() {
// if the client state's latest height is zero, the commitment's new_state must be non-nil
assert!(!message.elc_message.emitted_states.is_empty());
Expand Down Expand Up @@ -131,6 +138,39 @@ impl LCPClient {
Ok(())
}

fn submit_misbehaviour(
&self,
ctx: &mut dyn HostClientKeeper,
client_id: ClientId,
client_state: ClientState,
message: MisbehaviourMessage,
) -> Result<(), Error> {
message.elc_message.validate()?;

assert!(!client_state.frozen);

for state in message.elc_message.prev_states.iter() {
// check if the previous consensus state exists in the store
let prev_consensus_state: ConsensusState =
ctx.consensus_state(&client_id, &state.height)?.try_into()?;
assert!(prev_consensus_state.state_id == state.state_id);
}

// check if the specified signer exists in the client state
assert!(self.contains_enclave_key(ctx, &client_id, message.signer));
// check if the `header.signer` matches the commitment prover
let signer = verify_signature_address(&message.sign_bytes(), &message.signature)?;
assert!(message.signer == signer);

// check if proxy's validation context matches our's context
message.context().validate(ctx.host_timestamp())?;

let new_client_state = client_state.with_frozen();
ctx.store_any_client_state(client_id, new_client_state.into())?;

Ok(())
}

/// verify_membership is a generic proof verification method which verifies a proof of the existence of a value at a given path at the specified height.
pub fn verify_membership(
&self,
Expand Down Expand Up @@ -297,9 +337,10 @@ mod tests {
let lcp_client_id = {
let expired_at = (Time::now() + Duration::from_secs(60)).unwrap();
let initial_client_state = ClientState {
latest_height: Height::zero(),
mr_enclave: [0u8; 32].to_vec(),
key_expiration: Duration::from_secs(60 * 60 * 24 * 7),
frozen: false,
latest_height: Height::zero(),
};
let initial_consensus_state = ConsensusState {
state_id: Default::default(),
Expand Down
16 changes: 12 additions & 4 deletions modules/lcp-client/src/client_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@ pub const LCP_CLIENT_STATE_TYPE_URL: &str = "/ibc.lightclients.lcp.v1.ClientStat

#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct ClientState {
pub latest_height: Height,
pub mr_enclave: Vec<u8>,
pub key_expiration: Duration,
pub latest_height: Height,
pub frozen: bool,
}

impl ClientState {
Expand All @@ -29,17 +30,23 @@ impl ClientState {
}
self
}

pub fn with_frozen(mut self) -> Self {
self.frozen = true;
self
}
}

impl From<ClientState> for RawClientState {
fn from(value: ClientState) -> Self {
RawClientState {
mrenclave: value.mr_enclave,
key_expiration: value.key_expiration.as_secs(),
frozen: value.frozen,
latest_height: Some(ProtoHeight {
revision_number: value.latest_height.revision_number(),
revision_height: value.latest_height.revision_height(),
}),
mrenclave: value.mr_enclave,
key_expiration: value.key_expiration.as_secs(),
allowed_quote_statuses: Default::default(),
allowed_advisory_ids: Default::default(),
}
Expand All @@ -52,9 +59,10 @@ impl TryFrom<RawClientState> for ClientState {
fn try_from(raw: RawClientState) -> Result<Self, Self::Error> {
let height = raw.latest_height.unwrap();
Ok(ClientState {
latest_height: Height::new(height.revision_number, height.revision_height),
mr_enclave: raw.mrenclave,
key_expiration: Duration::from_secs(raw.key_expiration),
frozen: raw.frozen,
latest_height: Height::new(height.revision_number, height.revision_height),
})
}
}
Expand Down
83 changes: 65 additions & 18 deletions modules/lcp-client/src/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ use crate::prelude::*;
use attestation_report::EndorsedAttestationVerificationReport;
use crypto::Address;
use light_client::commitments::{
Message as ELCMessage, StateID, UpdateClientMessage as ELCUpdateClientMessage,
ValidationContext,
Message as ELCMessage, MisbehaviourMessage as ELCMisbehaviourMessage, StateID,
UpdateClientMessage as ELCUpdateClientMessage, ValidationContext,
};
use light_client::types::proto::ibc::lightclients::lcp::v1::{
MisbehaviourMessage as RawMisbehaviourMessage,
RegisterEnclaveKeyMessage as RawRegisterEnclaveKeyMessage,
UpdateClientMessage as RawUpdateClientMessage,
};
Expand All @@ -17,12 +18,30 @@ use serde::{Deserialize, Serialize};
pub const LCP_REGISTER_ENCLAVE_KEY_MESSAGE_TYPE_URL: &str =
"/ibc.lightclients.lcp.v1.RegisterEnclaveKeyMessage";
pub const LCP_UPDATE_CLIENT_MESSAGE_TYPE_URL: &str = "/ibc.lightclients.lcp.v1.UpdateClientMessage";
pub const LCP_MISBEHAVIOUR_MESSAGE_TYPE_URL: &str = "/ibc.lightclients.lcp.v1.MisbehaviourMessage";

#[allow(clippy::large_enum_variant)]
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
pub enum ClientMessage {
RegisterEnclaveKey(RegisterEnclaveKeyMessage),
UpdateClient(UpdateClientMessage),
Misbehaviour(MisbehaviourMessage),
}

impl ClientMessage {
pub fn get_height(&self) -> Option<Height> {
match self {
ClientMessage::UpdateClient(h) => Some(h.height()),
_ => None,
}
}

pub fn get_timestamp(&self) -> Option<Time> {
match self {
ClientMessage::UpdateClient(h) => Some(h.timestamp()),
_ => None,
}
}
}

impl Protobuf<Any> for ClientMessage {}
Expand Down Expand Up @@ -54,6 +73,10 @@ impl From<ClientMessage> for Any {
LCP_UPDATE_CLIENT_MESSAGE_TYPE_URL.to_string(),
h.encode_vec().unwrap(),
),
ClientMessage::Misbehaviour(h) => Any::new(
LCP_MISBEHAVIOUR_MESSAGE_TYPE_URL.to_string(),
h.encode_vec().unwrap(),
),
}
}
}
Expand Down Expand Up @@ -116,13 +139,43 @@ impl From<UpdateClientMessage> for RawUpdateClientMessage {
}
}

impl ELCMessageReader for UpdateClientMessage {
fn signer(&self) -> Address {
self.signer
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
pub struct MisbehaviourMessage {
pub signer: Address,
pub signature: Vec<u8>,
pub elc_message: ELCMisbehaviourMessage,
}

impl MisbehaviourMessage {
pub fn sign_bytes(&self) -> Vec<u8> {
ELCMessage::from(self.elc_message.clone()).to_bytes()
}

fn elc_message(&self) -> &ELCUpdateClientMessage {
&self.elc_message
pub fn context(&self) -> &ValidationContext {
&self.elc_message.context
}
}

impl Protobuf<RawMisbehaviourMessage> for MisbehaviourMessage {}

impl TryFrom<RawMisbehaviourMessage> for MisbehaviourMessage {
type Error = Error;
fn try_from(value: RawMisbehaviourMessage) -> Result<Self, Self::Error> {
Ok(MisbehaviourMessage {
signer: Address::try_from(value.signer.as_slice())?,
signature: value.signature,
elc_message: ELCMessage::from_bytes(&value.elc_message)?.try_into()?,
})
}
}

impl From<MisbehaviourMessage> for RawMisbehaviourMessage {
fn from(value: MisbehaviourMessage) -> Self {
RawMisbehaviourMessage {
elc_message: Into::<ELCMessage>::into(value.elc_message).to_bytes(),
signer: value.signer.into(),
signature: value.signature,
}
}
}

Expand Down Expand Up @@ -160,18 +213,12 @@ pub trait ELCMessageReader {
}
}

impl ClientMessage {
pub fn get_height(&self) -> Option<Height> {
match self {
ClientMessage::UpdateClient(h) => Some(h.height()),
_ => None,
}
impl ELCMessageReader for UpdateClientMessage {
fn signer(&self) -> Address {
self.signer
}

pub fn get_timestamp(&self) -> Option<Time> {
match self {
ClientMessage::UpdateClient(h) => Some(h.timestamp()),
_ => None,
}
fn elc_message(&self) -> &ELCUpdateClientMessage {
&self.elc_message
}
}
17 changes: 12 additions & 5 deletions proto/definitions/ibc/lightclients/lcp/v1/lcp.proto
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,21 @@ message RegisterEnclaveKeyMessage {
bytes signing_cert = 3;
}

message MisbehaviourMessage {
bytes elc_message = 1;
bytes signer = 2;
bytes signature = 3;
}

message ClientState {
ibc.core.client.v1.Height latest_height = 1 [(gogoproto.nullable) = false];
bytes mrenclave = 2;
uint64 key_expiration = 3;
bytes mrenclave = 1;
uint64 key_expiration = 2;
bool frozen = 3 [(gogoproto.nullable) = false];
ibc.core.client.v1.Height latest_height = 4 [(gogoproto.nullable) = false];
// e.g. SW_HARDENING_NEEDED, CONFIGURATION_AND_SW_HARDENING_NEEDED (except "OK")
repeated string allowed_quote_statuses = 4;
repeated string allowed_quote_statuses = 5;
// e.g. INTEL-SA-XXXXX
repeated string allowed_advisory_ids = 5;
repeated string allowed_advisory_ids = 6;
}

message ConsensusState {
Expand Down
Binary file modified proto/src/descriptor.bin
Binary file not shown.
26 changes: 19 additions & 7 deletions proto/src/prost/ibc.lightclients.lcp.v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,32 @@ pub struct RegisterEnclaveKeyMessage {
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct MisbehaviourMessage {
#[prost(bytes = "vec", tag = "1")]
pub elc_message: ::prost::alloc::vec::Vec<u8>,
#[prost(bytes = "vec", tag = "2")]
pub signer: ::prost::alloc::vec::Vec<u8>,
#[prost(bytes = "vec", tag = "3")]
pub signature: ::prost::alloc::vec::Vec<u8>,
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct ClientState {
#[prost(message, optional, tag = "1")]
#[prost(bytes = "vec", tag = "1")]
pub mrenclave: ::prost::alloc::vec::Vec<u8>,
#[prost(uint64, tag = "2")]
pub key_expiration: u64,
#[prost(bool, tag = "3")]
pub frozen: bool,
#[prost(message, optional, tag = "4")]
pub latest_height: ::core::option::Option<
super::super::super::core::client::v1::Height,
>,
#[prost(bytes = "vec", tag = "2")]
pub mrenclave: ::prost::alloc::vec::Vec<u8>,
#[prost(uint64, tag = "3")]
pub key_expiration: u64,
/// e.g. SW_HARDENING_NEEDED, CONFIGURATION_AND_SW_HARDENING_NEEDED (except "OK")
#[prost(string, repeated, tag = "4")]
#[prost(string, repeated, tag = "5")]
pub allowed_quote_statuses: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
/// e.g. INTEL-SA-XXXXX
#[prost(string, repeated, tag = "5")]
#[prost(string, repeated, tag = "6")]
pub allowed_advisory_ids: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
}
#[allow(clippy::derive_partial_eq_without_eq)]
Expand Down

0 comments on commit 71b2178

Please sign in to comment.