Skip to content

Commit 8659288

Browse files
committed
feat: support DumpCache, handle Logs in traces
Ref: filecoin-project/ref-fvm#2101
1 parent 037aa5c commit 8659288

File tree

6 files changed

+109
-3
lines changed

6 files changed

+109
-3
lines changed

cgo/fvm.go

+7
Original file line numberDiff line numberDiff line change
@@ -90,3 +90,10 @@ func FvmMachineFlush(executor *FvmMachine) ([]byte, error) {
9090
}
9191
return (SliceBoxedUint8)(resp.value).copy(), nil
9292
}
93+
94+
func FvmMachineDumpCache(executor *FvmMachine, blockstoreId uint64) error {
95+
resp := C.fvm_machine_dump_cache(executor, C.uint64_t(blockstoreId))
96+
defer resp.destroy()
97+
98+
return CheckErr(resp)
99+
}

fvm.go

+38
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"github.com/filecoin-project/go-state-types/abi"
2020
"github.com/filecoin-project/go-state-types/big"
2121
"github.com/filecoin-project/go-state-types/network"
22+
"github.com/ipfs/boxo/blockstore"
2223
"github.com/ipfs/go-cid"
2324
"golang.org/x/xerrors"
2425
)
@@ -187,6 +188,14 @@ func (f *FVM) Flush() (cid.Cid, error) {
187188
return cid.Cast(stateRoot)
188189
}
189190

