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 client queries to the relayer #38

Merged
merged 16 commits into from
Apr 10, 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
6 changes: 5 additions & 1 deletion modules/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,13 @@ default = ["paths-cosmos"]
paths-cosmos = []

[dependencies]
tendermint = { git = "https://github.com/informalsystems/tendermint-rs.git" }
tendermint = { git = "https://github.com/informalsystems/tendermint-rs.git", branch = "tendermint/v0.33" }

anomaly = "0.2.0"
thiserror = "1.0.11"
serde_derive = "1.0.104"
serde = "1.0.104"

[dev-dependencies]
serde_json = "1"

22 changes: 22 additions & 0 deletions modules/src/ics02_client/state.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use super::client_type::ClientType;

use crate::ics23_commitment::CommitmentRoot;
use crate::ics24_host::client::ClientId;
use crate::Height;

pub trait ConsensusState {
Expand All @@ -18,3 +19,24 @@ pub trait ConsensusState {
/// Performs basic validation of the consensus state
fn validate_basic(&self) -> Result<(), Self::ValidationError>;
}

pub trait ClientState {
type ValidationError: std::error::Error;

/// Client ID of this state
fn client_id(&self) -> ClientId;

/// Type of client associated with this state (eg. Tendermint)
fn client_type(&self) -> ClientType;

/// Height of consensus state
fn get_latest_height(&self) -> Height;

/// Freeze status of the client
fn is_frozen(&self) -> bool;

fn verify_client_consensus_state(
&self,
root: &CommitmentRoot,
) -> Result<(), Self::ValidationError>;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, a bit more work to get there :)

}
82 changes: 82 additions & 0 deletions modules/src/ics07_tendermint/client_state.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
use crate::ics02_client::client_type::ClientType;
use crate::ics23_commitment::CommitmentRoot;

use crate::ics07_tendermint::header::Header;
use crate::ics24_host::client::ClientId;
use serde_derive::{Deserialize, Serialize};
use std::time::Duration;
use tendermint::lite::Header as liteHeader;

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct ClientState {
id: String,
trusting_period: Duration,
Copy link
Member

@liamsi liamsi Apr 3, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note (mostly to myself):

in the go code, time.Duration actually is this type alias:

// A Duration represents the elapsed time between two instants
// as an int64 nanosecond count. The representation limits the
// largest representable duration to approximately 290 years.
type Duration int64

while rust's std::time::Duration actually is

/// A `Duration` type to represent a span of time, typically used for system
/// timeouts.
///
/// Each `Duration` is composed of a whole number of seconds and a fractional part
/// represented in nanoseconds. If the underlying system does not support
/// nanosecond-level precision, APIs binding a system timeout will typically round up
/// the number of nanoseconds.
/// [...]
pub struct Duration {
    secs: u64,
    nanos: u32, // Always 0 <= nanos < NANOS_PER_SEC
}

Same for the unbonding_period field below.

So for deserialization (independent from amino or not) we need to translate between the two.

ref #45

unbonding_period: Duration,
frozen_height: crate::Height,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The order in the go-code is different (latest header should be last):

Suggested change
frozen_height: crate::Height,
frozen_height: crate::Height,
latest_header: Header,

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oy! good catch! thx, just changed. The problem is that we cannot test properly with SDK since we don't deserialize yet. Once we move to protobuf and we do the decoding we will catch more of these.

latest_header: Header,
}

impl ClientState {
pub fn new(
id: String,
trusting_period: Duration,
unbonding_period: Duration,
latest_header: Header,
frozen_height: crate::Height,
) -> Self {
Self {
id,
trusting_period,
unbonding_period,
latest_header,
frozen_height,
}
}
}

impl crate::ics02_client::state::ClientState for ClientState {
type ValidationError = crate::ics07_tendermint::error::Error;

fn client_id(&self) -> ClientId {
self.id.parse().unwrap()
}

fn client_type(&self) -> ClientType {
ClientType::Tendermint
}

fn get_latest_height(&self) -> crate::Height {
self.latest_header.signed_header.header.height()
}

fn is_frozen(&self) -> bool {
false
}

fn verify_client_consensus_state(
&self,
_root: &CommitmentRoot,
) -> Result<(), Self::ValidationError> {
unimplemented!()
}
}

