Skip to content

Commit

Permalink
Add client queries to the relayer (#38)
Browse files Browse the repository at this point in the history
* debugging the consensus query with proof

* started on client state

* fixed unused warning

* add height param to client query

* cargo fmt

* make proof option for client state

* fix client state prove flag

* cleanup queries

* Try integration with tm-rs v0.33 to pick the new merkle proof

* add validation function for common params

* add utils

* some cleanup and err handling

* addressing Ismail's comments
  • Loading branch information
ancazamfir committed Apr 10, 2020
1 parent 88e0c0c commit 287bd64
Show file tree
Hide file tree
Showing 27 changed files with 680 additions and 39 deletions.
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>;
}
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,
unbonding_period: Duration,
frozen_height: crate::Height,
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!()
}
}
*/
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

0 comments on commit 287bd64

Please sign in to comment.