Skip to content

Commit 4c503e5

Browse files
authored
Merge pull request #365 from filecoin-project/asr/gas-charges
feat: fvm: pass all GasCharges to the client
2 parents 9e4fe75 + 58d2465 commit 4c503e5

File tree

1 file changed

+84
-44
lines changed

1 file changed

+84
-44
lines changed

rust/src/fvm/machine.rs

Lines changed: 84 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use cid::Cid;
66
use fvm3::executor::ApplyKind as ApplyKind3;
77
use fvm3::gas::GasCharge;
88
use fvm3::trace::ExecutionEvent;
9+
use fvm3_ipld_encoding::ipld_block::IpldBlock;
910
use fvm3_ipld_encoding::tuple::{Deserialize_tuple, Serialize_tuple};
1011
use fvm3_ipld_encoding::{to_vec, CborStore, RawBytes};
1112
use fvm3_shared::address::Address;
@@ -204,19 +205,38 @@ fn fvm_machine_execute_message(
204205

205206
let exec_trace = if !apply_ret.exec_trace.is_empty() {
206207
let mut trace_iter = apply_ret.exec_trace.into_iter();
207-
build_lotus_trace(
208-
(&mut trace_iter)
209-
// Skip gas charges before the first call, if any. Lotus can't handle them.
210-
.find(|item| !matches!(item, &ExecutionEvent::GasCharge(_)))
211-
.expect("already checked trace for emptiness"),
212-
&mut trace_iter,
213-
)
214-
.ok()
215-
.and_then(|t| to_vec(&t).ok())
216-
.map(|trace| trace.into_boxed_slice().into())
208+
let mut initial_gas_charges = Vec::new();
209+
loop {
210+
match trace_iter.next() {
211+
Some(gc @ ExecutionEvent::GasCharge(_)) => initial_gas_charges.push(gc),
212+
Some(ExecutionEvent::Call {
213+
from,
214+
to,
215+
method,
216+
params,
217+
value,
218+
}) => {
219+
break build_lotus_trace(
220+
from,
221+
to,
222+
method,
223+
params,
224+
value,
225+
&mut initial_gas_charges.into_iter().chain(&mut trace_iter),
226+
)
227+
.ok()
228+
}
229+
// Skip anything unexpected.
230+
Some(_) => {}
231+
// Return none if we don't even have a call.
232+
None => break None,
233+
}
234+
}
217235
} else {
218236
None
219-
};
237+
}
238+
.and_then(|t| to_vec(&t).ok())
239+
.map(|trace| trace.into_boxed_slice().into());
220240