#[cfg(test)]
mod tests {
use crate::test::test_serialization_roundtrip;
use tendermint::rpc::endpoint::abci_query::AbciQuery;

#[test]
fn serialization_roundtrip_no_proof() {
let json_data = include_str!("../tests/query/serialization/client_state.json");
println!("json_data: {:?}", json_data);
test_serialization_roundtrip::<AbciQuery>(json_data);
}

#[test]
fn serialization_roundtrip_with_proof() {
let json_data = include_str!("../tests/query/serialization/client_state_proof.json");
println!("json_data: {:?}", json_data);
test_serialization_roundtrip::<AbciQuery>(json_data);
}
}
20 changes: 20 additions & 0 deletions modules/src/ics07_tendermint/consensus_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,23 @@ impl crate::ics02_client::state::ConsensusState for ConsensusState {
unimplemented!()
}
}

#[cfg(test)]
mod tests {
use crate::test::test_serialization_roundtrip;
use tendermint::rpc::endpoint::abci_query::AbciQuery;

#[test]
fn serialization_roundtrip_no_proof() {
let json_data = include_str!("../tests/query/serialization/consensus_state.json");
println!("json_data: {:?}", json_data);
test_serialization_roundtrip::<AbciQuery>(json_data);
}

#[test]
fn serialization_roundtrip_with_proof() {
let json_data = include_str!("../tests/query/serialization/consensus_state_proof.json");
println!("json_data: {:?}", json_data);
test_serialization_roundtrip::<AbciQuery>(json_data);
}
}
1 change: 1 addition & 0 deletions modules/src/ics07_tendermint/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! ICS 07: Tendermint Client

pub mod client_state;
pub mod consensus_state;
pub mod error;
pub mod header;
Expand Down
7 changes: 4 additions & 3 deletions modules/src/ics23_commitment/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use serde_derive::{Deserialize, Serialize};

use crate::path::Path;
use tendermint::abci;

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct CommitmentRoot;
Expand All @@ -17,11 +18,11 @@ impl CommitmentPath {
}
}

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct CommitmentProof;

pub type CommitmentProof = abci::Proof;
/*
impl CommitmentProof {
pub fn from_bytes(_bytes: &[u8]) -> Self {
todo!()
}
}
*/
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't we delete this but but extend the abci::Proof type instead?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but will do in a separate issue/PR

3 changes: 3 additions & 0 deletions modules/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,6 @@ pub mod path;

/// Height of a block, same as in `tendermint` crate
pub type Height = tendermint::lite::Height;

#[cfg(test)]
mod test;
16 changes: 16 additions & 0 deletions modules/src/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,19 @@ impl Path for ConsensusStatePath {
paths::consensus_state_path(&self)
}
}

pub struct ClientStatePath {
pub client_id: ClientId,
}

impl ClientStatePath {
pub fn new(client_id: ClientId) -> Self {
Self { client_id }
}
}

impl Path for ClientStatePath {
fn to_string(&self) -> String {
paths::client_state_path(&self)
}
}
6 changes: 5 additions & 1 deletion modules/src/path/cosmos.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::{ConnectionPath, ConsensusStatePath};
use super::{ClientStatePath, ConnectionPath, ConsensusStatePath};

