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

Commit

Permalink
tendermint-rs: /status RPC endpoint
Browse files Browse the repository at this point in the history
Adds initial support for parsing JSON responses from the `/status`
JSONRPC endpoint.
  • Loading branch information
tony-iqlusion committed Apr 20, 2019
1 parent 917cdb9 commit bd0f8e1
Show file tree
Hide file tree
Showing 13 changed files with 474 additions and 105 deletions.
58 changes: 58 additions & 0 deletions tendermint-rs/src/channel.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
//! Channels (RPC types)

mod id;

pub use self::id::Id;
use crate::rpc;
pub use serde::{Deserialize, Serialize};
use std::fmt::{self, Display};

/// Channels
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Channel {
/// Channel ID
#[serde(rename = "ID")]
pub id: Id,

/// Capacity of the send queue
#[serde(
rename = "SendQueueCapacity",
serialize_with = "rpc::response::serialize_u64",
deserialize_with = "rpc::response::parse_u64"
)]
pub send_queue_capacity: u64,

/// Size of the send queue
#[serde(
rename = "SendQueueSize",
serialize_with = "rpc::response::serialize_u64",
deserialize_with = "rpc::response::parse_u64"
)]
pub send_queue_size: u64,

/// Priority value
#[serde(
rename = "Priority",
serialize_with = "rpc::response::serialize_u64",
deserialize_with = "rpc::response::parse_u64"
)]
pub priority: u64,

/// Amount of data recently sent
#[serde(
rename = "RecentlySent",
serialize_with = "rpc::response::serialize_u64",
deserialize_with = "rpc::response::parse_u64"
)]
pub recently_sent: u64,
}

/// Channel collections
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct Channels(String);

impl Display for Channels {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
24 changes: 24 additions & 0 deletions tendermint-rs/src/channel/id.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use serde::{Deserialize, Serialize};

/// Channel IDs
#[derive(Copy, Clone, Debug, Deserialize, Serialize)]
pub struct Id(pub u64);

impl Id {
/// Get the current voting power as an integer
pub fn value(self) -> u64 {
self.0
}
}

impl From<Id> for u64 {
fn from(id: Id) -> u64 {
id.value()
}
}

impl From<u64> for Id {
fn from(id: u64) -> Id {
Id(id)
}
}
6 changes: 5 additions & 1 deletion tendermint-rs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,11 @@ pub mod algorithm;
pub mod amino_types;
pub mod block;
pub mod chain;
#[cfg(feature = "rpc")]
pub mod channel;
pub mod error;
pub mod hash;
pub mod moniker;
mod moniker;
pub mod net;
pub mod node;
pub mod public_keys;
Expand All @@ -42,6 +44,7 @@ pub mod rpc;
#[cfg(feature = "secret-connection")]
pub mod secret_connection;
pub mod timestamp;
mod version;

#[cfg(feature = "secret-connection")]
pub use crate::secret_connection::SecretConnection;
Expand All @@ -52,4 +55,5 @@ pub use crate::{
moniker::Moniker,
public_keys::{PublicKey, TendermintKey},
timestamp::Timestamp,
version::Version,
};
110 changes: 6 additions & 104 deletions tendermint-rs/src/node.rs
Original file line number Diff line number Diff line change
@@ -1,107 +1,9 @@
//! Nodes in Tendermint blockchain networks

use crate::error::Error;
#[cfg(feature = "serde")]
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
use sha2::{Digest, Sha256};
use signatory::ed25519;
use std::{
fmt::{self, Display},
str::FromStr,
};
use subtle::{self, ConstantTimeEq};
use subtle_encoding::hex;
mod id;
#[cfg(feature = "rpc")]
pub mod info;

/// Size of a Node ID in bytes
pub const ID_LENGTH: usize = 20;

/// Node IDs
#[derive(Copy, Clone, Debug, Hash)]
pub struct Id([u8; ID_LENGTH]);

impl Id {
/// Create a new Node ID from raw bytes
pub fn new(bytes: [u8; ID_LENGTH]) -> Id {
Id(bytes)
}

/// Borrow the node ID as a byte slice
pub fn as_bytes(&self) -> &[u8] {
&self.0[..]
}
}

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

impl ConstantTimeEq for Id {
#[inline]
fn ct_eq(&self, other: &Id) -> subtle::Choice {
self.as_bytes().ct_eq(other.as_bytes())
}
}

impl Display for Id {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for byte in &self.0 {
write!(f, "{:02X}", byte)?;
}
Ok(())
}
}

