Skip to content
This repository has been archived by the owner on Jul 27, 2022. It is now read-only.

Problem: client code uses a custom tendermint client (CRO-101) #571

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
# IDE
.vscode
.idea
/tags

# TODOR
.todor
Expand Down
246 changes: 246 additions & 0 deletions Cargo.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions client-cli/src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use structopt::StructOpt;
use chain_core::init::coin::Coin;
use chain_core::state::account::StakedStateAddress;
use client_common::storage::SledStorage;
use client_common::tendermint::types::GenesisExt;
use client_common::tendermint::{Client, WebsocketRpcClient};
use client_common::{ErrorKind, Result, ResultExt, Storage};
#[cfg(not(feature = "mock-enc-dec"))]
Expand Down
1 change: 1 addition & 0 deletions client-common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ jsonrpc = { version = "0.11", optional = true }
serde_json = { version = "1.0", optional = true }
parity-scale-codec = { features = ["derive"], version = "1.0" }
websocket = { version = "0.24", default-features = false, features = ["sync"], optional = true }
tendermint = { git = "https://github.com/crypto-com/tendermint-rs.git", rev = "bb27fdc5dd0ce59767badab246d1d4c203cf3d23" }

[features]
default = ["sled", "websocket-rpc"]
Expand Down
5 changes: 2 additions & 3 deletions client-common/src/block_header.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
use chrono::{DateTime, Utc};

use chain_core::tx::data::TxId;
use chain_tx_filter::BlockFilter;

use crate::tendermint::types::Time;
use crate::Transaction;

/// Structure for representing a block header on Crypto.com Chain
Expand All @@ -13,7 +12,7 @@ pub struct BlockHeader {
/// Block height
pub block_height: u64,
/// Block time
pub block_time: DateTime<Utc>,
pub block_time: Time,
/// List of successfully committed transaction ids in this block
pub transaction_ids: Vec<TxId>,
/// Bloom filter for view keys and staking addresses
Expand Down
10 changes: 9 additions & 1 deletion client-common/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,15 @@ impl Error {
impl fmt::Display for Error {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}: {}", self.kind, self.message)
write!(
f,
"{}: {}, {}",
self.kind,
self.message,
self.origin
.as_ref()
.map_or("".to_owned(), |err| err.to_string())
)
}
}

Expand Down
5 changes: 2 additions & 3 deletions client-common/src/tendermint/client.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use crate::tendermint::types::QueryResult;
use crate::tendermint::types::*;
use crate::Result;

Expand Down Expand Up @@ -26,8 +25,8 @@ pub trait Client: Send + Sync {
) -> Result<Vec<BlockResults>>;

/// Makes `broadcast_tx_sync` call to tendermint
fn broadcast_transaction(&self, transaction: &[u8]) -> Result<BroadcastTxResult>;
fn broadcast_transaction(&self, transaction: &[u8]) -> Result<BroadcastTxResponse>;

