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

Misbehavior monitoring and handling #691

Merged
merged 41 commits into from
Apr 9, 2021
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
feece5a
Split client_def in state, consensus, header. Add sketch for Tx decod…
ancazamfir Feb 15, 2021
1272f19
Added misbehaviour message, structures, relayer submission
ancazamfir Feb 18, 2021
b693bed
tentative try with interim update event from cosmos PR
ancazamfir Feb 18, 2021
2056f24
Merge branch 'master' into anca/misbehavior
ancazamfir Feb 25, 2021
ddfedb6
trying to decode the header from event
ancazamfir Mar 2, 2021
c1cccf8
decode the header in client update event
ancazamfir Mar 2, 2021
edcb1d0
Added restart support, move some of the misbehaviour detection in lig…
ancazamfir Mar 8, 2021
85a0569
Merge branch 'master' into anca/misbehavior
ancazamfir Mar 8, 2021
1fc35b8
fix merge
ancazamfir Mar 8, 2021
0271f1d
add support for potential on-chain state pruning, cleanup
ancazamfir Mar 9, 2021
ea787f2
Update changelog
ancazamfir Mar 9, 2021
bd6eb26
sketch for time travelling lunatic attack check
ancazamfir Mar 9, 2021
396fa07
fmt
ancazamfir Mar 9, 2021
0555dee
Decode misbehaviour events, added comments
ancazamfir Mar 10, 2021
6eb9659
Merge branch 'master' into anca/misbehavior
ancazamfir Mar 15, 2021
bb201c0
Update to reflect bad updates in the middle
ancazamfir Mar 15, 2021
64aa705
Merge branch 'master' into anca/misbehavior
ancazamfir Mar 29, 2021
d7d4479
cargo fmt
ancazamfir Mar 30, 2021
b1f5439
Merge branch 'master' into anca/misbehavior
ancazamfir Mar 31, 2021
03f520c
Merge branch 'master' into anca/misbehavior
ancazamfir Apr 2, 2021
7b53ac5
Cleanup consensus query and allow query for all
ancazamfir Apr 2, 2021
c2129a9
Allow target and trusted heights to be specified in client updates
ancazamfir Apr 2, 2021
372a298
Allow update with any existing trusted height
ancazamfir Apr 2, 2021
cd576de
Disallow create client with same src and dst
ancazamfir Apr 2, 2021
5e26396
Fix tests
ancazamfir Apr 2, 2021
36ed699
Added mock misbehaviour
ancazamfir Apr 6, 2021
373fdb2
Fix CI and reorg code
ancazamfir Apr 7, 2021
48b86a0
Merge branch 'master' into anca/misbehavior
ancazamfir Apr 7, 2021
ea1a083
Cleanup
ancazamfir Apr 7, 2021
f435289
Merge branch 'master' into anca/misbehavior
ancazamfir Apr 8, 2021
e3ccb50
Updates after sitdown review
ancazamfir Apr 8, 2021
2050095
Update comments
ancazamfir Apr 8, 2021
7420aec
Flip back the logic in compatible_headers()
ancazamfir Apr 8, 2021
48b04fb
Rename client_misbehaviour to misbehaviour
ancazamfir Apr 8, 2021
35fcb14
review comments
ancazamfir Apr 9, 2021
cc003de
fmt
ancazamfir Apr 9, 2021
29d67f3
Return UpdateClient::consensus_height by copy instead of reference
romac Apr 9, 2021
a11c3c0
Small cleanup in LightClient::build_misbehaviour
romac Apr 9, 2021
7361934
Small cleanup in chain::cosmos
romac Apr 9, 2021
d7293dd
Set pagination limit to u64::MAX for all queries that support it to e…
romac Apr 9, 2021
3942d74
Addressed review comments
ancazamfir Apr 9, 2021
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
9 changes: 6 additions & 3 deletions modules/src/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use crate::Height;
#[derive(Debug, Clone, Deserialize, Serialize)]
pub enum IbcEventType {
CreateClient,
UpdateClient,
SendPacket,
WriteAck,
}
Expand All @@ -21,6 +22,7 @@ impl IbcEventType {
pub fn as_str(&self) -> &'static str {
match *self {
IbcEventType::CreateClient => "create_client",
IbcEventType::UpdateClient => "update_client",
IbcEventType::SendPacket => "send_packet",
IbcEventType::WriteAck => "write_acknowledgement",
}
Expand All @@ -34,7 +36,7 @@ pub enum IbcEvent {

CreateClient(ClientEvents::CreateClient),
UpdateClient(ClientEvents::UpdateClient),
ClientMisbehavior(ClientEvents::ClientMisbehavior),
ClientMisbehaviour(ClientEvents::ClientMisbehaviour),

OpenInitConnection(ConnectionEvents::OpenInit),
OpenTryConnection(ConnectionEvents::OpenTry),
Expand All @@ -57,6 +59,7 @@ pub enum IbcEvent {

Empty(String), // Special event, signifying empty response
ChainError(String), // Special event, signifying an error on CheckTx or DeliverTx
UpdateClient2(ClientEvents::UpdateClient2), // Special event, signifying an error on CheckTx or DeliverTx
}

// This is tendermint specific
Expand Down Expand Up @@ -86,7 +89,7 @@ impl IbcEvent {
IbcEvent::NewBlock(bl) => bl.height(),
IbcEvent::CreateClient(ev) => ev.height(),
IbcEvent::UpdateClient(ev) => ev.height(),
IbcEvent::ClientMisbehavior(ev) => ev.height(),
IbcEvent::ClientMisbehaviour(ev) => ev.height(),
IbcEvent::OpenInitConnection(ev) => ev.height(),
IbcEvent::OpenTryConnection(ev) => ev.height(),
IbcEvent::OpenAckConnection(ev) => ev.height(),
Expand All @@ -111,7 +114,7 @@ impl IbcEvent {
IbcEvent::NewBlock(ev) => ev.set_height(height),
IbcEvent::CreateClient(ev) => ev.set_height(height),
IbcEvent::UpdateClient(ev) => ev.set_height(height),
IbcEvent::ClientMisbehavior(ev) => ev.set_height(height),
IbcEvent::ClientMisbehaviour(ev) => ev.set_height(height),
IbcEvent::OpenInitConnection(ev) => ev.set_height(height),
IbcEvent::OpenTryConnection(ev) => ev.set_height(height),
IbcEvent::OpenAckConnection(ev) => ev.set_height(height),
Expand Down
150 changes: 150 additions & 0 deletions modules/src/ics02_client/client_consensus.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
use std::convert::{TryFrom, TryInto};

use prost_types::Any;
use serde_derive::Serialize;
use tendermint_proto::Protobuf;

use ibc_proto::ibc::core::client::v1::ConsensusStateWithHeight;

use crate::ics02_client::client_type::ClientType;
use crate::ics02_client::error::{Error, Kind};
use crate::ics02_client::height::Height;
use crate::ics07_tendermint::consensus_state::ConsensusState as TmConsensusState;
use crate::ics23_commitment::commitment::CommitmentRoot;
#[cfg(any(test, feature = "mocks"))]
use crate::mock::client_state::MockConsensusState;

#[cfg(any(test, feature = "mocks"))]
pub const MOCK_CONSENSUS_STATE_TYPE_URL: &str = "/ibc.mock.ConsensusState";

pub const TENDERMINT_CONSENSUS_STATE_TYPE_URL: &str =
"/ibc.lightclients.tendermint.v1.ConsensusState";

#[dyn_clonable::clonable]
pub trait ConsensusState: Clone + std::fmt::Debug + Send + Sync {
/// Type of client associated with this consensus state (eg. Tendermint)
fn client_type(&self) -> ClientType;

/// Commitment root of the consensus state, which is used for key-value pair verification.
fn root(&self) -> &CommitmentRoot;

/// Performs basic validation of the consensus state
fn validate_basic(&self) -> Result<(), Box<dyn std::error::Error>>;

/// Wrap into an `AnyConsensusState`
fn wrap_any(self) -> AnyConsensusState;
}

#[derive(Clone, Debug, PartialEq, Eq, Serialize)]
#[serde(tag = "type")]
pub enum AnyConsensusState {
Tendermint(TmConsensusState),

#[cfg(any(test, feature = "mocks"))]
Mock(MockConsensusState),
}

impl AnyConsensusState {
pub fn client_type(&self) -> ClientType {
match self {
AnyConsensusState::Tendermint(_cs) => ClientType::Tendermint,

#[cfg(any(test, feature = "mocks"))]
AnyConsensusState::Mock(_cs) => ClientType::Mock,
}
}
}

impl Protobuf<Any> for AnyConsensusState {}

impl TryFrom<Any> for AnyConsensusState {
type Error = Error;

fn try_from(value: Any) -> Result<Self, Self::Error> {
match value.type_url.as_str() {
"" => Err(Kind::EmptyConsensusState.into()),

TENDERMINT_CONSENSUS_STATE_TYPE_URL => Ok(AnyConsensusState::Tendermint(
TmConsensusState::decode_vec(&value.value)
.map_err(|e| Kind::InvalidRawConsensusState.context(e))?,
)),

#[cfg(any(test, feature = "mocks"))]
MOCK_CONSENSUS_STATE_TYPE_URL => Ok(AnyConsensusState::Mock(
MockConsensusState::decode_vec(&value.value)
.map_err(|e| Kind::InvalidRawConsensusState.context(e))?,
)),

_ => Err(Kind::UnknownConsensusStateType(value.type_url).into()),
}
}
}

impl From<AnyConsensusState> for Any {
fn from(value: AnyConsensusState) -> Self {
match value {
AnyConsensusState::Tendermint(value) => Any {
type_url: TENDERMINT_CONSENSUS_STATE_TYPE_URL.to_string(),
value: value.encode_vec().unwrap(),
},
#[cfg(any(test, feature = "mocks"))]
AnyConsensusState::Mock(value) => Any {
type_url: MOCK_CONSENSUS_STATE_TYPE_URL.to_string(),
value: value.encode_vec().unwrap(),
},
}
}
}

#[derive(Clone, Debug, PartialEq, Eq, Serialize)]
pub struct AnyConsensusStateWithHeight {
height: Height,
consensus_state: AnyConsensusState,
}

impl Protobuf<ConsensusStateWithHeight> for AnyConsensusStateWithHeight {}

impl TryFrom<ConsensusStateWithHeight> for AnyConsensusStateWithHeight {
type Error = Error;

fn try_from(value: ConsensusStateWithHeight) -> Result<Self, Self::Error> {
let state = value
.consensus_state
.map(AnyConsensusState::try_from)
.transpose()
.map_err(|e| Kind::InvalidRawConsensusState.context(e))?
.ok_or(Kind::EmptyConsensusState)?;

Ok(AnyConsensusStateWithHeight {
height: value.height.ok_or(Kind::InvalidHeightResult)?.try_into()?,
consensus_state: state,
})
}
}

impl From<AnyConsensusStateWithHeight> for ConsensusStateWithHeight {
fn from(value: AnyConsensusStateWithHeight) -> Self {
ConsensusStateWithHeight {
height: Some(value.height.into()),
consensus_state: Some(value.consensus_state.into()),
}
}
}

impl ConsensusState for AnyConsensusState {
fn client_type(&self) -> ClientType {
self.client_type()
}

fn root(&self) -> &CommitmentRoot {
todo!()
}

fn validate_basic(&self) -> Result<(), Box<dyn std::error::Error>> {
todo!()
}

fn wrap_any(self) -> AnyConsensusState {
self
}
}
Loading