Skip to content
This repository has been archived by the owner on Jun 3, 2020. It is now read-only.

Commit

Permalink
tendermint-rs: /abci_query RPC endpoint (closes #287)
Browse files Browse the repository at this point in the history
Adds support for invoking the ABCIQuery endpoint:

https://tendermint.com/rpc/#abciquery
  • Loading branch information
tony-iqlusion committed Jul 18, 2019
1 parent fcc52e5 commit 7491c6f
Show file tree
Hide file tree
Showing 10 changed files with 182 additions and 5 deletions.
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ yubihsm = { version = "0.26", features = ["setup", "usb"], optional = true }
zeroize = "0.9"

[dependencies.abscissa_core]
version = "0.2.0"
version = "0.2"

[dependencies.tendermint]
version = "0.9"
Expand All @@ -59,7 +59,7 @@ tempfile = "3"
rand = "0.6"

[dev-dependencies.abscissa_core]
version = "0.2.0"
version = "0.2"
features = ["testing"]

[features]
Expand Down
6 changes: 5 additions & 1 deletion tendermint-rs/src/abci.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,15 @@ mod info;
#[cfg(feature = "rpc")]
mod log;
#[cfg(feature = "rpc")]
mod path;
#[cfg(feature = "rpc")]
mod proof;
#[cfg(feature = "rpc")]
mod responses;
pub mod transaction;

#[cfg(feature = "rpc")]
pub use self::{
code::Code, data::Data, gas::Gas, info::Info, log::Log, responses::Responses,
code::Code, data::Data, gas::Gas, info::Info, log::Log, proof::Proof, responses::Responses,
transaction::Transaction,
};
1 change: 1 addition & 0 deletions tendermint-rs/src/abci/path.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

51 changes: 51 additions & 0 deletions tendermint-rs/src/abci/proof.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
//! ABCI Merkle proofs

use crate::error::Error;
use serde::{de::Error as _, Deserialize, Deserializer, Serialize, Serializer};
use std::{
fmt::{self, Display},
str::FromStr,
};
use subtle_encoding::{Encoding, Hex};

/// ABCI Merkle proofs
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct Proof(Vec<u8>);

impl AsRef<[u8]> for Proof {
fn as_ref(&self) -> &[u8] {
self.0.as_ref()
}
}

impl Display for Proof {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{}",
&Hex::upper_case().encode_to_string(&self.0).unwrap()
)
}
}

impl FromStr for Proof {
type Err = Error;

fn from_str(s: &str) -> Result<Self, Error> {
let bytes = Hex::upper_case().decode(s)?;
Ok(Proof(bytes))
}
}

impl<'de> Deserialize<'de> for Proof {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let hex = String::deserialize(deserializer)?;
Ok(Self::from_str(&hex).map_err(|e| D::Error::custom(format!("{}", e)))?)
}
}

impl Serialize for Proof {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
self.to_string().serialize(serializer)
}
}
2 changes: 1 addition & 1 deletion tendermint-rs/src/block/height.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use std::{
/// Block height for a particular chain (i.e. number of blocks created since
/// the chain began)
#[derive(Copy, Clone, Eq, Hash, PartialEq, PartialOrd, Ord)]
pub struct Height(pub u64);
pub struct Height(u64);

impl Height {
/// Convert `u64` to block height.
Expand Down
18 changes: 17 additions & 1 deletion tendermint-rs/src/rpc/client.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Tendermint RPC client

use crate::{
abci::Transaction,
abci::{self, Transaction},
block::Height,
net,
rpc::{self, endpoint::*, Error, Response},
Expand Down Expand Up @@ -33,6 +33,22 @@ impl Client {
Ok(self.perform(abci_info::Request)?.response)
}

/// `/abci_query`: query the ABCI application
pub fn abci_query(
&self,
path: Option<abci::Path>,
data: D,
height: Option<block::Height>,
prove: bool,
) -> Result<abci_query::AbciQuery, Error>
where
D: AsRef<[u8]>,
{
Ok(self
.perform(abci_query::Request::new(path, data, height, prove))?
.response)
}

/// `/block`: get block at a given height.
pub fn block<H>(&self, height: H) -> Result<block::Response, Error>
where
Expand Down
1 change: 1 addition & 0 deletions tendermint-rs/src/rpc/endpoint.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! Tendermint JSONRPC endpoints

pub mod abci_info;
pub mod abci_query;
pub mod block;
pub mod block_results;
pub mod blockchain;
Expand Down
80 changes: 80 additions & 0 deletions tendermint-rs/src/rpc/endpoint/abci_query.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
//! `/abci_query` endpoint JSONRPC wrapper

use crate::{
abci::{Code, Log, Proof},
block, rpc, serializers,
};
use serde::{Deserialize, Serialize};

/// Query the ABCI application for information
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct Request {
/// Path to the data
path: Option<String>,

/// Data to query
data: Vec<u8>,

/// Block height
height: Option<block::Height>,

/// Include proof in response
prove: bool,
}

impl rpc::Request for Request {
type Response = Response;

fn method(&self) -> rpc::Method {
rpc::Method::AbciInfo
}
}

/// ABCI query response wrapper
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Response {
/// ABCI query results
pub response: AbciQuery,
}

impl rpc::Response for Response {}

/// ABCI query results
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct AbciQuery {
/// Response code
pub code: Code,

/// Log value
pub log: Log,

/// Info value
pub info: Option<String>,

/// Index
#[cfg_attr(
feature = "serde",
serde(
serialize_with = "serializers::serialize_i64",
deserialize_with = "serializers::parse_i64"
)
)]
pub index: i64,

/// Key
// TODO(tarcieri): parse to Vec<u8>?
pub key: String,

/// Value
// TODO(tarcieri): parse to Vec<u8>?
pub value: String,

/// Proof (if requested)
pub proof: Option<Proof>,

/// Block height
pub height: block::Height,

/// Codespace
pub codespace: Option<String>,
}
9 changes: 9 additions & 0 deletions tendermint-rs/tests/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,15 @@ mod endpoints {
assert_eq!(response.last_block_height.value(), 488120);
}

#[test]
fn abci_query() {
let response = endpoint::abci_query::Response::from_json(&read_json_fixture("abci_query"))
.unwrap()
.response;

assert_eq!(response.height.value(), 1);
}

#[test]
fn block() {
let response = endpoint::block::Response::from_json(&read_json_fixture("block")).unwrap();
Expand Down
15 changes: 15 additions & 0 deletions tendermint-rs/tests/support/rpc/abci_query.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"jsonrpc": "2.0",
"id": "",
"result": {
"response": {
"log": "exists",
"height": "1",
"proof": "010114FED0DAD959F36091AD761C922ABA3CBF1D8349990101020103011406AA2262E2F448242DF2C2607C3CDC705313EE3B0001149D16177BC71E445476174622EA559715C293740C",
"value": "61626364",
"key": "61626364",
"index": "-1",
"code": "0"
}
}
}

0 comments on commit 7491c6f

Please sign in to comment.