Skip to content

Commit

Permalink
Fix #241 evidence JSON format (#242)
Browse files Browse the repository at this point in the history
  • Loading branch information
yihuang committed Apr 29, 2020
1 parent 26d81be commit 2f29d7a
Show file tree
Hide file tree
Showing 4 changed files with 143 additions and 36 deletions.
52 changes: 17 additions & 35 deletions tendermint/src/evidence.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,50 +2,32 @@

use std::slice;
use {
crate::serializers,
serde::{de::Error as _, Deserialize, Deserializer, Serialize, Serializer},
subtle_encoding::base64,
crate::{serializers, PublicKey, Vote},
serde::{Deserialize, Serialize},
};

/// Evidence of malfeasance by validators (i.e. signing conflicting votes).
/// encoded using an Amino prefix. There is currently only a single type of
/// evidence: `DuplicateVoteEvidence`.
///
/// <https://github.com/tendermint/tendermint/blob/master/docs/spec/blockchain/blockchain.md#evidence>
#[derive(Clone, Debug)]
pub struct Evidence(Vec<u8>);

impl Evidence {
/// Create a new raw evidence value from a byte vector
pub fn new<V>(into_vec: V) -> Evidence
where
V: Into<Vec<u8>>,
{
// TODO(tarcieri): parse/validate evidence contents from amino messages
Evidence(into_vec.into())
}

/// Serialize this evidence as an Amino message bytestring
pub fn to_amino_bytes(&self) -> Vec<u8> {
self.0.clone()
}
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(tag = "type", content = "value")]
pub enum Evidence {
/// Duplicate vote evidence
#[serde(rename = "tendermint/DuplicateVoteEvidence")]
DuplicateVote(DuplicateVoteEvidence),
}

impl<'de> Deserialize<'de> for Evidence {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let bytes = base64::decode(String::deserialize(deserializer)?.as_bytes())
.map_err(|e| D::Error::custom(format!("{}", e)))?;

Ok(Evidence::new(bytes))
}
}

impl Serialize for Evidence {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
String::from_utf8(base64::encode(self.to_amino_bytes()))
.unwrap()
.serialize(serializer)
}
/// Duplicate vote evidence
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct DuplicateVoteEvidence {
#[serde(rename = "PubKey")]
pub_key: PublicKey,
#[serde(rename = "VoteA")]
vote_a: Vote,
#[serde(rename = "VoteB")]
vote_b: Vote,
}

/// Evidence data is a wrapper for a list of `Evidence`.
Expand Down
1 change: 0 additions & 1 deletion tendermint/src/rpc/endpoint/abci_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
use crate::serializers;
use crate::{block, rpc};
use serde::{Deserialize, Serialize};
use serde_bytes;

/// Request ABCI information from a node
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
Expand Down
13 changes: 13 additions & 0 deletions tendermint/tests/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,19 @@ mod endpoints {
assert_eq!(last_commit.unwrap().signatures.len(), 1);
}

#[test]
fn block_with_evidences() {
let response =
endpoint::block::Response::from_string(&read_json_fixture("block_with_evidences"))
.unwrap();

let tendermint::Block { evidence, .. } = response.block;
let evidence = evidence.iter().next().unwrap();
match evidence {
tendermint::evidence::Evidence::DuplicateVote(_) => {}
}
}

