Skip to content

Commit

Permalink
Merge 9d57701 into e48ca93
Browse files Browse the repository at this point in the history
  • Loading branch information
jolestar authored Jun 23, 2021
2 parents e48ca93 + 9d57701 commit b6419b8
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 60 deletions.
95 changes: 56 additions & 39 deletions cmd/starcoin/src/cli_state.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// Copyright (c) The Starcoin Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::view::{ExecuteResultView, ExecutionOutputView, TransactionOptions};
use anyhow::{format_err, Result};
use crate::view::{DryRunOutputView, ExecuteResultView, ExecutionOutputView, TransactionOptions};
use anyhow::{bail, format_err, Result};
use starcoin_account_api::AccountInfo;
use starcoin_config::{ChainNetworkID, DataDirPath};
use starcoin_crypto::HashValue;
Expand Down Expand Up @@ -150,57 +150,69 @@ impl CliState {
txn_opts: TransactionOptions,
payload: TransactionPayload,
) -> Result<ExecuteResultView> {
self.execute_transaction(
self.build_transaction(
txn_opts.sender,
txn_opts.gas_price,
txn_opts.max_gas_amount,
txn_opts.expiration_time_secs,
payload,
)?,
txn_opts.dry_run,
txn_opts.blocking,
)
let (raw_txn, future_transaction) = self.build_transaction(
txn_opts.sender,
txn_opts.sequence_number,
txn_opts.gas_unit_price,
txn_opts.max_gas_amount,
txn_opts.expiration_time_secs,
payload,
)?;
if future_transaction {
//TODO figure out more graceful method to handle future transaction.
bail!("there is transaction from sender({}) in the txpool, please wait it to been executed or use sequence_number({}) to replace it.",raw_txn.sender(), raw_txn.sequence_number()-1);
}
self.execute_transaction(raw_txn, txn_opts.dry_run, txn_opts.blocking)
}

pub fn build_transaction(
fn build_transaction(
&self,
sender: Option<AccountAddress>,
sequence_number: Option<u64>,
gas_price: Option<u64>,
max_gas_amount: Option<u64>,
expiration_time_secs: Option<u64>,
payload: TransactionPayload,
) -> Result<RawUserTransaction> {
) -> Result<(RawUserTransaction, bool)> {
let chain_id = self.net().chain_id();
let sender = self.get_account_or_default(sender)?;
let sequence_number = match self.client.next_sequence_number_in_txpool(sender.address)? {
Some(sequence_number) => sequence_number,
None => {
let chain_state_reader = RemoteStateReader::new(&self.client)?;
chain_state_reader
.get_account_resource(*sender.address())?
.map(|account| account.sequence_number())
.ok_or_else(|| {
format_err!(
"Can not find account on chain by address:{}",
sender.address()
)
})?
}
let (sequence_number, future_transaction) = match sequence_number {
Some(sequence_number) => (sequence_number, false),
None => match self.client.next_sequence_number_in_txpool(sender.address)? {
Some(sequence_number) => {
eprintln!("get sequence_number {} from txpool", sequence_number);
(sequence_number, true)
}
None => {
let chain_state_reader = RemoteStateReader::new(&self.client)?;
chain_state_reader
.get_account_resource(*sender.address())?
.map(|account| (account.sequence_number(), false))
.ok_or_else(|| {
format_err!(
"Can not find account on chain by address:{}",
sender.address()
)
})?
}
},
};
let node_info = self.client.node_info()?;
let expiration_timestamp_secs = expiration_time_secs
.unwrap_or(Self::DEFAULT_EXPIRATION_TIME_SECS)
+ node_info.now_seconds;
Ok(RawUserTransaction::new(
sender.address,
sequence_number,
payload,
max_gas_amount.unwrap_or(Self::DEFAULT_MAX_GAS_AMOUNT),
gas_price.unwrap_or(Self::DEFAULT_GAS_PRICE),
expiration_timestamp_secs,
chain_id,
Self::DEFAULT_GAS_TOKEN.to_string(),
Ok((
RawUserTransaction::new(
sender.address,
sequence_number,
payload,
max_gas_amount.unwrap_or(Self::DEFAULT_MAX_GAS_AMOUNT),
gas_price.unwrap_or(Self::DEFAULT_GAS_PRICE),
expiration_timestamp_secs,
chain_id,
Self::DEFAULT_GAS_TOKEN.to_string(),
),
future_transaction,
))
}

Expand All @@ -227,7 +239,12 @@ impl CliState {
TransactionStatus::Keep(KeptVMStatus::Executed)
)
{
return Ok(ExecuteResultView::DryRun((vm_status, output.into())));
eprintln!("txn dry run failed");
return Ok(ExecuteResultView::DryRun(DryRunOutputView::new(
vm_status,
output.into(),
hex::encode(bcs_ext::to_bytes(&raw_txn)?),
)));
}
let signed_txn = self.client.account_sign_txn(raw_txn)?;

Expand Down
60 changes: 39 additions & 21 deletions cmd/starcoin/src/view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,34 +69,31 @@ pub struct TransactionOptions {
/// the account address for signing transaction, if `sender` is absent, use default account.
pub sender: Option<AccountAddress>,

#[structopt(
short = "g",
name = "max-gas-amount",
help = "max gas used to deploy the module"
)]
#[structopt(long = "sequence-number")]
/// transaction's sequence_number
/// if a transaction in the pool, you want to replace it, can use this option to set transaction's sequence_number
/// otherwise please let cli to auto get sequence_number from onchain and txpool.
pub sequence_number: Option<u64>,

#[structopt(short = "g", name = "max-gas-amount")]
/// max gas used to deploy the module
pub max_gas_amount: Option<u64>,

#[structopt(
short = "p",
long = "gas-price",
name = "price of gas",
help = "gas price used to deploy the module"
long = "gas_unit_price",
alias = "gas-price",
name = "price of gas"
)]
pub gas_price: Option<u64>,
/// gas price used to deploy the module
pub gas_unit_price: Option<u64>,

#[structopt(
name = "expiration-time-secs",
long = "expiration-time-secs",
help = "how long(in seconds) the txn stay alive from now"
)]
#[structopt(name = "expiration-time-secs", long = "expiration-time-secs")]
/// how long(in seconds) the txn stay alive from now
pub expiration_time_secs: Option<u64>,

#[structopt(
short = "b",
name = "blocking-mode",
long = "blocking",
help = "blocking wait txn mined"
)]
#[structopt(short = "b", name = "blocking-mode", long = "blocking")]
/// blocking wait txn mined
pub blocking: bool,

#[structopt(long = "dry-run")]
Expand Down Expand Up @@ -295,10 +292,31 @@ impl From<ContractEvent> for EventView {
#[derive(Debug, Serialize)]
#[serde(tag = "type")]
pub enum ExecuteResultView {
DryRun((VMStatus, TransactionOutputView)),
DryRun(DryRunOutputView),
Run(ExecutionOutputView),
}

#[derive(Serialize, Debug, Clone)]
pub struct DryRunOutputView {
pub vm_status: VMStatus,
pub output: TransactionOutputView,
pub raw_transaction_hex: String,
}

impl DryRunOutputView {
pub fn new(
vm_status: VMStatus,
output: TransactionOutputView,
raw_transaction_hex: String,
) -> Self {
Self {
vm_status,
output,
raw_transaction_hex,
}
}
}

#[derive(Serialize, Debug, Clone)]
pub struct ExecutionOutputView {
pub txn_hash: HashValue,
Expand Down

0 comments on commit b6419b8

Please sign in to comment.