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

Add commands to initialize light client for given chain and start verifying headers #26

Merged
merged 43 commits into from
Mar 20, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
41720f9
Add function to initialize lite client without trusted state
romac Mar 10, 2020
ff255e8
Make LightClient generic over chain type via a generic store
romac Mar 10, 2020
dc07271
Add stub to initialize the light client with trust options
romac Mar 10, 2020
bc34fc3
Use custom sum type for store heights
romac Mar 10, 2020
c2a6c8a
Rename LiteClient to LightClient
romac Mar 10, 2020
c2fc234
Add stub command `light init`
romac Mar 10, 2020
991cd02
Implement LightClient::init_with_node_trusted_state
romac Mar 11, 2020
cf3a2a9
Implement LightClient::init_with_trusted_state
romac Mar 11, 2020
1905e14
Refactor light client
romac Mar 11, 2020
9f8e0f8
Verify trusted state on light client initialization
romac Mar 12, 2020
f45fc07
Remove unused file
romac Mar 12, 2020
883362a
Add stub for Client::check_trusted_header
romac Mar 12, 2020
9e02e89
Fail when needed in Client::update_trusted_state
romac Mar 12, 2020
fb360ef
Partially implement Client::update
romac Mar 12, 2020
e1c93e3
Implement LightClient::verify_header
romac Mar 12, 2020
348168e
Update comment
romac Mar 12, 2020
023a695
Fix clippy warnings
romac Mar 12, 2020
13f9ab6
Use serde-humantime to parse trusting_period
romac Mar 12, 2020
afd6cd3
Move config defaults into their own module
romac Mar 12, 2020
0ea569c
Create light client and display last trusted state
romac Mar 12, 2020
b157162
Use checked arithmetic when incrementing height
romac Mar 12, 2020
272f681
Update trusted store in Client::update
romac Mar 12, 2020
3853042
Fix clippy warnings
romac Mar 12, 2020
179a844
Rename StoreHeight:GivenHeight to Given
romac Mar 13, 2020
39a9d94
Simplify verify_header signature
romac Mar 13, 2020
dc4bfc7
Spawn empty relayer, and one client per configured chain
romac Mar 16, 2020
cf78a1f
Update tendermint-rs repository
romac Mar 16, 2020
3578515
Remove dep on tendermint-rs/light_node by copying RpcRequester code over
romac Mar 16, 2020
d328d92
Improve reporting a bit
romac Mar 16, 2020
084f215
Fix RpcRequester unit test
romac Mar 16, 2020
0699ed7
Add persistent trusted store implementation
romac Mar 16, 2020
60e0066
Use persistent trusted store in commands
romac Mar 16, 2020
ba6235f
Ignore database folders in Git
romac Mar 16, 2020
ddeffb0
Fix clippy warnings
romac Mar 16, 2020
c47247d
Remove superfluous Tendermint type struct
romac Mar 17, 2020
180b253
Add some doc comments
romac Mar 17, 2020
e75b5a1
Document the relayer::client::Client struct
romac Mar 17, 2020
73ce4bf
More doc comments
romac Mar 17, 2020
d24f5fb
Ignore .db and .sh files in cli folder
romac Mar 19, 2020
0692408
Fix misleading doc comment
romac Mar 19, 2020
af7bf63
Update README and LICENSE file
romac Mar 20, 2020
602aa10
Remove verbose flag in README
romac Mar 20, 2020
ab13ede
Add status info to `light init` command
romac Mar 20, 2020
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
Prev Previous commit
Next Next commit
Add some doc comments
  • Loading branch information
romac committed Mar 17, 2020
commit 180b253835dd80878070046d8a5a6d09e3add2e8
20 changes: 20 additions & 0 deletions relayer/relay/src/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,26 +15,45 @@ use crate::error;

pub mod tendermint;

/// Handy type alias for the type of validator set associated with a chain
pub type ValidatorSet<Chain> = <<Chain as self::Chain>::Commit as tmlite::Commit>::ValidatorSet;

/// Defines a blockchain as understood by the relayer
pub trait Chain {
/// Type of headers for this chain
type Header: tmlite::Header + Serialize + DeserializeOwned;

/// Type of commits for this chain
type Commit: tmlite::Commit + Serialize + DeserializeOwned;

/// Type of consensus state for this chain
type ConsensusState: ConsensusState + Serialize + DeserializeOwned;

/// Type of RPC requester (wrapper around low-level RPC client) for this chain
type Requester: tmlite::Requester<Self::Commit, Self::Header>;

/// Returns the chain's identifier
fn id(&self) -> &ChainId {
&self.config().id
}

/// Returns the chain's configuration
fn config(&self) -> &ChainConfig;

/// Get a low-level RPC client for this chain
fn rpc_client(&self) -> &RpcClient;

/// Get a higher-level RPC requester for this chain
fn requester(&self) -> &Self::Requester;

/// The trusting period configured for this chain
fn trusting_period(&self) -> Duration;

/// The trust threshold configured for this chain
fn trust_threshold(&self) -> TrustThresholdFraction;
}

