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

tendermint-rs: Add tests for /block_results RPC endpoint #268

Merged
merged 1 commit into from
Jun 20, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions tendermint-rs/src/abci/gas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@ use std::{
#[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)
Expand Down
38 changes: 29 additions & 9 deletions tendermint-rs/src/abci/responses.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

use super::{code::Code, data::Data, gas::Gas, info::Info, log::Log};
use crate::{consensus, validator};
use serde::{Deserialize, Serialize};
use serde::{Deserialize, Deserializer, Serialize};
use std::fmt::{self, Display};

/// Responses for ABCI calls which occur during block processing.
Expand All @@ -11,24 +11,33 @@ use std::fmt::{self, Display};
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Responses {
/// Deliver TX response.
// TODO(tarcieri): remove the `rename` attribute when this lands upstream:
// TODO(tarcieri): remove the `alias` attribute when this lands upstream:
// <https://github.com/tendermint/tendermint/pull/3708/files>
#[serde(rename = "DeliverTx")]
pub deliver_tx: Option<DeliverTx>,
#[serde(alias = "DeliverTx")]
#[serde(default, deserialize_with = "deserialize_deliver_tx")]
pub deliver_tx: Vec<DeliverTx>,

/// Begin block response.
// TODO(tarcieri): remove the `rename` attribute when this lands upstream:
// TODO(tarcieri): remove the `alias` attribute when this lands upstream:
// <https://github.com/tendermint/tendermint/pull/3708/files>
#[serde(rename = "BeginBlock")]
#[serde(alias = "BeginBlock")]
pub begin_block: Option<BeginBlock>,

/// End block response.
// TODO(tarcieri): remove the `rename` attribute when this lands upstream:
// TODO(tarcieri): remove the `alias` attribute when this lands upstream:
// <https://github.com/tendermint/tendermint/pull/3708/files>
#[serde(rename = "EndBlock")]
#[serde(alias = "EndBlock")]
pub end_block: Option<EndBlock>,
}

/// Return an empty vec in the event `deliver_tx` is `null`
fn deserialize_deliver_tx<'de, D>(deserializer: D) -> Result<Vec<DeliverTx>, D::Error>
where
D: Deserializer<'de>,
{
Ok(Option::deserialize(deserializer)?.unwrap_or_default())
}

/// Deliver TX response.
///
/// This type corresponds to the `ResponseDeliverTx` proto from:
Expand Down Expand Up @@ -87,7 +96,8 @@ pub struct BeginBlock {
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct EndBlock {
/// Validator updates
pub validator_updates: Option<Vec<validator::Update>>,
#[serde(deserialize_with = "deserialize_validator_updates")]
pub validator_updates: Vec<validator::Update>,

/// New consensus params
pub consensus_param_updates: Option<consensus::Params>,
Expand All @@ -97,6 +107,16 @@ pub struct EndBlock {
pub tags: Vec<Tag>,
}

/// Return an empty vec in the event `validator_updates` is `null`
fn deserialize_validator_updates<'de, D>(
deserializer: D,
) -> Result<Vec<validator::Update>, D::Error>
where
D: Deserializer<'de>,
{
Ok(Option::deserialize(deserializer)?.unwrap_or_default())
}

/// Tags
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Tag {
Expand Down
38 changes: 36 additions & 2 deletions tendermint-rs/src/validator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
use crate::{account, vote, PublicKey};
#[cfg(feature = "serde")]
use serde::{de::Error as _, Deserialize, Deserializer, Serialize, Serializer};
#[cfg(feature = "rpc")]
use subtle_encoding::base64;

/// Validator information
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
Expand Down Expand Up @@ -57,12 +59,44 @@ impl Serialize for ProposerPriority {
}

/// Updates to the validator set
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, Debug)]
#[cfg(feature = "rpc")]
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Update {
/// Validator public key
#[serde(deserialize_with = "deserialize_public_key")]
pub pub_key: PublicKey,

/// New voting power
pub power: vote::Power,
}

/// Validator updates use a slightly different public key format than the one
/// implemented in `tendermint::PublicKey`.
///
/// This is an internal thunk type to parse the `validator_updates` format and
/// then convert to `tendermint::PublicKey`.
/// Public keys allowed in Tendermint protocols
#[cfg(feature = "rpc")]
#[derive(Serialize, Deserialize)]
#[serde(tag = "type", content = "data")]
enum PK {
/// Ed25519 keys
#[serde(rename = "ed25519")]
Ed25519(String),
}

#[cfg(feature = "rpc")]
fn deserialize_public_key<'de, D>(deserializer: D) -> Result<PublicKey, D::Error>
where
D: Deserializer<'de>,
{
match &PK::deserialize(deserializer)? {
PK::Ed25519(base64_value) => {
let bytes =
base64::decode(base64_value).map_err(|e| D::Error::custom(format!("{}", e)))?;

PublicKey::from_raw_ed25519(&bytes)
.ok_or_else(|| D::Error::custom("error parsing Ed25519 key"))
}
}
}
37 changes: 37 additions & 0 deletions tendermint-rs/tests/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,43 @@ mod endpoints {
assert_eq!(last_commit.precommits.len(), 65);
}

#[test]
fn block_results() {
let response =
endpoint::block_results::Response::from_json(&read_json_fixture("block_results"))
.unwrap();
assert_eq!(response.height.value(), 1814);

let tendermint::abci::Responses {
deliver_tx,
begin_block: _,
end_block,
} = response.results;

let log_json = &deliver_tx[0].log.as_ref().unwrap().parse_json().unwrap();
let log_json_value = &log_json.as_array().as_ref().unwrap()[0];

assert_eq!(log_json_value["msg_index"].as_str().unwrap(), "0");
assert_eq!(log_json_value["success"].as_bool().unwrap(), true);

assert_eq!(deliver_tx[0].gas_wanted.value(), 200000);
assert_eq!(deliver_tx[0].gas_used.value(), 105662);

let tag = deliver_tx[0]
.tags
.iter()
.find(|t| t.key.eq("ZGVzdGluYXRpb24tdmFsaWRhdG9y"))
.unwrap();

assert_eq!(
&tag.value,
"Y29zbW9zdmFsb3BlcjFlaDVtd3UwNDRnZDVudGtrYzJ4Z2ZnODI0N21nYzU2Zno0c2RnMw=="
);

let validator_update = &end_block.as_ref().unwrap().validator_updates[0];
assert_eq!(validator_update.power.value(), 1233243);
}

#[test]
fn blockchain() {
let response =
Expand Down
94 changes: 94 additions & 0 deletions tendermint-rs/tests/support/rpc/block_results.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
{
"jsonrpc": "2.0",
"id": "",
"result": {
"height": "1814",
"results": {
"DeliverTx": [
{
"log": "[{\"msg_index\":\"0\",\"success\":true,\"log\":\"\"}]",
"gasWanted": "200000",
"gasUsed": "105662",
"tags": [
{
"key": "YWN0aW9u",
"value": "ZGVsZWdhdGU="
},
{
"key": "ZGVsZWdhdG9y",
"value": "Y29zbW9zMW53eWV5cXVkenJ1NWw2NGU4M2RubXE3OXE0c3Rxejdmd2w1djVh"
},
{
"key": "ZGVzdGluYXRpb24tdmFsaWRhdG9y",
"value": "Y29zbW9zdmFsb3BlcjFlaDVtd3UwNDRnZDVudGtrYzJ4Z2ZnODI0N21nYzU2Zno0c2RnMw=="
}
]
},
{
"log": "[{\"msg_index\":\"0\",\"success\":true,\"log\":\"\"}]",
"gasWanted": "99164",
"gasUsed": "99164",
"tags": [
{
"key": "YWN0aW9u",
"value": "ZGVsZWdhdGU="
},
{
"key": "ZGVsZWdhdG9y",
"value": "Y29zbW9zMTBhN2V2eXlkY2s0Mm5odGE5M3RubXY3eXU0aGFxenQ5NHh5dTU0"
},
{
"key": "ZGVzdGluYXRpb24tdmFsaWRhdG9y",
"value": "Y29zbW9zdmFsb3BlcjF1cnRweHdmdXU4azU3YXF0MGg1emhzdm1qdDRtMm1tZHIwanV6Zw=="
}
]
},
{
"log": "[{\"msg_index\":\"0\",\"success\":true,\"log\":\"\"}]",
"gasWanted": "200000",
"gasUsed": "106515",
"tags": [
{
"key": "YWN0aW9u",
"value": "ZGVsZWdhdGU="
},
{
"key": "ZGVsZWdhdG9y",
"value": "Y29zbW9zMXFtcmNqenNrZ3Rsd21mczlwcWRyZnBtcDVsNWM4cDVyM3kzZTl0"
},
{
"key": "ZGVzdGluYXRpb24tdmFsaWRhdG9y",
"value": "Y29zbW9zdmFsb3BlcjFzeHg5bXN6dmUwZ2FlZHo1bGQ3cWRramtmdjh6OTkyYXg2OWswOA=="
}
]
}
],
"EndBlock": {
"validator_updates": [
{
"pub_key": {
"type": "ed25519",
"data": "lObsqlAjmPsnBfBE+orb8vBbKrH2G5VskSUlAq/YcXc="
},
"power": "1233243"
},
{
"pub_key": {
"type": "ed25519",
"data": "PflSgb+lC1GI22wc6N/54cNzD7KSYQyCWR5LuQxjYVY="
},
"power": "1194975"
},
{
"pub_key": {
"type": "ed25519",
"data": "AmPqEmF5YNmlv2vu8lEcDeQ3hyR+lymnqx2VixdMEzA="
},
"power": "12681"
}
]
},
"BeginBlock": {}
}
}
}