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

Consolidate and delete old implementation of the light client #500

Merged
merged 7 commits into from
Aug 5, 2020
Merged
Show file tree
Hide file tree
Changes from 5 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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@

- Add missing documentation to all items ([#472])
- Add major contributors as authors of the `light-client`, `light-node`, and `rpc` crate ([#472])
- Remove and consolidate deprecated [lite] and [lite_impl] modules from the `tendermint` crate ([#500])

[#472]: https://github.com/informalsystems/tendermint-rs/pull/472
[lite_impl]: https://github.com/informalsystems/tendermint-rs/tree/master/tendermint/src/lite_impl

## [0.15.0] (2020-07-17)

Expand Down
6 changes: 3 additions & 3 deletions light-client/src/components/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ pub enum AtHeight {

impl From<Height> for AtHeight {
fn from(height: Height) -> Self {
if height == 0 {
if height.value() == 0 {
Self::Highest
} else {
Self::At(height)
Expand Down Expand Up @@ -93,10 +93,10 @@ pub struct ProdIo {
impl Io for ProdIo {
fn fetch_light_block(&self, peer: PeerId, height: AtHeight) -> Result<LightBlock, IoError> {
let signed_header = self.fetch_signed_header(peer, height)?;
let height: Height = signed_header.header.height.into();
let height = signed_header.header.height;

let validator_set = self.fetch_validator_set(peer, height.into())?;
let next_validator_set = self.fetch_validator_set(peer, (height + 1).into())?;
let next_validator_set = self.fetch_validator_set(peer, height.increment().into())?;

let light_block = LightBlock::new(signed_header, validator_set, next_validator_set, peer);

Expand Down
2 changes: 1 addition & 1 deletion light-client/src/components/scheduler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,5 +122,5 @@ pub fn valid_schedule(
#[pre(low <= high)]
#[post(low <= ret && ret <= high)]
fn midpoint(low: Height, high: Height) -> Height {
low + (high + 1 - low) / 2
(low.value() + (high.value() + 1 - low.value()) / 2).into()
}
8 changes: 4 additions & 4 deletions light-client/src/components/verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,10 @@ impl ProdVerifier {
impl Default for ProdVerifier {
fn default() -> Self {
Self::new(
ProdPredicates,
ProdVotingPowerCalculator,
ProdCommitValidator,
ProdHasher,
ProdPredicates::default(),
ProdVotingPowerCalculator::default(),
ProdCommitValidator::default(),
ProdHasher::default(),
)
}
}
Expand Down
25 changes: 21 additions & 4 deletions light-client/src/operations/commit_validator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

use crate::{
bail,
operations::{Hasher, ProdHasher},
predicates::errors::VerificationError,
types::{SignedHeader, ValidatorSet},
};

use tendermint::block::CommitSig;
use tendermint::lite::types::ValidatorSet as _;

/// Validates the commit associated with a header against a validator set
pub trait CommitValidator: Send {
Expand All @@ -27,8 +27,25 @@ pub trait CommitValidator: Send {
}

/// Production-ready implementation of a commit validator
#[derive(Copy, Clone)]
pub struct ProdCommitValidator;
pub struct ProdCommitValidator {
hasher: Box<dyn Hasher>,
}

impl ProdCommitValidator {
/// Create a new commit validator using the given [`Hasher`]
/// to compute the hash of headers and validator sets.
pub fn new(hasher: impl Hasher + 'static) -> Self {
Self {
hasher: Box::new(hasher),
}
}
}

impl Default for ProdCommitValidator {
fn default() -> Self {
Self::new(ProdHasher::default())
}
}

impl CommitValidator for ProdCommitValidator {
fn validate(
Expand Down Expand Up @@ -81,7 +98,7 @@ impl CommitValidator for ProdCommitValidator {
bail!(VerificationError::ImplementationSpecific(format!(
"Found a faulty signer ({}) not present in the validator set ({})",
validator_address,
validator_set.hash()
self.hasher.hash_validator_set(validator_set)
)));
}
}
Expand Down
6 changes: 2 additions & 4 deletions light-client/src/operations/hasher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@

use crate::types::{Header, ValidatorSet};

use tendermint::lite::types::Header as _;
use tendermint::merkle;
use tendermint::Hash;
use tendermint::{merkle, Hash};

/// Hashing for headers and validator sets
pub trait Hasher: Send {
Expand All @@ -16,7 +14,7 @@ pub trait Hasher: Send {
}

/// Default implementation of a hasher
#[derive(Copy, Clone, Debug)]
#[derive(Copy, Clone, Default, Debug)]
romac marked this conversation as resolved.
Show resolved Hide resolved
pub struct ProdHasher;

impl Hasher for ProdHasher {
Expand Down
2 changes: 1 addition & 1 deletion light-client/src/operations/voting_power.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use std::collections::HashSet;
use std::fmt;

use tendermint::block::CommitSig;
use tendermint::lite::types::TrustThreshold as _;
use tendermint::trust_threshold::TrustThreshold as _;
use tendermint::vote::{SignedVote, Vote};

/// Tally for the voting power computed by the `VotingPowerCalculator`
Expand Down
12 changes: 6 additions & 6 deletions light-client/src/predicates.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::{
ensure,
light_client::Options,
operations::{CommitValidator, Hasher, VotingPowerCalculator},
types::{Header, Height, LightBlock, SignedHeader, Time, TrustThreshold, ValidatorSet},
types::{Header, LightBlock, SignedHeader, Time, TrustThreshold, ValidatorSet},
};

use errors::VerificationError;
Expand All @@ -14,7 +14,7 @@ pub mod errors;

/// Production predicates, using the default implementation
/// of the `VerificationPredicates` trait.
#[derive(Copy, Clone, Debug)]
#[derive(Copy, Clone, Default, Debug)]
romac marked this conversation as resolved.
Show resolved Hide resolved
pub struct ProdPredicates;
impl VerificationPredicates for ProdPredicates {}

Expand Down Expand Up @@ -152,13 +152,13 @@ pub trait VerificationPredicates: Send {
untrusted_header: &Header,
trusted_header: &Header,
) -> Result<(), VerificationError> {
let trusted_height: Height = trusted_header.height.into();
let trusted_height = trusted_header.height;

ensure!(
untrusted_header.height > trusted_header.height,
VerificationError::NonIncreasingHeight {
got: untrusted_header.height.into(),
expected: trusted_height + 1,
got: untrusted_header.height,
expected: trusted_height.increment(),
}
);

Expand Down Expand Up @@ -260,7 +260,7 @@ pub fn verify(
&trusted.signed_header.header,
)?;

let trusted_next_height = trusted.height().checked_add(1).expect("height overflow");
let trusted_next_height = trusted.height().increment();

if untrusted.height() == trusted_next_height {
// If the untrusted block is the very next block after the trusted block,
Expand Down
3 changes: 1 addition & 2 deletions light-client/src/supervisor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ use crate::light_client::LightClient;
use crate::peer_list::PeerList;
use crate::state::State;
use crate::types::{Height, LatestStatus, LightBlock, PeerId, Status};
use tendermint::lite::{Header, ValidatorSet};

/// Provides an interface to the supervisor for use in downstream code.
pub trait Handle {
Expand Down Expand Up @@ -189,7 +188,7 @@ impl Supervisor {

match latest_trusted {
Some(trusted) => LatestStatus::new(
Some(trusted.signed_header.header.height()),
Some(trusted.signed_header.header.height.value()),
Some(trusted.signed_header.header.hash()),
Some(trusted.next_validators.hash()),
connected_nodes,
Expand Down
12 changes: 6 additions & 6 deletions light-client/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ use tendermint::{
header::Header as TMHeader, signed_header::SignedHeader as TMSignedHeader,
Commit as TMCommit,
},
lite::TrustThresholdFraction,
trust_threshold::TrustThresholdFraction,
validator::Info as TMValidatorInfo,
validator::Set as TMValidatorSet,
};

pub use tendermint::{hash::Hash, lite::Height, time::Time};
pub use tendermint::{block::Height, hash::Hash, time::Time};

/// Peer ID (public key) of a full node
pub type PeerId = tendermint::node::Id;
Expand Down Expand Up @@ -113,9 +113,9 @@ impl LightBlock {
/// Returns the height of this block.
///
/// ## Note
/// This is a shorthand for `block.signed_header.header.height.into()`.
/// This is a shorthand for `block.signed_header.header.height`.
pub fn height(&self) -> Height {
self.signed_header.header.height.into()
self.signed_header.header.height
}
}

Expand All @@ -125,7 +125,7 @@ impl LightBlock {
#[display(fmt = "{:?}", self)]
pub struct LatestStatus {
/// The latest height we are trusting.
pub height: Option<Height>,
pub height: Option<u64>,
/// The latest block hash we are trusting.
pub block_hash: Option<Hash>,
/// The latest validator set we are trusting.
Expand All @@ -143,7 +143,7 @@ impl LatestStatus {
valset_hash: Option<Hash>,
connected_nodes: Vec<PeerId>,
) -> Self {
LatestStatus {
Self {
height,
block_hash,
valset_hash,
Expand Down
10 changes: 5 additions & 5 deletions light-client/tests/light_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,19 +247,19 @@ fn run_bisection_tests(dir: &str) {
/// the bisection test as normal. We then assert that we get the expected error.
fn run_bisection_lower_tests(dir: &str) {
foreach_bisection_test(dir, |file, mut tc| {
let mut trusted_height: Height = tc.trust_options.height.into();
let mut trusted_height = tc.trust_options.height;

if trusted_height <= 1 {
tc.trust_options.height = (trusted_height + 1).into();
trusted_height += 1;
if trusted_height.value() <= 1 {
tc.trust_options.height = trusted_height.increment();
trusted_height = trusted_height.increment();
}

println!(
"Running light client against bisection test file with target height too low: {}",
file
);

tc.height_to_verify = (trusted_height - 1).into();
tc.height_to_verify = (trusted_height.value() - 1).into();

let test_result = run_bisection_test(tc);
match test_result.new_states {
Expand Down
2 changes: 1 addition & 1 deletion light-client/tests/supervisor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ fn load_multi_peer_testcases(dir: &str) -> Vec<TestBisection<LightBlock>> {
}

fn make_instance(peer_id: PeerId, trust_options: TrustOptions, io: MockIo, now: Time) -> Instance {
let trusted_height = trust_options.height.value();
let trusted_height = trust_options.height;
let trusted_state = io
.fetch_light_block(peer_id, AtHeight::At(trusted_height))
.expect("could not 'request' light block");
Expand Down
1 change: 0 additions & 1 deletion light-client/tests/support

This file was deleted.

10 changes: 4 additions & 6 deletions light-node/src/commands/initialize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,14 @@ use abscissa_core::Command;
use abscissa_core::Options;
use abscissa_core::Runnable;

use tendermint::hash;
use tendermint::lite::Header;
use tendermint::Hash;
use tendermint::{hash, Hash};

use tendermint_light_client::components::io::{AtHeight, Io, ProdIo};
use tendermint_light_client::operations::ProdHasher;
use tendermint_light_client::predicates::{ProdPredicates, VerificationPredicates};
use tendermint_light_client::store::sled::SledStore;
use tendermint_light_client::store::LightStore;
use tendermint_light_client::types::Status;
use tendermint_light_client::types::{Height, Status};

/// `initialize` subcommand
#[derive(Command, Debug, Default, Options)]
Expand Down Expand Up @@ -51,7 +49,7 @@ impl Runnable for InitCmd {

let io = ProdIo::new(peer_map, Some(app_cfg.rpc_config.request_timeout));

initialize_subjectively(self.height, subjective_header_hash, &lc, &io);
initialize_subjectively(self.height.into(), subjective_header_hash, &lc, &io);
}
}

Expand All @@ -60,7 +58,7 @@ impl Runnable for InitCmd {
// TODO(ismail): additionally here and everywhere else, we should return errors
// instead of std::process::exit because no destructors will be run.
fn initialize_subjectively(
height: u64,
height: Height,
subjective_header_hash: Hash,
l_conf: &LightClientConfig,
io: &ProdIo,
Expand Down
1 change: 0 additions & 1 deletion rpc/tests/integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
mod endpoints {
use std::{fs, path::PathBuf};
use tendermint::abci::Code;
use tendermint::lite::Header;

use tendermint_rpc::{self as rpc, endpoint, Response};

Expand Down
58 changes: 58 additions & 0 deletions tendermint/src/block/header.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//! Block headers

use crate::amino_types::{message::AminoMessage, BlockId, ConsensusVersion, TimeMsg};
use crate::merkle::simple_hash_from_byte_vectors;
use crate::serializers;
use crate::{account, block, chain, Hash, Time};
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -60,6 +62,62 @@ pub struct Header {
pub proposer_address: account::Id,
}

impl Header {
/// Hash this header
pub fn hash(&self) -> Hash {
// Note that if there is an encoding problem this will
// panic (as the golang code would):
// https://github.com/tendermint/tendermint/blob/134fe2896275bb926b49743c1e25493f6b24cc31/types/block.go#L393
// https://github.com/tendermint/tendermint/blob/134fe2896275bb926b49743c1e25493f6b24cc31/types/encoding_helper.go#L9:6

let mut fields_bytes: Vec<Vec<u8>> = Vec::with_capacity(16);
fields_bytes.push(AminoMessage::bytes_vec(&ConsensusVersion::from(
&self.version,
)));
fields_bytes.push(encode_bytes(self.chain_id.as_bytes()));
fields_bytes.push(encode_varint(self.height.value()));
fields_bytes.push(AminoMessage::bytes_vec(&TimeMsg::from(self.time)));
fields_bytes.push(
self.last_block_id
.as_ref()
.map_or(vec![], |id| AminoMessage::bytes_vec(&BlockId::from(id))),
);
fields_bytes.push(self.last_commit_hash.as_ref().map_or(vec![], encode_hash));
fields_bytes.push(self.data_hash.as_ref().map_or(vec![], encode_hash));
fields_bytes.push(encode_hash(&self.validators_hash));
fields_bytes.push(encode_hash(&self.next_validators_hash));
fields_bytes.push(encode_hash(&self.consensus_hash));
fields_bytes.push(encode_bytes(&self.app_hash));
fields_bytes.push(self.last_results_hash.as_ref().map_or(vec![], encode_hash));
fields_bytes.push(self.evidence_hash.as_ref().map_or(vec![], encode_hash));
fields_bytes.push(encode_bytes(self.proposer_address.as_bytes()));

Hash::Sha256(simple_hash_from_byte_vectors(fields_bytes))
}
}

fn encode_bytes(bytes: &[u8]) -> Vec<u8> {
let bytes_len = bytes.len();
if bytes_len > 0 {
let mut encoded = vec![];
prost_amino::encode_length_delimiter(bytes_len, &mut encoded).unwrap();
encoded.append(&mut bytes.to_vec());
encoded
} else {
vec![]
}
}

fn encode_hash(hash: &Hash) -> Vec<u8> {
encode_bytes(hash.as_bytes())
}

fn encode_varint(val: u64) -> Vec<u8> {
let mut val_enc = vec![];
prost_amino::encoding::encode_varint(val, &mut val_enc);
val_enc
}

liamsi marked this conversation as resolved.
Show resolved Hide resolved
/// `Version` contains the protocol version for the blockchain and the
/// application.
///
Expand Down
Loading