Skip to content

Commit

Permalink
Add commands to initialize light client for given chain and start ver…
Browse files Browse the repository at this point in the history
…ifying headers (#26)

* Add function to initialize lite client without trusted state

* Make LightClient generic over chain type via a generic store

* Add stub to initialize the light client with trust options

* Use custom sum type for store heights

* Rename LiteClient to LightClient

* Add stub command `light init`

* Implement LightClient::init_with_node_trusted_state

* Implement LightClient::init_with_trusted_state

* Refactor light client

* Verify trusted state on light client initialization

* Remove unused file

* Add stub for Client::check_trusted_header

* Fail when needed in Client::update_trusted_state

* Partially implement Client::update

* Implement LightClient::verify_header

* Update comment

* Fix clippy warnings

* Use serde-humantime to parse trusting_period

* Move config defaults into their own module

* Create light client and display last trusted state

* Use checked arithmetic when incrementing height

* Update trusted store in Client::update

* Fix clippy warnings

* Rename StoreHeight:GivenHeight to Given

* Simplify verify_header signature

* Spawn empty relayer, and one client per configured chain

* Update tendermint-rs repository

* Remove dep on tendermint-rs/light_node by copying RpcRequester code over

* Improve reporting a bit

* Fix RpcRequester unit test

* Add persistent trusted store implementation

* Use persistent trusted store in commands

* Ignore database folders in Git

* Fix clippy warnings

* Remove superfluous Tendermint type struct

* Add some doc comments

* Document the relayer::client::Client struct

* More doc comments

* Ignore .db and .sh files in cli folder

* Fix misleading doc comment

* Update README and LICENSE file

* Remove verbose flag in README

* Add status info to `light init` command
  • Loading branch information
romac authored Mar 20, 2020
1 parent de418e3 commit 96ee56d
Show file tree
Hide file tree
Showing 26 changed files with 1,284 additions and 62 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,5 @@ Cargo.lock
# These are backup files generated by rustfmt
**/*.rs.bk

# Ignore database folders
**/*.db/
4 changes: 2 additions & 2 deletions LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.

Copyright [yyyy] [name of copyright owner]
Copyright 2020 Informal Systems

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand All @@ -199,4 +199,4 @@
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
limitations under the License.
49 changes: 48 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,49 @@
# ibc-rs
Rust implementation of IBC modules and relayer

> Rust implementation of IBC modules and relayer
## Disclaimer

THIS PROJECT IS UNDER HEAVY DEVELOPMENT AND IS NOT IN A WORKING STAGE NOW, USE AT YOUR OWN RISK.

## Requirements

- Rust 1.42+ (might work on earlier versions but this has not been tested yet)

## Usage

Provided that one has a Tendermint node running on port 26657, one can
configure and spawn two light clients for this chain with the following commands:

1. Fetch a trusted header from the chain:

```bash
$ curl -s http://localhost:26657/status | jq '.result.sync_info|.latest_block_hash,.latest_block_height'
```

2. Initialize a light client for chain A with the trusted height and hash fetched in step 1:

```bash
ibc-rs > cargo run --bin relayer -- -c ./relayer/relay/tests/config/fixtures/relayer_conf_example.toml light init -x HASH -h HEIGHT chain_A
```
> Replace `HASH` and `HEIGHT` with the appropriate values.
3. Repeat step 1 and 2 above for `chain_B`.

> For this, update the height and hash, and change the chain identifier in the command above from `chain_A` to `chain_B`.
4. Start the light clients and a dummy relayer thread:

```bash
ibc-rs > cargo run --bin relayer -- -c ./relayer/relay/tests/config/fixtures/relayer_conf_example.toml run
```

## License

Copyright © 2020 Informal Systems

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

https://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
2 changes: 1 addition & 1 deletion modules/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ default = ["paths-cosmos"]
paths-cosmos = []

[dependencies]
tendermint = { git = "https://github.com/interchainio/tendermint-rs.git" }
tendermint = { git = "https://github.com/informalsystems/tendermint-rs.git" }

anomaly = "0.2.0"
thiserror = "1.0.11"
Expand Down
8 changes: 0 additions & 8 deletions modules/src/ics02_client/client_type.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
use super::error;
use anomaly::fail;

pub struct Tendermint;

/// Type of the consensus algorithm
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum ClientType {
Expand All @@ -18,12 +16,6 @@ impl ClientType {
}
}

impl From<Tendermint> for ClientType {
fn from(_: Tendermint) -> Self {
Self::Tendermint
}
}

impl std::str::FromStr for ClientType {
type Err = error::Error;

Expand Down
3 changes: 3 additions & 0 deletions relayer/cli/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
/target
**/*.rs.bk

*.sh
*.db
3 changes: 3 additions & 0 deletions relayer/cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,14 @@ authors = [

[dependencies]
relayer = { path = "../relay" }
tendermint = { git = "https://github.com/informalsystems/tendermint-rs.git" }

anomaly = "0.2.0"
gumdrop = "0.7"
serde = { version = "1", features = ["serde_derive"] }
thiserror = "1"
abscissa_tokio = "0.5.1"
tokio = "0.2.13"

[dependencies.abscissa_core]
version = "0.5.2"
Expand Down
6 changes: 5 additions & 1 deletion relayer/cli/src/application.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,11 @@ impl Application for CliApp {
/// beyond the default ones provided by the framework, this is the place
/// to do so.
fn register_components(&mut self, command: &Self::Cmd) -> Result<(), FrameworkError> {
let components = self.framework_components(command)?;
use abscissa_tokio::TokioComponent;

let mut components = self.framework_components(command)?;
components.push(Box::new(TokioComponent::new()?));

self.state.components.register(components)
}

Expand Down
13 changes: 9 additions & 4 deletions relayer/cli/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@
//! application's configuration file.
mod config;
mod light;
mod start;
mod version;

use self::{config::ConfigCmd, start::StartCmd, version::VersionCmd};
use self::{config::ConfigCmd, light::LightCmd, start::StartCmd, version::VersionCmd};

use crate::config::Config;
use abscissa_core::{Command, Configurable, FrameworkError, Help, Options, Runnable};
Expand All @@ -25,6 +26,10 @@ pub enum CliCmd {
#[options(help = "get usage information")]
Help(Help<Self>),

/// The `version` subcommand
#[options(help = "display version information")]
Version(VersionCmd),

/// The `start` subcommand
#[options(help = "start the relayer")]
Start(StartCmd),
Expand All @@ -33,9 +38,9 @@ pub enum CliCmd {
#[options(help = "manipulate the relayer configuration")]
Config(ConfigCmd),

/// The `version` subcommand
#[options(help = "display version information")]
Version(VersionCmd),
/// The `light` subcommand
#[options(help = "basic functionality for managing the lite clients")]
Light(LightCmd),
}

/// This trait allows you to define how application configuration is loaded.
Expand Down
13 changes: 13 additions & 0 deletions relayer/cli/src/commands/light.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//! `light` subcommand
use abscissa_core::{Command, Options, Runnable};

mod init;

/// `light` subcommand
#[derive(Command, Debug, Options, Runnable)]
pub enum LightCmd {
/// The `light init` subcommand
#[options(help = "initiate a light client for a given chain")]
Init(init::InitCmd),
}
118 changes: 118 additions & 0 deletions relayer/cli/src/commands/light/init.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
use std::future::Future;

// use crate::application::APPLICATION;
use crate::prelude::*;

use abscissa_core::{Command, Options, Runnable};

use tendermint::chain::Id as ChainId;
use tendermint::hash::Hash;
use tendermint::lite::Height;

use relayer::chain::tendermint::TendermintChain;
use relayer::client::trust_options::TrustOptions;
use relayer::config::{ChainConfig, Config};
use relayer::store::{sled::SledStore, Store};

#[derive(Command, Debug, Options)]
pub struct InitCmd {
#[options(free, help = "identifier of the chain to initialize light client for")]
chain_id: Option<ChainId>,

#[options(help = "trusted header hash", short = "x")]
hash: Option<Hash>,

#[options(help = "trusted header height", short = "h")]
height: Option<Height>,
}

#[derive(Clone, Debug)]
struct InitOptions {
/// identifier of chain to initialize light client for
chain_id: ChainId,

/// trusted header hash
trusted_hash: Hash,

/// trusted header height
trusted_height: Height,
}

impl InitCmd {
fn get_chain_config_and_options(
&self,
config: &Config,
) -> Result<(ChainConfig, InitOptions), String> {
match (&self.chain_id, &self.hash, self.height) {
(Some(chain_id), Some(trusted_hash), Some(trusted_height)) => {
let chain_config = config.chains.iter().find(|c| c.id == *chain_id);

match chain_config {
Some(chain_config) => {
let opts = InitOptions {
chain_id: *chain_id,
trusted_hash: *trusted_hash,
trusted_height,
};

Ok((chain_config.clone(), opts))
}
None => Err(format!("cannot find chain {} in config", chain_id)),
}
}

(None, _, _) => Err("missing chain identifier".to_string()),
(_, None, _) => Err("missing trusted hash".to_string()),
(_, _, None) => Err("missing trusted height".to_string()),
}
}
}

impl Runnable for InitCmd {
/// Initialize the light client for the given chain
fn run(&self) {
// FIXME: This just hangs and never runs the given future
// abscissa_tokio::run(&APPLICATION, ...).unwrap();

let config = app_config();

let (chain_config, opts) = match self.get_chain_config_and_options(&config) {
Err(err) => {
status_err!("invalid options: {}", err);
return;
}
Ok(result) => result,
};

block_on(async {
let trust_options = TrustOptions::new(
opts.trusted_hash,
opts.trusted_height,
chain_config.trusting_period,
Default::default(),
)
.unwrap();

let mut store: SledStore<TendermintChain> =
relayer::store::persistent(format!("store_{}.db", chain_config.id));

store.set_trust_options(trust_options).unwrap(); // FIXME: unwrap

status_ok!(
chain_config.id,
"Set trusted options: hash={} height={}",
opts.trusted_hash,
opts.trusted_height
);
});
}
}

fn block_on<F: Future>(future: F) -> F::Output {
tokio::runtime::Builder::new()
.basic_scheduler()
.enable_all()
.build()
.unwrap()
.block_on(future)
}
Loading

0 comments on commit 96ee56d

Please sign in to comment.