191+
// DumpCache dumps the intermediate blockstore cache of the FVM to the provided blockstore.
192+
func (f *FVM) DumpCache(bs blockstore.Blockstore) error {
193+
defer runtime.KeepAlive(f)
194+
bsHandle := cgo.Register(context.TODO(), blockStoreAsExterns{Blockstore: bs})
195+
defer cgo.Unregister(bsHandle)
196+
return cgo.FvmMachineDumpCache(f.executor, bsHandle)
197+
}
198+
190199
type ApplyRet struct {
191200
Return []byte
192201
ExitCode uint64
@@ -238,3 +247,32 @@ func reformBigInt(hi, lo uint64) big.Int {
238247
int.SetBits(words)
239248
return big.NewFromGo(int)
240249
}
250+
251+
// blockStoreAsExterns is a wrapper around a blockstore.Blockstore that implements the cgo.Externs.
252+
// It is only intended for use strictly as a Blockstore, and does not support any of the other
253+
// Externs methods.
254+
type blockStoreAsExterns struct {
255+
blockstore.Blockstore
256+
}
257+
258+
var _ cgo.Externs = blockStoreAsExterns{}
259+
260+
func (b blockStoreAsExterns) GetChainRandomness(ctx context.Context, epoch abi.ChainEpoch) ([32]byte, error) {
261+
return [32]byte{}, xerrors.Errorf("GetChainRandomness not supported")
262+
}
263+
264+
func (b blockStoreAsExterns) GetBeaconRandomness(ctx context.Context, epoch abi.ChainEpoch) ([32]byte, error) {
265+
return [32]byte{}, xerrors.Errorf("GetBeaconRandomness not supported")
266+
}
267+
268+
func (b blockStoreAsExterns) VerifyConsensusFault(ctx context.Context, h1, h2, extra []byte) (*cgo.ConsensusFault, int64) {
269+
panic("VerifyConsensusFault not supported")
270+
}
271+
272+
func (b blockStoreAsExterns) TipsetCid(ctx context.Context, epoch abi.ChainEpoch) (cid.Cid, error) {
273+
return cid.Undef, xerrors.Errorf("TipsetCid not supported")
274+
}
275+
276+
func (b blockStoreAsExterns) View(ctx context.Context, cid cid.Cid, callback func([]byte) error) error {
277+
return xerrors.Errorf("View not supported")
278+
}

rust/Cargo.lock

+12-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

rust/Cargo.toml

+6
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,12 @@ safer-ffi = { version = "0.1.13", features = ["proc_macros"] }
5050
filecoin-proofs-api = { version = "18.1", default-features = false }
5151
yastl = "0.1.2"
5252

53+
[patch.crates-io]
54+
fvm4 = { package = "fvm", path = "/home/rvagg/git/pl/filecoin-project/ref-fvm/fvm" }
55+
fvm4_shared = { package = "fvm_shared", path = "/home/rvagg/git/pl/filecoin-project/ref-fvm/shared" }
56+
fvm_ipld_blockstore = { path = "/home/rvagg/git/pl/filecoin-project/ref-fvm/ipld/blockstore" }
57+
fvm_ipld_encoding = { path = "/home/rvagg/git/pl/filecoin-project/ref-fvm/ipld/encoding" }
58+
5359
[dev-dependencies]
5460
memmap2 = "0.9"
5561
tempfile = "3.12.0"

rust/src/fvm/engine.rs

+18-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use super::blockstore::CgoBlockstore;
1616
use super::externs::CgoExterns;
1717
use super::types::*;
1818

19-
// Generic executor; uses the current (v3) engine types
19+
// Generic executor; uses the current engine types
2020
pub trait CgoExecutor: Send {
2121
fn execute_message(
2222
&mut self,
@@ -26,6 +26,8 @@ pub trait CgoExecutor: Send {
2626
) -> anyhow::Result<ApplyRet>;
2727

2828
fn flush(&mut self) -> anyhow::Result<Cid>;
29+
30+
fn dump_cache(&mut self, bs: CgoBlockstore) -> anyhow::Result<()>;
2931
}
3032

3133
pub struct Config {
@@ -148,6 +150,11 @@ mod v4 {
148150
fn flush(&mut self) -> anyhow::Result<Cid> {
149151
fvm4::executor::Executor::flush(self)
150152
}
153+
154+
fn dump_cache(&mut self, bs: CgoBlockstore) -> anyhow::Result<()> {
155+
log::info!("CgoExecutor4::dump_cache");
156+
fvm4::executor::Executor::dump_cache(self, bs)
157+
}
151158
}
152159

153160
impl AbstractMultiEngine for MultiEngine4 {
@@ -420,6 +427,11 @@ mod v3 {
420427
fn flush(&mut self) -> anyhow::Result<Cid> {
421428
fvm3::executor::Executor::flush(self)
422429
}
430+
431+
// dump_cache is only implemented in v4
432+
fn dump_cache(&mut self, _: CgoBlockstore) -> anyhow::Result<()> {
433+
Err(anyhow::anyhow!("dump_cache not implemented for fvm v3"))
434+
}
423435
}
424436

425437
impl AbstractMultiEngine for MultiEngine3 {
@@ -681,6 +693,11 @@ mod v2 {
681693
fn flush(&mut self) -> anyhow::Result<Cid> {
682694
fvm2::executor::Executor::flush(self)
683695
}
696+
697+
// dump_cache is only implemented in v4
698+
fn dump_cache(&mut self, _: CgoBlockstore) -> anyhow::Result<()> {
699+
Err(anyhow::anyhow!("dump_cache not implemented for fvm v2"))
700+
}
684701
}
685702

686703
impl AbstractMultiEngine for MultiEngine2 {

rust/src/fvm/machine.rs

+28
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,23 @@ fn fvm_machine_execute_message(
398398
})
399399
}
400400

401+
#[ffi_export]
402+
fn fvm_machine_dump_cache(
403+
executor: &'_ InnerFvmMachine,
404+
blockstore_id: u64,
405+
) -> repr_c::Box<Result<()>> {
406+
catch_panic_response("fvm_machine_dump_cache", || {
407+
let blockstore = CgoBlockstore::new(blockstore_id);
408+
let mut executor = executor
409+
.machine
410+
.as_ref()
411+
.context("missing executor")?
412+
.lock()
413+
.map_err(|e| anyhow!("executor lock poisoned: {e}"))?;
414+
executor.dump_cache(blockstore)
415+
})
416+
}
417+
401418
#[ffi_export]
402419
fn fvm_machine_flush(executor: &'_ InnerFvmMachine) -> repr_c::Box<Result<c_slice::Box<u8>>> {
403420
catch_panic_response("fvm_machine_flush", || {
@@ -422,6 +439,7 @@ destructor!(
422439
);
423440

424441
destructor!(destroy_fvm_machine_flush_response, Result<c_slice::Box<u8>>);
442+
destructor!(destroy_fvm_machine_dump_cache_response, Result<()>);
425443

426444
#[derive(Clone, Debug, PartialEq, Eq, Serialize_tuple, Deserialize_tuple)]
427445
struct LotusGasCharge {
@@ -439,6 +457,7 @@ struct Trace {
439457
pub msg_invoked: Option<TraceActor>,
440458
pub gas_charges: Vec<LotusGasCharge>,
441459
pub subcalls: Vec<Trace>,
460+
pub logs: Vec<String>,
442461
}
443462

444463
#[derive(Serialize_tuple, Deserialize_tuple, Debug, PartialEq, Eq, Clone)]
@@ -499,6 +518,7 @@ fn build_lotus_trace(
499518
},
500519
gas_charges: vec![],
501520
subcalls: vec![],
521+
logs: vec![],
502522
};
503523

504524
while let Some(trace) = trace_iter.next() {
@@ -568,6 +588,9 @@ fn build_lotus_trace(
568588
.unwrap_or(u64::MAX),
569589
});
570590
}
591+
ExecutionEvent::Log(s) => {
592+
new_trace.logs.push(s);
593+
}
571594
_ => (), // ignore unknown events.
572595
};
573596
}
@@ -605,10 +628,12 @@ mod test {
605628
ExecutionEvent::GasCharge(initial_gas_charge.clone()),
606629
call_event.clone(),
607630
return_result.clone(),
631+
ExecutionEvent::Log("something happened".to_string()),
608632
call_event.clone(),
609633
call_event,
610634
return_result.clone(),
611635
return_result.clone(),
636+
ExecutionEvent::Log("something else happened".to_string()),
612637
return_result,
613638
];
614639

@@ -648,5 +673,8 @@ mod test {
648673
assert_eq!(lotus_trace.subcalls[0].subcalls.len(), 0);
649674
assert_eq!(lotus_trace.subcalls[1].subcalls.len(), 1);
650675
assert_eq!(lotus_trace.subcalls[1].subcalls[0].subcalls.len(), 0);
676+
assert_eq!(lotus_trace.logs.len(), 2);
677+
assert_eq!(lotus_trace.logs[0], "something happened");
678+
assert_eq!(lotus_trace.logs[1], "something else happened");
651679
}
652680
}

0 commit comments

Comments
 (0)