pub fn connection_path(path: &ConnectionPath) -> String {
format!("connection/{}", path.connection_id)
Expand All @@ -7,3 +7,7 @@ pub fn connection_path(path: &ConnectionPath) -> String {
pub fn consensus_state_path(path: &ConsensusStatePath) -> String {
format!("consensusState/{}/{}", path.client_id, path.height)
}

pub fn client_state_path(path: &ClientStatePath) -> String {
format!("clientState/{}", path.client_id)
}
6 changes: 5 additions & 1 deletion modules/src/path/ics.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::{ConnectionPath, ConsensusStatePath};
use super::{ClientStatePath, ConnectionPath, ConsensusStatePath};

pub fn connection_path(_path: &ConnectionPath) -> String {
todo!()
Expand All @@ -7,3 +7,7 @@ pub fn connection_path(_path: &ConnectionPath) -> String {
pub fn consensus_state_path(_path: &ConsensusStatePath) -> String {
todo!()
}

pub fn client_state_path(_path: &ClientStatePath) -> String {
todo!()
}
30 changes: 30 additions & 0 deletions modules/src/test.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
use serde::{de::DeserializeOwned, Serialize};
use std::fmt::Debug;

/// Test that a struct `T` can be:
///
/// - parsed out of the provided JSON data
/// - serialized back to JSON
/// - parsed back from the serialized JSON of the previous step
/// - that the two parsed structs are equal according to their `PartialEq` impl
pub fn test_serialization_roundtrip<T>(json_data: &str)
where
T: Debug + Serialize + DeserializeOwned,
{
let parsed0 = serde_json::from_str::<T>(json_data);
assert!(parsed0.is_ok());
let parsed0 = parsed0.unwrap();

let serialized = serde_json::to_string(&parsed0);
assert!(serialized.is_ok());
let serialized = serialized.unwrap();

let parsed1 = serde_json::from_str::<T>(&serialized);
assert!(parsed1.is_ok());
let parsed1 = parsed1.unwrap();
println!("json_data0: {:?}", parsed0);
println!("json_data1: {:?}", parsed1);

// TODO - fix PartialEq bound issue in AbciQuery
//assert_eq!(parsed0, parsed1);
}
11 changes: 11 additions & 0 deletions modules/src/tests/query/serialization/client_state.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"code": 0,
"log": "",
"info": "",
"index": "0",
"key": "Y2xpZW50U3RhdGUvaWJjb25lY2xpZW50",
"value": "rwUhoYiWCgxpYmNvbmVjbGllbnQQgIDIkv+DkwIYgIDs2/7FnAMqiAUKgAQKxQIKAggKEgRpYmMxGBYiCwjMvIL0BRDIu58kKkgKICyeWhXpKZwrrUlzbaZ0DQnPqzkdNc8+k9eOogSLx43aEiQIARIgCFeoy6YD9BwuE0C1AU9BdEa2V51Cs28MXKewBA1rNtMyIBNgBAObhFbZAWB4KQGBQaC7Z/azZUkkSj2hMdZFFFppQiDses9b3+5uOFW4wZL6WWA0xtv9hTPe3Ib6BA7pzYQySUog7HrPW9/ubjhVuMGS+llgNMbb/YUz3tyG+gQO6c2EMklSIASAkbx93Cg/d7+/kdc8RNpYw9+KnLyGdAXYt/ParaIvWiBq+Q9GJMZNlWMQCpPikuUo+bJNzOKyjZSthVT8qdTQRmIgbjQLnP+zepicpUTmu3gKLHiQHT+zNzh2hRGjBhevoB1yFPbqil8EwnDU5G93rMLZvekApgKBErUBCBYaSAogZik4C8oy55EdSL4OhMTIAy8jsDvCYiK6ZYH58Wv6Q88SJAgBEiBIpIMYxWV2OFZh72/ooILjIPvaHEMZ008+w1h+rpi7WiJnCAISFPbqil8EwnDU5G93rMLZvekApgKBGgsIzbyC9AUQqI/hRyJAbloumBKmq9nNQ22y/XoogOCrp33xeHjzA2JyuxpR2oAtL+8KGwKbcCJvAZjwpqOEEiRdXJnQ1rHrubVJhg3WBRKCAQo/ChT26opfBMJw1ORvd6zC2b3pAKYCgRIlFiTeZCBdmybLcqCWKo8EBc9ZOM+rYKVUx4QmxhMYv93tBdcNDxhkEj8KFPbqil8EwnDU5G93rMLZvekApgKBEiUWJN5kIF2bJstyoJYqjwQFz1k4z6tgpVTHhCbGExi/3e0F1w0PGGQ=",
"proof": null,
"height": "100",
"codespace": ""
}
24 changes: 24 additions & 0 deletions modules/src/tests/query/serialization/client_state_proof.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"code": 0,
"log": "",
"info": "",
"index": "0",
"key": "Y2xpZW50U3RhdGUvaWJjb25lY2xpZW50",
"value": "rwUhoYiWCgxpYmNvbmVjbGllbnQQgIDIkv+DkwIYgIDs2/7FnAMqiAUKgAQKxQIKAggKEgRpYmMxGBYiCwjMvIL0BRDIu58kKkgKICyeWhXpKZwrrUlzbaZ0DQnPqzkdNc8+k9eOogSLx43aEiQIARIgCFeoy6YD9BwuE0C1AU9BdEa2V51Cs28MXKewBA1rNtMyIBNgBAObhFbZAWB4KQGBQaC7Z/azZUkkSj2hMdZFFFppQiDses9b3+5uOFW4wZL6WWA0xtv9hTPe3Ib6BA7pzYQySUog7HrPW9/ubjhVuMGS+llgNMbb/YUz3tyG+gQO6c2EMklSIASAkbx93Cg/d7+/kdc8RNpYw9+KnLyGdAXYt/ParaIvWiBq+Q9GJMZNlWMQCpPikuUo+bJNzOKyjZSthVT8qdTQRmIgbjQLnP+zepicpUTmu3gKLHiQHT+zNzh2hRGjBhevoB1yFPbqil8EwnDU5G93rMLZvekApgKBErUBCBYaSAogZik4C8oy55EdSL4OhMTIAy8jsDvCYiK6ZYH58Wv6Q88SJAgBEiBIpIMYxWV2OFZh72/ooILjIPvaHEMZ008+w1h+rpi7WiJnCAISFPbqil8EwnDU5G93rMLZvekApgKBGgsIzbyC9AUQqI/hRyJAbloumBKmq9nNQ22y/XoogOCrp33xeHjzA2JyuxpR2oAtL+8KGwKbcCJvAZjwpqOEEiRdXJnQ1rHrubVJhg3WBRKCAQo/ChT26opfBMJw1ORvd6zC2b3pAKYCgRIlFiTeZCBdmybLcqCWKo8EBc9ZOM+rYKVUx4QmxhMYv93tBdcNDxhkEj8KFPbqil8EwnDU5G93rMLZvekApgKBEiUWJN5kIF2bJstyoJYqjwQFz1k4z6tgpVTHhCbGExi/3e0F1w0PGGQ=",
"proof": {
"ops": [
{
"type": "iavl:v",
"key": "Y2xpZW50U3RhdGUvaWJjb25lY2xpZW50",
"data": "6wEK6AEKKAgIEAwYHCogr722bXSL9572EU1Jgdz6re1sVtpscxSW4cjaLrCtKPoKKAgGEAcYHCIg1wO/S0DOyBX5/zwOTIQt5lY7SkEJUORfEfZtHH6ZcLcKKAgEEAQYHCIgvBVVJn1U3LKVuitwm6hAvnwujQDcyMOOp5YdNbwdyTEKKAgCEAIYFyIgcuZfF//lb+VDAKtkXsR/J2/QPYlaw8HvrSmNqDf1iVYaPgoYY2xpZW50U3RhdGUvaWJjb25lY2xpZW50EiDV6DHA5N7GJNbSj0hzc586MXPwXDj4H57rYWZesk2XjRgX"
},
{
"type": "multistore",
"key": "aWJj",
"data": "CtUECi4KBGJhbmsSJgokCGQSIPfIBFZd98DupWwTml7I8kZFWKgF8ZTlslblitSLTJjqCi0KA2FjYxImCiQIZBIg3ZgdzN65c2/J62tIVCmQJwnN8Ho9dULDSL9dKEyA+cgKDwoHdXBncmFkZRIECgIIZAoxCgdzdGFraW5nEiYKJAhkEiCWTzW3aCWkLAyuZxi9z2CSXhmtmcRWEKi6K9ywkrVZMwoyCghzbGFzaGluZxImCiQIZBIgj6AcKVZzEJeL1r3wf9Qi5B53bjomfcn3g76fvuJn/FkKMAoGc3VwcGx5EiYKJAhkEiCRsUBZCybnNEYnaNqDTOO1pNEuAfGgY7pQMrgLCyUWBQotCgNnb3YSJgokCGQSIGDNE3wZYuysYWOJ1oA0gz8pIVCcLShapfUVOZfOlop0Ci0KA2liYxImCiQIZBIgWnpokBJ4idAoXzLzbjOOaBwU5E3oz4QJuAV8mShsqzwKLgoEbWFpbhImCiQIZBIgsZzwmLQ7PH1UeZ/vCUSqlQmfgt3CGfoMgJLkUqKCv0EKMAoGcGFyYW1zEiYKJAhkEiB8VIzExUHX+SvHZFz/P9NM9THnw/gTDDLVReuZX8htLgo2CgxkaXN0cmlidXRpb24SJgokCGQSIMaSvcpnTBH1nyPp/m3Ab+A/fowTOIWmuMtlbCda/2SsChAKCHRyYW5zZmVyEgQKAghkChAKCGV2aWRlbmNlEgQKAghkCi4KBG1pbnQSJgokCGQSIPvdoKLt1qhBYkRKjo39yCkQ0c1pOYM0kohjsVVGx9ae"
}
]
},
"height": "100",
"codespace": ""
}
11 changes: 11 additions & 0 deletions modules/src/tests/query/serialization/consensus_state.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"code": 0,
"log": "",
"info": "",
"index": "0",
"key": "Y29uc2Vuc3VzU3RhdGUvaWJjb25lY2xpZW50LzIy",
"value": "wAE7xH38CgsIzLyC9AUQyLufJBImzXAxMQogavkPRiTGTZVjEAqT4pLlKPmyTcziso2UrYVU/KnU0EYYFiKCAQo/ChT26opfBMJw1ORvd6zC2b3pAKYCgRIlFiTeZCBdmybLcqCWKo8EBc9ZOM+rYKVUx4QmxhMYv93tBdcNDxhkEj8KFPbqil8EwnDU5G93rMLZvekApgKBEiUWJN5kIF2bJstyoJYqjwQFz1k4z6tgpVTHhCbGExi/3e0F1w0PGGQ=",
"proof": null,
"height": "60295",
"codespace": ""
}
24 changes: 24 additions & 0 deletions modules/src/tests/query/serialization/consensus_state_proof.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"code": 0,
"log": "",
"info": "",
"index": "0",
"key": "Y29uc2Vuc3VzU3RhdGUvaWJjb25lY2xpZW50LzIy",
"value": "wAE7xH38CgsIzLyC9AUQyLufJBImzXAxMQogavkPRiTGTZVjEAqT4pLlKPmyTcziso2UrYVU/KnU0EYYFiKCAQo/ChT26opfBMJw1ORvd6zC2b3pAKYCgRIlFiTeZCBdmybLcqCWKo8EBc9ZOM+rYKVUx4QmxhMYv93tBdcNDxhkEj8KFPbqil8EwnDU5G93rMLZvekApgKBEiUWJN5kIF2bJstyoJYqjwQFz1k4z6tgpVTHhCbGExi/3e0F1w0PGGQ=",
"proof": {
"ops": [
{
"type": "iavl:v",
"key": "Y29uc2Vuc3VzU3RhdGUvaWJjb25lY2xpZW50LzIy",
"data": "8QEK7gEKKAgIEAwYHCIgG9RAkJgHlxNjmyzOW6bUAidhiRSja0x6+GXCVENPG1oKKAgGEAUYFyIgwRns+dJvjf1Zk2BaFrXz8inPbvYHB7xx2HCy9ima5f8KKAgEEAMYFyogOr8EGajEV6fG5fzJ2fAAvVMgRLhdMJTzCPlogl9rxlIKKAgCEAIYFyIgcjzX/a+2bFbnNldpawQqZ+kYhIwz5r4wCUzuu1IFW04aRAoeY29uc2Vuc3VzU3RhdGUvaWJjb25lY2xpZW50LzIyEiAZ1uuG60K4NHJZZMuS9QX6o4eEhica5jIHYwflRiYkDBgX"
},
{
"type": "multistore",
"key": "aWJj",
"data": "CvEECjAKBGJhbmsSKAomCIjYAxIg2MEyyonbZButYnvSRkf2bPQg+nqA+Am1MeDxG6F4p1UKLwoDYWNjEigKJgiI2AMSIN2YHczeuXNvyetrSFQpkCcJzfB6PXVCw0i/XShMgPnIChEKB3VwZ3JhZGUSBgoECIjYAwovCgNnb3YSKAomCIjYAxIgYM0TfBli7KxhY4nWgDSDPykhUJwtKFql9RU5l86WinQKLwoDaWJjEigKJgiI2AMSIFp6aJASeInQKF8y824zjmgcFORN6M+ECbgFfJkobKs8CjAKBG1haW4SKAomCIjYAxIgsZzwmLQ7PH1UeZ/vCUSqlQmfgt3CGfoMgJLkUqKCv0EKMwoHc3Rha2luZxIoCiYIiNgDEiCiBZoBLyDGj5euy3n33ik+SpqYK9eB5xbI+iY8ycYVbwo0CghzbGFzaGluZxIoCiYIiNgDEiAJz3gEYuIhdensHU3b5qH5ons2quepd6EaRgCHXab6PQoyCgZzdXBwbHkSKAomCIjYAxIglWLA5/THPTiTxAlaLHOBYFIzEJTmKPznItUwAc8zD+AKEgoIZXZpZGVuY2USBgoECIjYAwowCgRtaW50EigKJgiI2AMSIMS8dZ1j8F6JVVv+hB1rHBZC+gIFJxHan2hM8qDC64n/CjIKBnBhcmFtcxIoCiYIiNgDEiB8VIzExUHX+SvHZFz/P9NM9THnw/gTDDLVReuZX8htLgo4CgxkaXN0cmlidXRpb24SKAomCIjYAxIg3u/Nd4L+8LT8OXJCh14o8PHIJ/GLQwsmE7KYIl1GdSYKEgoIdHJhbnNmZXISBgoECIjYAw=="
}
]
},
"height": "60424",
"codespace": ""
}
3 changes: 2 additions & 1 deletion relayer/cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ authors = [

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

anomaly = "0.2.0"
gumdrop = "0.7"
Expand Down
Loading