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

Commit

Permalink
Merge pull request #268 from tendermint/tendermint-rs/block-results-test
Browse files Browse the repository at this point in the history
tendermint-rs: Add tests for `/block_results` RPC endpoint
  • Loading branch information
tarcieri authored Jun 20, 2019
2 parents 45d5261 + 3e1c142 commit 7fa19fd
Show file tree
Hide file tree
Showing 5 changed files with 203 additions and 11 deletions.
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": {}
}
}
}

0 comments on commit 7fa19fd

Please sign in to comment.