Skip to content

Commit

Permalink
Split out verifier parts of tendermint-light-client to `tendermint-…
Browse files Browse the repository at this point in the history
…light-client-verifier` (#1071)

* Split out verifier parts of tendermint-light-client to tendermint-light-client-verifier

* Add Time::now() method behind clock feature

* light-client refactor: Re-export new verifier crate from `tendermint-light-client` (#1074)

* Re-export tendermint_light_client_verifier as verifier from tendermint_light_client

Signed-off-by: Thane Thomson <[email protected]>

* Remove unnecessary tendermint-light-client import

Signed-off-by: Thane Thomson <[email protected]>

* Fix crate docs to reflect verifier extraction

Signed-off-by: Thane Thomson <[email protected]>

* Add changelog entry

Signed-off-by: Thane Thomson <[email protected]>

* Re-export the original exports in light-client crate

Co-authored-by: Thane Thomson <[email protected]>
  • Loading branch information
soareschen and thanethomson authored Jan 12, 2022
1 parent 8d77986 commit b52a5af
Show file tree
Hide file tree
Showing 48 changed files with 305 additions and 187 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
- `[tendermint-light-client]` Split out the verification functionality from the
`tendermint-light-client` crate into its own `no_std`-compatible crate:
`tendermint-light-client-verifier`. This helps move us closer to `no_std`
compliance in both tendermint-rs and ibc-rs
([#1027](https://github.com/informalsystems/tendermint-rs/issues/1027))
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ members = [
"config",
"light-client",
"light-client-js",
"light-client-verifier",
"p2p",
"pbt-gen",
"proto",
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 @@ -25,7 +25,7 @@ serde_json = { version = "1.0", default-features = false }
# TODO(thane): Remove once https://github.com/rustwasm/wasm-bindgen/issues/2508 is resolved
syn = { version = "=1.0.65", default-features = false }
tendermint = { version = "0.23.0", default-features = false, path = "../tendermint" }
tendermint-light-client = { version = "0.23.0", default-features = false, path = "../light-client" }
tendermint-light-client-verifier = { version = "0.23.0", default-features = false, path = "../light-client-verifier" }
wasm-bindgen = { version = "0.2.63", default-features = false, features = [ "serde-serialize" ] }

# The `console_error_panic_hook` crate provides better debugging of panics by
Expand Down
10 changes: 5 additions & 5 deletions light-client-js/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
//! Tendermint Light Client JavaScript/WASM interface.
//!
//! This crate exposes some of the [`tendermint-light-client`] crate's
//! This crate exposes some of the [`tendermint-light-client-verifier`] crate's
//! functionality to be used from the JavaScript ecosystem.
//!
//! For a detailed example, please see the [`verifier-web` example] in the
//! repository.
//!
//! [`tendermint-light-client`]: https://github.com/informalsystems/tendermint-rs/tree/master/light-client
//! [`tendermint-light-client-verifier`]: https://github.com/informalsystems/tendermint-rs/tree/master/light-client-verifier
//! [`verifier-web` example]: https://github.com/informalsystems/tendermint-rs/tree/master/light-client-js/examples/verifier-web
mod utils;

use serde::{Deserialize, Serialize};
use std::time::Duration;
use tendermint::Time;
use tendermint_light_client::components::verifier::{ProdVerifier, Verifier};
use tendermint_light_client::light_client::Options;
use tendermint_light_client::types::{LightBlock, TrustThreshold};
use tendermint_light_client_verifier::options::Options;
use tendermint_light_client_verifier::types::{LightBlock, TrustThreshold};
use tendermint_light_client_verifier::{ProdVerifier, Verifier};
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsValue;

Expand Down
4 changes: 2 additions & 2 deletions light-client-js/tests/web.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@

extern crate wasm_bindgen_test;
use tendermint::Time;
use tendermint_light_client::components::verifier::Verdict;
use tendermint_light_client::types::LightBlock;
use tendermint_light_client_js::{verify, Error, JsOptions};
use tendermint_light_client_verifier::types::LightBlock;
use tendermint_light_client_verifier::Verdict;
use wasm_bindgen::JsValue;
use wasm_bindgen_test::*;

Expand Down
38 changes: 38 additions & 0 deletions light-client-verifier/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
[package]
name = "tendermint-light-client-verifier"
version = "0.23.0"
edition = "2021"
license = "Apache-2.0"
readme = "README.md"
keywords = ["blockchain", "bft", "consensus", "cosmos", "tendermint"]
categories = ["cryptography::cryptocurrencies", "network-programming"]
repository = "https://github.com/informalsystems/tendermint-rs"
authors = [
"Informal Systems <[email protected]>",
]

description = """
Implementation of the Tendermint Light Client Verification Algorithm.
"""

# docs.rs-specific configuration
[package.metadata.docs.rs]
# document all features
all-features = true
# defines the configuration attribute `docsrs`
rustdoc-args = ["--cfg", "docsrs"]

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

[dependencies]
tendermint = { version = "0.23.0", path = "../tendermint", default-features = false }
tendermint-rpc = { version = "0.23.0", path = "../rpc", default-features = false }

derive_more = { version = "0.99.5", default-features = false, features = ["display"] }
serde = { version = "1.0.106", default-features = false }
time = { version = "0.3.5", default-features = false }
flex-error = { version = "0.4.4", default-features = false }

[dev-dependencies]
tendermint-testgen = { path = "../testgen", default-features = false }
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
//! Errors which may be raised when verifying a `LightBlock`
use core::time::Duration;
use flex_error::define_error;
use serde::{Deserialize, Serialize};
use std::time::Duration;
use tendermint::account::Id;
use tendermint::Error as TendermintError;

use crate::errors::ErrorExt;
use crate::operations::voting_power::VotingPowerTally;
use crate::prelude::*;
use crate::types::{Hash, Height, Time, Validator, ValidatorAddress};
use tendermint::account::Id;
use tendermint::Error as TendermintError;

define_error! {
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
Expand All @@ -27,15 +27,6 @@ define_error! {
e.header_time, e.now)
},

ImplementationSpecific
{
detail: String,
}
| e | {
format_args!("implementation specific: {0}",
e.detail)
},

NotEnoughTrust
{
tally: VotingPowerTally,
Expand Down Expand Up @@ -171,6 +162,21 @@ define_error! {
}
}

/// Extension methods for `ErrorKind`
pub trait ErrorExt {
/// Whether this error means that the light block
/// cannot be trusted w.r.t. the latest trusted state.
fn not_enough_trust(&self) -> Option<VotingPowerTally>;

/// Whether this error means that the light block has expired,
/// ie. it's outside of the trusting period.
fn has_expired(&self) -> bool;

/// Whether this error means that a timeout occured when
/// querying a node.
fn is_timeout(&self) -> Option<Duration>;
}

impl ErrorExt for VerificationErrorDetail {
fn not_enough_trust(&self) -> Option<VotingPowerTally> {
match &self {
Expand Down
14 changes: 14 additions & 0 deletions light-client-verifier/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#![no_std]

extern crate alloc;

mod prelude;

pub mod errors;
pub mod operations;
pub mod options;
pub mod predicates;
pub mod types;
mod verifier;

pub use verifier::{PredicateVerifier, ProdVerifier, Verdict, Verifier};
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
//! Provides an interface and default implementation for the `CommitValidator` operation
use crate::{
errors::VerificationError,
operations::{Hasher, ProdHasher},
predicates::errors::VerificationError,
types::{SignedHeader, ValidatorSet},
};

Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
//! Provides an interface and default implementation for the `VotingPower` operation
use crate::prelude::*;
use crate::{
predicates::errors::VerificationError,
errors::VerificationError,
types::{Commit, SignedHeader, TrustThreshold, ValidatorSet},
};

use alloc::collections::BTreeSet as HashSet;
use core::fmt;
use serde::{Deserialize, Serialize};
use std::collections::HashSet;
use std::fmt;

use std::convert::TryFrom;
use core::convert::TryFrom;
use tendermint::block::CommitSig;
use tendermint::trust_threshold::TrustThreshold as _;
use tendermint::vote::{SignedVote, ValidatorIndex, Vote};
Expand Down Expand Up @@ -220,7 +221,7 @@ fn non_absent_vote(
#[cfg(test)]
mod tests {
use super::*;
use crate::predicates::errors::VerificationErrorDetail;
use crate::errors::VerificationErrorDetail;
use crate::types::LightBlock;
use tendermint::trust_threshold::TrustThresholdFraction;
use tendermint_testgen::light_block::generate_signed_header;
Expand Down
30 changes: 30 additions & 0 deletions light-client-verifier/src/options.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//! Light client implementation as per the [Core Verification specification][1].
//!
//! [1]: https://github.com/informalsystems/tendermint-rs/blob/master/docs/spec/lightclient/verification/verification.md
use core::time::Duration;

use derive_more::Display;
use serde::{Deserialize, Serialize};

use crate::types::TrustThreshold;

/// Verification parameters
#[derive(Copy, Clone, Debug, PartialEq, Display, Serialize, Deserialize)]
#[display(fmt = "{:?}", self)]
pub struct Options {
/// Defines what fraction of the total voting power of a known
/// and trusted validator set is sufficient for a commit to be
/// accepted going forward.
pub trust_threshold: TrustThreshold,

/// How long a validator set is trusted for (must be shorter than the chain's
/// unbonding period)
pub trusting_period: Duration,

/// Correction parameter dealing with only approximately synchronized clocks.
/// The local clock should always be ahead of timestamps from the blockchain; this
/// is the maximum amount that the local clock may drift behind a timestamp from the
/// blockchain.
pub clock_drift: Duration,
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
//! Predicates for light block validation and verification.
use crate::errors::VerificationError;
use crate::prelude::*;
use crate::{
operations::{CommitValidator, Hasher, VotingPowerCalculator},
types::{Header, SignedHeader, Time, TrustThreshold, ValidatorSet},
};

use errors::VerificationError;
use std::time::Duration;
use core::time::Duration;
use tendermint::{block::Height, hash::Hash};

pub mod errors;

/// Production predicates, using the default implementation
/// of the `VerificationPredicates` trait.
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
Expand Down Expand Up @@ -205,8 +204,8 @@ pub trait VerificationPredicates: Send + Sync {

#[cfg(test)]
mod tests {
use std::convert::TryInto;
use std::time::Duration;
use core::convert::TryInto;
use core::time::Duration;
use tendermint::block::CommitSig;
use tendermint::validator::Set;
use time::OffsetDateTime;
Expand All @@ -216,9 +215,10 @@ mod tests {
Commit, Generator, Header, Validator, ValidatorSet,
};

use crate::predicates::{
use crate::prelude::*;
use crate::{
errors::{VerificationError, VerificationErrorDetail},
ProdPredicates, VerificationPredicates,
predicates::{ProdPredicates, VerificationPredicates},
};

use crate::operations::{
Expand Down
14 changes: 14 additions & 0 deletions light-client-verifier/src/prelude.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
pub use core::prelude::v1::*;

// Re-export according to alloc::prelude::v1 because it is not yet stabilized
// https://doc.rust-lang.org/src/alloc/prelude/v1.rs.html
pub use alloc::borrow::ToOwned;
pub use alloc::boxed::Box;
pub use alloc::string::{String, ToString};
pub use alloc::vec::Vec;

pub use alloc::format;
pub use alloc::vec;

// will be included in 2021 edition.
pub use core::convert::{TryFrom, TryInto};
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//! Defines or just re-exports the main datatypes used by the light client.
use crate::prelude::*;

use derive_more::Display;
use serde::{Deserialize, Serialize};

Expand Down Expand Up @@ -73,7 +75,7 @@ impl Status {
///
/// From least to most trusted: `Failed`, `Unverified`, `Verified`, `Trusted`.
pub fn most_trusted(a: Self, b: Self) -> Self {
std::cmp::max(a, b)
core::cmp::max(a, b)
}
}

Expand Down Expand Up @@ -201,6 +203,7 @@ impl LatestStatus {
mod tests {

mod status {
use crate::prelude::*;
use crate::types::Status;
use Status::*;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,18 @@
//! Provides an interface and default implementation of the `Verifier` component
use crate::errors::{ErrorExt, VerificationError, VerificationErrorDetail};
use crate::operations::voting_power::VotingPowerTally;
use crate::predicates as preds;
use crate::types::{TrustedBlockState, UntrustedBlockState};
use crate::{
errors::ErrorExt,
light_client::Options,
operations::{
CommitValidator, Hasher, ProdCommitValidator, ProdHasher, ProdVotingPowerCalculator,
VotingPowerCalculator,
},
options::Options,
types::Time,
};
use preds::{
errors::{VerificationError, VerificationErrorDetail},
ProdPredicates, VerificationPredicates,
};
use preds::{ProdPredicates, VerificationPredicates};
use serde::{Deserialize, Serialize};

/// Represents the result of the verification performed by the
Expand Down
1 change: 1 addition & 0 deletions light-client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ mbt = []
[dependencies]
tendermint = { version = "0.23.0", path = "../tendermint", default-features = false }
tendermint-rpc = { version = "0.23.0", path = "../rpc", default-features = false }
tendermint-light-client-verifier = { version = "0.23.0", path = "../light-client-verifier", default-features = false }

contracts = { version = "0.4.0", default-features = false }
crossbeam-channel = { version = "0.4.2", default-features = false }
Expand Down
9 changes: 4 additions & 5 deletions light-client/examples/light_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,14 @@ use std::{path::PathBuf, time::Duration};
use gumdrop::Options;

use tendermint::Hash;
use tendermint_rpc as rpc;

use tendermint_light_client::supervisor::{Handle as _, Instance};
use tendermint_light_client::verifier::options::Options as LightClientOptions;
use tendermint_light_client::verifier::types::{Height, PeerId, TrustThreshold};
use tendermint_light_client::{
builder::{LightClientBuilder, SupervisorBuilder},
light_client,
store::memory::MemoryStore,
types::{Height, PeerId, TrustThreshold},
};
use tendermint_rpc as rpc;

#[derive(Debug, Options)]
struct CliOptions {
Expand Down Expand Up @@ -82,7 +81,7 @@ fn make_instance(
) -> Result<Instance, Box<dyn std::error::Error>> {
let light_store = MemoryStore::new();
let rpc_client = rpc::HttpClient::new(addr).unwrap();
let options = light_client::Options {
let options = LightClientOptions {
trust_threshold: TrustThreshold::default(),
trusting_period: Duration::from_secs(36000),
clock_drift: Duration::from_secs(1),
Expand Down
2 changes: 1 addition & 1 deletion light-client/src/builder/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use tendermint::block::Height;
use tendermint::Hash;

use crate::components::io::IoError;
use crate::predicates::errors::VerificationError;
use crate::verifier::errors::VerificationError;

define_error! {
Error {
Expand Down
Loading

0 comments on commit b52a5af

Please sign in to comment.