Skip to content

Commit

Permalink
feat: fvm: pass all GasCharges to the client
Browse files Browse the repository at this point in the history
  • Loading branch information
arajasek committed Feb 10, 2023
1 parent 9e4fe75 commit 8af9f29
Showing 1 changed file with 59 additions and 18 deletions.
77 changes: 59 additions & 18 deletions rust/src/fvm/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@ use std::convert::{TryFrom, TryInto};
use anyhow::{anyhow, Context};
use cid::Cid;
use fvm3::executor::ApplyKind as ApplyKind3;
use fvm3::gas::GasCharge;
use fvm3::gas::{Gas, GasCharge};
use fvm3::trace::ExecutionEvent;
use fvm3_ipld_encoding::tuple::{Deserialize_tuple, Serialize_tuple};
use fvm3_ipld_encoding::{to_vec, CborStore, RawBytes};
use fvm3_shared::address::Address;
use num_traits::Zero;

use fvm3_shared::error::{ErrorNumber, ExitCode};
use fvm3_shared::receipt::Receipt;
Expand Down Expand Up @@ -204,16 +205,21 @@ fn fvm_machine_execute_message(

let exec_trace = if !apply_ret.exec_trace.is_empty() {
let mut trace_iter = apply_ret.exec_trace.into_iter();
build_lotus_trace(
(&mut trace_iter)
// Skip gas charges before the first call, if any. Lotus can't handle them.
.find(|item| !matches!(item, &ExecutionEvent::GasCharge(_)))
.expect("already checked trace for emptiness"),
&mut trace_iter,
)
.ok()
.and_then(|t| to_vec(&t).ok())
.map(|trace| trace.into_boxed_slice().into())
let initial_gas_charges: Vec<GasCharge> = trace_iter
.clone()
.take_while(|e| matches!(e, &ExecutionEvent::GasCharge(_)))
.map(|e| match e {
ExecutionEvent::GasCharge(gc) => gc,
_ => GasCharge::new("none", Gas::zero(), Gas::zero()),
})
.collect();
match trace_iter.nth(initial_gas_charges.len()) {
Some(c) => build_lotus_trace(initial_gas_charges, c, &mut trace_iter)
.ok()
.and_then(|t| to_vec(&t).ok())
.map(|trace| trace.into_boxed_slice().into()),
_ => None,
}
} else {
None
};
Expand Down Expand Up @@ -312,12 +318,12 @@ destructor!(

destructor!(destroy_fvm_machine_flush_response, Result<c_slice::Box<u8>>);

#[derive(Clone, Debug, Serialize_tuple, Deserialize_tuple)]
#[derive(Clone, Debug, PartialEq, Eq, Serialize_tuple, Deserialize_tuple)]
struct LotusGasCharge {
pub name: Cow<'static, str>,
pub total_gas: u64,
pub compute_gas: u64,
pub storage_gas: u64,
pub other_gas: u64,
}

#[derive(Clone, Debug, Serialize_tuple, Deserialize_tuple)]
Expand All @@ -337,6 +343,7 @@ pub struct LotusReceipt {
}

fn build_lotus_trace(
initial_gas_charges: Vec<GasCharge>,
new_call: ExecutionEvent,
trace_iter: &mut impl Iterator<Item = ExecutionEvent>,
) -> anyhow::Result<LotusTrace> {
Expand Down Expand Up @@ -370,7 +377,23 @@ fn build_lotus_trace(
gas_used: 0,
},
error: String::new(),
gas_charges: vec![],
gas_charges: initial_gas_charges
.iter()
.cloned()
.map(
|GasCharge {
name,
compute_gas,
other_gas,
elapsed: _, // TODO: thread timing through to lotus.
}| LotusGasCharge {
name,
total_gas: (compute_gas + other_gas).round_up(),
compute_gas: compute_gas.round_up(),
other_gas: other_gas.round_up(),
},
)
.collect(),
subcalls: vec![],
};

Expand All @@ -379,7 +402,7 @@ fn build_lotus_trace(
ExecutionEvent::Call { .. } => {
new_trace
.subcalls
.push(build_lotus_trace(trace, trace_iter)?);
.push(build_lotus_trace(vec![], trace, trace_iter)?);
}
ExecutionEvent::CallReturn(exit_code, return_data) => {
new_trace.msg_receipt = LotusReceipt {
Expand Down Expand Up @@ -416,7 +439,7 @@ fn build_lotus_trace(
name,
total_gas: (compute_gas + other_gas).round_up(),
compute_gas: compute_gas.round_up(),
storage_gas: other_gas.round_up(),
other_gas: other_gas.round_up(),
});
}
_ => (), // ignore unknown events.
Expand All @@ -428,7 +451,9 @@ fn build_lotus_trace(

#[cfg(test)]
mod test {
use crate::fvm::machine::build_lotus_trace;
use crate::fvm::machine::{build_lotus_trace, LotusGasCharge};
use fvm3::gas::Gas;
use fvm3::gas::GasCharge;
use fvm3::kernel::SyscallError;
use fvm3::trace::ExecutionEvent;
use fvm3_shared::address::Address;
Expand Down Expand Up @@ -460,10 +485,26 @@ mod test {

let mut trace_iter = trace.into_iter();

let lotus_trace = build_lotus_trace(trace_iter.next().unwrap(), &mut trace_iter).unwrap();
let initial_gas_charge = GasCharge::new("gas_test", Gas::new(1), Gas::new(2));
let lotus_trace = build_lotus_trace(
vec![initial_gas_charge.clone()],
trace_iter.next().unwrap(),
&mut trace_iter,
)
.unwrap();

assert!(trace_iter.next().is_none());

assert_eq!(lotus_trace.gas_charges.len(), 1);
assert_eq!(
*lotus_trace.gas_charges.get(0).unwrap(),
LotusGasCharge {
name: initial_gas_charge.clone().name,
total_gas: initial_gas_charge.total().round_up(),
compute_gas: initial_gas_charge.compute_gas.round_up(),
other_gas: initial_gas_charge.other_gas.round_up(),
}
);
assert_eq!(lotus_trace.subcalls.len(), 2);
assert_eq!(lotus_trace.subcalls[0].subcalls.len(), 0);
assert_eq!(lotus_trace.subcalls[1].subcalls.len(), 1);
Expand Down

0 comments on commit 8af9f29

Please sign in to comment.