Skip to content

Commit

Permalink
feat(iota): add --dev-inspect flag to CLI (#5021)
Browse files Browse the repository at this point in the history
* feat(iota): add dev-inspect flag to CLI

* fix(iota): dev inspect in iota client ptb

* clippy

* handle possible empty gas_payment vec
  • Loading branch information
Thoralf-M authored Jan 24, 2025
1 parent d33a093 commit 6007611
Show file tree
Hide file tree
Showing 9 changed files with 197 additions and 7 deletions.
95 changes: 88 additions & 7 deletions crates/iota/src/client_commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ use fastcrypto::{
};
use iota_json::IotaJsonValue;
use iota_json_rpc_types::{
Coin, DryRunTransactionBlockResponse, DynamicFieldPage, IotaCoinMetadata, IotaData,
IotaExecutionStatus, IotaObjectData, IotaObjectDataOptions, IotaObjectResponse,
IotaObjectResponseQuery, IotaParsedData, IotaProtocolConfigValue, IotaRawData,
IotaTransactionBlockEffects, IotaTransactionBlockEffectsAPI, IotaTransactionBlockResponse,
IotaTransactionBlockResponseOptions,
Coin, DevInspectArgs, DevInspectResults, DryRunTransactionBlockResponse, DynamicFieldPage,
IotaCoinMetadata, IotaData, IotaExecutionStatus, IotaObjectData, IotaObjectDataOptions,
IotaObjectResponse, IotaObjectResponseQuery, IotaParsedData, IotaProtocolConfigValue,
IotaRawData, IotaTransactionBlockEffects, IotaTransactionBlockEffectsAPI,
IotaTransactionBlockResponse, IotaTransactionBlockResponseOptions,
};
use iota_keys::keystore::AccountKeystore;
use iota_move::manage_package::resolve_lock_file_path;
Expand Down Expand Up @@ -54,6 +54,7 @@ use iota_types::{
error::IotaError,
gas::GasCostSummary,
gas_coin::GasCoin,
iota_serde,
message_envelope::Envelope,
metrics::BytecodeVerifierMetrics,
move_package::UpgradeCap,
Expand Down Expand Up @@ -561,6 +562,9 @@ pub struct Opts {
/// Perform a dry run of the transaction, without executing it.
#[arg(long)]
pub dry_run: bool,
/// Perform a dev inspect of the transaction, without executing it.
#[arg(long)]
pub dev_inspect: bool,
/// Instead of executing the transaction, serialize the bcs bytes of the
/// unsigned transaction data (TransactionData) using base64 encoding,
/// and print out the string <TX_BYTES>. The string can be used to
Expand Down Expand Up @@ -604,6 +608,7 @@ impl Opts {
Self {
gas_budget: Some(gas_budget),
dry_run: false,
dev_inspect: false,
serialize_unsigned_transaction: false,
serialize_signed_transaction: false,
emit: HashSet::new(),
Expand All @@ -616,6 +621,7 @@ impl Opts {
Self {
gas_budget: Some(gas_budget),
dry_run: true,
dev_inspect: false,
serialize_unsigned_transaction: false,
serialize_signed_transaction: false,
emit: HashSet::new(),
Expand All @@ -629,6 +635,7 @@ impl Opts {
Self {
gas_budget: Some(gas_budget),
dry_run: false,
dev_inspect: false,
serialize_unsigned_transaction: false,
serialize_signed_transaction: false,
emit,
Expand Down Expand Up @@ -2223,6 +2230,9 @@ impl Display for IotaClientCommandResult {
IotaClientCommandResult::DryRun(response) => {
writeln!(f, "{}", Pretty(response))?;
}
IotaClientCommandResult::DevInspect(response) => {
writeln!(f, "{}", Pretty(response))?;
}
}
write!(f, "{}", writer.trim_end_matches('\n'))
}
Expand Down Expand Up @@ -2325,6 +2335,7 @@ impl IotaClientCommandResult {
| IotaClientCommandResult::Balance(_, _)
| IotaClientCommandResult::ChainIdentifier(_)
| IotaClientCommandResult::DynamicFieldQuery(_)
| IotaClientCommandResult::DevInspect(_)
| IotaClientCommandResult::Envs(_, _)
| IotaClientCommandResult::Gas(_)
| IotaClientCommandResult::NewAddress(_)
Expand Down Expand Up @@ -2474,6 +2485,7 @@ pub enum IotaClientCommandResult {
ChainIdentifier(String),
DynamicFieldQuery(DynamicFieldPage),
DryRun(DryRunTransactionBlockResponse),
DevInspect(DevInspectResults),
Envs(Vec<IotaEnv>, Option<String>),
Gas(Vec<GasCoin>),
NewAddress(NewAddressOutput),
Expand Down Expand Up @@ -2804,8 +2816,15 @@ pub(crate) async fn dry_run_or_execute_or_serialize(
gas: Option<ObjectID>,
opts: Opts,
) -> Result<IotaClientCommandResult, anyhow::Error> {
let (dry_run, gas_budget, serialize_unsigned_transaction, serialize_signed_transaction) = (
let (
dry_run,
dev_inspect,
gas_budget,
serialize_unsigned_transaction,
serialize_signed_transaction,
) = (
opts.dry_run,
opts.dev_inspect,
opts.gas_budget,
opts.serialize_unsigned_transaction,
opts.serialize_signed_transaction,
Expand All @@ -2820,12 +2839,27 @@ pub(crate) async fn dry_run_or_execute_or_serialize(
context.get_reference_gas_price().await?
};

let client = context.get_client().await?;

if dev_inspect {
return execute_dev_inspect(
context,
signer,
tx_kind,
gas_budget,
gas_price,
gas_payment,
None,
None,
)
.await;
}

let gas = match gas_payment {
Some(obj_ids) => Some(obj_ids),
None => gas.map(|x| vec![x]),
};

let client = context.get_client().await?;
if dry_run {
return execute_dry_run(
context,
Expand Down Expand Up @@ -2916,6 +2950,53 @@ pub(crate) async fn dry_run_or_execute_or_serialize(
}
}

async fn execute_dev_inspect(
context: &mut WalletContext,
signer: IotaAddress,
tx_kind: TransactionKind,
gas_budget: Option<u64>,
gas_price: u64,
gas_payment: Option<Vec<ObjectID>>,
gas_sponsor: Option<IotaAddress>,
skip_checks: Option<bool>,
) -> Result<IotaClientCommandResult, anyhow::Error> {
let client = context.get_client().await?;
let gas_budget = gas_budget.map(iota_serde::BigInt::from);
let mut gas_objs = vec![];
let gas_objects = if let Some(gas_payment) = gas_payment {
if gas_payment.is_empty() {
None
} else {
for o in gas_payment.iter() {
let obj_ref = context.get_object_ref(*o).await?;
gas_objs.push(obj_ref);
}
Some(gas_objs)
}
} else {
None
};

let dev_inspect_args = DevInspectArgs {
gas_sponsor,
gas_budget,
gas_objects,
skip_checks,
show_raw_txn_data_and_effects: None,
};
let dev_inspect_result = client
.read_api()
.dev_inspect_transaction_block(
signer,
tx_kind,
Some(iota_serde::BigInt::from(gas_price)),
None,
Some(dev_inspect_args),
)
.await?;
Ok(IotaClientCommandResult::DevInspect(dev_inspect_result))
}

pub(crate) async fn prerender_clever_errors(
effects: &mut IotaTransactionBlockEffects,
read_api: &ReadApi,
Expand Down
3 changes: 3 additions & 0 deletions crates/iota/src/client_ptb/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ pub const SUMMARY: &str = "summary";
pub const GAS_COIN: &str = "gas-coin";
pub const JSON: &str = "json";
pub const DRY_RUN: &str = "dry-run";
pub const DEV_INSPECT: &str = "dev-inspect";
pub const SERIALIZE_UNSIGNED: &str = "serialize-unsigned-transaction";
pub const SERIALIZE_SIGNED: &str = "serialize-signed-transaction";

Expand Down Expand Up @@ -74,6 +75,7 @@ pub const COMMANDS: &[&str] = &[
GAS_COIN,
JSON,
DRY_RUN,
DEV_INSPECT,
SERIALIZE_UNSIGNED,
SERIALIZE_SIGNED,
];
Expand Down Expand Up @@ -111,6 +113,7 @@ pub struct ProgramMetadata {
pub gas_object_id: Option<Spanned<ObjectID>>,
pub json_set: bool,
pub dry_run_set: bool,
pub dev_inspect_set: bool,
pub gas_budget: Option<Spanned<u64>>,
}

Expand Down
4 changes: 4 additions & 0 deletions crates/iota/src/client_ptb/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ struct ProgramParsingState {
serialize_signed_set: bool,
json_set: bool,
dry_run_set: bool,
dev_inspect_set: bool,
gas_object_id: Option<Spanned<ObjectID>>,
gas_budget: Option<Spanned<u64>>,
}
Expand All @@ -63,6 +64,7 @@ impl<'a, I: Iterator<Item = &'a str>> ProgramParser<'a, I> {
serialize_signed_set: false,
json_set: false,
dry_run_set: false,
dev_inspect_set: false,
gas_object_id: None,
gas_budget: None,
},
Expand Down Expand Up @@ -111,6 +113,7 @@ impl<'a, I: Iterator<Item = &'a str>> ProgramParser<'a, I> {
L(T::Command, A::SUMMARY) => flag!(summary_set),
L(T::Command, A::JSON) => flag!(json_set),
L(T::Command, A::DRY_RUN) => flag!(dry_run_set),
L(T::Command, A::DEV_INSPECT) => flag!(dev_inspect_set),
L(T::Command, A::PREVIEW) => flag!(preview_set),
L(T::Command, A::WARN_SHADOWS) => flag!(warn_shadows_set),
L(T::Command, A::GAS_COIN) => {
Expand Down Expand Up @@ -208,6 +211,7 @@ impl<'a, I: Iterator<Item = &'a str>> ProgramParser<'a, I> {
gas_object_id: self.state.gas_object_id,
json_set: self.state.json_set,
dry_run_set: self.state.dry_run_set,
dev_inspect_set: self.state.dev_inspect_set,
gas_budget: self.state.gas_budget,
},
))
Expand Down
9 changes: 9 additions & 0 deletions crates/iota/src/client_ptb/ptb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ impl PTB {
gas: program_metadata.gas_object_id.map(|x| x.value),
rest: Opts {
dry_run: program_metadata.dry_run_set,
dev_inspect: program_metadata.dev_inspect_set,
gas_budget: program_metadata.gas_budget.map(|x| x.value),
serialize_unsigned_transaction: program_metadata.serialize_unsigned_set,
serialize_signed_transaction: program_metadata.serialize_signed_set,
Expand All @@ -176,6 +177,10 @@ impl PTB {
return Ok(());
}
IotaClientCommandResult::TransactionBlock(response) => response,
IotaClientCommandResult::DevInspect(response) => {
println!("{}", Pretty(&response));
return Ok(());
}
_ => anyhow::bail!("Internal error, unexpected response from PTB execution."),
};

Expand Down Expand Up @@ -299,6 +304,10 @@ pub fn ptb_description() -> clap::Command {
--"dry-run"
"Perform a dry run of the PTB instead of executing it."
))
.arg(arg!(
--"dev-inspect"
"Perform a dev-inspect of the PTB instead of executing it."
))
.arg(arg!(
--"gas-coin" <ID> ...
"The object ID of the gas coin to use. If not specified, it will try to use the first \
Expand Down
Loading

0 comments on commit 6007611

Please sign in to comment.