Skip to content

Commit

Permalink
Investiage some design tweaks over CryptoProvider
Browse files Browse the repository at this point in the history
  • Loading branch information
Farhad-Shabani committed Dec 19, 2022
1 parent eac7b5a commit b85bb88
Show file tree
Hide file tree
Showing 34 changed files with 253 additions and 360 deletions.
2 changes: 1 addition & 1 deletion config/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ all-features = true
rustdoc-args = ["--cfg", "docsrs"]

[dependencies]
tendermint = { version = "0.28.0", default-features = false, features = ["rust-crypto"], path = "../tendermint" }
tendermint = { version = "0.28.0", default-features = false, path = "../tendermint" }
flex-error = { version = "0.4.4", default-features = false }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
Expand Down
2 changes: 1 addition & 1 deletion light-client-js/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ default = ["console_error_panic_hook"]
serde = { version = "1.0", default-features = false, features = [ "derive" ] }
serde_json = { version = "1.0", default-features = false }
tendermint = { version = "0.28.0", default-features = false, path = "../tendermint" }
tendermint-light-client-verifier = { version = "0.28.0", features = ["rust-crypto"], default-features = false, path = "../light-client-verifier" }
tendermint-light-client-verifier = { version = "0.28.0", default-features = false, path = "../light-client-verifier" }
wasm-bindgen = { version = "0.2.63", default-features = false, features = [ "serde-serialize" ] }
serde-wasm-bindgen = { version = "0.4.5", default-features = false }

Expand Down
7 changes: 3 additions & 4 deletions light-client-js/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,16 @@ use std::time::Duration;

use serde::{Deserialize, Serialize};
use tendermint::Time;
// TODO: Use Web Crypto API for cryptographic routines.
// https://github.com/informalsystems/tendermint-rs/issues/1241
use tendermint_light_client_verifier::ProdVerifier;
use tendermint_light_client_verifier::{
options::Options,
types::{LightBlock, TrustThreshold},
Verifier,
};
use wasm_bindgen::{prelude::*, JsValue};

// TODO: Use Web Crypto API for cryptographic routines.
// https://github.com/informalsystems/tendermint-rs/issues/1241
use tendermint_light_client_verifier::ProdVerifier;

