Skip to content

Commit

Permalink
split A.1, tendermint and abci changes
Browse files Browse the repository at this point in the history
  • Loading branch information
hdevalence committed Sep 20, 2022
1 parent 38a5de3 commit b7f3125
Show file tree
Hide file tree
Showing 99 changed files with 3,236 additions and 1,107 deletions.
12 changes: 3 additions & 9 deletions abci/src/application.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ pub mod kvstore;
use tendermint_proto::abci::{
request::Value, 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 @@ -76,12 +76,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 @@ -123,7 +117,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 All @@ -141,6 +134,7 @@ impl<A: Application> RequestDispatcher for A {
Value::ApplySnapshotChunk(req) => {
response::Value::ApplySnapshotChunk(self.apply_snapshot_chunk(req))
},
Value::SetOption(_) => response::Value::SetOption(Default::default()),
}),
}
}
Expand Down
38 changes: 19 additions & 19 deletions abci/src/application/kvstore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,15 +50,15 @@ use crate::{
/// // 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 @@ -129,25 +129,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 @@ -158,7 +158,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 @@ -171,7 +171,7 @@ 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,
Expand All @@ -183,17 +183,17 @@ impl Application for KeyValueStoreApp {
}

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 @@ -202,18 +202,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().into_bytes().into(),
value: key.to_string().into_bytes().into(),
index: true,
},
EventAttribute {
key: "index_key".as_bytes().to_owned(),
value: "index is working".as_bytes().to_owned(),
key: "index_key".to_string().into_bytes().into(),
value: "index is working".to_string().into_bytes().into(),
index: true,
},
EventAttribute {
key: "noindex_key".as_bytes().to_owned(),
value: "index is working".as_bytes().to_owned(),
key: "noindex_key".to_string().into_bytes().into(),
value: "index is working".to_string().into_bytes().into(),
index: false,
},
],
Expand All @@ -228,7 +228,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 @@ -285,7 +285,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
5 changes: 0 additions & 5 deletions abci/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,11 +113,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 @@ -130,7 +130,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 @@ -142,11 +142,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 @@ -164,14 +164,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 @@ -25,19 +25,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 config/src/prelude.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Re-export according to alloc::prelude::v1 because it is not yet stabilized
// https://doc.rust-lang.org/src/alloc/prelude/v1.rs.html
pub use alloc::borrow::ToOwned;
pub use alloc::{
borrow::ToOwned,
boxed::Box,
format,
string::{String, ToString},
Expand Down
4 changes: 3 additions & 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.11", default-features = false }
prost-types = { version = "0.11", 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 All @@ -28,6 +28,8 @@ num-derive = { version = "0.3", default-features = false }
# TODO(thane): Remove restrictions once js-sys issue is resolved (causes the Substrate no_std check to fail)
time = { version = ">=0.3, <0.3.12", default-features = false, features = ["macros", "parsing"] }
flex-error = { version = "0.4.4", default-features = false }
# TODO(hdevalence): re-added while rebasing the ABCI domain types PR again
chrono = { version = "0.4", default-features = false, features = ["serde", "alloc"] }

[dev-dependencies]
serde_json = { version = "1.0", default-features = false, features = ["alloc"] }
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 @@ -19,6 +19,7 @@ pub mod google {
}
}

mod chrono;
mod error;
#[allow(warnings)]
mod tendermint;
Expand Down
2 changes: 1 addition & 1 deletion proto/src/prelude.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Re-export according to alloc::prelude::v1 because it is not yet stabilized
// https://doc.rust-lang.org/src/alloc/prelude/v1.rs.html
pub use alloc::borrow::ToOwned;
pub use alloc::{
borrow::ToOwned,
boxed::Box,
format,
string::{String, ToString},
Expand Down
Empty file added proto/src/prost/gogoproto.rs
Empty file.
Empty file.
Loading

0 comments on commit b7f3125

Please sign in to comment.