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

Generalize signature verifier of tendermint client. #958

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
106 changes: 81 additions & 25 deletions crates/ibc/src/clients/ics07_tendermint/client_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@ use prost::Message;
use tendermint::chain::id::MAX_LENGTH as MaxChainIdLen;
use tendermint::trust_threshold::TrustThresholdFraction as TendermintTrustThresholdFraction;
use tendermint_light_client_verifier::options::Options;
use tendermint_light_client_verifier::ProdVerifier;
use tendermint_light_client_verifier::{
operations::{ProdCommitValidator, ProvidedVotingPowerCalculator},
predicates::ProdPredicates,
PredicateVerifier,
};

use super::trust_threshold::TrustThreshold;
use super::{
Expand Down Expand Up @@ -63,7 +67,10 @@ pub struct AllowUpdate {
/// Contains the core implementation of the Tendermint light client
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Clone, Debug, PartialEq)]
pub struct ClientState {
pub struct ClientState<V>
where
V: Clone + tendermint::crypto::signature::Verifier,
{
pub chain_id: ChainId,
pub trust_level: TrustThreshold,
pub trusting_period: Duration,
Expand All @@ -75,10 +82,14 @@ pub struct ClientState {
allow_update: AllowUpdate,
frozen_height: Option<Height>,
#[cfg_attr(feature = "serde", serde(skip))]
verifier: ProdVerifier,
verifier:
PredicateVerifier<ProdPredicates, ProvidedVotingPowerCalculator<V>, ProdCommitValidator>,
}

impl ClientState {
impl<V> ClientState<V>
where
V: Clone + tendermint::crypto::signature::Verifier,
{
#[allow(clippy::too_many_arguments)]
fn new_without_validation(
chain_id: ChainId,
Expand All @@ -102,7 +113,11 @@ impl ClientState {
upgrade_path,
allow_update,
frozen_height: None,
verifier: ProdVerifier::default(),
verifier: PredicateVerifier::new(
ProdPredicates::default(),
ProvidedVotingPowerCalculator::<V>::default(),
ProdCommitValidator::default(),
),
}
}

Expand Down Expand Up @@ -263,7 +278,10 @@ impl ClientState {
}
}

impl ClientStateCommon for ClientState {
impl<V> ClientStateCommon for ClientState<V>
where
V: Clone + tendermint::crypto::signature::Verifier,
{
fn verify_consensus_state(&self, consensus_state: Any) -> Result<(), ClientError> {
let tm_consensus_state = TmConsensusState::try_from(consensus_state)?;
if tm_consensus_state.root().is_empty() {
Expand Down Expand Up @@ -410,11 +428,12 @@ impl ClientStateCommon for ClientState {
}
}

impl<V> ClientStateValidation<V> for ClientState
impl<V, R> ClientStateValidation<V> for ClientState<R>
where
V: ClientValidationContext + TmValidationContext,
V::AnyConsensusState: TryInto<TmConsensusState>,
ClientError: From<<V::AnyConsensusState as TryInto<TmConsensusState>>::Error>,
R: Clone + tendermint::crypto::signature::Verifier,
{
fn verify_client_message(
&self,
Expand Down Expand Up @@ -488,11 +507,12 @@ where
}
}

impl<E> ClientStateExecution<E> for ClientState
impl<E, V> ClientStateExecution<E> for ClientState<V>
where
E: TmExecutionContext + ExecutionContext,
<E as ClientExecutionContext>::AnyClientState: From<ClientState>,
<E as ClientExecutionContext>::AnyClientState: From<ClientState<V>>,
<E as ClientExecutionContext>::AnyConsensusState: From<TmConsensusState>,
V: Clone + tendermint::crypto::signature::Verifier,
{
fn initialise(
&self,
Expand Down Expand Up @@ -636,9 +656,15 @@ where
}
}

impl Protobuf<RawTmClientState> for ClientState {}
impl<V> Protobuf<RawTmClientState> for ClientState<V> where
V: Clone + tendermint::crypto::signature::Verifier
{
}

impl TryFrom<RawTmClientState> for ClientState {
impl<V> TryFrom<RawTmClientState> for ClientState<V>
where
V: Clone + tendermint::crypto::signature::Verifier,
{
type Error = Error;

fn try_from(raw: RawTmClientState) -> Result<Self, Self::Error> {
Expand Down Expand Up @@ -715,8 +741,11 @@ impl TryFrom<RawTmClientState> for ClientState {
}
}

impl From<ClientState> for RawTmClientState {
fn from(value: ClientState) -> Self {
impl<V> From<ClientState<V>> for RawTmClientState
where
V: Clone + tendermint::crypto::signature::Verifier,
{
fn from(value: ClientState<V>) -> Self {
#[allow(deprecated)]
Self {
chain_id: value.chain_id.to_string(),
Expand All @@ -739,17 +768,22 @@ impl From<ClientState> for RawTmClientState {
}
}

impl Protobuf<Any> for ClientState {}
impl<V> Protobuf<Any> for ClientState<V> where V: Clone + tendermint::crypto::signature::Verifier {}

impl TryFrom<Any> for ClientState {
impl<V> TryFrom<Any> for ClientState<V>
where
V: Clone + tendermint::crypto::signature::Verifier,
{
type Error = ClientError;

fn try_from(raw: Any) -> Result<Self, Self::Error> {
use core::ops::Deref;

use bytes::Buf;

fn decode_client_state<B: Buf>(buf: B) -> Result<ClientState, Error> {
fn decode_client_state<B: Buf, V: Clone + tendermint::crypto::signature::Verifier>(
buf: B,
) -> Result<ClientState<V>, Error> {
RawTmClientState::decode(buf)
.map_err(Error::Decode)?
.try_into()
Expand All @@ -766,8 +800,11 @@ impl TryFrom<Any> for ClientState {
}
}

impl From<ClientState> for Any {
fn from(client_state: ClientState) -> Self {
impl<V> From<ClientState<V>> for Any
where
V: Clone + tendermint::crypto::signature::Verifier,
{
fn from(client_state: ClientState<V>) -> Self {
Any {
type_url: TENDERMINT_CLIENT_STATE_TYPE_URL.to_string(),
value: Protobuf::<RawTmClientState>::encode_vec(client_state),
Expand Down Expand Up @@ -966,7 +1003,7 @@ mod tests {
for test in tests {
let p = test.params.clone();

let cs_result = ClientState::new(
let cs_result = ClientState::<tendermint::crypto::default::signature::Verifier>::new(
p.id,
p.trust_level,
p.trusting_period,
Expand Down Expand Up @@ -1010,7 +1047,14 @@ mod tests {
struct Test {
name: String,
height: Height,
setup: Option<Box<dyn FnOnce(ClientState) -> ClientState>>,
setup: Option<
Box<
dyn FnOnce(
ClientState<tendermint::crypto::default::signature::Verifier>,
)
-> ClientState<tendermint::crypto::default::signature::Verifier>,
>,
>,
want_pass: bool,
}

Expand Down Expand Up @@ -1063,7 +1107,9 @@ mod tests {
#[test]
fn tm_client_state_conversions_healthy() {
// check client state creation path from a proto type
let tm_client_state_from_raw = ClientState::new_dummy_from_raw(RawHeight {
let tm_client_state_from_raw = ClientState::<
tendermint::crypto::default::signature::Verifier,
>::new_dummy_from_raw(RawHeight {
revision_number: 0,
revision_height: 0,
});
Expand All @@ -1084,7 +1130,9 @@ mod tests {

// check client state creation path from a tendermint header
let tm_header = get_dummy_tendermint_header();
let tm_client_state_from_header = ClientState::new_dummy_from_header(tm_header);
let tm_client_state_from_header = ClientState::<
tendermint::crypto::default::signature::Verifier,
>::new_dummy_from_header(tm_header);
let any_from_header = Any::from(tm_client_state_from_header.clone());
let tm_client_state_from_any = ClientState::try_from(any_from_header);
assert!(tm_client_state_from_any.is_ok());
Expand All @@ -1096,7 +1144,9 @@ mod tests {

#[test]
fn tm_client_state_malformed_with_frozen_height() {
let tm_client_state_from_raw = ClientState::new_dummy_from_raw(RawHeight {
let tm_client_state_from_raw = ClientState::<
tendermint::crypto::default::signature::Verifier,
>::new_dummy_from_raw(RawHeight {
revision_number: 0,
revision_height: 10,
});
Expand Down Expand Up @@ -1144,7 +1194,10 @@ pub mod test_util {
use crate::core::ics24_host::identifier::ChainId;
use crate::prelude::*;

impl ClientState {
impl<V> ClientState<V>
where
V: Clone + tendermint::crypto::signature::Verifier,
{
pub fn new_dummy_from_raw(frozen_height: RawHeight) -> Result<Self, Error> {
Self::try_from(get_dummy_raw_tm_client_state(frozen_height))
}
Expand Down Expand Up @@ -1210,7 +1263,10 @@ pub mod test_util {
allow_update: AllowUpdate,
}

impl TryFrom<ClientStateConfig> for ClientState {
impl<V> TryFrom<ClientStateConfig> for ClientState<V>
where
V: Clone + tendermint::crypto::signature::Verifier,
{
type Error = ClientError;

fn try_from(config: ClientStateConfig) -> Result<Self, Self::Error> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ use crate::core::ics24_host::path::ClientConsensusStatePath;
use crate::core::timestamp::Timestamp;
use crate::prelude::*;

impl ClientState {
impl<V> ClientState<V>
where V: Clone + tendermint::crypto::signature::Verifier {
// verify_misbehaviour determines whether or not two conflicting headers at
// the same height would have convinced the light client.
pub fn verify_misbehaviour<ClientValidationContext>(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ use crate::core::ics24_host::identifier::ClientId;
use crate::core::ics24_host::path::ClientConsensusStatePath;
use crate::prelude::*;

impl ClientState {
impl<V> ClientState<V>
where V: Clone + tendermint::crypto::signature::Verifier {
pub fn verify_header<ClientValidationContext>(
&self,
ctx: &ClientValidationContext,
Expand Down
2 changes: 1 addition & 1 deletion crates/ibc/src/core/ics02_client/handler/create_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ mod tests {

let tm_header = get_dummy_tendermint_header();

let tm_client_state = TmClientState::new_dummy_from_header(tm_header.clone()).into();
let tm_client_state = TmClientState::<tendermint::crypto::default::signature::Verifier>::new_dummy_from_header(tm_header.clone()).into();

let client_type = tm_client_type();

Expand Down
17 changes: 10 additions & 7 deletions crates/ibc/src/core/ics02_client/handler/upgrade_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,13 +124,16 @@ mod tests {
let low_upgrade_height = Height::new(0, 26).unwrap();
let msg_with_low_upgrade_height = MsgUpgradeClient::new_dummy(low_upgrade_height);

let msg_with_unknown_upgraded_cs = MsgUpgradeClient {
upgraded_client_state: TmClientState::new_dummy_from_header(
get_dummy_tendermint_header(),
)
.into(),
..msg_default.clone()
};
let msg_with_unknown_upgraded_cs =
MsgUpgradeClient {
upgraded_client_state: TmClientState::<
tendermint::crypto::default::signature::Verifier,
>::new_dummy_from_header(
get_dummy_tendermint_header()
)
.into(),
..msg_default.clone()
};

let msg = match msg_variant {
Msg::Default => msg_default,
Expand Down
2 changes: 1 addition & 1 deletion crates/ibc/src/core/ics02_client/msgs/create_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ mod tests {
let signer = get_dummy_account_id();

let tm_header = get_dummy_tendermint_header();
let tm_client_state = TmClientState::new_dummy_from_header(tm_header.clone()).into();
let tm_client_state = TmClientState::<tendermint::crypto::default::signature::Verifier>::new_dummy_from_header(tm_header.clone()).into();

let msg = MsgCreateClient::new(
tm_client_state,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@
) -> Result<TmEvent, UpgradeClientError>
where
Ctx: UpgradeExecutionContext,
Ctx::AnyClientState: From<TmClientState>,
Ctx::AnyClientState: From<TmClientState<tendermint::crypto::default::signature::Verifier>>,
{
let plan = proposal.plan;

if ctx.upgrade_plan().is_ok() {

Check warning on line 27 in crates/ibc/src/hosts/tendermint/upgrade_proposal/handler.rs

View check run for this annotation

Codecov / codecov/patch

crates/ibc/src/hosts/tendermint/upgrade_proposal/handler.rs#L23-L27

Added lines #L23 - L27 were not covered by tests
ctx.clear_upgrade_plan(plan.height)?;
}

Expand Down
5 changes: 4 additions & 1 deletion crates/ibc/src/hosts/tendermint/validate_self_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ pub trait ValidateSelfClientContext {
&self,
client_state_of_host_on_counterparty: Any,
) -> Result<(), ContextError> {
let tm_client_state = TmClientState::try_from(client_state_of_host_on_counterparty)
let tm_client_state =
TmClientState::<tendermint::crypto::default::signature::Verifier>::try_from(
client_state_of_host_on_counterparty,
)
.map_err(|_| ConnectionError::InvalidClientState {
reason: "client must be a tendermint client".to_string(),
})
Expand Down
4 changes: 2 additions & 2 deletions crates/ibc/src/mock/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ pub const DEFAULT_BLOCK_TIME_SECS: u64 = 3;
]
#[mock]
pub enum AnyClientState {
Tendermint(TmClientState),
Tendermint(TmClientState<tendermint::crypto::default::signature::Verifier>),
Mock(MockClientState),
}

Expand Down Expand Up @@ -723,7 +723,7 @@ impl MockContext {
})
.collect();

let client_state: TmClientState = TmClientStateConfig::builder()
let client_state: TmClientState<tendermint::crypto::default::signature::Verifier> = TmClientStateConfig::builder()
.chain_id(client.client_chain_id)
.latest_height(client.client_state_height)
.trusting_period(client.trusting_period)
Expand Down
Loading