/// Makes `abci_query` call to tendermint
fn query(&self, path: &str, data: &[u8]) -> Result<QueryResult>;
fn query(&self, path: &str, data: &[u8]) -> Result<AbciQuery>;
}
40 changes: 26 additions & 14 deletions client-common/src/tendermint/http_rpc_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,9 @@ impl RpcClient {

impl Client for RpcClient {
fn genesis(&self) -> Result<Genesis> {
self.call("genesis", Default::default())
Ok(self
.call::<GenesisResponse>("genesis", Default::default())?
.genesis)
}

fn status(&self) -> Result<Status> {
Expand All @@ -115,18 +117,20 @@ impl Client for RpcClient {

fn block(&self, height: u64) -> Result<Block> {
let params = [json!(height.to_string())];
self.call("block", &params)
Ok(self.call::<BlockResponse>("block", &params)?.block)
}

fn block_batch<'a, T: Iterator<Item = &'a u64>>(&self, heights: T) -> Result<Vec<Block>> {
let params = heights
.map(|height| ("block", vec![json!(height.to_string())]))
.collect::<Vec<(&str, Vec<Value>)>>();
let response = self.call_batch::<Block>(&params)?;

response
.into_iter()
.map(|block| block.chain(|| (ErrorKind::InvalidInput, "Block information not found")))
let mut rsps = self.call_batch::<BlockResponse>(&params)?;
rsps.drain(..)
.map(|rsp| {
rsp.chain(|| (ErrorKind::InvalidInput, "Block information not found"))
.map(|rsp_| rsp_.block)
})
.collect::<Result<Vec<Block>>>()
}

Expand Down Expand Up @@ -157,29 +161,37 @@ impl Client for RpcClient {
.collect::<Result<Vec<BlockResults>>>()
}

fn broadcast_transaction(&self, transaction: &[u8]) -> Result<BroadcastTxResult> {
fn broadcast_transaction(&self, transaction: &[u8]) -> Result<BroadcastTxResponse> {
let params = [json!(transaction)];
self.call::<BroadcastTxResult>("broadcast_tx_sync", &params)
self.call::<BroadcastTxResponse>("broadcast_tx_sync", &params)
.and_then(|result| {
if result.code != 0 {
Err(Error::new(ErrorKind::TendermintRpcError, result.log))
if result.code.is_err() {
Err(Error::new(
ErrorKind::TendermintRpcError,
result.log.to_string(),
))
} else {
Ok(result)
}
})
}

fn query(&self, path: &str, data: &[u8]) -> Result<QueryResult> {
fn query(&self, path: &str, data: &[u8]) -> Result<AbciQuery> {
let params = [
json!(path),
json!(hex::encode(data)),
json!(null),
json!(null),
];
let result = self.call::<QueryResult>("abci_query", &params)?;
let result = self
.call::<AbciQueryResponse>("abci_query", &params)?
.response;

if result.code() != 0 {
return Err(Error::new(ErrorKind::TendermintRpcError, result.log()));
if result.code.is_err() {
return Err(Error::new(
ErrorKind::TendermintRpcError,
result.log.to_string(),
));
}

Ok(result)
Expand Down
109 changes: 97 additions & 12 deletions client-common/src/tendermint/types.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,98 @@
//! Structures used in Tendermint RPC (auto-generated)
mod block;
//! Structures used in Tendermint RPC
mod block_results;
mod broadcast_tx_result;
mod genesis;
mod query;
mod status;
pub use block::*;
pub use block_results::*;
pub use broadcast_tx_result::*;
pub use genesis::*;
pub use query::*;
pub use status::*;
pub mod mock;

use base64::decode;
use parity_scale_codec::Decode;
use serde::{Deserialize, Serialize};

use crate::{ErrorKind, Result, ResultExt, Transaction};
use chain_core::init::config::InitConfig;
use chain_core::tx::fee::LinearFee;
use chain_core::tx::{TxAux, TxEnclaveAux};

pub use self::block_results::*;
pub use tendermint::rpc::endpoint::{
abci_query::AbciQuery, abci_query::Response as AbciQueryResponse,
block::Response as BlockResponse, broadcast::tx_sync::Response as BroadcastTxResponse,
status::Response as Status,
};
pub use tendermint::rpc::endpoint::{broadcast, status};
pub use tendermint::{
abci, abci::transaction::Data, abci::Code, block::Header, block::Height, Block,
Genesis as GenericGenesis, Hash, Time,
};

/// crypto-com instantiated genesis type
pub type Genesis = GenericGenesis<InitConfig>;

/// crypto-com instantiated genesis type
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct GenesisResponse {
/// Genesis data
pub genesis: Genesis,
}

/// crypto-chain specific methods.
pub trait BlockExt {
/// Returns un-encrypted transactions in a block (this may also contain invalid transactions)
fn unencrypted_transactions(&self) -> Result<Vec<Transaction>>;
}

impl BlockExt for Block {
/// NOTE: Un-encrypted transactions only contain deposit stake and unbond stake transactions
fn unencrypted_transactions(&self) -> Result<Vec<Transaction>> {
self.data
.iter()
.map(|raw| -> Result<TxAux> {
TxAux::decode(&mut raw.clone().into_vec().as_slice()).chain(|| {
(
ErrorKind::DeserializationError,
"Unable to decode transactions from bytes in a block",
)
})
})
.filter_map(|tx_aux_result| match tx_aux_result {
Err(e) => Some(Err(e)),
Ok(tx_aux) => match tx_aux {
TxAux::EnclaveTx(TxEnclaveAux::DepositStakeTx { tx, .. }) => {
Some(Ok(Transaction::DepositStakeTransaction(tx)))
}
TxAux::UnbondStakeTx(tx, _) => {
Some(Ok(Transaction::UnbondStakeTransaction(tx)))
}
_ => None,
},
})
.collect::<Result<Vec<Transaction>>>()
}
}

/// crypto-chain specific methods.
pub trait GenesisExt {
/// get fee policy
fn fee_policy(&self) -> LinearFee;
}

impl GenesisExt for Genesis {
fn fee_policy(&self) -> LinearFee {
self.app_state.network_params.initial_fee_policy
}
}

/// crypto-chain specific methods.
pub trait AbciQueryExt {
/// decode query result with base64
fn bytes(&self) -> Result<Vec<u8>>;
}

impl AbciQueryExt for AbciQuery {
fn bytes(&self) -> Result<Vec<u8>> {
Ok(decode(&self.value).chain(|| {
(
ErrorKind::DeserializationError,
"Unable to decode base64 bytes on query result",
)
})?)
}
}
Loading