-
Notifications
You must be signed in to change notification settings - Fork 221
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Decouple RPC from ABCI domain types.
The original contents of `tendermint::abci` were created only to model RPC responses, not to model ABCI itself. The old types are shaped to fit the details of the JSON encoding used by the RPC. Eventually, they should be eliminated and merged with the new ABCI domain types. Moving them to the RPC crate in the meantime disentangles that work from the work of finishing the modeling of the ABCI domain types.
- Loading branch information
1 parent
70122e2
commit e19fb31
Showing
20 changed files
with
848 additions
and
62 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
//! Old ABCI structures, formerly defined in `tendermint::abci`. | ||
//! | ||
//! The original contents of `tendermint::abci` were created only to model RPC | ||
//! responses, not to model ABCI itself. The old types should be eliminated and | ||
//! merged with the new ABCI domain types. Moving them here in the meantime | ||
//! disentangles improving the ABCI domain modeling from changes to the RPC | ||
//! interface. | ||
|
||
mod code; | ||
mod data; | ||
mod gas; | ||
mod info; | ||
mod log; | ||
mod path; | ||
|
||
pub mod responses; | ||
pub mod tag; | ||
pub mod transaction; | ||
|
||
pub use self::{ | ||
code::Code, | ||
data::Data, | ||
gas::Gas, | ||
info::Info, | ||
log::Log, | ||
path::Path, | ||
responses::{DeliverTx, Event, Responses}, | ||
transaction::Transaction, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
use serde::de::{Deserialize, Deserializer, Visitor}; | ||
use serde::{Serialize, Serializer}; | ||
use std::fmt; | ||
use std::num::NonZeroU32; | ||
|
||
/// ABCI application response codes. | ||
/// | ||
/// These presently use 0 for success and non-zero for errors: | ||
/// | ||
/// <https://tendermint.com/docs/spec/abci/abci.html#errors> | ||
/// | ||
/// Note that in the future there may potentially be non-zero success codes. | ||
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)] | ||
pub enum Code { | ||
/// Success | ||
Ok, | ||
|
||
/// Error codes | ||
Err(NonZeroU32), | ||
} | ||
|
||
impl Default for Code { | ||
fn default() -> Code { | ||
Code::Ok | ||
} | ||
} | ||
|
||
impl Code { | ||
/// Was the response OK? | ||
pub fn is_ok(self) -> bool { | ||
match self { | ||
Code::Ok => true, | ||
Code::Err(_) => false, | ||
} | ||
} | ||
|
||
/// Was the response an error? | ||
pub fn is_err(self) -> bool { | ||
!self.is_ok() | ||
} | ||
|
||
/// Get the integer error value for this code | ||
pub fn value(self) -> u32 { | ||
u32::from(self) | ||
} | ||
} | ||
|
||
impl From<u32> for Code { | ||
fn from(value: u32) -> Code { | ||
match NonZeroU32::new(value) { | ||
Some(value) => Code::Err(value), | ||
None => Code::Ok, | ||
} | ||
} | ||
} | ||
|
||
impl From<Code> for u32 { | ||
fn from(code: Code) -> u32 { | ||
match code { | ||
Code::Ok => 0, | ||
Code::Err(err) => err.get(), | ||
} | ||
} | ||
} | ||
|
||
impl Serialize for Code { | ||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { | ||
self.value().serialize(serializer) | ||
} | ||
} | ||
|
||
impl<'de> Deserialize<'de> for Code { | ||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> | ||
where | ||
D: Deserializer<'de>, | ||
{ | ||
struct CodeVisitor; | ||
|
||
impl<'de> Visitor<'de> for CodeVisitor { | ||
type Value = Code; | ||
|
||
fn expecting(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
fmt.write_str("integer or string") | ||
} | ||
|
||
fn visit_u64<E>(self, val: u64) -> Result<Self::Value, E> | ||
where | ||
E: serde::de::Error, | ||
{ | ||
Ok(Code::from(val as u32)) | ||
} | ||
|
||
fn visit_str<E>(self, val: &str) -> Result<Self::Value, E> | ||
where | ||
E: serde::de::Error, | ||
{ | ||
match val.parse::<u64>() { | ||
Ok(val) => self.visit_u64(val), | ||
Err(_) => Err(E::custom("failed to parse integer")), | ||
} | ||
} | ||
} | ||
|
||
deserializer.deserialize_any(CodeVisitor) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
use serde::{Deserialize, Serialize}; | ||
|
||
/// ABCI transaction data. | ||
/// | ||
/// Transactions are opaque binary blobs which are validated according to | ||
/// application-specific rules. | ||
#[derive(Clone, Debug, Eq, PartialEq, Default, Serialize, Deserialize)] | ||
#[serde(transparent)] | ||
pub struct Data(#[serde(with = "tendermint::serializers::bytes::base64string")] Vec<u8>); | ||
|
||
impl From<Vec<u8>> for Data { | ||
fn from(value: Vec<u8>) -> Self { | ||
Self(value) | ||
} | ||
} | ||
|
||
impl From<Data> for Vec<u8> { | ||
fn from(value: Data) -> Self { | ||
value.0 | ||
} | ||
} | ||
|
||
impl Data { | ||
/// Get value | ||
pub fn value(&self) -> &Vec<u8> { | ||
&self.0 | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use crate::abci::Data; | ||
|
||
#[test] | ||
fn test_deserialization() { | ||
let json = "\"ChYKFGNvbm5lY3Rpb25fb3Blbl9pbml0\""; | ||
let mydata: Data = serde_json::from_str(json).unwrap(); | ||
assert_eq!( | ||
mydata.0, | ||
vec![ | ||
// By chance this is a protobuf struct. | ||
10, // Field 1 is a String | ||
22, // Field 1 length is 22 | ||
10, // Sub-field 1 is String | ||
20, // Sub-field 1 length is 20 | ||
99, 111, 110, 110, 101, 99, 116, 105, 111, 110, 95, 111, 112, 101, 110, 95, 105, | ||
110, 105, 116 // "connection_open_init" | ||
] | ||
); | ||
} | ||
|
||
#[test] | ||
fn test_serialization() { | ||
let mydata: Data = vec![1, 2, 3, 4].into(); | ||
let json = serde_json::to_string(&mydata).unwrap(); | ||
assert_eq!(json, "\"AQIDBA==\""); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
//! Gas: abstract representation for the cost of resources used by nodes when | ||
//! processing transactions. | ||
//! | ||
//! For more information, see: | ||
//! | ||
//! <https://tendermint.com/docs/spec/abci/apps.html#gas> | ||
|
||
use tendermint::{Error, Kind}; | ||
use serde::{de::Error as _, Deserialize, Deserializer, Serialize, Serializer}; | ||
use std::{ | ||
fmt::{self, Display}, | ||
str::FromStr, | ||
}; | ||
|
||
/// Gas: representation of transaction processing resource costs | ||
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, PartialOrd, Ord)] | ||
pub struct Gas(u64); | ||
|
||
impl Gas { | ||
/// Get the inner integer value | ||
pub fn value(self) -> u64 { | ||
self.0 | ||
} | ||
} | ||
|
||
impl From<u64> for Gas { | ||
fn from(amount: u64) -> Gas { | ||
Gas(amount) | ||
} | ||
} | ||
|
||
impl From<Gas> for u64 { | ||
fn from(gas: Gas) -> u64 { | ||
gas.0 | ||
} | ||
} | ||
|
||
impl Display for Gas { | ||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
write!(f, "{}", self.0) | ||
} | ||
} | ||
|
||
impl FromStr for Gas { | ||
type Err = Error; | ||
|
||
fn from_str(s: &str) -> Result<Self, Error> { | ||
Ok(Self::from(s.parse::<u64>().map_err(|_| Kind::Parse)?)) | ||
} | ||
} | ||
|
||
impl<'de> Deserialize<'de> for Gas { | ||
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> { | ||
Self::from_str(&String::deserialize(deserializer)?) | ||
.map_err(|e| D::Error::custom(format!("{}", e))) | ||
} | ||
} | ||
|
||
impl Serialize for Gas { | ||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { | ||
self.to_string().serialize(serializer) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
use serde::{Deserialize, Serialize}; | ||
use std::fmt::{self, Display}; | ||
|
||
/// ABCI info | ||
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] | ||
pub struct Info(String); | ||
|
||
impl AsRef<str> for Info { | ||
fn as_ref(&self) -> &str { | ||
self.0.as_ref() | ||
} | ||
} | ||
|
||
impl Display for Info { | ||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
write!(f, "{}", self.0) | ||
} | ||
} | ||
|
||
impl Default for Info { | ||
fn default() -> Self { | ||
Self(String::new()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
use serde::{Deserialize, Serialize}; | ||
use std::fmt; | ||
use std::fmt::Display; | ||
|
||
/// ABCI log data | ||
#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] | ||
#[serde(transparent)] | ||
pub struct Log(String); | ||
|
||
impl Log { | ||
/// Convenience function: get value | ||
pub fn value(&self) -> &String { | ||
&self.0 | ||
} | ||
} | ||
|
||
impl From<&str> for Log { | ||
fn from(s: &str) -> Self { | ||
Log(s.to_owned()) | ||
} | ||
} | ||
|
||
impl AsRef<str> for Log { | ||
fn as_ref(&self) -> &str { | ||
self.0.as_ref() | ||
} | ||
} | ||
|
||
impl Display for Log { | ||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
write!(f, "{}", self.0) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
//! Paths to ABCI data | ||
|
||
use crate::error::Error; | ||
use serde::{Deserialize, Serialize}; | ||
use std::{ | ||
fmt::{self, Display}, | ||
str::FromStr, | ||
}; | ||
|
||
/// Path to ABCI data | ||
#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] | ||
pub struct Path(String); | ||
|
||
impl Display for Path { | ||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
write!(f, "{}", &self.0) | ||
} | ||
} | ||
|
||
impl FromStr for Path { | ||
type Err = Error; | ||
|
||
fn from_str(s: &str) -> Result<Self, Error> { | ||
Ok(Path(s.to_owned())) | ||
} | ||
} |
Oops, something went wrong.