diff --git a/tendermint/src/evidence.rs b/tendermint/src/evidence.rs index d274e60d2..86b2eafc8 100644 --- a/tendermint/src/evidence.rs +++ b/tendermint/src/evidence.rs @@ -2,9 +2,8 @@ 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). @@ -12,40 +11,23 @@ use { /// evidence: `DuplicateVoteEvidence`. /// /// -#[derive(Clone, Debug)] -pub struct Evidence(Vec); - -impl Evidence { - /// Create a new raw evidence value from a byte vector - pub fn new(into_vec: V) -> Evidence - where - V: Into>, - { - // 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 { - 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>(deserializer: D) -> Result { - 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(&self, serializer: S) -> Result { - 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`. diff --git a/tendermint/src/rpc/endpoint/abci_info.rs b/tendermint/src/rpc/endpoint/abci_info.rs index d40032621..ce0a621c6 100644 --- a/tendermint/src/rpc/endpoint/abci_info.rs +++ b/tendermint/src/rpc/endpoint/abci_info.rs @@ -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)] diff --git a/tendermint/tests/rpc.rs b/tendermint/tests/rpc.rs index 853d4293f..1aec471eb 100644 --- a/tendermint/tests/rpc.rs +++ b/tendermint/tests/rpc.rs @@ -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() { diff --git a/tendermint/tests/support/rpc/block_with_evidences.json b/tendermint/tests/support/rpc/block_with_evidences.json new file mode 100644 index 000000000..194a20bdc --- /dev/null +++ b/tendermint/tests/support/rpc/block_with_evidences.json @@ -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==" + } + ] + } + } + } +}