/// Check whether a given untrusted block can be trusted.
#[wasm_bindgen]
pub fn verify(untrusted: JsValue, trusted: JsValue, options: JsValue, now: JsValue) -> JsValue {
Expand Down
3 changes: 1 addition & 2 deletions light-client-verifier/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@ all-features = true
rustdoc-args = ["--cfg", "docsrs"]

[features]
default = ["rust-crypto", "flex-error/std", "flex-error/eyre_tracer"]
rust-crypto = ["tendermint/rust-crypto"]
default = ["flex-error/std", "flex-error/eyre_tracer"]

[dependencies]
tendermint = { version = "0.28.0", path = "../tendermint", default-features = false }
Expand Down
5 changes: 1 addition & 4 deletions light-client-verifier/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,4 @@ pub mod predicates;
pub mod types;
mod verifier;

pub use verifier::{PredicateVerifier, Verdict, Verifier};

#[cfg(feature = "rust-crypto")]
pub use verifier::ProdVerifier;
pub use verifier::{PredicateVerifier, ProdVerifier, Verdict, Verifier};
2 changes: 1 addition & 1 deletion light-client-verifier/src/operations/voting_power.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ impl VotingPowerCalculator for ProdVotingPowerCalculator {
// Check vote is valid
let sign_bytes = signed_vote.sign_bytes();
if validator
.verify_signature(&sign_bytes, signed_vote.signature())
.verify(&sign_bytes, signed_vote.signature())
.is_err()
{
return Err(VerificationError::invalid_signature(
Expand Down
23 changes: 14 additions & 9 deletions light-client-verifier/src/predicates.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@
use core::time::Duration;

use tendermint::{
block::Height, chain::Id as ChainId, crypto::Sha256, hash::Hash, merkle::MerkleHash,
block::Height,
chain::Id as ChainId,
crypto::{Sha256, SignatureVerifier},
hash::Hash,
merkle::MerkleHash,
PublicKey,
};

use crate::{
Expand All @@ -15,13 +20,12 @@ use crate::{

/// Production predicates, using the default implementation
/// of the `VerificationPredicates` trait.
#[cfg(feature = "rust-crypto")]
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub struct ProdPredicates;

#[cfg(feature = "rust-crypto")]
impl VerificationPredicates for ProdPredicates {
type Sha256 = tendermint::crypto::default::Sha256;
type Hasher = Sha256;
type SignatureVerifier = PublicKey;
}

/// Defines the various predicates used to validate and verify light blocks.
Expand All @@ -32,7 +36,8 @@ impl VerificationPredicates for ProdPredicates {
/// have to re-define every predicate.
pub trait VerificationPredicates: Send + Sync {
/// The implementation of SHA256 digest
type Sha256: MerkleHash + Sha256 + Default;
type Hasher: MerkleHash + Default;
type SignatureVerifier: SignatureVerifier;

/// Compare the provided validator_set_hash against the hash produced from hashing the validator
/// set.
Expand All @@ -41,7 +46,7 @@ pub trait VerificationPredicates: Send + Sync {
validators: &ValidatorSet,
header_validators_hash: Hash,
) -> Result<(), VerificationError> {
let validators_hash = validators.hash_with::<Self::Sha256>();
let validators_hash = validators.hash_with::<Self::Hasher>();
if header_validators_hash == validators_hash {
Ok(())
} else {
Expand All @@ -58,7 +63,7 @@ pub trait VerificationPredicates: Send + Sync {
next_validators: &ValidatorSet,
header_next_validators_hash: Hash,
) -> Result<(), VerificationError> {
let next_validators_hash = next_validators.hash_with::<Self::Sha256>();
let next_validators_hash = next_validators.hash_with::<Self::Hasher>();
if header_next_validators_hash == next_validators_hash {
Ok(())
} else {
Expand All @@ -75,7 +80,7 @@ pub trait VerificationPredicates: Send + Sync {
header: &Header,
commit_hash: Hash,
) -> Result<(), VerificationError> {
let header_hash = header.hash_with::<Self::Sha256>();
let header_hash = header.hash_with::<Self::Hasher>();
if header_hash == commit_hash {
Ok(())
} else {
Expand Down Expand Up @@ -226,7 +231,7 @@ pub trait VerificationPredicates: Send + Sync {
}
}

#[cfg(all(test, feature = "rust-crypto"))]
#[cfg(test)]
mod tests {
use core::{convert::TryInto, time::Duration};

Expand Down
14 changes: 5 additions & 9 deletions light-client-verifier/src/verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,15 @@ use serde::{Deserialize, Serialize};

use crate::{
errors::{ErrorExt, VerificationError, VerificationErrorDetail},
operations::{voting_power::VotingPowerTally, CommitValidator, VotingPowerCalculator},
operations::{
voting_power::VotingPowerTally, CommitValidator, ProdCommitValidator,
ProdVotingPowerCalculator, VotingPowerCalculator,
},
options::Options,
predicates::VerificationPredicates,
predicates::{ProdPredicates, VerificationPredicates},
types::{Time, TrustedBlockState, UntrustedBlockState},
};

#[cfg(feature = "rust-crypto")]
use crate::{
operations::{ProdCommitValidator, ProdVotingPowerCalculator},
predicates::ProdPredicates,
};

/// Represents the result of the verification performed by the
/// verifier component.
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
Expand Down Expand Up @@ -267,7 +264,6 @@ where
}
}

#[cfg(feature = "rust-crypto")]
/// The default production implementation of the [`PredicateVerifier`].
pub type ProdVerifier =
PredicateVerifier<ProdPredicates, ProdVotingPowerCalculator, ProdCommitValidator>;
Expand Down
7 changes: 3 additions & 4 deletions light-client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,12 @@ rustdoc-args = ["--cfg", "docsrs"]

[features]
default = ["rpc-client", "flex-error/std", "flex-error/eyre_tracer"]
rpc-client = ["tokio", "rust-crypto", "tendermint-rpc/http-client"]
rust-crypto = ["tendermint/rust-crypto", "tendermint-light-client-verifier/rust-crypto"]
rpc-client = ["tokio", "tendermint-rpc/http-client"]
secp256k1 = ["tendermint/secp256k1", "tendermint-rpc/secp256k1"]
lightstore-sled = ["sled"]
unstable = ["rust-crypto"]
unstable = []
# Enable to execute long-running model-based tests
mbt = ["rust-crypto"]
mbt = []

[dependencies]
tendermint = { version = "0.28.0", path = "../tendermint", default-features = false }
Expand Down
40 changes: 23 additions & 17 deletions light-client/src/builder/light_client.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
//! DSL for building a light client [`Instance`]
use tendermint::{block::Height, crypto::Sha256, merkle::MerkleHash, Hash};

use tendermint::{
block::Height,
crypto::{Sha256, SignatureVerifier},
merkle::MerkleHash,
Hash, PublicKey,
};
#[cfg(feature = "rpc-client")]
use {
crate::components::clock::SystemClock,
Expand Down Expand Up @@ -39,26 +43,27 @@ pub struct HasTrustedState;

/// Builder for a light client [`Instance`]
#[must_use]
pub struct LightClientBuilder<State, H: MerkleHash + Sha256 + Default> {
pub struct LightClientBuilder<State, H: MerkleHash + Default, S: SignatureVerifier> {
peer_id: PeerId,
options: Options,
io: Box<dyn Io>,
clock: Box<dyn Clock>,
verifier: Box<dyn Verifier>,
scheduler: Box<dyn Scheduler>,
predicates: Box<dyn VerificationPredicates<Sha256 = H>>,
predicates: Box<dyn VerificationPredicates<Hasher = H, SignatureVerifier = S>>,
light_store: Box<dyn LightStore>,

#[allow(dead_code)]
state: State,
}

impl<Current, H> LightClientBuilder<Current, H>
impl<Current, H, S> LightClientBuilder<Current, H, S>
where
H: MerkleHash + Sha256 + Default,
H: MerkleHash + Default,
S: SignatureVerifier,
{
/// Private method to move from one state to another
fn with_state<Next>(self, state: Next) -> LightClientBuilder<Next, H> {
fn with_state<Next>(self, state: Next) -> LightClientBuilder<Next, H, S> {
LightClientBuilder {
peer_id: self.peer_id,
options: self.options,
Expand All @@ -73,8 +78,7 @@ where
}
}

#[cfg(feature = "rpc-client")]
impl LightClientBuilder<NoTrustedState, tendermint::crypto::default::Sha256> {
impl LightClientBuilder<NoTrustedState, Sha256, PublicKey> {
/// Initialize a builder for a production (non-mock) light client.
pub fn prod(
peer_id: PeerId,
Expand All @@ -96,9 +100,10 @@ impl LightClientBuilder<NoTrustedState, tendermint::crypto::default::Sha256> {
}
}

impl<H> LightClientBuilder<NoTrustedState, H>
impl<H, S> LightClientBuilder<NoTrustedState, H, S>
where
H: MerkleHash + Sha256 + Default,
H: MerkleHash + Default,
S: SignatureVerifier,
{
/// Initialize a builder for a custom light client, by providing all dependencies upfront.
// TODO: redesign this, it's a builder API!
Expand All @@ -111,7 +116,7 @@ where
clock: Box<dyn Clock>,
verifier: Box<dyn Verifier>,
scheduler: Box<dyn Scheduler>,
predicates: Box<dyn VerificationPredicates<Sha256 = H>>,
predicates: Box<dyn VerificationPredicates<Hasher = H, SignatureVerifier = S>>,
) -> Self {
Self {
peer_id,
Expand All @@ -130,7 +135,7 @@ where
fn trust_light_block(
mut self,
trusted_state: LightBlock,
) -> Result<LightClientBuilder<HasTrustedState, H>, Error> {
) -> Result<LightClientBuilder<HasTrustedState, H, S>, Error> {
self.validate(&trusted_state)?;

// TODO(liamsi, romac): it is unclear if this should be Trusted or only Verified
Expand All @@ -141,7 +146,7 @@ where

/// Keep using the latest verified or trusted block in the light store.
/// Such a block must exists otherwise this will fail.
pub fn trust_from_store(self) -> Result<LightClientBuilder<HasTrustedState, H>, Error> {
pub fn trust_from_store(self) -> Result<LightClientBuilder<HasTrustedState, H, S>, Error> {
let trusted_state = self
.light_store
.highest_trusted_or_verified()
Expand All @@ -155,7 +160,7 @@ where
self,
trusted_height: Height,
trusted_hash: Hash,
) -> Result<LightClientBuilder<HasTrustedState, H>, Error> {
) -> Result<LightClientBuilder<HasTrustedState, H, S>, Error> {
let trusted_state = self
.io
.fetch_light_block(AtHeight::At(trusted_height))
Expand Down Expand Up @@ -207,9 +212,10 @@ where
}
}

impl<H> LightClientBuilder<HasTrustedState, H>
impl<H, S> LightClientBuilder<HasTrustedState, H, S>
where
H: MerkleHash + Sha256 + Default,
H: MerkleHash + Default,
S: SignatureVerifier,
{
/// Build the light client [`Instance`].
#[must_use]
Expand Down
8 changes: 4 additions & 4 deletions light-client/src/fork_detector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,7 @@ pub struct ProvidedForkDetector<H> {
_crypto: PhantomData<H>,
}

#[cfg(feature = "rust-crypto")]
pub type ProdForkDetector = ProvidedForkDetector<tendermint::crypto::default::Sha256>;
pub type ProdForkDetector = ProvidedForkDetector<Sha256>;

impl<H> ProvidedForkDetector<H> {
/// Construct a new fork detector that will use the given header hasher.
Expand All @@ -88,8 +87,9 @@ impl<H: Default> Default for ProvidedForkDetector<H> {

impl<H> ForkDetector for ProvidedForkDetector<H>
where
// Sync + Send have to be added only because of forbid(unsafe_code)
H: MerkleHash + Sha256 + Default + Sync + Send,
// Sync + Send have to be added only because of
// forbid(unsafe_code)
H: MerkleHash + Default + Sync + Send,
{
/// Perform fork detection. See the documentation `ProdForkDetector` for details.
fn detect_forks(
Expand Down
2 changes: 1 addition & 1 deletion light-client/src/supervisor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,7 @@ impl Handle for SupervisorHandle {
}
}

#[cfg(all(test, feature = "rust-crypto"))]
#[cfg(test)]
mod tests {
use core::{
convert::{Into, TryFrom},
Expand Down
14 changes: 4 additions & 10 deletions light-client/src/tests.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
//! Utilities and datatypes for use in tests.
use std::collections::HashMap;

#[cfg(feature = "rust-crypto")]
use std::time::Duration;
use std::{collections::HashMap, time::Duration};

use contracts::contract_trait;
use serde::{Deserialize, Serialize};
Expand All @@ -24,14 +21,12 @@ use crate::{
evidence::EvidenceReporter,
light_client::LightClient,
state::State,
verifier::types::{
Height, LightBlock, PeerId, SignedHeader, Time, TrustThreshold, ValidatorSet,
verifier::{
types::{Height, LightBlock, PeerId, SignedHeader, Time, TrustThreshold, ValidatorSet},
Verdict, Verifier,
},
};

#[cfg(feature = "rust-crypto")]
use crate::verifier::{Verdict, Verifier};

#[derive(Deserialize, Clone, Debug)]
pub struct TestCases<LB> {
pub batch_name: String,
Expand Down Expand Up @@ -148,7 +143,6 @@ impl MockEvidenceReporter {
}
}

#[cfg(feature = "rust-crypto")]
pub fn verify_single(
trusted_block: LightBlock,
input: LightBlock,
Expand Down
2 changes: 0 additions & 2 deletions light-client/tests/supervisor.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
#![cfg(feature = "rust-crypto")]

use std::{collections::HashMap, time::Duration};

use tendermint_light_client::{
Expand Down
3 changes: 1 addition & 2 deletions rpc/src/endpoint/block_results.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
use serde::{Deserialize, Serialize};
use tendermint::{abci, block, consensus, validator};

use crate::prelude::*;
use crate::serializers;
use crate::{prelude::*, serializers};

/// Get ABCI results at a given height.
#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
Expand Down
Loading

0 comments on commit b85bb88

Please sign in to comment.