/// Query the latest height the chain is at via a RPC query
pub async fn query_latest_height(chain: &impl Chain) -> Result<Height, error::Error> {
let status = chain
.rpc_client()
Expand All @@ -54,6 +73,7 @@ pub async fn query_latest_height(chain: &impl Chain) -> Result<Height, error::Er
Ok(status.sync_info.latest_block_height.into())
}

/// Query a header at the given height via the RPC requester
pub async fn query_header_at_height<C>(
chain: &C,
height: Height,
Expand Down
1 change: 1 addition & 0 deletions relayer/relay/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use tendermint::net;

use crate::error;

/// Defaults for various fields
mod default {
use super::*;

Expand Down
11 changes: 11 additions & 0 deletions relayer/relay/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,28 @@ pub enum Kind {
#[error("invalid configuration")]
Config,

/// RPC error (typcally raised by the RPC client or the RPC requester)
#[error("RPC error")]
Rpc,

/// Light client error, typically raised by a `Client`
#[error("light client error")]
LightClient,

/// Trusted store error, raised by instances of `Store`
#[error("store error")]
Store,
}

impl Kind {
/// Add a given source error as context for this error kind
///
/// This is typically use with `map_err` as follows:
///
/// ```ignore
/// let x = self.something.do_stuff()
/// .map_err(|e| error::Kind::Config.context(e))?;
/// ```
pub fn context(self, source: impl Into<BoxError>) -> Context<Self> {
Context::new(self, Some(source.into()))
}
Expand Down
13 changes: 13 additions & 0 deletions relayer/relay/src/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,20 @@ use crate::error;

pub mod client_consensus_state;

/// The type of IBC response sent back for a given IBC `Query`.
pub trait IbcResponse<Query>: Sized {
/// The type of the raw response returned by the interface used to query the chain
///
/// TODO: Uncomment once we abstract over the IBC client
// type RawType;

/// Build a response of this type from the initial `query` and the IBC `response`.
///
/// TODO: Replace `AbciQuery` with `Self::RawType`
fn from_abci_response(query: Query, response: AbciQuery) -> Result<Self, error::Error>;
}

/// Defines an IBC query
pub trait IbcQuery: Sized {
type Response: IbcResponse<Self>;

Expand All @@ -20,6 +30,9 @@ pub trait IbcQuery: Sized {
fn prove(&self) -> bool;
fn data(&self) -> Vec<u8>;

/// Build a `Response` from a raw `AbciQuery` response
///
/// TODO: Replace `AbciQuery` with `<Self::Response as IbcResponse<Self>>::RawType`
fn build_response(self, response: AbciQuery) -> Result<Self::Response, error::Error> {
Self::Response::from_abci_response(self, response)
}
Expand Down
28 changes: 26 additions & 2 deletions relayer/relay/src/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,39 +9,63 @@ use crate::chain::Chain;
use crate::client::trust_options::TrustOptions;
use crate::error;

/// In-memory store
pub mod mem;

/// Persistent store via the `sled` database
pub mod sled;

/// Either the last stored height or a given one
pub enum StoreHeight {
/// The last stored height
Last,

/// The given height
Given(Height),
}

/// Defines a trusted store, which tracks:
///
/// - the latest height a light client as synced up to
/// - all the trusted state (header+commit) the light client has verified
/// - the trust options configured for the associated chain
pub trait Store<C>
where
C: Chain,
{
/// Get the last height to which the light client has synced up to, if any
fn last_height(&self) -> Option<Height>;

/// Add a trusted state to the store
fn add(&mut self, state: TrustedState<C::Commit, C::Header>) -> Result<(), error::Error>;

/// Fetch the trusted state at the given height from the store, if it exists
fn get(&self, height: StoreHeight) -> Result<TrustedState<C::Commit, C::Header>, error::Error>;

/// Check whether the trusted store contains a trusted state at the given height
fn has(&self, height: StoreHeight) -> bool {
self.get(height).is_ok()
}

/// Get the trust options configured for the associated chain, if any
fn get_trust_options(&self) -> Result<TrustOptions, error::Error>;

/// Set the trust options for the associated chain
fn set_trust_options(&mut self, trust_options: TrustOptions) -> Result<(), error::Error>;
}

pub fn persistent<C: Chain>(path: impl AsRef<Path>) -> sled::SledStore<C>
/// Returns a persistent trusted store whose `sled` database is stored
/// in the folder specified in the `path` argument.
///
/// TODO: Remove this horrible where clause by moving the serialize constraint in tendermint-rs
pub fn persistent<C: Chain>(db_path: impl AsRef<Path>) -> sled::SledStore<C>
where
<<C as Chain>::Commit as tmlite::Commit>::ValidatorSet: Serialize + DeserializeOwned,
{
sled::SledStore::new(path)
sled::SledStore::new(db_path)
}

/// Returns a non-persistent in-memory store
pub fn in_memory<C: Chain>() -> mem::MemStore<C> {
mem::MemStore::new()
}