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

Implement query_header_at_height via plain RPC queries (no light client verification) #344

Merged
merged 2 commits into from
Oct 28, 2020
Merged
Show file tree
Hide file tree
Changes from all 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 @@ -7,10 +7,12 @@
- [changelog] Added "unreleased" section in `CHANGELOG.MD` to help streamline releases ([#274])
- [relayer] Integrate relayer spike into relayer crate ([#335])
- [modules] Implement flexible connection id selection ([#332])
- [relayer] Implement `query_header_at_height` via plain RPC queries (no light client verification) ([#336])

[#274]: https://github.com/informalsystems/ibc-rs/issues/274
[#332]: https://github.com/informalsystems/ibc-rs/issues/332
[#335]: https://github.com/informalsystems/ibc-rs/pulls/335
[#336]: https://github.com/informalsystems/ibc-rs/issues/336

### IMPROVEMENTS

Expand Down
8 changes: 7 additions & 1 deletion relayer-cli/tests/fixtures/two_chains.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ strategy = "naive"
gas_price = "0.025stake"
trusting_period = "336h"

# TODO: Move to light client config
peer_id = "BADFADAD0BEFEEDC0C0ADEADBEEFC0FFEEFACADE"

[[chains]]
id = "ibc1"
rpc_addr = "localhost:26557"
Expand All @@ -26,4 +29,7 @@ strategy = "naive"
gas = 200000
gas_adjustement = 1.3
gas_price = "0.025stake"
trusting_period = "336h"
trusting_period = "336h"

# TODO: Move to light client config
peer_id = "DC0C0ADEADBEEFC0FFEEFACADEBADFADAD0BEFEE"
1 change: 1 addition & 0 deletions relayer-cli/tests/integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ fn simd_config() -> Config {
client_ids: vec!["ethbridge".to_string()],
gas: 200000,
trusting_period: Default::default(),
peer_id: "BADFADAD0BEFEEDC0C0ADEADBEEFC0FFEEFACADE".parse().unwrap(),
}];
config
}
Expand Down
59 changes: 23 additions & 36 deletions relayer/src/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use ibc::ics24_host::Path;
use crate::client::LightClient;
use crate::config::ChainConfig;
use crate::error;
use crate::util::block_on;

use std::error::Error;

Expand Down Expand Up @@ -79,44 +80,30 @@ pub trait Chain {
/// Sign message
/// TODO - waiting for tendermint-rs upgrade to v0.16
fn sign_tx(&self, _msgs: &[Any]) -> Result<Vec<u8>, Self::Error>;
}

/// 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()
.status()
.await
.map_err(|e| error::Kind::Rpc.context(e))?;

if status.sync_info.catching_up {
fail!(
error::Kind::LightClient,
"node at {} running chain {} not caught up",
chain.config().rpc_addr,
chain.config().id,
);
}
/// Query a header at the given height via RPC
fn query_header_at_height(&self, height: Height) -> Result<Self::LightBlock, error::Error>;

Ok(status.sync_info.latest_block_height)
}
/// Query the latest height the chain is at via a RPC query
fn query_latest_height(&self) -> Result<Height, error::Error> {
let status =
block_on(self.rpc_client().status()).map_err(|e| error::Kind::Rpc.context(e))?;

/// Query the latest header
pub async fn query_latest_header<C>(chain: &C) -> Result<C::LightBlock, error::Error>
where
C: Chain,
{
let h = query_latest_height(chain).await?;
Ok(query_header_at_height(chain, h).await?)
}
if status.sync_info.catching_up {
fail!(
error::Kind::LightClient,
"node at {} running chain {} not caught up",
self.config().rpc_addr,
self.config().id,
);
}

/// Query a header at the given height via the RPC requester
pub async fn query_header_at_height<C>(
chain: &C,
height: Height,
) -> Result<C::LightBlock, error::Error>
where
C: Chain,
{
todo!()
Ok(status.sync_info.latest_block_height)
}

/// Query the latest header via RPC
fn query_latest_header(&self) -> Result<Self::LightBlock, error::Error> {
let height = self.query_latest_height()?;
self.query_header_at_height(height)
}
}
58 changes: 43 additions & 15 deletions relayer/src/chain/cosmos.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
use std::future::Future;
use std::str::FromStr;
use std::time::Duration;

use bytes::Bytes;
use prost::Message;
use prost_types::Any;

use tendermint::abci::Path as TendermintABCIPath;
use tendermint::block::Height;
use tendermint_light_client::types::LightBlock;
use tendermint_light_client::types::TrustThreshold;
use tendermint_light_client::types::{LightBlock, ValidatorSet};
use tendermint_light_client::types::{SignedHeader, TrustThreshold};
use tendermint_rpc::Client;
use tendermint_rpc::HttpClient;

Expand All @@ -16,11 +21,7 @@ use super::Chain;
use crate::client::tendermint::LightClient;
use crate::config::ChainConfig;
use crate::error::{Error, Kind};

use bytes::Bytes;
use prost::Message;
use prost_types::Any;
use std::future::Future;
use crate::util::block_on;

pub struct CosmosSDKChain {
config: ChainConfig,
Expand Down Expand Up @@ -103,6 +104,25 @@ impl Chain for CosmosSDKChain {
Duration::from_secs(24 * 7 * 3)
}

fn query_header_at_height(&self, height: Height) -> Result<LightBlock, Error> {
let client = self.rpc_client();

let signed_header = fetch_signed_header(client, height)?;
assert_eq!(height, signed_header.header.height);

let validator_set = fetch_validator_set(client, height)?;
let next_validator_set = fetch_validator_set(client, height.increment())?;

let light_block = LightBlock::new(
signed_header,
validator_set,
next_validator_set,
self.config().peer_id,
);

Ok(light_block)
}

fn sign_tx(&self, _msgs: &[Any]) -> Result<Vec<u8>, Error> {
unimplemented!()

Expand Down Expand Up @@ -249,12 +269,20 @@ async fn abci_query(
Ok(response.value)
}

/// block on future
pub fn block_on<F: Future>(future: F) -> F::Output {
tokio::runtime::Builder::new()
.basic_scheduler()
.enable_all()
.build()
.unwrap()
.block_on(future)
fn fetch_signed_header(client: &HttpClient, height: Height) -> Result<SignedHeader, Error> {
let res = block_on(client.commit(height));

match res {
Ok(response) => Ok(response.signed_header),
Err(err) => Err(Kind::Rpc.context(err).into()),
}
}

fn fetch_validator_set(client: &HttpClient, height: Height) -> Result<ValidatorSet, Error> {
let res = block_on(client.validators(height));

match res {
Ok(response) => Ok(ValidatorSet::new(response.validators)),
Err(err) => Err(Kind::Rpc.context(err).into()),
}
}
3 changes: 3 additions & 0 deletions relayer/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ pub struct ChainConfig {
pub gas: u64,
#[serde(default = "default::trusting_period", with = "humantime_serde")]
pub trusting_period: Duration,

// TODO: Move the light client config
pub peer_id: node::Id,
}

#[derive(Clone, Debug, Deserialize, Serialize)]
Expand Down
19 changes: 9 additions & 10 deletions relayer/src/tx/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ use ibc::ics24_host::identifier::{ChainId, ClientId};
use ibc::ics24_host::Path::ClientState as ClientStatePath;
use ibc::tx_msg::Msg;

use crate::chain::cosmos::block_on;
use crate::chain::{query_latest_header, Chain, CosmosSDKChain};
use crate::chain::{Chain, CosmosSDKChain};
use crate::config::ChainConfig;
use crate::error::{Error, Kind};
use crate::util::block_on;
use ibc::ics02_client::height::Height;

#[derive(Clone, Debug)]
Expand Down Expand Up @@ -41,14 +41,13 @@ pub fn create_client(opts: CreateClientOptions) -> Result<(), Error> {

// Get the latest header from the source chain and build the consensus state.
let src_chain = CosmosSDKChain::from_config(opts.clone().src_chain_config)?;
let tm_latest_header =
block_on(query_latest_header::<CosmosSDKChain>(&src_chain)).map_err(|e| {
Kind::CreateClient(
opts.dest_client_id.clone(),
"failed to get the latest header".into(),
)
.context(e)
})?;
let tm_latest_header = src_chain.query_latest_header().map_err(|e| {
Kind::CreateClient(
opts.dest_client_id.clone(),
"failed to get the latest header".into(),
)
.context(e)
})?;

let height = u64::from(tm_latest_header.signed_header.header.height);
let version = tm_latest_header.signed_header.header.chain_id.to_string();
Expand Down
3 changes: 3 additions & 0 deletions relayer/src/util.rs
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
mod block_on;
pub use block_on::block_on;

pub mod sled;
13 changes: 13 additions & 0 deletions relayer/src/util/block_on.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//! Utility function to execute a future synchronously

use futures::Future;

/// Spawns a new tokio runtime and use it to block on the given future.
pub fn block_on<F: Future>(future: F) -> F::Output {
tokio::runtime::Builder::new()
.basic_scheduler()
.enable_all()
.build()
.unwrap()
.block_on(future)
}
6 changes: 6 additions & 0 deletions relayer/tests/config/fixtures/relayer_conf_example.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ strategy = "naive"
gas_price = "0.025stake"
trusting_period = "336h"

# TODO: Move to light client config
peer_id = "BADFADAD0BEFEEDC0C0ADEADBEEFC0FFEEFACADE"

[[chains]]
id = "chain_B"
rpc_addr = "localhost:26557"
Expand All @@ -29,6 +32,9 @@ strategy = "naive"
gas_price = "0.025stake"
trusting_period = "336h"

# TODO: Move to light client config
peer_id = "DC0C0ADEADBEEFC0FFEEFACADEBADFADAD0BEFEE"

[[connections]]

[connections.src]
Expand Down
6 changes: 6 additions & 0 deletions relayer/tests/config/fixtures/simple_config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ strategy = "naive"
gas_price = "0.025stake"
trusting_period = "336h"

# TODO: Move to light client config
peer_id = "BADFADAD0BEFEEDC0C0ADEADBEEFC0FFEEFACADE"

[[chains]]
id = "chain_B"
rpc_addr = "localhost:26557"
Expand All @@ -30,6 +33,9 @@ strategy = "naive"
gas_price = "0.025stake"
trusting_period = "336h"

# TODO: Move to light client config
peer_id = "DC0C0ADEADBEEFC0FFEEFACADEBADFADAD0BEFEE"

[[connections]]

[connections.src]
Expand Down