221241
let failure_info = apply_ret
222242
.failure_info
@@ -312,12 +332,12 @@ destructor!(
312332

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

315-
#[derive(Clone, Debug, Serialize_tuple, Deserialize_tuple)]
335+
#[derive(Clone, Debug, PartialEq, Eq, Serialize_tuple, Deserialize_tuple)]
316336
struct LotusGasCharge {
317337
pub name: Cow<'static, str>,
318338
pub total_gas: u64,
319339
pub compute_gas: u64,
320-
pub storage_gas: u64,
340+
pub other_gas: u64,
321341
}
322342

323343
#[derive(Clone, Debug, Serialize_tuple, Deserialize_tuple)]
@@ -337,32 +357,25 @@ pub struct LotusReceipt {
337357
}
338358

339359
fn build_lotus_trace(
340-
new_call: ExecutionEvent,
360+
from: u64,
361+
to: Address,
362+
method: u64,
363+
params: Option<IpldBlock>,
364+
value: TokenAmount,
341365
trace_iter: &mut impl Iterator<Item = ExecutionEvent>,
342366
) -> anyhow::Result<LotusTrace> {
343367
let mut new_trace = LotusTrace {
344-
msg: match new_call {
345-
ExecutionEvent::Call {
346-
from,
347-
to,
348-
method,
349-
params,
350-
value,
351-
} => Message {
352-
version: 0,
353-
from: Address::new_id(from),
354-
to,
355-
value,
356-
sequence: 0,
357-
method_num: method,
358-
params: params.map(|b| b.data).unwrap_or_default().into(),
359-
gas_limit: 0,
360-
gas_fee_cap: TokenAmount::default(),
361-
gas_premium: TokenAmount::default(),
362-
},
363-
_ => {
364-
return Err(anyhow!("expected ExecutionEvent of type Call"));
365-
}
368+
msg: Message {
369+
version: 0,
370+
from: Address::new_id(from),
371+
to,
372+
value,
373+
sequence: 0,
374+
method_num: method,
375+
params: params.map(|b| b.data).unwrap_or_default().into(),
376+
gas_limit: 0,
377+
gas_fee_cap: TokenAmount::default(),
378+
gas_premium: TokenAmount::default(),
366379
},
367380
msg_receipt: LotusReceipt {
368381
exit_code: ExitCode::OK,
@@ -376,10 +389,16 @@ fn build_lotus_trace(
376389

377390
while let Some(trace) = trace_iter.next() {
378391
match trace {
379-
ExecutionEvent::Call { .. } => {
380-
new_trace
381-
.subcalls
382-
.push(build_lotus_trace(trace, trace_iter)?);
392+
ExecutionEvent::Call {
393+
from,
394+
to,
395+
method,
396+
params,
397+
value,
398+
} => {
399+
new_trace.subcalls.push(build_lotus_trace(
400+
from, to, method, params, value, trace_iter,
401+
)?);
383402
}
384403
ExecutionEvent::CallReturn(exit_code, return_data) => {
385404
new_trace.msg_receipt = LotusReceipt {
@@ -416,7 +435,7 @@ fn build_lotus_trace(
416435
name,
417436
total_gas: (compute_gas + other_gas).round_up(),
418437
compute_gas: compute_gas.round_up(),
419-
storage_gas: other_gas.round_up(),
438+
other_gas: other_gas.round_up(),
420439
});
421440
}
422441
_ => (), // ignore unknown events.
@@ -428,7 +447,9 @@ fn build_lotus_trace(
428447

429448
#[cfg(test)]
430449
mod test {
431-
use crate::fvm::machine::build_lotus_trace;
450+
use crate::fvm::machine::{build_lotus_trace, LotusGasCharge};
451+
use fvm3::gas::Gas;
452+
use fvm3::gas::GasCharge;
432453
use fvm3::kernel::SyscallError;
433454
use fvm3::trace::ExecutionEvent;
434455
use fvm3_shared::address::Address;
@@ -447,8 +468,9 @@ mod test {
447468
};
448469
let return_result =
449470
ExecutionEvent::CallError(SyscallError::new(IllegalArgument, "illegal"));
471+
let initial_gas_charge = GasCharge::new("gas_test", Gas::new(1), Gas::new(2));
450472
let trace = vec![
451-
call_event.clone(),
473+
ExecutionEvent::GasCharge(initial_gas_charge.clone()),
452474
call_event.clone(),
453475
return_result.clone(),
454476
call_event.clone(),
@@ -460,10 +482,28 @@ mod test {
460482

461483
let mut trace_iter = trace.into_iter();
462484

463-
let lotus_trace = build_lotus_trace(trace_iter.next().unwrap(), &mut trace_iter).unwrap();
485+
let lotus_trace = build_lotus_trace(
486+
0,
487+
Address::new_id(0),
488+
0,
489+
None,
490+
TokenAmount::default(),
491+
&mut trace_iter,
492+
)
493+
.unwrap();
464494

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

497+
assert_eq!(lotus_trace.gas_charges.len(), 1);
498+
assert_eq!(
499+
*lotus_trace.gas_charges.get(0).unwrap(),
500+
LotusGasCharge {
501+
name: initial_gas_charge.clone().name,
502+
total_gas: initial_gas_charge.total().round_up(),
503+
compute_gas: initial_gas_charge.compute_gas.round_up(),
504+
other_gas: initial_gas_charge.other_gas.round_up(),
505+
}
506+
);
467507
assert_eq!(lotus_trace.subcalls.len(), 2);
468508
assert_eq!(lotus_trace.subcalls[0].subcalls.len(), 0);
469509
assert_eq!(lotus_trace.subcalls[1].subcalls.len(), 1);

0 commit comments

Comments
 (0)