// TODO: Update this test and its json file
// #[test]
// fn block_empty_block_id() {
Expand Down
113 changes: 113 additions & 0 deletions tendermint/tests/support/rpc/block_with_evidences.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
{
"jsonrpc": "2.0",
"id": -1,
"result": {
"block_id": {
"hash": "649A276C615AD3B922A620ADBE5484DE9D87E2154469AE8F90DC40769350A52B",
"parts": {
"total": "1",
"hash": "D2A0D52E67AAD464122612577AD80049D785BC4DB9D0A992FC143C276B2B65DB"
}
},
"block": {
"header": {
"version": {
"block": "10",
"app": "0"
},
"chain_id": "test-chain-y3m1e6-AB",
"height": "22",
"time": "2020-04-28T15:48:20.640286Z",
"last_block_id": {
"hash": "B5F14F439A73EBDF8EF5222C957CFE6E15C95EE825C8B22E423464E675278C47",
"parts": {
"total": "1",
"hash": "C5A0FADCFFF5A69D088DE7BB6836C9C5DB7955B549509E548C296D2C099D2D5D"
}
},
"last_commit_hash": "6494B45CF9B18F150FE20D77DBFC598592E4B2B559071FA1E7346274A5AA544F",
"data_hash": "",
"validators_hash": "8AE7D181D0574535850924934C0B1B5BBB5E82F29B99B37A4BA6EBC92F0D97C9",
"next_validators_hash": "8AE7D181D0574535850924934C0B1B5BBB5E82F29B99B37A4BA6EBC92F0D97C9",
"consensus_hash": "048091BC7DDC283F77BFBF91D73C44DA58C3DF8A9CBC867405D8B7F3DAADA22F",
"app_hash": "48685380CBC6D4C0B31D9A226912FA6D72B4F0C7B3EE84000222D5AE0469AA8E",
"last_results_hash": "",
"evidence_hash": "CBC5FBCE18AE8A6043B9C64F913F708D641E58B811CD1B5BA03D2F6D0054DA0E",
"proposer_address": "9642515585D8F27423CE1BDDB91CD076862AFC63"
},
"data": {
"txs": null
},
"evidence": {
"evidence": [
{
"type": "tendermint/DuplicateVoteEvidence",
"value": {
"PubKey": {
"type": "tendermint/PubKeyEd25519",
"value": "MjQn17Z4VocTjeHm60JVjPV9A6hUTKYSNDTpQiglXlY="
},
"VoteA": {
"type": 1,
"height": "21",
"round": "0",
"block_id": {
"hash": "86EB9FCF52C4A81F2445157B0BF7AFBB107DF156D0853F38A019200F69465883",
"parts": {
"total": "1",
"hash": "B8F7219F14CB9EAA167A4E56FC8D2D4F3545C93A04357B33C34121C801D7E4F2"
}
},
"timestamp": "2020-04-28T15:48:20.368551Z",
"validator_address": "0F1F93CC25A6CFC083F54E4DA26F73B7F24DC85B",
"validator_index": "0",
"signature": "JDVzUjWVP9qWZJpKmN14FvmS4mXoLnwW7C1UjFtNQrVTQpL+ONg+IkYKGzVTDQtpOcGDbOLC2dbKvY/OToaWDA=="
},
"VoteB": {
"type": 1,
"height": "21",
"round": "0",
"block_id": {
"hash": "B5F14F439A73EBDF8EF5222C957CFE6E15C95EE825C8B22E423464E675278C47",
"parts": {
"total": "1",
"hash": "C5A0FADCFFF5A69D088DE7BB6836C9C5DB7955B549509E548C296D2C099D2D5D"
}
},
"timestamp": "2020-04-28T15:48:20.354851Z",
"validator_address": "0F1F93CC25A6CFC083F54E4DA26F73B7F24DC85B",
"validator_index": "0",
"signature": "gT2fdleX4BUzbAuUDazkbJBJ99HX7YgSTml7rumzWAm4hlOWtBGPe9BmkUF6Ypy8kzgMU/0P0D96KxCts5tpCQ=="
}
}
}
]
},
"last_commit": {
"height": "21",
"round": "0",
"block_id": {
"hash": "B5F14F439A73EBDF8EF5222C957CFE6E15C95EE825C8B22E423464E675278C47",
"parts": {
"total": "1",
"hash": "C5A0FADCFFF5A69D088DE7BB6836C9C5DB7955B549509E548C296D2C099D2D5D"
}
},
"signatures": [
{
"block_id_flag": 2,
"validator_address": "0F1F93CC25A6CFC083F54E4DA26F73B7F24DC85B",
"timestamp": "2020-04-28T15:48:20.640286Z",
"signature": "XMPZyI/KX9qTS6R3y4zz2tBwHFyII7VqqRj0D9vrLonIJffOsqU2m6Hk0mkcZmce9YUUi0BPHybfGn+li7goDg=="
},
{
"block_id_flag": 2,
"validator_address": "9642515585D8F27423CE1BDDB91CD076862AFC63",
"timestamp": "2020-04-28T15:48:20.570401Z",
"signature": "jieW+dsiGgQUTAG7LjdJQqomvrPyQR707HzOhXlUHaZ73xXRQxSpWXNZvWcqP8LwcNF2+ho5yt6NoAmYoCWPCQ=="
}
]
}
}
}
}

0 comments on commit 2f29d7a

Please sign in to comment.