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

Commit

Permalink
tendermint-rs: Add TendermintConfig and Error(Kind) types
Browse files Browse the repository at this point in the history
Adds types which describes the structure of `config.toml` files, and
support for parsing them with serde and the `toml` crate.

This should describe every configuration field generated by the default
boilerplate.

Additionally this commit changes the `Error` type in `tendermint-rs`
from an enum to a struct, renaming the original `Error` enum to
`ErrorKind`. This allows incorporating additional information into each
error: this commit uses it to add a "msg" field to each error which is
needed to get reasonable parse errors from config files, however since
it's built on the `failure` crate and using a `failure::Context`, this
will also capture a backtrace at the time the error is generated.
  • Loading branch information
tony-iqlusion committed Jul 22, 2019
1 parent 9cf3858 commit 69693e9
Show file tree
Hide file tree
Showing 32 changed files with 1,580 additions and 173 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 10 additions & 10 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,18 +135,18 @@ impl From<serde_json::error::Error> for Error {

impl From<tendermint::Error> for Error {
fn from(other: tendermint::error::Error) -> Self {
let kind = match other {
tendermint::Error::Crypto => ErrorKind::CryptoError,
tendermint::Error::InvalidKey => ErrorKind::InvalidKey,
tendermint::Error::Io => ErrorKind::IoError,
tendermint::Error::Protocol => ErrorKind::ProtocolError,
tendermint::Error::Length
| tendermint::Error::Parse
| tendermint::Error::OutOfRange => ErrorKind::ParseError,
tendermint::Error::SignatureInvalid => ErrorKind::VerificationError,
let kind = match other.kind() {
tendermint::ErrorKind::Crypto => ErrorKind::CryptoError,
tendermint::ErrorKind::InvalidKey => ErrorKind::InvalidKey,
tendermint::ErrorKind::Io => ErrorKind::IoError,
tendermint::ErrorKind::Protocol => ErrorKind::ProtocolError,
tendermint::ErrorKind::Length
| tendermint::ErrorKind::Parse
| tendermint::ErrorKind::OutOfRange => ErrorKind::ParseError,
tendermint::ErrorKind::SignatureInvalid => ErrorKind::VerificationError,
};

abscissa_core::Error::new(kind, None).into()
abscissa_core::Error::new(kind, other.msg().map(|s| s.to_owned())).into()
}
}

Expand Down
4 changes: 3 additions & 1 deletion tendermint-rs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ sha2 = { version = "0.8", default-features = false }
subtle = "2"
subtle-encoding = { version = "0.3", features = ["bech32-preview"] }
tai64 = { version = "2", optional = true, features = ["chrono"] }
toml = { version = "0.5", optional = true }
uuid = { version = "0.7", optional = true, default-features = false }
x25519-dalek = { version = "0.5", optional = true, default-features = false, features = ["u64_backend"] }
zeroize = { version = "0.9", optional = true }
Expand All @@ -57,7 +58,8 @@ serde_json = "1"
[features]
default = ["serde", "tai64"]
amino-types = ["prost-amino", "prost-amino-derive"]
integration = []
config = ["serde", "toml"]
integration-test = []
rpc = ["hyper", "rand_os", "serde", "serde_json", "uuid"]
secret-connection = [
"amino-types",
Expand Down
2 changes: 2 additions & 0 deletions tendermint-rs/src/abci.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ mod path;
mod proof;
#[cfg(feature = "rpc")]
mod responses;
#[cfg(any(feature = "config", feature = "rpc"))]
pub mod tag;
pub mod transaction;

#[cfg(feature = "rpc")]
Expand Down
4 changes: 2 additions & 2 deletions tendermint-rs/src/abci/data.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::Error;
use crate::{Error, ErrorKind};
use serde::{de::Error as _, Deserialize, Deserializer, Serialize, Serializer};
use std::{
fmt::{self, Display},
Expand Down Expand Up @@ -42,7 +42,7 @@ impl FromStr for Data {
// Accept either upper or lower case hex
let bytes = hex::decode_upper(s)
.or_else(|_| hex::decode(s))
.map_err(|_| Error::Parse)?;
.map_err(|_| ErrorKind::Parse)?;

Ok(Data(bytes))
}
Expand Down
4 changes: 2 additions & 2 deletions tendermint-rs/src/abci/gas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
//!
//! <https://tendermint.com/docs/spec/abci/apps.html#gas>

use crate::Error;
use crate::{Error, ErrorKind};
use serde::{de::Error as _, Deserialize, Deserializer, Serialize, Serializer};
use std::{
fmt::{self, Display},
Expand Down Expand Up @@ -45,7 +45,7 @@ impl FromStr for Gas {
type Err = Error;

fn from_str(s: &str) -> Result<Self, Error> {
Ok(Self::from(s.parse::<u64>().map_err(|_| Error::Parse)?))
Ok(Self::from(s.parse::<u64>().map_err(|_| ErrorKind::Parse)?))
}
}

Expand Down
4 changes: 2 additions & 2 deletions tendermint-rs/src/abci/log.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#[cfg(feature = "serde_json")]
use crate::Error;
use crate::{Error, ErrorKind};
use serde::{Deserialize, Serialize};
use std::fmt::{self, Display};

Expand All @@ -11,7 +11,7 @@ impl Log {
/// Parse the log data as JSON, returning a `serde_json::Value`
#[cfg(feature = "serde_json")]
pub fn parse_json(&self) -> Result<serde_json::Value, Error> {
serde_json::from_str(&self.0).map_err(|_| Error::Parse)
serde_json::from_str(&self.0).map_err(|_| ErrorKind::Parse.into())
}
}

Expand Down
12 changes: 1 addition & 11 deletions tendermint-rs/src/abci/responses.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! ABCI response types used by the `/block_results` RPC endpoint.

use super::{code::Code, data::Data, gas::Gas, info::Info, log::Log};
use super::{code::Code, data::Data, gas::Gas, info::Info, log::Log, tag::Tag};
use crate::{consensus, validator};
use serde::{Deserialize, Deserializer, Serialize};
use std::fmt::{self, Display};
Expand Down Expand Up @@ -117,16 +117,6 @@ where
Ok(Option::deserialize(deserializer)?.unwrap_or_default())
}

/// Tags
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Tag {
/// Key
pub key: String,

/// Value
pub value: String,
}

/// Codespace
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct Codespace(String);
Expand Down
63 changes: 63 additions & 0 deletions tendermint-rs/src/abci/tag.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
//! Tags

use crate::error::Error;
use serde::{Deserialize, Serialize};
use std::{fmt, str::FromStr};

/// Tags
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Tag {
/// Key
pub key: Key,

/// Value
pub value: Value,
}

/// Tag keys
#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize)]
pub struct Key(String);

impl AsRef<str> for Key {
fn as_ref(&self) -> &str {
self.0.as_ref()
}
}

impl FromStr for Key {
type Err = Error;

fn from_str(s: &str) -> Result<Self, Error> {
Ok(Key(s.into()))
}
}

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

/// Tag values
#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub struct Value(String);

impl AsRef<str> for Value {
fn as_ref(&self) -> &str {
self.0.as_ref()
}
}

impl FromStr for Value {
type Err = Error;

fn from_str(s: &str) -> Result<Self, Error> {
Ok(Value(s.into()))
}
}

impl fmt::Display for Value {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", &self.0)
}
}
6 changes: 3 additions & 3 deletions tendermint-rs/src/abci/transaction/hash.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Transaction hashes

use crate::error::Error;
use crate::error::{Error, ErrorKind};
#[cfg(feature = "serde")]
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
use std::{
Expand Down Expand Up @@ -65,10 +65,10 @@ impl FromStr for Hash {
// Accept either upper or lower case hex
let bytes = hex::decode_upper(s)
.or_else(|_| hex::decode(s))
.map_err(|_| Error::Parse)?;
.map_err(|_| ErrorKind::Parse)?;

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

let mut result_bytes = [0u8; LENGTH];
Expand Down
6 changes: 3 additions & 3 deletions tendermint-rs/src/account.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Tendermint accounts

use crate::error::Error;
use crate::error::{Error, ErrorKind};
#[cfg(feature = "serde")]
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
use sha2::{Digest, Sha256};
Expand Down Expand Up @@ -87,10 +87,10 @@ impl FromStr for Id {
// Accept either upper or lower case hex
let bytes = hex::decode_upper(s)
.or_else(|_| hex::decode(s))
.map_err(|_| Error::Parse)?;
.map_err(|_| ErrorKind::Parse)?;

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

let mut result_bytes = [0u8; LENGTH];
Expand Down
6 changes: 3 additions & 3 deletions tendermint-rs/src/block/height.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::error::Error;
use crate::error::{Error, ErrorKind};
#[cfg(feature = "serde")]
use serde::{de::Error as _, Deserialize, Deserializer, Serialize, Serializer};
use std::{
Expand All @@ -20,7 +20,7 @@ impl Height {
if n > 0 {
Ok(Height(n))
} else {
Err(Error::OutOfRange)
Err(ErrorKind::OutOfRange.into())
}
}

Expand Down Expand Up @@ -86,7 +86,7 @@ impl FromStr for Height {
type Err = Error;

fn from_str(s: &str) -> Result<Self, Error> {
Self::try_from_u64(s.parse::<u64>().map_err(|_| Error::Parse)?)
Self::try_from_u64(s.parse::<u64>().map_err(|_| ErrorKind::Parse)?)
}
}

Expand Down
10 changes: 10 additions & 0 deletions tendermint-rs/src/block/size.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,14 @@ pub struct Size {
)
)]
pub max_gas: u64,

/// Time iota in ms
#[cfg_attr(
feature = "serde",
serde(
serialize_with = "serializers::serialize_u64",
deserialize_with = "serializers::parse_u64"
)
)]
pub time_iota_ms: u64,
}
13 changes: 8 additions & 5 deletions tendermint-rs/src/chain/id.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Tendermint blockchain identifiers

use crate::error::Error;
use crate::error::{Error, ErrorKind};
#[cfg(feature = "serde")]
use serde::{de::Error as _, Deserialize, Deserializer, Serialize, Serializer};
use std::{
Expand Down Expand Up @@ -62,13 +62,13 @@ impl FromStr for Id {
/// Parses string to create a new chain ID
fn from_str(name: &str) -> Result<Self, Error> {
if name.is_empty() || name.len() > MAX_LENGTH {
return Err(Error::Length);
Err(ErrorKind::Length)?;
}

for byte in name.as_bytes() {
match byte {
b'a'..=b'z' | b'A'..=b'Z' | b'0'..=b'9' | b'-' | b'_' => (),
_ => return Err(Error::Parse),
_ => Err(ErrorKind::Parse)?,
}
}

Expand Down Expand Up @@ -144,12 +144,15 @@ mod tests {

#[test]
fn rejects_empty_chain_ids() {
assert_eq!("".parse::<Id>(), Err(Error::Length))
assert_eq!(*"".parse::<Id>().err().unwrap().kind(), ErrorKind::Length);
}

#[test]
fn rejects_overlength_chain_ids() {
let overlong_id = String::from_utf8(vec![b'x'; MAX_LENGTH + 1]).unwrap();
assert_eq!(overlong_id.parse::<Id>(), Err(Error::Length))
assert_eq!(
*overlong_id.parse::<Id>().err().unwrap().kind(),
ErrorKind::Length
);
}
}
Loading

0 comments on commit 69693e9

Please sign in to comment.