Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rpc: Add temporary fix and tests for block_results serialization #1061

Merged
merged 16 commits into from
Dec 20, 2021
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
4 changes: 4 additions & 0 deletions .changelog/unreleased/workarounds/1021-rpc-block_results.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
- `[tendermint-rpc]` Allow deserialization of public keys from validator updates
from `block_results` endpoint in multiple JSON formats until this is fixed in
Tendermint
([#1021](https://github.com/informalsystems/tendermint-rs/issues/1021))
3 changes: 2 additions & 1 deletion proto/src/prost/tendermint.abci.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,9 +228,10 @@ pub struct ResponseInfo {
#[prost(string, tag="1")]
pub data: ::prost::alloc::string::String,
#[prost(string, tag="2")]
#[serde(default)]
pub version: ::prost::alloc::string::String,
#[prost(uint64, tag="3")]
#[serde(with = "crate::serializers::from_str")]
#[serde(with = "crate::serializers::from_str", default)]
pub app_version: u64,
#[prost(int64, tag="4")]
#[serde(with = "crate::serializers::from_str")]
Expand Down
21 changes: 11 additions & 10 deletions rpc/src/client/transport/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,9 +239,11 @@ mod test {
use tokio::fs;

async fn read_json_fixture(name: &str) -> String {
fs::read_to_string(PathBuf::from("./tests/support/").join(name.to_owned() + ".json"))
.await
.unwrap()
fs::read_to_string(
PathBuf::from("./tests/kvstore_fixtures/incoming/").join(name.to_owned() + ".json"),
)
.await
.unwrap()
}

async fn read_event(name: &str) -> Event {
Expand All @@ -251,20 +253,19 @@ mod test {
#[tokio::test]
async fn mock_client() {
let abci_info_fixture = read_json_fixture("abci_info").await;
let block_fixture = read_json_fixture("block").await;
let block_fixture = read_json_fixture("block_at_height_10").await;
let matcher = MockRequestMethodMatcher::default()
.map(Method::AbciInfo, Ok(abci_info_fixture))
.map(Method::Block, Ok(block_fixture));
let (client, driver) = MockClient::new(matcher);
let driver_hdl = tokio::spawn(async move { driver.run().await });

let abci_info = client.abci_info().await.unwrap();
assert_eq!("GaiaApp".to_string(), abci_info.data);
assert_eq!(Height::from(488120_u32), abci_info.last_block_height);
assert_eq!("{\"size\":0}".to_string(), abci_info.data);

let block = client.block(Height::from(10_u32)).await.unwrap().block;
assert_eq!(Height::from(10_u32), block.header.height);
assert_eq!("cosmoshub-2".parse::<Id>().unwrap(), block.header.chain_id);
assert_eq!("dockerchain".parse::<Id>().unwrap(), block.header.chain_id);

client.close();
driver_hdl.await.unwrap().unwrap();
Expand All @@ -275,9 +276,9 @@ mod test {
let (client, driver) = MockClient::new(MockRequestMethodMatcher::default());
let driver_hdl = tokio::spawn(async move { driver.run().await });

let event1 = read_event("event_new_block_1").await;
let event2 = read_event("event_new_block_2").await;
let event3 = read_event("event_new_block_3").await;
let event1 = read_event("subscribe_newblock_0").await;
let event2 = read_event("subscribe_newblock_1").await;
let event3 = read_event("subscribe_newblock_2").await;
let events = vec![event1, event2, event3];

let subs1 = client.subscribe(EventType::NewBlock.into()).await.unwrap();
Expand Down
10 changes: 6 additions & 4 deletions rpc/src/client/transport/router.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,9 +147,11 @@ mod test {
use tokio::time::{self, Duration};

async fn read_json_fixture(name: &str) -> String {
fs::read_to_string(PathBuf::from("./tests/support/").join(name.to_owned() + ".json"))
.await
.unwrap()
fs::read_to_string(
PathBuf::from("./tests/kvstore_fixtures/incoming/").join(name.to_owned() + ".json"),
)
.await
.unwrap()
}

async fn read_event(name: &str) -> Event {
Expand Down Expand Up @@ -193,7 +195,7 @@ mod test {
// Another subscription with a different query
router.add(subs3_id, "query2", subs3_event_tx);

let mut ev = read_event("event_new_block_1").await;
let mut ev = read_event("subscribe_newblock_0").await;
ev.query = "query1".into();
router.publish_event(ev.clone());

Expand Down
14 changes: 8 additions & 6 deletions rpc/src/client/transport/websocket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1094,9 +1094,11 @@ mod test {
}

async fn read_json_fixture(name: &str) -> String {
fs::read_to_string(PathBuf::from("./tests/support/").join(name.to_owned() + ".json"))
.await
.unwrap()
fs::read_to_string(
PathBuf::from("./tests/kvstore_fixtures/incoming/").join(name.to_owned() + ".json"),
)
.await
.unwrap()
}

async fn read_event(name: &str) -> Event {
Expand All @@ -1105,9 +1107,9 @@ mod test {

#[tokio::test]
async fn websocket_client_happy_path() {
let event1 = read_event("event_new_block_1").await;
let event2 = read_event("event_new_block_2").await;
let event3 = read_event("event_new_block_3").await;
let event1 = read_event("subscribe_newblock_0").await;
let event2 = read_event("subscribe_newblock_1").await;
let event3 = read_event("subscribe_newblock_2").await;
let test_events = vec![event1, event2, event3];

println!("Starting WebSocket server...");
Expand Down
8 changes: 7 additions & 1 deletion rpc/src/request.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! JSON-RPC requests

use super::{Id, Method, Version};
use crate::prelude::*;
use crate::{prelude::*, Error};
use core::fmt::Debug;
use serde::{de::DeserializeOwned, Deserialize, Serialize};

Expand All @@ -17,6 +17,12 @@ pub trait Request: Debug + DeserializeOwned + Serialize + Sized + Send {
fn into_json(self) -> String {
Wrapper::new(self).into_json()
}

/// Parse a JSON-RPC request from a JSON string.
fn from_string(s: impl AsRef<[u8]>) -> Result<Self, Error> {
let wrapper: Wrapper<Self> = serde_json::from_slice(s.as_ref()).map_err(Error::serde)?;
Ok(wrapper.params)
}
}

/// Simple JSON-RPC requests which correlate with a single response from the
Expand Down
163 changes: 163 additions & 0 deletions rpc/tests/gaia_fixtures.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
use std::fs;
use std::path::PathBuf;
use tendermint_rpc::event::Event;
use tendermint_rpc::{endpoint, Request, Response};
use walkdir::WalkDir;

fn find_fixtures(in_out_folder_name: &str) -> Vec<PathBuf> {
WalkDir::new(
PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("tests")
.join("gaia_fixtures")
.join(in_out_folder_name),
)
.into_iter()
.filter_map(|e| e.ok())
.filter(|e| {
e.file_type().is_file()
&& e.path().extension().is_some()
&& e.path().extension().unwrap() == "json"
})
.map(|e| e.into_path())
.collect::<Vec<PathBuf>>()
}

#[test]
fn incoming_fixtures() {
for json_file in find_fixtures("incoming") {
let file_name = json_file
.file_name()
.unwrap()
.to_str()
.unwrap()
.strip_suffix(".json")
.unwrap();
let content = fs::read_to_string(&json_file).unwrap();
match file_name {
"abci_info" => {
let r = endpoint::abci_info::Response::from_string(content);
assert!(r.is_ok(), "{:?}", r)
}
"block_at_height_0" => {
assert!(endpoint::block::Response::from_string(content).is_err())
}
"block_at_height_1" => {
assert!(endpoint::block::Response::from_string(content).is_ok())
}
"block_at_height_10" => {
assert!(endpoint::block::Response::from_string(content).is_ok())
}
"block_at_height_4555980" => {
let r = endpoint::block::Response::from_string(content);
assert!(r.is_ok(), "{:?}", r);
}
"block_results_at_height_10" => {
let r = endpoint::block_results::Response::from_string(content);
assert!(r.is_ok(), "block_results_at_height_10: {:?}", r);
}
"block_results_at_height_4555980" => {
let r = endpoint::block_results::Response::from_string(content);
assert!(r.is_ok(), "block_results_at_height_4555980: {:?}", r);
}
"blockchain_from_1_to_10" => {
assert!(endpoint::blockchain::Response::from_string(content).is_ok())
}
"commit_at_height_10" => {
assert!(endpoint::commit::Response::from_string(content).is_ok())
}
"consensus_params" => {
assert!(endpoint::consensus_params::Response::from_string(content).is_ok())
}
"consensus_state" => {
assert!(endpoint::consensus_state::Response::from_string(content).is_ok())
}
"genesis" => {
assert!(endpoint::genesis::Response::from_string(content).is_ok())
}
"net_info" => {
assert!(endpoint::net_info::Response::from_string(content).is_ok())
}
"status" => {
assert!(endpoint::status::Response::from_string(content).is_ok())
}
"subscribe_newblock" => {
let r = endpoint::subscribe::Response::from_string(content);
assert!(r.is_err(), "{:?}", r);
}
_ => {
if file_name.starts_with("subscribe_newblock_") {
let r = Event::from_string(content);
assert!(r.is_ok(), "failed to parse event {}: {:?}", file_name, r);
} else {
panic!("unhandled incoming fixture: {}", file_name);
}
}
}
}
}

#[test]
fn outgoing_fixtures() {
for json_file in find_fixtures("outgoing") {
let file_name = json_file
.file_name()
.unwrap()
.to_str()
.unwrap()
.strip_suffix(".json")
.unwrap();
let content = fs::read_to_string(&json_file).unwrap();
match file_name {
"abci_info" => {
let r = endpoint::abci_info::Request::from_string(content);
assert!(r.is_ok(), "{:?}", r)
}
"block_at_height_0" => {
assert!(endpoint::block::Request::from_string(content).is_ok())
}
"block_at_height_1" => {
assert!(endpoint::block::Request::from_string(content).is_ok())
}
"block_at_height_10" => {
assert!(endpoint::block::Request::from_string(content).is_ok())
}
"block_at_height_4555980" => {
assert!(endpoint::block::Request::from_string(content).is_ok())
}
"block_results_at_height_10" => {
let r = endpoint::block_results::Request::from_string(content);
assert!(r.is_ok(), "block_results_at_height_10: {:?}", r);
}
"block_results_at_height_4555980" => {
let r = endpoint::block_results::Request::from_string(content);
assert!(r.is_ok(), "block_results_at_height_4555980: {:?}", r);
}
"blockchain_from_1_to_10" => {
assert!(endpoint::blockchain::Request::from_string(content).is_ok())
}
"commit_at_height_10" => {
assert!(endpoint::commit::Request::from_string(content).is_ok())
}
"consensus_params" => {
assert!(endpoint::consensus_params::Request::from_string(content).is_ok())
}
"consensus_state" => {
assert!(endpoint::consensus_state::Request::from_string(content).is_ok())
}
"genesis" => {
assert!(endpoint::genesis::Request::from_string(content).is_ok())
}
"net_info" => {
assert!(endpoint::net_info::Request::from_string(content).is_ok())
}
"status" => {
assert!(endpoint::status::Request::from_string(content).is_ok())
}
"subscribe_newblock" => {
let r = endpoint::subscribe::Request::from_string(content);
assert!(r.is_ok(), "{:?}", r);
}
_ => panic!("unhandled outgoing fixture: {}", file_name),
}
}
}
11 changes: 11 additions & 0 deletions rpc/tests/gaia_fixtures/incoming/abci_info.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"id": "279cb095-9064-4620-bcaa-3c9383847575",
"jsonrpc": "2.0",
"result": {
"response": {
"data": "GaiaApp",
"last_block_app_hash": "vMfcSlXF/bB/xdsaQeFALAzVoY6AKqiFwchFz9ZUguc=",
"last_block_height": "154"
}
}
}
9 changes: 9 additions & 0 deletions rpc/tests/gaia_fixtures/incoming/block_at_height_0.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"error": {
"code": -32603,
"data": "height must be greater than 0, but got 0",
"message": "Internal error"
},
"id": "29b5f462-d1cb-4b33-ab23-f0c96aa462b0",
"jsonrpc": "2.0"
}
57 changes: 57 additions & 0 deletions rpc/tests/gaia_fixtures/incoming/block_at_height_1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
{
"id": "6b12587c-a02b-441b-9350-6a8a5ee6fb3b",
"jsonrpc": "2.0",
"result": {
"block": {
"data": {
"txs": []
},
"evidence": {
"evidence": []
},
"header": {
"app_hash": "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855",
"chain_id": "ibc-0",
"consensus_hash": "048091BC7DDC283F77BFBF91D73C44DA58C3DF8A9CBC867405D8B7F3DAADA22F",
"data_hash": "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855",
"evidence_hash": "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855",
"height": "1",
"last_block_id": {
"hash": "",
"parts": {
"hash": "",
"total": 0
}
},
"last_commit_hash": "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855",
"last_results_hash": "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855",
"next_validators_hash": "0A6CA9001DB07E985DF9043045B392588DF7C1C720E30EBAEFDC8A848C551D6A",
"proposer_address": "BB22AD764B674CC08753B24175E2FC61B22B1419",
"time": "2021-12-17T20:27:28.966992937Z",
"validators_hash": "0A6CA9001DB07E985DF9043045B392588DF7C1C720E30EBAEFDC8A848C551D6A",
"version": {
"block": "11"
}
},
"last_commit": {
"block_id": {
"hash": "",
"parts": {
"hash": "",
"total": 0
}
},
"height": "0",
"round": 0,
"signatures": []
}
},
"block_id": {
"hash": "739127E7942BEF14DFF0C3C9C4A9BF0DF1A97BEFF085153817B8960273830439",
"parts": {
"hash": "AF225F2883AFC75DB7F481E5BDEE396CE9B5787399F8F9876CA980BD026C02D1",
"total": 1
}
}
}
}
Loading