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

Add domain types (updated) and fix integration tests for Tendermint v0.35.0 #1022

Merged
merged 45 commits into from
Nov 27, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
3fa00dc
tendermint: add From<Infallible> for Error
hdevalence Nov 16, 2021
69f0082
Use hex for AppHash Debug formatting
hdevalence Jul 28, 2021
c43a78e
Regenerate protobuf types using tools/proto-compiler.
hdevalence Oct 28, 2021
57dd21b
Regenerate protos against tendermint v0.35.0-rc3.
hdevalence Oct 28, 2021
d6c8395
Remove SetOption-related code in tendermint-abci.
hdevalence Sep 9, 2021
39a9bd4
Update imports to reflect protobuf movements.
hdevalence Sep 9, 2021
6e48efa
Update tendermint-abci to reflect upstream proto changes.
hdevalence Sep 9, 2021
ee4c84a
p2p: treat all non-Ed25519 keys as unsupported
hdevalence Sep 9, 2021
d9ed69a
Improve ABCI response code modeling with NonZeroU32
hdevalence Aug 2, 2021
4f47712
Use the Bytes type in ABCI protos.
hdevalence Apr 14, 2021
156cce9
Add conversions between protobuf and chrono types.
hdevalence Apr 14, 2021
89e6659
tendermint: define Serde for Block in terms of RawBlock
hdevalence Sep 10, 2021
9beadce
tendermint: simpler transaction modeling in Block
hdevalence Sep 9, 2021
ecc309d
rpc: take over tendermint::abci
hdevalence Sep 9, 2021
28682cd
tendermint: add ABCI domain types.
hdevalence Apr 13, 2021
0dcdc6f
tendermint: eliminate &'static str errors in ABCI domain types.
hdevalence Nov 16, 2021
4dbbbd0
Merge `abci::params::ConsensusParams` with `consensus::Params`.
hdevalence Nov 15, 2021
3c5eff5
Add hex encoding Serde attribute to Sr25519 keys.
hdevalence Nov 15, 2021
1f1a4c8
Replace integers with `block::Height`, `vote::Power`
hdevalence Nov 15, 2021
9660feb
Replace integer with block::Round
hdevalence Nov 15, 2021
2a0ccf4
Fix tools build by using correct imports
thanethomson Nov 18, 2021
23a05d4
Fix clippy complaints in tools
thanethomson Nov 18, 2021
6308759
Fix clippy warning
thanethomson Nov 18, 2021
48e9f83
Fix clippy lints
thanethomson Nov 18, 2021
f8cf4d2
Fix more clippy lints
thanethomson Nov 18, 2021
2b4274d
Fix deprecation notices from ed25519 crate
thanethomson Nov 19, 2021
0b13301
Regenerate protos for Tendermint v0.35.0
thanethomson Nov 20, 2021
f3b8924
Fix raw bytes conversion in tests/docs
thanethomson Nov 20, 2021
ee8e2e4
Add Tendermint v0.35.0 Docker config
thanethomson Nov 25, 2021
cc316cf
Add Tendermint v0.35.0 Docker image for ABCI integration testing
thanethomson Nov 25, 2021
04c8074
Remove RPC deserialization tests
thanethomson Nov 25, 2021
6ed54bd
Reformat Docker folder readme
thanethomson Nov 25, 2021
7651ef7
Bump version of Tendermint used in ABCI integration test
thanethomson Nov 25, 2021
9e52c5e
Bump version of Tendermint used in rpc probe
thanethomson Nov 25, 2021
56aa3ab
Bump version of Tendermint used in kvstore integration test
thanethomson Nov 25, 2021
8f176e6
Bump version of Tendermint used in proto-compiler
thanethomson Nov 25, 2021
f1a4823
Regenerate kvstore fixtures with rpc-probe for Tendermint v0.35.0
thanethomson Nov 25, 2021
e4d976e
Update kvstore integration test to accommodate newly generated fixtures
thanethomson Nov 25, 2021
673d780
Update RPC tests and data structures to accommodate Tendermint v0.35.…
thanethomson Nov 25, 2021
8abc428
Update ABCI encoding scheme to accommodate breaking change in https:/…
thanethomson Nov 25, 2021
2a21f38
Bump Tendermint version in GitHub Actions kvstore integration test
thanethomson Nov 25, 2021
3663c16
Add changelog entries to capture breaking changes
thanethomson Nov 25, 2021
60cba9e
Change tx hash encoding from base64 to hex and update tests
thanethomson Nov 26, 2021
b583aa0
Add changelog entry for /tx endpoint change
thanethomson Nov 26, 2021
07a8efe
Merge latest changes from master and fix conflicts
thanethomson Nov 26, 2021
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
2 changes: 2 additions & 0 deletions .changelog/unreleased/breaking-changes/862-035-tendermint.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- Updated integration testing to test against Tendermint v0.35.0
([#862](https://github.com/informalsystems/tendermint-rs/issues/862))
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- `[tendermint]` Added domain types for ABCI
([#862](https://github.com/informalsystems/tendermint-rs/issues/862))
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
- `[tendermint-abci]` Changed low-level wire encoding protocol to
accommodate <https://github.com/tendermint/tendermint/issues/5783>
([#862](https://github.com/informalsystems/tendermint-rs/issues/862))
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
- `[tendermint-rpc]` The `event::Event::events` field is now represented as
`Option<Vec<crate::abci::Event>>` as opposed to `Option<HashMap<String,
Vec<String>>>` to accommodate breaking change in Tendermint v0.35.0
subscription interface ([#862](https://github.com/informalsystems/tendermint-
rs/issues/862))
3 changes: 3 additions & 0 deletions .changelog/unreleased/breaking-changes/862-rpc-tx-hash-hex.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
- `[tendermint-rpc]` The `/tx` endpoint now encodes
the `hash` parameter as hexadecimal instead of base64
([#862](https://github.com/informalsystems/tendermint-rs/issues/862))
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ jobs:
runs-on: ubuntu-latest
services:
tendermint:
image: informaldev/tendermint:0.34.13
image: informaldev/tendermint:0.35.0
ports:
- 26656:26656
- 26657:26657
Expand Down
11 changes: 2 additions & 9 deletions abci/src/application.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ use tendermint_proto::abci::request::Value;
use tendermint_proto::abci::{
response, Request, RequestApplySnapshotChunk, RequestBeginBlock, RequestCheckTx,
RequestDeliverTx, RequestEcho, RequestEndBlock, RequestInfo, RequestInitChain,
RequestLoadSnapshotChunk, RequestOfferSnapshot, RequestQuery, RequestSetOption, Response,
RequestLoadSnapshotChunk, RequestOfferSnapshot, RequestQuery, Response,
ResponseApplySnapshotChunk, ResponseBeginBlock, ResponseCheckTx, ResponseCommit,
ResponseDeliverTx, ResponseEcho, ResponseEndBlock, ResponseFlush, ResponseInfo,
ResponseInitChain, ResponseListSnapshots, ResponseLoadSnapshotChunk, ResponseOfferSnapshot,
ResponseQuery, ResponseSetOption,
ResponseQuery,
};

/// An ABCI application.
Expand Down Expand Up @@ -77,12 +77,6 @@ pub trait Application: Send + Clone + 'static {
Default::default()
}

/// Allows the Tendermint node to request that the application set an
/// option to a particular value.
fn set_option(&self, _request: RequestSetOption) -> ResponseSetOption {
Default::default()
}

/// Used during state sync to discover available snapshots on peers.
fn list_snapshots(&self) -> ResponseListSnapshots {
Default::default()
Expand Down Expand Up @@ -124,7 +118,6 @@ impl<A: Application> RequestDispatcher for A {
Value::Echo(req) => response::Value::Echo(self.echo(req)),
Value::Flush(_) => response::Value::Flush(self.flush()),
Value::Info(req) => response::Value::Info(self.info(req)),
Value::SetOption(req) => response::Value::SetOption(self.set_option(req)),
Value::InitChain(req) => response::Value::InitChain(self.init_chain(req)),
Value::Query(req) => response::Value::Query(self.query(req)),
Value::BeginBlock(req) => response::Value::BeginBlock(self.begin_block(req)),
Expand Down
43 changes: 23 additions & 20 deletions abci/src/application/kvstore.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! In-memory key/value store ABCI application.

use crate::codec::{encode_varint, MAX_VARINT_LENGTH};
use crate::codec::MAX_VARINT_LENGTH;
use crate::{Application, Error};
use bytes::BytesMut;
use std::collections::HashMap;
Expand Down Expand Up @@ -44,15 +44,15 @@ use tracing::{debug, info};
/// // Deliver a transaction and then commit the transaction
/// client
/// .deliver_tx(RequestDeliverTx {
/// tx: "test-key=test-value".as_bytes().to_owned(),
/// tx: "test-key=test-value".into(),
/// })
/// .unwrap();
/// client.commit().unwrap();
///
/// // We should be able to query for the data we just delivered above
/// let res = client
/// .query(RequestQuery {
/// data: "test-key".as_bytes().to_owned(),
/// data: "test-key".into(),
/// path: "".to_string(),
/// height: 0,
/// prove: false,
Expand Down Expand Up @@ -123,25 +123,25 @@ impl Application for KeyValueStoreApp {
version: "0.1.0".to_string(),
app_version: 1,
last_block_height,
last_block_app_hash,
last_block_app_hash: last_block_app_hash.into(),
}
}

fn query(&self, request: RequestQuery) -> ResponseQuery {
let key = match String::from_utf8(request.data.clone()) {
let key = match std::str::from_utf8(&request.data) {
Ok(s) => s,
Err(e) => panic!("Failed to intepret key as UTF-8: {}", e),
};
debug!("Attempting to get key: {}", key);
match self.get(key.clone()) {
match self.get(key) {
Ok((height, value_opt)) => match value_opt {
Some(value) => ResponseQuery {
code: 0,
log: "exists".to_string(),
info: "".to_string(),
index: 0,
key: request.data,
value: value.into_bytes(),
value: value.into_bytes().into(),
proof_ops: None,
height,
codespace: "".to_string(),
Expand All @@ -152,7 +152,7 @@ impl Application for KeyValueStoreApp {
info: "".to_string(),
index: 0,
key: request.data,
value: vec![],
value: Default::default(),
proof_ops: None,
height,
codespace: "".to_string(),
Expand All @@ -165,28 +165,31 @@ impl Application for KeyValueStoreApp {
fn check_tx(&self, _request: RequestCheckTx) -> ResponseCheckTx {
ResponseCheckTx {
code: 0,
data: vec![],
data: Default::default(),
log: "".to_string(),
info: "".to_string(),
gas_wanted: 1,
gas_used: 0,
events: vec![],
codespace: "".to_string(),
mempool_error: "".to_string(),
priority: 0,
sender: "".to_string(),
}
}

fn deliver_tx(&self, request: RequestDeliverTx) -> ResponseDeliverTx {
let tx = String::from_utf8(request.tx).unwrap();
let tx = std::str::from_utf8(&request.tx).unwrap();
let tx_parts = tx.split('=').collect::<Vec<&str>>();
let (key, value) = if tx_parts.len() == 2 {
(tx_parts[0], tx_parts[1])
} else {
(tx.as_ref(), tx.as_ref())
(tx, tx)
};
let _ = self.set(key, value).unwrap();
ResponseDeliverTx {
code: 0,
data: vec![],
data: Default::default(),
log: "".to_string(),
info: "".to_string(),
gas_wanted: 0,
Expand All @@ -195,18 +198,18 @@ impl Application for KeyValueStoreApp {
r#type: "app".to_string(),
attributes: vec![
EventAttribute {
key: "key".as_bytes().to_owned(),
value: key.as_bytes().to_owned(),
key: "key".to_string(),
value: key.to_string(),
index: true,
},
EventAttribute {
key: "index_key".as_bytes().to_owned(),
value: "index is working".as_bytes().to_owned(),
key: "index_key".to_string(),
value: "index is working".to_string(),
index: true,
},
EventAttribute {
key: "noindex_key".as_bytes().to_owned(),
value: "index is working".as_bytes().to_owned(),
key: "noindex_key".to_string(),
value: "index is working".to_string(),
index: false,
},
],
Expand All @@ -221,7 +224,7 @@ impl Application for KeyValueStoreApp {
let (height, app_hash) = channel_recv(&result_rx).unwrap();
info!("Committed height {}", height);
ResponseCommit {
data: app_hash,
data: app_hash.into(),
retain_height: height - 1,
}
}
Expand Down Expand Up @@ -278,7 +281,7 @@ impl KeyValueStoreDriver {
// As in the Go-based key/value store, simply encode the number of
// items as the "app hash"
let mut app_hash = BytesMut::with_capacity(MAX_VARINT_LENGTH);
encode_varint(self.store.len() as u64, &mut app_hash);
prost::encoding::encode_varint(self.store.len() as u64, &mut app_hash);
self.app_hash = app_hash.to_vec();
self.height += 1;
channel_send(&result_tx, (self.height, self.app_hash.clone()))
Expand Down
12 changes: 3 additions & 9 deletions abci/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,9 @@ use tendermint_proto::abci::{
request, response, RequestApplySnapshotChunk, RequestBeginBlock, RequestCheckTx, RequestCommit,
RequestDeliverTx, RequestEndBlock, RequestFlush, RequestInfo, RequestInitChain,
RequestListSnapshots, RequestLoadSnapshotChunk, RequestOfferSnapshot, RequestQuery,
RequestSetOption, ResponseApplySnapshotChunk, ResponseBeginBlock, ResponseCheckTx,
ResponseCommit, ResponseDeliverTx, ResponseEndBlock, ResponseFlush, ResponseInfo,
ResponseInitChain, ResponseListSnapshots, ResponseLoadSnapshotChunk, ResponseOfferSnapshot,
ResponseQuery, ResponseSetOption,
ResponseApplySnapshotChunk, ResponseBeginBlock, ResponseCheckTx, ResponseCommit,
ResponseDeliverTx, ResponseEndBlock, ResponseFlush, ResponseInfo, ResponseInitChain,
ResponseListSnapshots, ResponseLoadSnapshotChunk, ResponseOfferSnapshot, ResponseQuery,
};
use tendermint_proto::abci::{Request, RequestEcho, ResponseEcho};

Expand Down Expand Up @@ -113,11 +112,6 @@ impl Client {
perform!(self, Commit, RequestCommit {})
}

/// Request that the application set an option to a particular value.
pub fn set_option(&mut self, req: RequestSetOption) -> Result<ResponseSetOption, Error> {
perform!(self, SetOption, req)
}

/// Used during state sync to discover available snapshots on peers.
pub fn list_snapshots(&mut self) -> Result<ResponseListSnapshots, Error> {
perform!(self, ListSnapshots, RequestListSnapshots {})
Expand Down
17 changes: 3 additions & 14 deletions abci/src/codec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ where
message.encode(&mut buf).map_err(Error::encode)?;

let buf = buf.freeze();
encode_varint(buf.len() as u64, &mut dst);
prost::encoding::encode_varint(buf.len() as u64, &mut dst);
dst.put(buf);
Ok(())
}
Expand All @@ -139,11 +139,11 @@ where
{
let src_len = src.len();
let mut tmp = src.clone().freeze();
let encoded_len = match decode_varint(&mut tmp) {
let encoded_len = match prost::encoding::decode_varint(&mut tmp) {
Ok(len) => len,
// We've potentially only received a partial length delimiter
Err(_) if src_len <= MAX_VARINT_LENGTH => return Ok(None),
Err(e) => return Err(e),
Err(e) => return Err(Error::decode(e)),
};
let remaining = tmp.remaining() as u64;
if remaining < encoded_len {
Expand All @@ -161,14 +161,3 @@ where
Ok(Some(res))
}
}

// encode_varint and decode_varint will be removed once
// https://github.com/tendermint/tendermint/issues/5783 lands in Tendermint.
pub fn encode_varint<B: BufMut>(val: u64, mut buf: &mut B) {
prost::encoding::encode_varint(val << 1, &mut buf);
}

pub fn decode_varint<B: Buf>(mut buf: &mut B) -> Result<u64, Error> {
let len = prost::encoding::decode_varint(&mut buf).map_err(Error::decode)?;
Ok(len >> 1)
}
6 changes: 3 additions & 3 deletions abci/tests/kvstore_app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,19 @@ mod kvstore_app_integration {

client
.deliver_tx(RequestDeliverTx {
tx: "test-key=test-value".as_bytes().to_owned(),
tx: "test-key=test-value".into(),
})
.unwrap();
client.commit().unwrap();

let res = client
.query(RequestQuery {
data: "test-key".as_bytes().to_owned(),
data: "test-key".into(),
path: "".to_string(),
height: 0,
prove: false,
})
.unwrap();
assert_eq!(res.value, "test-value".as_bytes().to_owned());
assert_eq!(res.value, "test-value".as_bytes());
}
}
2 changes: 1 addition & 1 deletion light-client/src/evidence.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

use crate::{components::io::IoError, types::PeerId};

use tendermint::abci::transaction::Hash;
use tendermint_rpc::abci::transaction::Hash;

use contracts::contract_trait;

Expand Down
2 changes: 1 addition & 1 deletion light-client/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
use crate::types::{Height, LightBlock, PeerId, SignedHeader, Time, TrustThreshold, ValidatorSet};

use serde::{Deserialize, Serialize};
use tendermint::abci::transaction::Hash;
use tendermint_rpc as rpc;
use tendermint_rpc::abci::transaction::Hash;

use crate::components::clock::Clock;
use crate::components::io::{AtHeight, Io, IoError};
Expand Down
2 changes: 1 addition & 1 deletion p2p/src/secret_connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ impl Handshake<AwaitingAuthSig> {
proto::crypto::public_key::Sum::Ed25519(ref bytes) => {
ed25519::PublicKey::from_bytes(bytes).map_err(Error::signature)
}
proto::crypto::public_key::Sum::Secp256k1(_) => Err(Error::unsupported_key()),
_ => Err(Error::unsupported_key()),
}?;

let remote_sig =
Expand Down
2 changes: 1 addition & 1 deletion proto/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ all-features = true
[dependencies]
prost = { version = "0.9", default-features = false }
prost-types = { version = "0.9", default-features = false }
bytes = { version = "1.0", default-features = false }
bytes = { version = "1.0", default-features = false, features = ["serde"] }
serde = { version = "1.0", default-features = false, features = ["derive"] }
serde_bytes = { version = "0.11", default-features = false, features = ["alloc"] }
subtle-encoding = { version = "0.5", default-features = false, features = ["hex", "base64", "alloc"] }
Expand Down
53 changes: 53 additions & 0 deletions proto/src/chrono.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
use core::convert::TryInto;

use chrono::{DateTime, Duration, TimeZone, Utc};

use crate::google::protobuf as pb;

impl From<DateTime<Utc>> for pb::Timestamp {
fn from(dt: DateTime<Utc>) -> pb::Timestamp {
pb::Timestamp {
seconds: dt.timestamp(),
// This can exceed 1_000_000_000 in the case of a leap second, but
// even with a leap second it should be under 2_147_483_647.
nanos: dt
.timestamp_subsec_nanos()
.try_into()
.expect("timestamp_subsec_nanos bigger than i32::MAX"),
}
}
}

impl From<pb::Timestamp> for DateTime<Utc> {
fn from(ts: pb::Timestamp) -> DateTime<Utc> {
Utc.timestamp(ts.seconds, ts.nanos as u32)
}
}

// Note: we convert a protobuf::Duration into a chrono::Duration, not a
// std::time::Duration, because std::time::Durations are unsigned, but the
// protobuf duration is signed.

impl From<Duration> for pb::Duration {
fn from(d: Duration) -> pb::Duration {
// chrono's Duration stores the fractional part as `nanos: i32`
// internally but doesn't provide a way to access it, only a way to get
// the *total* number of nanoseconds. so we have to do this cool and fun
// hoop-jumping maneuver
let seconds = d.num_seconds();
let nanos = (d - Duration::seconds(seconds))
.num_nanoseconds()
.expect("we computed the fractional part, so there's no overflow")
.try_into()
.expect("the fractional part fits in i32");

pb::Duration { seconds, nanos }
}
}

impl From<pb::Duration> for Duration {
fn from(d: pb::Duration) -> Duration {
// there's no constructor that supplies both at once
Duration::seconds(d.seconds) + Duration::nanoseconds(d.nanos as i64)
}
}
1 change: 1 addition & 0 deletions proto/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ pub mod google {
}
}

mod chrono;
mod error;
#[allow(warnings)]
mod tendermint;
Expand Down
Loading