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

Commit

Permalink
Merge #1458 #1466
Browse files Browse the repository at this point in the history
1458: Problem (Fix #1457): No mock mode for developing on non-sgx platform r=tomtau a=yihuang

Solution:
- Add mock mode

The basic idea is described in #1457.

1466: Problem (WIP #1313): light client doesn't verify the fetched staking state r=tomtau a=yihuang

Solution:
- Support query merkle inclusion proof
- Also support query historical staking state
- Query json encoded staking from abci_query directly #1464

This feature(query historical staked state) is also needed to make the reward integration tests more stable.
Added a new abci_query path "staking" which is like "account", but it returns JSON directly, also support the new features (historical query, proof), the next step will be update the "staking_state" API in client-rpc and client-cli to use the new one.

Co-authored-by: yihuang <[email protected]>
  • Loading branch information
bors[bot] and yihuang authored Apr 23, 2020
3 parents 636e032 + 867a1f2 + 3bfb287 commit 0c9738f
Show file tree
Hide file tree
Showing 33 changed files with 519 additions and 188 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,15 @@
*Unreleased*
## v0.5.0
### Breaking changes

- *chain-storage* [1466](https://github.com/crypto-com/chain/pull/1466): add a colume to store historical staking versions

### Features

- *chain-abci* [1458](https://github.com/crypto-com/chain/pull/1458): new abci_query path "sealed", query sealed log of transaction id.

### Improvements

### Bug Fixes

*April 22, 2020*
Expand Down
10 changes: 10 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ members = [
"chain-tx-enclave/tx-query/enclave",
"chain-tx-enclave/tx-query-next/app-runner",
"chain-tx-enclave/tx-query-next/enclave-app",
"chain-tx-enclave/mock-utils",
"cro-clib",
]

Expand Down
3 changes: 2 additions & 1 deletion chain-abci/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ readme = "README.md"
edition = "2018"

[features]
mock-validation = []
default = []
sgx-test = []
mock-enclave = []

[dependencies]
abci = "0.7"
Expand All @@ -18,6 +18,7 @@ chain-storage = { path = "../chain-storage" }
chain-tx-filter = { path = "../chain-tx-filter" }
chain-tx-validation = { path = "../chain-tx-validation" }
enclave-protocol = { path = "../enclave-protocol" }
mock-utils = { path = "../chain-tx-enclave/mock-utils" }
log = "0.4.8"
env_logger = "0.7.1"
bit-vec = { version = "0.6.1", features = ["serde_no_std"] }
Expand Down
2 changes: 1 addition & 1 deletion chain-abci/fuzz/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ hex = "0.4"

[dependencies.chain-abci]
path = ".."
features = ["mock-validation"]
features = ["mock-enclave"]

# Prevent this from interfering with workspaces
[workspace]
Expand Down
8 changes: 6 additions & 2 deletions chain-abci/src/app/app_init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use parity_scale_codec::{Decode, Encode};
use protobuf::Message;
use serde::{Deserialize, Serialize};

#[cfg(all(not(feature = "mock-validation"), target_os = "linux"))]
#[cfg(all(not(feature = "mock-enclave"), target_os = "linux"))]
use crate::enclave_bridge::real::start_zmq;
use crate::enclave_bridge::EnclaveProxy;
use crate::staking::StakingTable;
Expand Down Expand Up @@ -67,6 +67,10 @@ impl StoredChainState for ChainNodeState {
fn get_last_app_hash(&self) -> H256 {
self.last_apphash
}

fn get_staking_version(&self) -> Version {
self.staking_version
}
}

impl ChainNodeState {
Expand Down Expand Up @@ -290,7 +294,7 @@ impl<T: EnclaveProxy> ChainNodeApp<T> {
.expect("failed to decode two last hex digits in chain ID")[0];

if let (Some(_), Some(_conn_str)) = (tx_query_address.as_ref(), enclave_server.as_ref()) {
#[cfg(all(not(feature = "mock-validation"), target_os = "linux"))]
#[cfg(all(not(feature = "mock-enclave"), target_os = "linux"))]
let _ = start_zmq(_conn_str, chain_hex_id, storage.get_read_only());
}

Expand Down
29 changes: 29 additions & 0 deletions chain-abci/src/app/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,27 @@ impl<T: EnclaveProxy> ChainNodeApp<T> {
resp.code = 3;
}
}
"staking" => {
let height: BlockHeight = _req.height.try_into().expect("Invalid block height");
let mversion = if height == BlockHeight::genesis() {
self.last_state.as_ref().map(|state| state.staking_version)
} else {
self.storage.get_historical_staking_version(height)
};
let account_address = StakedStateAddress::try_from(_req.data.as_slice());
if let (Some(version), Ok(address)) = (mversion, account_address) {
let (maccount, proof) = get_with_proof(&self.storage, version, &address);
resp.value = serde_json::to_string(&(
maccount,
if _req.prove { Some(proof) } else { None },
))
.unwrap()
.into_bytes();
} else {
resp.log += "account lookup failed (either invalid address or node not correctly restored / initialized)";
resp.code = 3;
}
}
"state" => {
if self.tx_query_address.is_none() {
resp.code = 1;
Expand Down Expand Up @@ -226,6 +247,14 @@ impl<T: EnclaveProxy> ChainNodeApp<T> {
.expect("Unable to serialize validator metadata into json")
.into_bytes();
}
"sealed" => {
self.lookup(
&mut resp,
LookupItem::TxSealed,
&_req.data[..],
"sealed log not found",
);
}
_ => {
resp.log += "invalid path";
resp.code = 1;
Expand Down
70 changes: 21 additions & 49 deletions chain-abci/src/enclave_bridge/mock.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
#![allow(dead_code)]
///! TODO: feature-guard when workspaces can be built with --features flag: https://github.com/rust-lang/cargo/issues/5015
use super::*;
use chain_core::state::account::DepositBondTx;
use chain_core::tx::PlainTxAux;
use chain_core::tx::TxEnclaveAux;
use chain_core::tx::TxObfuscated;
use chain_core::tx::TxWithOutputs;
use chain_core::tx::{PlainTxAux, TxEnclaveAux, TxWithOutputs};
use chain_tx_filter::BlockFilter;
use chain_tx_validation::{verify_bonded_deposit_core, verify_transfer, verify_unbonded_withdraw};
use enclave_protocol::IntraEnclaveResponseOk;
use mock_utils::{decrypt, seal, unseal};

use super::*;

pub struct MockClient {
chain_hex_id: u8,
Expand Down Expand Up @@ -60,57 +57,31 @@ impl EnclaveProxy for MockClient {
Ok(IntraEnclaveResponseOk::EndBlock(maybe_filter))
}
IntraEnclaveRequest::Encrypt(_) => {
// TODO: mock / simulate ?
// In mock mode, client will do the encryption on their own.
Err(chain_tx_validation::Error::EnclaveRejected)
}
IntraEnclaveRequest::ValidateTx { request, tx_inputs } => {
let (tx, account, info) =
(request.tx.clone(), request.account.clone(), request.info);

let (txpayload, inputs) = match (&tx, tx_inputs) {
(
TxEnclaveAux::TransferTx {
payload: TxObfuscated { txpayload, .. },
..
},
Some(inputs),
) => (
txpayload,
inputs
.iter()
.map(|x| TxWithOutputs::decode(&mut x.as_slice()).expect("TODO mock"))
.collect(),
),
let (payload, inputs) = match (&tx, tx_inputs) {
(TxEnclaveAux::TransferTx { payload, .. }, Some(inputs)) => {
(payload, inputs.iter().map(|log| unseal(&log)).collect())
}
(
TxEnclaveAux::DepositStakeTx {
tx: DepositBondTx { .. },
payload: TxObfuscated { txpayload, .. },
payload,
..
},
Some(inputs),
) => (
txpayload,
inputs
.iter()
.map(|x| TxWithOutputs::decode(&mut x.as_slice()).expect("TODO mock"))
.collect(),
),
(
TxEnclaveAux::WithdrawUnbondedStakeTx {
payload: TxObfuscated { txpayload, .. },
..
},
_,
) => (txpayload, vec![]),
) => (payload, inputs.iter().map(|log| unseal(&log)).collect()),
(TxEnclaveAux::WithdrawUnbondedStakeTx { payload, .. }, _) => (payload, vec![]),
_ => unreachable!(),
};
// FIXME
let plain_tx = PlainTxAux::decode(&mut txpayload.as_slice());
let plain_tx = decrypt(&payload);
match (tx, plain_tx) {
(
TxEnclaveAux::TransferTx { .. },
Ok(PlainTxAux::TransferTx(maintx, witness)),
) => {
(TxEnclaveAux::TransferTx { .. }, PlainTxAux::TransferTx(maintx, witness)) => {
let result = verify_transfer(&maintx, &witness, &info, inputs);
match result {
Ok(fee) => {
Expand All @@ -119,15 +90,15 @@ impl EnclaveProxy for MockClient {

Ok(IntraEnclaveResponseOk::TxWithOutputs {
paid_fee: fee,
sealed_tx: txwo.encode(),
sealed_tx: seal(&txwo),
})
}
Err(e) => Err(e),
}
}
(
TxEnclaveAux::DepositStakeTx { tx, .. },
Ok(PlainTxAux::DepositStakeTx(witness)),
PlainTxAux::DepositStakeTx(witness),
) => {
let result = verify_bonded_deposit_core(&tx, &witness, &info, inputs);
match result {
Expand All @@ -139,19 +110,20 @@ impl EnclaveProxy for MockClient {
}
(
TxEnclaveAux::WithdrawUnbondedStakeTx { .. },
Ok(PlainTxAux::WithdrawUnbondedStakeTx(tx)),
PlainTxAux::WithdrawUnbondedStakeTx(tx),
) => {
let fee = verify_unbonded_withdraw(
let result = verify_unbonded_withdraw(
&tx,
&info,
&account.expect("account exists in withdraw"),
)?;
);
let fee = result?;
let txwo = TxWithOutputs::StakeWithdraw(tx);
self.add_view_keys(&txwo);

Ok(IntraEnclaveResponseOk::TxWithOutputs {
paid_fee: fee,
sealed_tx: txwo.encode(),
sealed_tx: seal(&txwo),
})
}
_ => Err(chain_tx_validation::Error::EnclaveRejected),
Expand Down
3 changes: 1 addition & 2 deletions chain-abci/src/enclave_bridge/mod.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
use enclave_protocol::{IntraEnclaveRequest, IntraEnclaveResponse};
use parity_scale_codec::{Decode, Encode};

/// TODO: feature-guard when workspaces can be built with --features flag: https://github.com/rust-lang/cargo/issues/5015
pub mod mock;

#[cfg(all(not(feature = "mock-validation"), target_os = "linux"))]
#[cfg(all(not(feature = "mock-enclave"), target_os = "linux"))]
pub mod real;

/// Abstracts over communication with an external part that does enclave calls
Expand Down
10 changes: 5 additions & 5 deletions chain-abci/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ use std::net::SocketAddr;
use std::path::{Path, PathBuf};

use chain_abci::app::ChainNodeApp;
#[cfg(any(feature = "mock-validation", not(target_os = "linux")))]
#[cfg(any(feature = "mock-enclave", not(target_os = "linux")))]
use chain_abci::enclave_bridge::mock::MockClient;
#[cfg(all(not(feature = "mock-validation"), target_os = "linux"))]
#[cfg(all(not(feature = "mock-enclave"), target_os = "linux"))]
use chain_abci::enclave_bridge::real::TxValidationApp;
use chain_core::init::network::{get_network, get_network_id, init_chain_id};
use chain_storage::{Storage, StorageConfig, StorageType};
#[cfg(any(feature = "mock-validation", not(target_os = "linux")))]
#[cfg(any(feature = "mock-enclave", not(target_os = "linux")))]
use log::warn;
use serde::Deserialize;
use std::io::BufReader;
Expand Down Expand Up @@ -130,13 +130,13 @@ pub struct AbciOpt {
}

/// normal
#[cfg(all(not(feature = "mock-validation"), target_os = "linux"))]
#[cfg(all(not(feature = "mock-enclave"), target_os = "linux"))]
fn get_enclave_proxy() -> TxValidationApp {
TxValidationApp::default()
}

/// for development
#[cfg(any(feature = "mock-validation", not(target_os = "linux")))]
#[cfg(any(feature = "mock-enclave", not(target_os = "linux")))]
fn get_enclave_proxy() -> MockClient {
warn!("Using mock (non-enclave) infrastructure");
MockClient::new(get_network_id())
Expand Down
4 changes: 2 additions & 2 deletions chain-abci/src/staking/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -747,10 +747,10 @@ impl StakingTable {
pub(crate) fn set_staking(
heap: &mut impl StoreStaking,
staking: StakedState,
minimal_required_staking: Coin,
_minimal_required_staking: Coin,
) {
#[cfg(debug_assertions)]
staking.check_invariants(minimal_required_staking);
staking.check_invariants(_minimal_required_staking);
heap.set_staking(staking)
}

Expand Down
Loading

0 comments on commit 0c9738f

Please sign in to comment.