impl From<ed25519::PublicKey> for Id {
fn from(pk: ed25519::PublicKey) -> Id {
let digest = Sha256::digest(pk.as_bytes());
let mut bytes = [0u8; ID_LENGTH];
bytes.copy_from_slice(&digest[..ID_LENGTH]);
Id(bytes)
}
}

/// Decode Node ID from hex
impl FromStr for Id {
type Err = Error;

fn from_str(s: &str) -> Result<Self, Self::Err> {
// Accept either upper or lower case hex
let bytes = hex::decode_upper(s)
.or_else(|_| hex::decode(s))
.map_err(|_| Error::Parse)?;

if bytes.len() != ID_LENGTH {
return Err(Error::Parse);
}

let mut result_bytes = [0u8; ID_LENGTH];
result_bytes.copy_from_slice(&bytes);
Ok(Id(result_bytes))
}
}

#[cfg(feature = "serde")]
impl<'de> Deserialize<'de> for Id {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
Self::from_str(&s).map_err(|_| {
de::Error::custom(format!(
"expected {}-character hex string, got {:?}",
ID_LENGTH * 2,
s
))
})
}
}

#[cfg(feature = "serde")]
impl Serialize for Id {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
self.to_string().serialize(serializer)
}
}
pub use self::id::Id;
#[cfg(feature = "rpc")]
pub use self::info::Info;
107 changes: 107 additions & 0 deletions tendermint-rs/src/node/id.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
//! Tendermint node IDs

use crate::error::Error;
#[cfg(feature = "serde")]
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
use sha2::{Digest, Sha256};
use signatory::ed25519;
use std::{
fmt::{self, Display},
str::FromStr,
};
use subtle::{self, ConstantTimeEq};
use subtle_encoding::hex;

/// Size of a Node ID in bytes
pub const ID_LENGTH: usize = 20;

/// Node IDs
#[derive(Copy, Clone, Debug, Hash)]
pub struct Id([u8; ID_LENGTH]);

impl Id {
/// Create a new Node ID from raw bytes
pub fn new(bytes: [u8; ID_LENGTH]) -> Id {
Id(bytes)
}

/// Borrow the node ID as a byte slice
pub fn as_bytes(&self) -> &[u8] {
&self.0[..]
}
}

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

impl ConstantTimeEq for Id {
#[inline]
fn ct_eq(&self, other: &Id) -> subtle::Choice {
self.as_bytes().ct_eq(other.as_bytes())
}
}

impl Display for Id {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for byte in &self.0 {
write!(f, "{:02X}", byte)?;
}
Ok(())
}
}

impl From<ed25519::PublicKey> for Id {
fn from(pk: ed25519::PublicKey) -> Id {
let digest = Sha256::digest(pk.as_bytes());
let mut bytes = [0u8; ID_LENGTH];
bytes.copy_from_slice(&digest[..ID_LENGTH]);
Id(bytes)
}
}

/// Decode Node ID from hex
impl FromStr for Id {
type Err = Error;

fn from_str(s: &str) -> Result<Self, Self::Err> {
// Accept either upper or lower case hex
let bytes = hex::decode_upper(s)
.or_else(|_| hex::decode(s))
.map_err(|_| Error::Parse)?;

if bytes.len() != ID_LENGTH {
return Err(Error::Parse);
}

let mut result_bytes = [0u8; ID_LENGTH];
result_bytes.copy_from_slice(&bytes);
Ok(Id(result_bytes))
}
}

#[cfg(feature = "serde")]
impl<'de> Deserialize<'de> for Id {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
Self::from_str(&s).map_err(|_| {
de::Error::custom(format!(
"expected {}-character hex string, got {:?}",
ID_LENGTH * 2,
s
))
})
}
}

#[cfg(feature = "serde")]
impl Serialize for Id {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
self.to_string().serialize(serializer)
}
}
Loading

0 comments on commit bd0f8e1

Please sign in to comment.