@@ -6,6 +6,7 @@ use cid::Cid;
6
6
use fvm3:: executor:: ApplyKind as ApplyKind3 ;
7
7
use fvm3:: gas:: GasCharge ;
8
8
use fvm3:: trace:: ExecutionEvent ;
9
+ use fvm3_ipld_encoding:: ipld_block:: IpldBlock ;
9
10
use fvm3_ipld_encoding:: tuple:: { Deserialize_tuple , Serialize_tuple } ;
10
11
use fvm3_ipld_encoding:: { to_vec, CborStore , RawBytes } ;
11
12
use fvm3_shared:: address:: Address ;
@@ -204,19 +205,38 @@ fn fvm_machine_execute_message(
204
205
205
206
let exec_trace = if !apply_ret. exec_trace . is_empty ( ) {
206
207
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
+ }
217
235
} else {
218
236
None
219
- } ;
237
+ }
238
+ . and_then ( |t| to_vec ( & t) . ok ( ) )
239
+ . map ( |trace| trace. into_boxed_slice ( ) . into ( ) ) ;
220
240
221
241
let failure_info = apply_ret
222
242
. failure_info
@@ -312,12 +332,12 @@ destructor!(
312
332
313
333
destructor ! ( destroy_fvm_machine_flush_response, Result <c_slice:: Box <u8 >>) ;
314
334
315
- #[ derive( Clone , Debug , Serialize_tuple , Deserialize_tuple ) ]
335
+ #[ derive( Clone , Debug , PartialEq , Eq , Serialize_tuple , Deserialize_tuple ) ]
316
336
struct LotusGasCharge {
317
337
pub name : Cow < ' static , str > ,
318
338
pub total_gas : u64 ,
319
339
pub compute_gas : u64 ,
320
- pub storage_gas : u64 ,
340
+ pub other_gas : u64 ,
321
341
}
322
342
323
343
#[ derive( Clone , Debug , Serialize_tuple , Deserialize_tuple ) ]
@@ -337,32 +357,25 @@ pub struct LotusReceipt {
337
357
}
338
358
339
359
fn build_lotus_trace (
340
- new_call : ExecutionEvent ,
360
+ from : u64 ,
361
+ to : Address ,
362
+ method : u64 ,
363
+ params : Option < IpldBlock > ,
364
+ value : TokenAmount ,
341
365
trace_iter : & mut impl Iterator < Item = ExecutionEvent > ,
342
366
) -> anyhow:: Result < LotusTrace > {
343
367
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 ( ) ,
366
379
} ,
367
380
msg_receipt : LotusReceipt {
368
381
exit_code : ExitCode :: OK ,
@@ -376,10 +389,16 @@ fn build_lotus_trace(
376
389
377
390
while let Some ( trace) = trace_iter. next ( ) {
378
391
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
+ ) ?) ;
383
402
}
384
403
ExecutionEvent :: CallReturn ( exit_code, return_data) => {
385
404
new_trace. msg_receipt = LotusReceipt {
@@ -416,7 +435,7 @@ fn build_lotus_trace(
416
435
name,
417
436
total_gas : ( compute_gas + other_gas) . round_up ( ) ,
418
437
compute_gas : compute_gas. round_up ( ) ,
419
- storage_gas : other_gas. round_up ( ) ,
438
+ other_gas : other_gas. round_up ( ) ,
420
439
} ) ;
421
440
}
422
441
_ => ( ) , // ignore unknown events.
@@ -428,7 +447,9 @@ fn build_lotus_trace(
428
447
429
448
#[ cfg( test) ]
430
449
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 ;
432
453
use fvm3:: kernel:: SyscallError ;
433
454
use fvm3:: trace:: ExecutionEvent ;
434
455
use fvm3_shared:: address:: Address ;
@@ -447,8 +468,9 @@ mod test {
447
468
} ;
448
469
let return_result =
449
470
ExecutionEvent :: CallError ( SyscallError :: new ( IllegalArgument , "illegal" ) ) ;
471
+ let initial_gas_charge = GasCharge :: new ( "gas_test" , Gas :: new ( 1 ) , Gas :: new ( 2 ) ) ;
450
472
let trace = vec ! [
451
- call_event . clone( ) ,
473
+ ExecutionEvent :: GasCharge ( initial_gas_charge . clone( ) ) ,
452
474
call_event. clone( ) ,
453
475
return_result. clone( ) ,
454
476
call_event. clone( ) ,
@@ -460,10 +482,28 @@ mod test {
460
482
461
483
let mut trace_iter = trace. into_iter ( ) ;
462
484
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 ( ) ;
464
494
465
495
assert ! ( trace_iter. next( ) . is_none( ) ) ;
466
496
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
+ ) ;
467
507
assert_eq ! ( lotus_trace. subcalls. len( ) , 2 ) ;
468
508
assert_eq ! ( lotus_trace. subcalls[ 0 ] . subcalls. len( ) , 0 ) ;
469
509
assert_eq ! ( lotus_trace. subcalls[ 1 ] . subcalls. len( ) , 1 ) ;
0 commit comments