From 59d1390acf220c389e6b12903937fff401aec122 Mon Sep 17 00:00:00 2001 From: tiangong3624749 Date: Fri, 27 Nov 2020 17:41:29 +0800 Subject: [PATCH] [cmd]add block id for account show. (#1715) * [cmd]add block id for account show. * Refactor RemoteStateReader. * fix clippy. --- cmd/faucet/src/faucet.rs | 2 +- cmd/starcoin/src/account/accept_token_cmd.rs | 2 +- .../src/account/execute_builtin_script_cmd.rs | 2 +- cmd/starcoin/src/account/show_cmd.rs | 12 +++++++++-- cmd/starcoin/src/account/transfer_cmd.rs | 2 +- cmd/starcoin/src/dev/deploy_cmd.rs | 2 +- cmd/starcoin/src/dev/execute_cmd.rs | 4 ++-- .../src/dev/generate_multisig_txn_cmd.rs | 2 +- cmd/starcoin/src/dev/get_coin_cmd.rs | 2 +- cmd/starcoin/src/dev/sign_txn_helper.rs | 6 +++--- cmd/starcoin/src/state/get_cmd.rs | 2 +- cmd/tx-factory/src/main.rs | 16 +++++++-------- rpc/api/src/state/mod.rs | 7 +++++++ rpc/client/src/lib.rs | 15 ++++++++++++++ rpc/client/src/remote_state_reader.rs | 20 +++++++++++++------ rpc/server/src/module/state_rpc.rs | 13 ++++++++++++ state/api/src/chain_state.rs | 4 ++++ testsuite/tests/steps/transaction.rs | 4 ++-- 18 files changed, 86 insertions(+), 31 deletions(-) diff --git a/cmd/faucet/src/faucet.rs b/cmd/faucet/src/faucet.rs index 9f29175944..32d27dc338 100644 --- a/cmd/faucet/src/faucet.rs +++ b/cmd/faucet/src/faucet.rs @@ -32,7 +32,7 @@ impl Faucet { receiver: AccountAddress, public_key: Vec, ) -> Result> { - let chain_state_reader = RemoteStateReader::new(&self.client); + let chain_state_reader = RemoteStateReader::new(&self.client)?; let account_state_reader = AccountStateReader::new(&chain_state_reader); let account_resource = account_state_reader .get_account_resource(self.faucet_account.address())? diff --git a/cmd/starcoin/src/account/accept_token_cmd.rs b/cmd/starcoin/src/account/accept_token_cmd.rs index ca32428bd4..f0cb3843e9 100644 --- a/cmd/starcoin/src/account/accept_token_cmd.rs +++ b/cmd/starcoin/src/account/accept_token_cmd.rs @@ -67,7 +67,7 @@ impl CommandAction for AcceptTokenCommand { let client = ctx.state().client(); let node_info = client.node_info()?; let sender = ctx.state().get_account_or_default(opt.sender)?; - let chain_state_reader = RemoteStateReader::new(client); + let chain_state_reader = RemoteStateReader::new(client)?; let account_state_reader = AccountStateReader::new(&chain_state_reader); let account_resource = account_state_reader.get_account_resource(&sender.address)?; diff --git a/cmd/starcoin/src/account/execute_builtin_script_cmd.rs b/cmd/starcoin/src/account/execute_builtin_script_cmd.rs index 3f538c1075..281d322e9d 100644 --- a/cmd/starcoin/src/account/execute_builtin_script_cmd.rs +++ b/cmd/starcoin/src/account/execute_builtin_script_cmd.rs @@ -92,7 +92,7 @@ impl CommandAction for ExecuteBuildInCommand { let node_info = client.node_info()?; let sender = ctx.state().get_account_or_default(opt.sender)?; - let chain_state_reader = RemoteStateReader::new(client); + let chain_state_reader = RemoteStateReader::new(client)?; let account_state_reader = AccountStateReader::new(&chain_state_reader); let account_resource = account_state_reader.get_account_resource(&sender.address)?; diff --git a/cmd/starcoin/src/account/show_cmd.rs b/cmd/starcoin/src/account/show_cmd.rs index 83168efff9..32129dc31e 100644 --- a/cmd/starcoin/src/account/show_cmd.rs +++ b/cmd/starcoin/src/account/show_cmd.rs @@ -6,7 +6,7 @@ use crate::view::AccountWithStateView; use crate::StarcoinOpt; use anyhow::{format_err, Result}; use scmd::{CommandAction, ExecContext}; -use starcoin_crypto::ValidCryptoMaterialStringExt; +use starcoin_crypto::{HashValue, ValidCryptoMaterialStringExt}; use starcoin_rpc_client::RemoteStateReader; use starcoin_state_api::AccountStateReader; use starcoin_vm_types::account_address::AccountAddress; @@ -18,6 +18,9 @@ use structopt::StructOpt; pub struct ShowOpt { #[structopt(name = "account_address")] account_address: Option, + + #[structopt(name = "block_id", short = "b")] + block_id: Option, } pub struct ShowCommand; @@ -46,7 +49,12 @@ impl CommandAction for ShowCommand { .account_get(account_address)? .ok_or_else(|| format_err!("Account with address {} not exist.", account_address))?; - let chain_state_reader = RemoteStateReader::new(client); + let chain_state_reader = if let Some(block_id) = opt.block_id { + let block = client.chain_get_block_by_hash(block_id)?; + RemoteStateReader::new_with_root(client, block.header.state_root) + } else { + RemoteStateReader::new(client)? + }; let account_state_reader = AccountStateReader::new(&chain_state_reader); let sequence_number = account_state_reader .get_account_resource(account.address())? diff --git a/cmd/starcoin/src/account/transfer_cmd.rs b/cmd/starcoin/src/account/transfer_cmd.rs index 2fdae3568a..7de9c6745e 100644 --- a/cmd/starcoin/src/account/transfer_cmd.rs +++ b/cmd/starcoin/src/account/transfer_cmd.rs @@ -89,7 +89,7 @@ impl CommandAction for TransferCommand { }; let receiver = opt.receiver; - let chain_state_reader = RemoteStateReader::new(client); + let chain_state_reader = RemoteStateReader::new(client)?; let account_state_reader = AccountStateReader::new(&chain_state_reader); let receiver_exist_on_chain = account_state_reader .get_account_resource(&receiver)? diff --git a/cmd/starcoin/src/dev/deploy_cmd.rs b/cmd/starcoin/src/dev/deploy_cmd.rs index 741a8d543d..bfbfb886a4 100644 --- a/cmd/starcoin/src/dev/deploy_cmd.rs +++ b/cmd/starcoin/src/dev/deploy_cmd.rs @@ -81,7 +81,7 @@ impl CommandAction for DeployCommand { let module_address = *compiled_module.address(); let client = ctx.state().client(); let node_info = client.node_info()?; - let chain_state_reader = RemoteStateReader::new(client); + let chain_state_reader = RemoteStateReader::new(client)?; let account_state_reader = AccountStateReader::new(&chain_state_reader); let account_resource = account_state_reader.get_account_resource(&module_address)?; diff --git a/cmd/starcoin/src/dev/execute_cmd.rs b/cmd/starcoin/src/dev/execute_cmd.rs index 3121aacfa0..6b39d391f5 100644 --- a/cmd/starcoin/src/dev/execute_cmd.rs +++ b/cmd/starcoin/src/dev/execute_cmd.rs @@ -171,7 +171,7 @@ impl CommandAction for ExecuteCommand { let client = ctx.state().client(); let node_info = client.node_info()?; - let chain_state_reader = RemoteStateReader::new(client); + let chain_state_reader = RemoteStateReader::new(client)?; let account_state_reader = AccountStateReader::new(&chain_state_reader); let account_resource = account_state_reader.get_account_resource(&sender)?; @@ -210,7 +210,7 @@ impl CommandAction for ExecuteCommand { let signed_txn = client.account_sign_txn(script_txn)?; let txn_hash = signed_txn.crypto_hash(); let (vm_status, output) = if opt.local_mode { - let state_view = RemoteStateReader::new(client); + let state_view = RemoteStateReader::new(client)?; playground::dry_run( &state_view, Transaction::UserTransaction(signed_txn.clone()), diff --git a/cmd/starcoin/src/dev/generate_multisig_txn_cmd.rs b/cmd/starcoin/src/dev/generate_multisig_txn_cmd.rs index 25637a4369..016e0299e5 100644 --- a/cmd/starcoin/src/dev/generate_multisig_txn_cmd.rs +++ b/cmd/starcoin/src/dev/generate_multisig_txn_cmd.rs @@ -158,7 +158,7 @@ impl CommandAction for GenerateMultisigTxnCommand { let client = ctx.state().client(); let node_info = client.node_info()?; - let chain_state_reader = RemoteStateReader::new(client); + let chain_state_reader = RemoteStateReader::new(client)?; let account_state_reader = AccountStateReader::new(&chain_state_reader); let account_resource = account_state_reader.get_account_resource(&sender)?; diff --git a/cmd/starcoin/src/dev/get_coin_cmd.rs b/cmd/starcoin/src/dev/get_coin_cmd.rs index 63afe04261..a5369e57ae 100644 --- a/cmd/starcoin/src/dev/get_coin_cmd.rs +++ b/cmd/starcoin/src/dev/get_coin_cmd.rs @@ -57,7 +57,7 @@ impl CommandAction for GetCoinCommand { })?; let association_address = account_config::association_address(); - let chain_state_reader = RemoteStateReader::new(client); + let chain_state_reader = RemoteStateReader::new(client)?; let account_state_reader = AccountStateReader::new(&chain_state_reader); let account_resource = account_state_reader .get_account_resource(&association_address)? diff --git a/cmd/starcoin/src/dev/sign_txn_helper.rs b/cmd/starcoin/src/dev/sign_txn_helper.rs index af031fd1d2..e059fae7c2 100644 --- a/cmd/starcoin/src/dev/sign_txn_helper.rs +++ b/cmd/starcoin/src/dev/sign_txn_helper.rs @@ -74,7 +74,7 @@ fn sign_txn_by_rpc_client( let account = cli_state.get_account_or_default(account_address)?; let client = cli_state.client(); let node_info = client.node_info()?; - let chain_state_reader = RemoteStateReader::new(client); + let chain_state_reader = RemoteStateReader::new(client)?; let account_state_reader = AccountStateReader::new(&chain_state_reader); let account_resource = account_state_reader .get_account_resource(account.address())? @@ -101,7 +101,7 @@ fn sign_txn_by_rpc_client( pub fn get_dao_config(cli_state: &CliState) -> Result { let client = cli_state.client(); - let chain_state_reader = RemoteStateReader::new(client); + let chain_state_reader = RemoteStateReader::new(client)?; let account_state_reader = AccountStateReader::new(&chain_state_reader); Ok(account_state_reader .get_on_chain_config::()? @@ -137,7 +137,7 @@ mod tests { cli_state: &CliState, addr: AccountAddress, ) -> Result<(AccountResource, u128)> { - let chain_state_reader = RemoteStateReader::new(cli_state.client()); + let chain_state_reader = RemoteStateReader::new(cli_state.client())?; let account_state_reader = AccountStateReader::new(&chain_state_reader); let account_resource = account_state_reader .get_account_resource(&addr)? diff --git a/cmd/starcoin/src/state/get_cmd.rs b/cmd/starcoin/src/state/get_cmd.rs index 3c95ef061d..a0d42f11fd 100644 --- a/cmd/starcoin/src/state/get_cmd.rs +++ b/cmd/starcoin/src/state/get_cmd.rs @@ -59,7 +59,7 @@ impl CommandAction for GetCommand { let state = client .state_get(AccessPath::new(account_addr, struct_tag.access_vector()))? .ok_or_else(|| format_err!("Account with address {} state not exist.", account_addr))?; - let chain_state_reader = RemoteStateReader::new(client); + let chain_state_reader = RemoteStateReader::new(client)?; let viewer = MoveValueAnnotator::new(&chain_state_reader); let annotated_resource = viewer.view_struct(struct_tag, state.as_slice())?; Ok(annotated_resource) diff --git a/cmd/tx-factory/src/main.rs b/cmd/tx-factory/src/main.rs index a933601990..d8ae70faf6 100644 --- a/cmd/tx-factory/src/main.rs +++ b/cmd/tx-factory/src/main.rs @@ -94,7 +94,7 @@ fn get_account_or_default( } let addr = default_account.clone().unwrap().address; - let state_reader = RemoteStateReader::new(&client); + let state_reader = RemoteStateReader::new(&client)?; let account_state_reader = AccountStateReader::new(&state_reader); let mut balance = account_state_reader.get_balance(&addr)?; // balance resource has not been created @@ -231,7 +231,7 @@ impl TxnMocker { account_password: String, unlock_duration: Duration, ) -> Result { - let state_reader = RemoteStateReader::new(&client); + let state_reader = RemoteStateReader::new(&client)?; let account_state_reader = AccountStateReader::new(&state_reader); let account_resource = account_state_reader.get_account_resource(&account_address)?; @@ -275,7 +275,7 @@ impl TxnMocker { self.next_sequence_number = match seq_number_in_pool { Some(n) => n, None => { - let state_reader = RemoteStateReader::new(&self.client); + let state_reader = RemoteStateReader::new(&self.client)?; let account_state_reader = AccountStateReader::new(&state_reader); let account_resource = @@ -292,14 +292,14 @@ impl TxnMocker { Ok(()) } - fn is_account_exist(&mut self, account: &AccountAddress) -> bool { - let state_reader = RemoteStateReader::new(&self.client); + fn is_account_exist(&mut self, account: &AccountAddress) -> Result { + let state_reader = RemoteStateReader::new(&self.client)?; let account_state_reader = AccountStateReader::new(&state_reader); let account_resource = account_state_reader .get_account_resource(account) .unwrap_or(None); - account_resource.is_some() + Ok(account_resource.is_some()) } fn gen_and_submit_txn(&mut self, blocking: bool) -> Result<()> { @@ -456,7 +456,7 @@ impl TxnMocker { account_list.push(account); i += 1; } else { - if self.is_account_exist(&account.address) { + if self.is_account_exist(&account.address)? { account_list.push(account); i += 1; info!("watch timeout.") @@ -511,7 +511,7 @@ impl TxnMocker { let result = match seq_number_in_pool { Some(n) => Some(n), None => { - let state_reader = RemoteStateReader::new(&self.client); + let state_reader = RemoteStateReader::new(&self.client)?; let account_state_reader = AccountStateReader::new(&state_reader); let account_resource = account_state_reader.get_account_resource(&address)?; diff --git a/rpc/api/src/state/mod.rs b/rpc/api/src/state/mod.rs index cf674f1aa1..de9570e85e 100644 --- a/rpc/api/src/state/mod.rs +++ b/rpc/api/src/state/mod.rs @@ -27,4 +27,11 @@ pub trait StateApi { #[rpc(name = "state.get_state_root")] fn get_state_root(&self) -> FutureResult; + + #[rpc(name = "state.get_with_proof_by_root")] + fn get_with_proof_by_root( + &self, + access_path: AccessPath, + state_root: HashValue, + ) -> FutureResult; } diff --git a/rpc/client/src/lib.rs b/rpc/client/src/lib.rs index 194893a9fc..50ccee49ad 100644 --- a/rpc/client/src/lib.rs +++ b/rpc/client/src/lib.rs @@ -412,6 +412,21 @@ impl RpcClient { .map_err(map_err) } + pub fn state_get_with_proof_by_root( + &self, + access_path: AccessPath, + state_root: HashValue, + ) -> anyhow::Result { + self.call_rpc_blocking(|inner| async move { + inner + .state_client + .get_with_proof_by_root(access_path, state_root) + .compat() + .await + }) + .map_err(map_err) + } + pub fn state_get_state_root(&self) -> anyhow::Result { self.call_rpc_blocking( |inner| async move { inner.state_client.get_state_root().compat().await }, diff --git a/rpc/client/src/remote_state_reader.rs b/rpc/client/src/remote_state_reader.rs index 41a39ec2ee..06e5a6b119 100644 --- a/rpc/client/src/remote_state_reader.rs +++ b/rpc/client/src/remote_state_reader.rs @@ -13,11 +13,17 @@ use starcoin_types::state_set::ChainStateSet; pub struct RemoteStateReader<'a> { //TODO add cache. client: &'a RpcClient, + state_root: HashValue, } impl<'a> RemoteStateReader<'a> { - pub fn new(client: &'a RpcClient) -> Self { - Self { client } + pub fn new(client: &'a RpcClient) -> Result { + let state_root = client.state_get_state_root()?; + Ok(Self::new_with_root(client, state_root)) + } + + pub fn new_with_root(client: &'a RpcClient, state_root: HashValue) -> Self { + Self { client, state_root } } } @@ -32,9 +38,7 @@ impl<'a> ChainStateReader for RemoteStateReader<'a> { fn state_root(&self) -> HashValue { //TODO change trait api to return Result - self.client - .state_get_state_root() - .expect("unexpected error.") + self.state_root } fn dump(&self) -> Result { @@ -44,7 +48,11 @@ impl<'a> ChainStateReader for RemoteStateReader<'a> { impl<'a> StateView for RemoteStateReader<'a> { fn get(&self, access_path: &AccessPath) -> Result>> { - self.client.state_get(access_path.clone()) + Ok(self + .client + .state_get_with_proof_by_root(access_path.clone(), self.state_root())? + .get_state() + .clone()) } fn multi_get(&self, _access_paths: &[AccessPath]) -> Result>>> { diff --git a/rpc/server/src/module/state_rpc.rs b/rpc/server/src/module/state_rpc.rs index a0711c04a4..07b0333cce 100644 --- a/rpc/server/src/module/state_rpc.rs +++ b/rpc/server/src/module/state_rpc.rs @@ -72,4 +72,17 @@ where let fut = self.service.clone().state_root().map_err(map_err); Box::new(fut.compat()) } + + fn get_with_proof_by_root( + &self, + access_path: AccessPath, + state_root: HashValue, + ) -> FutureResult { + let fut = self + .service + .clone() + .get_with_proof_by_root(access_path, state_root) + .map_err(map_err); + Box::new(fut.compat()) + } } diff --git a/state/api/src/chain_state.rs b/state/api/src/chain_state.rs index 080b8118d7..aea64f6e42 100644 --- a/state/api/src/chain_state.rs +++ b/state/api/src/chain_state.rs @@ -98,6 +98,10 @@ impl StateWithProof { pub fn new(state: Option>, proof: StateProof) -> Self { Self { state, proof } } + + pub fn get_state(&self) -> &Option> { + &self.state + } } pub trait ChainStateReader: StateView { diff --git a/testsuite/tests/steps/transaction.rs b/testsuite/tests/steps/transaction.rs index 1342a51438..afc504828e 100644 --- a/testsuite/tests/steps/transaction.rs +++ b/testsuite/tests/steps/transaction.rs @@ -24,7 +24,7 @@ pub fn steps() -> Steps { let result = transfer_txn(client, to, pre_mine_address, None); assert!(result.is_ok()); std::thread::sleep(Duration::from_millis(3000)); - let chain_state_reader = RemoteStateReader::new(client); + let chain_state_reader = RemoteStateReader::new(client).unwrap(); let account_state_reader = AccountStateReader::new(&chain_state_reader); let balances = account_state_reader.get_balance(to.address()); assert!(balances.is_ok()); @@ -50,7 +50,7 @@ fn transfer_txn( from: AccountAddress, amount: Option, ) -> Result<(), Error> { - let chain_state_reader = RemoteStateReader::new(client); + let chain_state_reader = RemoteStateReader::new(client)?; let account_state_reader = AccountStateReader::new(&chain_state_reader); let account_resource = account_state_reader .get_account_resource(&from)