Skip to content

Commit

Permalink
[cli] Use simulation errors from API
Browse files Browse the repository at this point in the history
The API errors for simulation are fixed, so we will use those now
in the cli rather than fetching from the ABI
  • Loading branch information
gregnazario committed Nov 9, 2022
1 parent a225278 commit cef25a4
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 35 deletions.
47 changes: 28 additions & 19 deletions crates/aptos-rest-client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ use anyhow::{anyhow, Result};
use aptos_api_types::{
deserialize_from_string,
mime_types::{BCS, BCS_SIGNED_TRANSACTION as BCS_CONTENT_TYPE},
AptosError, BcsBlock, Block, Bytecode, ExplainVMStatus, GasEstimation, HexEncodedBytes,
IndexResponse, MoveModuleId, TransactionData, TransactionOnChainData,
TransactionsBatchSubmissionResult, UserTransaction, VersionedEvent,
AptosError, BcsBlock, Block, GasEstimation, HexEncodedBytes, IndexResponse, MoveModuleId,
TransactionData, TransactionOnChainData, TransactionsBatchSubmissionResult, UserTransaction,
VersionedEvent,
};
use aptos_crypto::HashValue;
use aptos_logger::{debug, info, sample, sample::SampleRate};
Expand All @@ -37,16 +37,13 @@ use aptos_types::{
contract_event::EventWithVersion,
transaction::SignedTransaction,
};
use futures::executor::block_on;
use move_binary_format::CompiledModule;
use move_core_types::language_storage::{ModuleId, StructTag};
use move_core_types::language_storage::StructTag;
use reqwest::header::ACCEPT;
use reqwest::{header::CONTENT_TYPE, Client as ReqwestClient, StatusCode};
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use serde_json::{json, Value};
use std::collections::BTreeMap;
use std::future::Future;
use std::rc::Rc;
use std::time::Duration;
use tokio::time::Instant;
use url::Url;
Expand Down Expand Up @@ -323,6 +320,30 @@ impl Client {
self.json(response).await
}

pub async fn simulate_with_gas_estimation(
&self,
txn: &SignedTransaction,
estimate_max_gas_amount: bool,
estimate_max_gas_unit_price: bool,
) -> AptosResult<Response<Vec<UserTransaction>>> {
let txn_payload = bcs::to_bytes(txn)?;

let url = self.build_path(&format!(
"transactions/simulate?estimate_max_gas_amount={}&estimate_gas_unit_price={}",
estimate_max_gas_amount, estimate_max_gas_unit_price
))?;

let response = self
.inner
.post(url)
.header(CONTENT_TYPE, BCS_CONTENT_TYPE)
.body(txn_payload)
.send()
.await?;

self.json(response).await
}

pub async fn simulate_bcs(
&self,
txn: &SignedTransaction,
Expand Down Expand Up @@ -1450,15 +1471,3 @@ enum WaitForTransactionResult<T> {
Pending(State),
Success(Response<T>),
}

impl ExplainVMStatus for Client {
// TODO: Add some caching
fn get_module_bytecode(&self, module_id: &ModuleId) -> Result<Rc<dyn Bytecode>> {
let bytes =
block_on(self.get_account_module_bcs(*module_id.address(), module_id.name().as_str()))?
.into_inner();

let compiled_module = CompiledModule::deserialize(bytes.as_ref())?;
Ok(Rc::new(compiled_module) as Rc<dyn Bytecode>)
}
}
28 changes: 12 additions & 16 deletions crates/aptos/src/common/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use aptos_crypto::{
};
use aptos_global_constants::adjust_gas_headroom;
use aptos_keygen::KeyGen;
use aptos_rest_client::aptos_api_types::{ExplainVMStatus, HashValue, UserTransaction};
use aptos_rest_client::aptos_api_types::{HashValue, UserTransaction};
use aptos_rest_client::error::RestError;
use aptos_rest_client::{Client, Transaction};
use aptos_sdk::{transaction_builder::TransactionFactory, types::LocalAccount};
Expand Down Expand Up @@ -1333,32 +1333,28 @@ impl TransactionOptions {
Ed25519Signature::try_from([0u8; 64].as_ref()).unwrap(),
);
// TODO: Cleanup to use the gas price estimation here
let simulated_txn = client
.simulate_bcs_with_gas_estimation(&signed_transaction, true, false)
let txns = client
.simulate_with_gas_estimation(&signed_transaction, true, false)
.await?
.into_inner();
let simulated_txn = txns.first().unwrap();

// Check if the transaction will pass, if it doesn't then fail
// TODO: Add move resolver so we can explain the VM status with a proper error map
let status = simulated_txn.info.status();
if !status.is_success() {
let status = client.explain_vm_status(status);
return Err(CliError::SimulationError(status));
if simulated_txn.info.success {
return Err(CliError::SimulationError(
simulated_txn.info.vm_status.clone(),
));
}

// Take the gas used and use a headroom factor on it
let adjusted_max_gas = adjust_gas_headroom(
simulated_txn.info.gas_used(),
simulated_txn
.transaction
.as_signed_user_txn()
.expect("Should be signed user transaction")
.max_gas_amount(),
);
let gas_used = simulated_txn.info.gas_used.0;
let adjusted_max_gas =
adjust_gas_headroom(gas_used, simulated_txn.request.max_gas_amount.0);

// Ask if you want to accept the estimate amount
let upper_cost_bound = adjusted_max_gas * gas_unit_price;
let lower_cost_bound = simulated_txn.info.gas_used() * gas_unit_price;
let lower_cost_bound = gas_used * gas_unit_price;
let message = format!(
"Do you want to submit a transaction for a range of [{} - {}] Octas at a gas unit price of {} Octas?",
lower_cost_bound,
Expand Down

0 comments on commit cef25a4

Please sign in to comment.