Skip to content

Commit

Permalink
Implement relaying of ConnOpenAck and ConnOpenConfirm (informalsystem…
Browse files Browse the repository at this point in the history
  • Loading branch information
ancazamfir authored Nov 12, 2020
1 parent dfb72a5 commit d816644
Show file tree
Hide file tree
Showing 9 changed files with 481 additions and 67 deletions.
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,13 @@ Special thanks to external contributors for this release: @CharlyCst ([#347]).
- [modules]
- Implement flexible connection id selection ([#332])
- ICS 4 Domain Types for channel handshakes ([#315])
- [relayer] Implement `query_header_at_height` via plain RPC queries (no light client verification) ([#336])
- [relayer]
- Implement `query_header_at_height` via plain RPC queries (no light client verification) ([#336])
- Implement the relayer logic for connection handshake message ([#358], [#359], [#360])
- [relayer-cli]
- Merge light clients config in relayer config and add commands to add/remove light clients ([#348])
- CLI for client update message ([#277])
- Implement the relayer CLI for connection handshake message ([#358], [#359], [#360])
- [proto-compiler]
- Refactor and allow specifying a commit at which the Cosmos SDK should be checked out ([#366])
- Add a `--tag` option to the `clone-sdk` command to check out a tag instead of a commit ([#369])
Expand All @@ -27,6 +30,9 @@ Special thanks to external contributors for this release: @CharlyCst ([#347]).
[#335]: https://github.com/informalsystems/ibc-rs/pulls/335
[#336]: https://github.com/informalsystems/ibc-rs/issues/336
[#348]: https://github.com/informalsystems/ibc-rs/pulls/348
[#358]: https://github.com/informalsystems/ibc-rs/issues/358
[#358]: https://github.com/informalsystems/ibc-rs/issues/359
[#358]: https://github.com/informalsystems/ibc-rs/issues/360
[#366]: https://github.com/informalsystems/ibc-rs/issues/366
[#368]: https://github.com/informalsystems/ibc-rs/issues/368
[#369]: https://github.com/informalsystems/ibc-rs/pulls/369
Expand Down
2 changes: 1 addition & 1 deletion relayer-cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ As shown above the tx commands currently require specifying a seed file:
#### Steps to testing the transactions:

* Start two chains using the `dev-env` script from the [ovrclk/relayer](https://github.com/ovrclk/relayer) (make sure to checkout stargate-4 version)
* After you run the script, the Go relayer will create a `data` folder for the chains. Open the key seed file `./data/ibc1/key_seed.json` for chain `ibc-1` and look for the account value
* After you run the script, the Go relayer will create a `data` folder for the chains. Copy the key seed file `./data/ibc1/key_seed.json` for chain `ibc-1` to a convenient location.


{
Expand Down
8 changes: 8 additions & 0 deletions relayer-cli/src/commands/tx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,12 @@ pub enum TxRawCommands {
/// The `tx raw conn-try` subcommand
#[options(help = "tx raw conn-try")]
ConnTry(connection::TxRawConnTryCmd),

/// The `tx raw conn-ack` subcommand
#[options(help = "tx raw conn-ack")]
ConnAck(connection::TxRawConnAckCmd),

/// The `tx raw conn-confirm` subcommand
#[options(help = "tx raw conn-confirm")]
ConnConfirm(connection::TxRawConnConfirmCmd),
}
172 changes: 168 additions & 4 deletions relayer-cli/src/commands/tx/connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ use ibc::ics24_host::identifier::{ClientId, ConnectionId};

use relayer::config::Config;
use relayer::tx::connection::{
build_conn_init_and_send, build_conn_try_and_send, ConnectionOpenInitOptions,
ConnectionOpenTryOptions,
build_conn_ack_and_send, build_conn_confirm_and_send, build_conn_init_and_send,
build_conn_try_and_send, ConnectionOpenInitOptions, ConnectionOpenOptions,
};

use crate::error::{Error, Kind};
Expand Down Expand Up @@ -122,7 +122,7 @@ pub struct TxRawConnTryCmd {
}

impl TxRawConnTryCmd {
fn validate_options(&self, config: &Config) -> Result<ConnectionOpenTryOptions, String> {
fn validate_options(&self, config: &Config) -> Result<ConnectionOpenOptions, String> {
let dest_chain_config = config
.chains
.iter()
Expand All @@ -139,7 +139,7 @@ impl TxRawConnTryCmd {
anomaly::Context::new("invalid signer seed file", Some(e.into())).to_string()
})?;

let opts = ConnectionOpenTryOptions {
let opts = ConnectionOpenOptions {
src_chain_config: src_chain_config.clone(),
dest_chain_config: dest_chain_config.clone(),
src_client_id: self.src_client_id.clone(),
Expand Down Expand Up @@ -175,3 +175,167 @@ impl Runnable for TxRawConnTryCmd {
}
}
}

#[derive(Clone, Command, Debug, Options)]
pub struct TxRawConnAckCmd {
#[options(free, help = "identifier of the destination chain")]
dest_chain_id: String,

#[options(free, help = "identifier of the source chain")]
src_chain_id: String,

#[options(free, help = "identifier of the destination client")]
dest_client_id: ClientId,

#[options(free, help = "identifier of the source client")]
src_client_id: ClientId,

#[options(free, help = "identifier of the destination connection")]
dest_connection_id: ConnectionId,

#[options(free, help = "identifier of the source connection")]
src_connection_id: ConnectionId,

#[options(
help = "json key file for the signer, must include mnemonic",
short = "k"
)]
seed_file: String,
}

impl TxRawConnAckCmd {
fn validate_options(&self, config: &Config) -> Result<ConnectionOpenOptions, String> {
let dest_chain_config = config
.chains
.iter()
.find(|c| c.id == self.dest_chain_id.parse().unwrap())
.ok_or_else(|| "missing destination chain configuration".to_string())?;

let src_chain_config = config
.chains
.iter()
.find(|c| c.id == self.src_chain_id.parse().unwrap())
.ok_or_else(|| "missing src chain configuration".to_string())?;

let signer_seed = std::fs::read_to_string(&self.seed_file).map_err(|e| {
anomaly::Context::new("invalid signer seed file", Some(e.into())).to_string()
})?;

let opts = ConnectionOpenOptions {
src_chain_config: src_chain_config.clone(),
dest_chain_config: dest_chain_config.clone(),
src_client_id: self.src_client_id.clone(),
dest_client_id: self.dest_client_id.clone(),
src_connection_id: self.src_connection_id.clone(),
dest_connection_id: self.dest_connection_id.clone(),
signer_seed,
};

Ok(opts)
}
}

impl Runnable for TxRawConnAckCmd {
fn run(&self) {
let config = app_config();

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

let res: Result<String, Error> =
build_conn_ack_and_send(opts).map_err(|e| Kind::Tx.context(e).into());

match res {
Ok(receipt) => status_info!("conn ack, result: ", "{:?}", receipt),
Err(e) => status_info!("conn ack failed, error: ", "{}", e),
}
}
}

#[derive(Clone, Command, Debug, Options)]
pub struct TxRawConnConfirmCmd {
#[options(free, help = "identifier of the destination chain")]
dest_chain_id: String,

#[options(free, help = "identifier of the source chain")]
src_chain_id: String,

#[options(free, help = "identifier of the destination client")]
dest_client_id: ClientId,

#[options(free, help = "identifier of the source client")]
src_client_id: ClientId,

#[options(free, help = "identifier of the destination connection")]
dest_connection_id: ConnectionId,

#[options(free, help = "identifier of the source connection")]
src_connection_id: ConnectionId,

#[options(
help = "json key file for the signer, must include mnemonic",
short = "k"
)]
seed_file: String,
}

impl TxRawConnConfirmCmd {
fn validate_options(&self, config: &Config) -> Result<ConnectionOpenOptions, String> {
let dest_chain_config = config
.chains
.iter()
.find(|c| c.id == self.dest_chain_id.parse().unwrap())
.ok_or_else(|| "missing destination chain configuration".to_string())?;

let src_chain_config = config
.chains
.iter()
.find(|c| c.id == self.src_chain_id.parse().unwrap())
.ok_or_else(|| "missing src chain configuration".to_string())?;

let signer_seed = std::fs::read_to_string(&self.seed_file).map_err(|e| {
anomaly::Context::new("invalid signer seed file", Some(e.into())).to_string()
})?;

let opts = ConnectionOpenOptions {
src_chain_config: src_chain_config.clone(),
dest_chain_config: dest_chain_config.clone(),
src_client_id: self.src_client_id.clone(),
dest_client_id: self.dest_client_id.clone(),
src_connection_id: self.src_connection_id.clone(),
dest_connection_id: self.dest_connection_id.clone(),
signer_seed,
};

Ok(opts)
}
}

impl Runnable for TxRawConnConfirmCmd {
fn run(&self) {
let config = app_config();

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

let res: Result<String, Error> =
build_conn_confirm_and_send(opts).map_err(|e| Kind::Tx.context(e).into());

match res {
Ok(receipt) => status_info!("conn confirm, result: ", "{:?}", receipt),
Err(e) => status_info!("conn confirm failed, error: ", "{}", e),
}
}
}
35 changes: 20 additions & 15 deletions relayer/src/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ use ibc::ics02_client::state::{ClientState, ConsensusState};
use ibc::ics03_connection::connection::{ConnectionEnd, Counterparty, State};
use ibc::ics03_connection::msgs::conn_open_init::MsgConnectionOpenInit;
use ibc::ics03_connection::msgs::conn_open_try::MsgConnectionOpenTry;
use ibc::ics03_connection::msgs::ConnectionMsgType;
use ibc::ics03_connection::version::get_compatible_versions;
use ibc::ics23_commitment::commitment::{CommitmentPrefix, CommitmentProof};
use ibc::ics24_host::identifier::{ClientId, ConnectionId};
Expand All @@ -37,7 +36,7 @@ use crate::client::LightClient;
use crate::config::ChainConfig;
use crate::error::{Error, Kind};
use crate::keyring::store::{KeyEntry, KeyRing};
use crate::tx::connection::{ConnectionOpenInitOptions, ConnectionOpenTryOptions};
use crate::tx::connection::{ConnectionMsgType, ConnectionOpenInitOptions, ConnectionOpenOptions};
use crate::util::block_on;

pub(crate) mod cosmos;
Expand Down Expand Up @@ -204,45 +203,48 @@ pub trait Chain {
})?)
}

/// Build the required proofs for connection handshake messages. The proofs are obtained from
/// queries at height - 1
fn build_connection_proofs(
/// Builds the required proofs and the client state for connection handshake messages.
/// The proofs and client state must be obtained from queries at same height with value
/// `height - 1`
fn build_connection_proofs_and_client_state(
&self,
message_type: ConnectionMsgType,
connection_id: &ConnectionId,
client_id: &ClientId,
height: ICSHeight,
) -> Result<Proofs, Error> {
) -> Result<(Option<AnyClientState>, Proofs), Error> {
// Set the height of the queries at height - 1
let query_height = height
.decrement()
.map_err(|e| Kind::InvalidHeight.context(e))?;

// Collect all proofs as required
let connection_proof =
CommitmentProof::from(self.proven_connection(&connection_id, query_height)?.1);

let mut client_proof: Option<CommitmentProof> = None;
let mut client_state = None;
let mut client_proof = None;
let mut consensus_proof = None;

match message_type {
ConnectionMsgType::OpenTry | ConnectionMsgType::OpenAck => {
let (client_state, client_state_proof) =
let (client_state_value, client_state_proof) =
self.proven_client_state(&client_id, query_height)?;

client_proof = Some(CommitmentProof::from(client_state_proof));
client_proof = Option::from(CommitmentProof::from(client_state_proof));

let consensus_state_proof = self
.proven_client_consensus(
&client_id,
client_state.latest_height(),
client_state_value.latest_height(),
query_height,
)?
.1;

consensus_proof = Some(
consensus_proof = Option::from(
ConsensusProof::new(
CommitmentProof::from(consensus_state_proof),
client_state.latest_height(),
client_state_value.latest_height(),
)
.map_err(|e| {
Kind::ConnOpenTry(
Expand All @@ -252,13 +254,16 @@ pub trait Chain {
.context(e)
})?,
);

client_state = Option::from(client_state_value);
}
_ => {}
}

Ok(
Ok((
client_state,
Proofs::new(connection_proof, client_proof, consensus_proof, height)
.map_err(|e| Kind::MalformedProof)?,
)
.map_err(|_| Kind::MalformedProof)?,
))
}
}
3 changes: 0 additions & 3 deletions relayer/src/chain/cosmos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,9 +239,6 @@ impl Chain for CosmosSDKChain {
let mut body_buf = Vec::new();
prost::Message::encode(&body, &mut body_buf).unwrap();

// let key = self.keybase.get(signer.clone()).map_err(|e| error::Kind::KeyBase.context(e))?;
let pub_key_bytes = key.public_key.public_key.to_bytes();

let mut pk_buf = Vec::new();
prost::Message::encode(&key.public_key.public_key.to_bytes(), &mut pk_buf).unwrap();

Expand Down
8 changes: 8 additions & 0 deletions relayer/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,14 @@ pub enum Kind {
#[error("Failed to build conn open try {0}: {1}")]
ConnOpenTry(ConnectionId, String),

/// Connection open ack failure
#[error("Failed to build conn open ack {0}: {1}")]
ConnOpenAck(ConnectionId, String),

/// Connection open confirm failure
#[error("Failed to build conn open confirm {0}: {1}")]
ConnOpenConfirm(ConnectionId, String),

/// A message transaction failure
#[error("Message transaction failure: {0}")]
MessageTransaction(String),
Expand Down
8 changes: 4 additions & 4 deletions relayer/src/tx/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ pub fn build_create_client(
)));
}

// Get the key and signer from key seed file.
let (key, signer) = dest_chain.key_and_signer(signer_seed)?;
// Get the signer from key seed file
let (_, signer) = dest_chain.key_and_signer(signer_seed)?;

// Build client create message with the data from source chain at latest height.
let latest_height = src_chain.query_latest_height()?;
Expand Down Expand Up @@ -101,8 +101,8 @@ pub fn build_update_client(
.query_client_state(&dest_client_id, Height::default())?
.latest_height();

// Get the key and signer from key seed file.
let (key, signer) = dest_chain.key_and_signer(signer_seed)?;
// Get the signer from key seed file
let (_, signer) = dest_chain.key_and_signer(signer_seed)?;

let new_msg = MsgUpdateAnyClient {
client_id: dest_client_id,
Expand Down
Loading

0 comments on commit d816644

Please sign in to comment.