Skip to content

Commit

Permalink
Tendermint/v0.33 (#196)
Browse files Browse the repository at this point in the history
* initial new commit struct

* update functions

* fixed deserialization for new commit struct

* updated links to generator + val_set_test file

* Ismail/commit struct followup (#182)

* initial new commit struct

* update functions

* fixed deserialization for new commit struct

* updated links to generator + val_set_test file

* Update tendermint/src/account.rs

Co-Authored-By: Ismail Khoffi <[email protected]>

* fmt

* clippy

* rpc tests: grab latest example fro commit:
 - use https://docs.tendermint.com/master/rpc/#/Info/commit
 - update chain_id: cosmoshub-1 to cosmoshub-2 everywhere else
 - manually kept `id` a string in JSONrpc responses

* Actually let's go cosmoshub-3:

 - grabbed from: https://rpc.cosmos.network/commit?height=2

* Fix commit test

- regenerated commit.json via
`curl -X GET "http://localhost:26657/commit?height=10" -H "accept: application/json"`

* Fix block test

- "regenerated" block.json via
`curl -X GET "http://localhost:26657/block?height=10" -H "accept: application/json"`

* Fix first_block test

- "regenerated" block.json via
`curl -X GET "http://localhost:26657/block?height=1" -H "accept: application/json" `

Co-authored-by: Shivani Joshi <[email protected]>
Co-authored-by: Shivani Joshi <[email protected]>

* fix error

* more json bisection tests

* abci_info struct app_version implemented

* Fixed fmt

* Updated integration tests to tendermint v0.33 node

* update block result response

* changes to abci_info and block_results

* Removed CircleCI reference and added codecov reference to Cargo

* removing unwanted Option from DeliverTx struct fields

* last_block_app_hash is now Option<Vec<u8>>

* AbciInfo.last_block_app_hash is base64 encoded instead of hex

* last_block_app_hash changed to Vec<u8>

* Cherry-pick from 87e888b (Liamsi)
fix /abci_info & /genesis:
 - add app_version & use #[serde(default)] to deal with omitted fields in JSON
 - make app_state in /genesis reply optional
 - fix string in abci_info test (kvstore wont reply with "GaiaApp")

 verify tests pass via running `tendermint node --proxy_app=kvstore` and
 `cargo test -- --nocapture --ignored

* [88] Fix JSON ID

* [192] Fix abci_info compatibility for v0.33

* [4] block_results test fix

* [184][120] Tendermint v0.33 compatibility fixes + integration tests for CI

* Added one abci_query test

* FMT + get rid of warnings

* Relaxed genesis struct AppHash requirements from strict hex to anything

* Removed unused Protocol struct

* Removed unused Protocol struct

* IdType removed and JSON ID made as enum

* Duration looks better now

* fix fmt

* Update tendermint/src/lite_impl/signed_header.rs

Co-Authored-By: Ismail Khoffi <[email protected]>

* Update tendermint/src/lite_impl/signed_header.rs

Co-Authored-By: Ismail Khoffi <[email protected]>

* Removed AsRef from JSON ID

* Update Proof and ProofOp (#206)

* manually update Proof and introduce ProofOp to match the actual JSON encoding

* 0.33 branch seems out of date with master, committing to switch back

* Fix test

* Fix rpc endpoint test (how wasn't this detected before by the integration tests)?

* Add missing serializer for TrustThresholdFraction fields (#210)

* commit followup (#199)

* rename iter -> signed_votes and add validation checks

 - add basic validation to validate method (depending on `BlockIDFlag`)
 - move check for unknown validator to validate method (for CommitSig)

Co-authored-by: Shivani Joshi <[email protected]>
Co-authored-by: Ismail Khoffi <[email protected]>
Co-authored-by: Shivani Joshi <[email protected]>
Co-authored-by: Romain Ruetschi <[email protected]>
  • Loading branch information
5 people authored Apr 21, 2020
1 parent 56400a3 commit 3003fef
Show file tree
Hide file tree
Showing 47 changed files with 18,872 additions and 15,939 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ jobs:
runs-on: ubuntu-latest
services:
tendermint:
image: interchainio/tendermint
image: tendermint/tendermint
ports:
- 26656:26656
- 26657:26657
Expand Down
3 changes: 2 additions & 1 deletion tendermint/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ authors = [
all-features = true

[badges]
circle-ci = { repository = "interchainio/tendermint-rs" }
codecov = { repository = "..."}

[dependencies]
anomaly = "0.2"
Expand All @@ -44,6 +44,7 @@ prost-amino = "0.5"
prost-amino-derive = "0.5"
serde = { version = "1", features = ["derive"] }
serde_json = { version = "1" }
serde_bytes = "0.11"
sha2 = { version = "0.8", default-features = false }
signatory = { version = "0.19", features = ["ed25519", "ecdsa"] }
signatory-dalek = "0.19"
Expand Down
13 changes: 10 additions & 3 deletions tendermint/src/abci.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,18 @@ mod info;
mod log;
mod path;
mod proof;
mod responses;
pub mod responses;
pub mod tag;
pub mod transaction;

pub use self::{
code::Code, data::Data, gas::Gas, info::Info, log::Log, path::Path, proof::Proof,
responses::Responses, transaction::Transaction,
code::Code,
data::Data,
gas::Gas,
info::Info,
log::Log,
path::Path,
proof::Proof,
responses::{DeliverTx, Event, Responses},
transaction::Transaction,
};
96 changes: 53 additions & 43 deletions tendermint/src/abci/proof.rs
Original file line number Diff line number Diff line change
@@ -1,51 +1,61 @@
//! ABCI Merkle proofs

use crate::error::Error;
use serde::{de::Error as _, Deserialize, Deserializer, Serialize, Serializer};
use std::{
fmt::{self, Display},
str::FromStr,
};
use subtle_encoding::{Encoding, Hex};

/// ABCI Merkle proofs
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct Proof(Vec<u8>);

impl AsRef<[u8]> for Proof {
fn as_ref(&self) -> &[u8] {
self.0.as_ref()
}
}

impl Display for Proof {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{}",
&Hex::upper_case().encode_to_string(&self.0).unwrap()
)
}
use crate::serializers;
use serde::{Deserialize, Serialize};

/// Proof is Merkle proof defined by the list of ProofOps
#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
pub struct Proof {
/// The list of ProofOps
pub ops: Vec<ProofOp>,
}

impl FromStr for Proof {
type Err = Error;

fn from_str(s: &str) -> Result<Self, Error> {
let bytes = Hex::upper_case().decode(s)?;
Ok(Proof(bytes))
}
}

impl<'de> Deserialize<'de> for Proof {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let hex = String::deserialize(deserializer)?;
Ok(Self::from_str(&hex).map_err(|e| D::Error::custom(format!("{}", e)))?)
}
/// ProofOp defines an operation used for calculating Merkle root
/// The data could be arbitrary format, providing necessary data
/// for example neighbouring node hash
#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
pub struct ProofOp {
/// Type of the ProofOp
#[serde(alias = "type")]
pub field_type: String,
/// Key of the ProofOp
#[serde(
default,
serialize_with = "serializers::serialize_base64",
deserialize_with = "serializers::parse_base64"
)]
pub key: Vec<u8>,
/// Actual data
#[serde(
default,
serialize_with = "serializers::serialize_base64",
deserialize_with = "serializers::parse_base64"
)]
pub data: Vec<u8>,
}

impl Serialize for Proof {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
self.to_string().serialize(serializer)
#[cfg(test)]
mod test {
use super::Proof;
use crate::test::test_serialization_roundtrip;

#[test]
fn serialization_roundtrip() {
let payload = r#"
{
"ops": [
{
"type": "iavl:v",
"key": "Y29uc2Vuc3VzU3RhdGUvaWJjb25lY2xpZW50LzIy",
"data": "8QEK7gEKKAgIEAwYHCIgG9RAkJgHlxNjmyzOW6bUAidhiRSja0x6+GXCVENPG1oKKAgGEAUYFyIgwRns+dJvjf1Zk2BaFrXz8inPbvYHB7xx2HCy9ima5f8KKAgEEAMYFyogOr8EGajEV6fG5fzJ2fAAvVMgRLhdMJTzCPlogl9rxlIKKAgCEAIYFyIgcjzX/a+2bFbnNldpawQqZ+kYhIwz5r4wCUzuu1IFW04aRAoeY29uc2Vuc3VzU3RhdGUvaWJjb25lY2xpZW50LzIyEiAZ1uuG60K4NHJZZMuS9QX6o4eEhica5jIHYwflRiYkDBgX"
},
{
"type": "multistore",
"key": "aWJj",
"data": "CvEECjAKBGJhbmsSKAomCIjYAxIg2MEyyonbZButYnvSRkf2bPQg+nqA+Am1MeDxG6F4p1UKLwoDYWNjEigKJgiI2AMSIN2YHczeuXNvyetrSFQpkCcJzfB6PXVCw0i/XShMgPnIChEKB3VwZ3JhZGUSBgoECIjYAwovCgNnb3YSKAomCIjYAxIgYM0TfBli7KxhY4nWgDSDPykhUJwtKFql9RU5l86WinQKLwoDaWJjEigKJgiI2AMSIFp6aJASeInQKF8y824zjmgcFORN6M+ECbgFfJkobKs8CjAKBG1haW4SKAomCIjYAxIgsZzwmLQ7PH1UeZ/vCUSqlQmfgt3CGfoMgJLkUqKCv0EKMwoHc3Rha2luZxIoCiYIiNgDEiCiBZoBLyDGj5euy3n33ik+SpqYK9eB5xbI+iY8ycYVbwo0CghzbGFzaGluZxIoCiYIiNgDEiAJz3gEYuIhdensHU3b5qH5ons2quepd6EaRgCHXab6PQoyCgZzdXBwbHkSKAomCIjYAxIglWLA5/THPTiTxAlaLHOBYFIzEJTmKPznItUwAc8zD+AKEgoIZXZpZGVuY2USBgoECIjYAwowCgRtaW50EigKJgiI2AMSIMS8dZ1j8F6JVVv+hB1rHBZC+gIFJxHan2hM8qDC64n/CjIKBnBhcmFtcxIoCiYIiNgDEiB8VIzExUHX+SvHZFz/P9NM9THnw/gTDDLVReuZX8htLgo4CgxkaXN0cmlidXRpb24SKAomCIjYAxIg3u/Nd4L+8LT8OXJCh14o8PHIJ/GLQwsmE7KYIl1GdSYKEgoIdHJhbnNmZXISBgoECIjYAw=="
}
]
}"#;
test_serialization_roundtrip::<Proof>(payload);
}
}
32 changes: 20 additions & 12 deletions tendermint/src/abci/responses.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,36 +42,44 @@ where
///
/// This type corresponds to the `ResponseDeliverTx` proto from:
///
/// <https://github.com/tendermint/tendermint/blob/develop/abci/types/types.proto>
/// <https://github.com/tendermint/tendermint/blob/master/abci/types/types.proto>
// TODO(tarcieri): generate this automatically from the proto
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct DeliverTx {
/// ABCI application response code
pub code: Option<Code>,
pub code: Code,

/// ABCI application data
pub data: Option<Data>,
pub data: Data,

/// ABCI log data (nondeterministic)
pub log: Option<Log>,
pub log: Log,

/// ABCI info (nondeterministic)
pub info: Option<Info>,
pub info: Info,

/// Amount of gas wanted
#[serde(default, rename = "gasWanted")]
pub gas_wanted: Gas,

/// Amount of gas used
#[serde(default, rename = "gasUsed")]
pub gas_used: Gas,

/// Tags
#[serde(default)]
pub tags: Vec<Tag>,
/// Events
pub events: Vec<Event>,

/// Codespace
pub codespace: Option<Codespace>,
pub codespace: Codespace,
}

/// Event
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Event {
/// Event type
#[serde(rename = "type")]
pub type_str: String,

/// Attributes
pub attributes: Vec<Tag>,
}

/// Begin block response.
Expand Down Expand Up @@ -108,7 +116,7 @@ pub struct EndBlock {
}

/// Return an empty vec in the event `validator_updates` is `null`
fn deserialize_validator_updates<'de, D>(
pub fn deserialize_validator_updates<'de, D>(
deserializer: D,
) -> Result<Vec<validator::Update>, D::Error>
where
Expand Down
2 changes: 1 addition & 1 deletion tendermint/src/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use subtle::{self, ConstantTimeEq};
use subtle_encoding::hex;

/// Size of an account ID in bytes
const LENGTH: usize = 20;
pub const LENGTH: usize = 20;

/// Account IDs
#[derive(Copy, Clone, Eq, Hash, PartialEq, PartialOrd, Ord)]
Expand Down
18 changes: 14 additions & 4 deletions tendermint/src/block.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! Blocks within the chains of a Tendermint network

mod commit;
pub mod commit_sig;
pub mod header;
mod height;
mod id;
Expand All @@ -11,6 +12,7 @@ mod size;

pub use self::{
commit::*,
commit_sig::*,
header::Header,
height::*,
id::{Id, ParseId},
Expand Down Expand Up @@ -46,18 +48,26 @@ where
{
#[derive(Deserialize)]
struct TmpCommit {
pub height: Height,
#[serde(
serialize_with = "serializers::serialize_u64",
deserialize_with = "serializers::parse_u64"
)]
pub round: u64,
#[serde(deserialize_with = "serializers::parse_non_empty_block_id")]
block_id: Option<Id>,
precommits: Option<Precommits>,
pub block_id: Option<Id>,
pub signatures: Option<CommitSigs>,
}

let commit = TmpCommit::deserialize(deserializer)?;
if commit.block_id.is_none() || commit.precommits.is_none() {
if commit.block_id.is_none() || commit.signatures.is_none() {
Ok(None)
} else {
Ok(Some(Commit {
height: commit.height,
round: commit.round,
block_id: commit.block_id.unwrap(),
precommits: commit.precommits.unwrap(),
signatures: commit.signatures.unwrap(),
}))
}
}
58 changes: 35 additions & 23 deletions tendermint/src/block/commit.rs
Original file line number Diff line number Diff line change
@@ -1,62 +1,74 @@
//! Commits to a Tendermint blockchain

use crate::{block, Vote};
use crate::block::commit_sig::CommitSig;
use crate::block::{Height, Id};
use crate::serializers;
use serde::{Deserialize, Serialize};
use std::{ops::Deref, slice};

/// Commit contains the justification (ie. a set of signatures) that a block was committed by a set
/// of validators.
///
/// TODO: Update links below!
/// <https://github.com/tendermint/tendermint/blob/51dc810d041eaac78320adc6d53ad8b160b06601/types/block.go#L486-L502>
/// <https://github.com/tendermint/tendermint/blob/master/docs/spec/blockchain/blockchain.md#lastcommit>
#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
pub struct Commit {
/// Block ID of the last commit
pub block_id: block::Id,
/// Block height
pub height: Height,

/// Precommits
pub precommits: Precommits,
/// Round
#[serde(
serialize_with = "serializers::serialize_u64",
deserialize_with = "serializers::parse_u64"
)]
pub round: u64,

/// Block ID
pub block_id: Id,

/// Signatures
pub signatures: CommitSigs,
}

/// Precommits which certify that a block is valid
/// CommitSigs which certify that a block is valid
#[derive(Serialize, Deserialize, Clone, Debug, Default)]
pub struct Precommits(Vec<Option<Vote>>);
pub struct CommitSigs(Vec<CommitSig>);

impl Precommits {
/// Create a new precommit collection
pub fn new<I>(into_precommits: I) -> Self
impl CommitSigs {
/// Create a new CommitSig collection
pub fn new<I>(into_commit_sigs: I) -> Self
where
I: Into<Vec<Option<Vote>>>,
I: Into<Vec<CommitSig>>,
{
Self(into_precommits.into())
Self(into_commit_sigs.into())
}

/// Convert this collection of precommits into a vector
pub fn into_vec(self) -> Vec<Option<Vote>> {
/// Convert this collection of CommitSigs into a vector
pub fn into_vec(self) -> Vec<CommitSig> {
self.0
}

/// Iterate over the precommits in the collection
pub fn iter(&self) -> slice::Iter<'_, Option<Vote>> {
/// Iterate over the CommitSigs in the collection
pub fn iter(&self) -> slice::Iter<'_, CommitSig> {
self.0.iter()
}
}

impl AsRef<[Option<Vote>]> for Precommits {
fn as_ref(&self) -> &[Option<Vote>] {
impl AsRef<[CommitSig]> for CommitSigs {
fn as_ref(&self) -> &[CommitSig] {
self.0.as_slice()
}
}

impl Deref for Precommits {
type Target = [Option<Vote>];
impl Deref for CommitSigs {
type Target = [CommitSig];

fn deref(&self) -> &[Option<Vote>] {
fn deref(&self) -> &[CommitSig] {
self.as_ref()
}
}

impl PartialEq for Precommits {
impl PartialEq for CommitSigs {
fn eq(&self, other: &Self) -> bool {
// Note: this is used for asserts in tests:
self.0.clone().into_iter().eq(other.0.clone().into_iter())
Expand Down
Loading

0 comments on commit 3003fef

Please sign in to comment.