Skip to content

Commit

Permalink
feat: support DumpCache, handle Logs in traces
Browse files Browse the repository at this point in the history
  • Loading branch information
rvagg committed Jan 11, 2025
1 parent 609c864 commit e08bbe8
Show file tree
Hide file tree
Showing 6 changed files with 136 additions and 15 deletions.
7 changes: 7 additions & 0 deletions cgo/fvm.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,10 @@ func FvmMachineFlush(executor *FvmMachine) ([]byte, error) {
}
return resp.value.copy(), nil
}

func FvmMachineDumpCache(executor *FvmMachine, blockstoreId uint64) error {
resp := C.fvm_machine_dump_cache(executor, C.uint64_t(blockstoreId))
defer resp.destroy()

return CheckErr(resp)
}
38 changes: 38 additions & 0 deletions fvm.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/go-state-types/network"
"github.com/ipfs/boxo/blockstore"
"github.com/ipfs/go-cid"
"golang.org/x/xerrors"
)
Expand Down Expand Up @@ -187,6 +188,14 @@ func (f *FVM) Flush() (cid.Cid, error) {
return cid.Cast(stateRoot)
}

// DumpCache dumps the intermediate blockstore cache of the FVM to the provided blockstore.
func (f *FVM) DumpCache(bs blockstore.Blockstore) error {
defer runtime.KeepAlive(f)
bsHandle := cgo.Register(context.TODO(), blockStoreAsExterns{Blockstore: bs})
defer cgo.Unregister(bsHandle)
return cgo.FvmMachineDumpCache(f.executor, bsHandle)
}

type ApplyRet struct {
Return []byte
ExitCode uint64
Expand Down Expand Up @@ -238,3 +247,32 @@ func reformBigInt(hi, lo uint64) big.Int {
int.SetBits(words)
return big.NewFromGo(int)
}

// blockStoreAsExterns is a wrapper around a blockstore.Blockstore that implements the cgo.Externs.
// It is only intended for use strictly as a Blockstore, and does not support any of the other
// Externs methods.
type blockStoreAsExterns struct {
blockstore.Blockstore
}

var _ cgo.Externs = blockStoreAsExterns{}

func (b blockStoreAsExterns) GetChainRandomness(ctx context.Context, epoch abi.ChainEpoch) ([32]byte, error) {
return [32]byte{}, xerrors.Errorf("GetChainRandomness not supported")
}

func (b blockStoreAsExterns) GetBeaconRandomness(ctx context.Context, epoch abi.ChainEpoch) ([32]byte, error) {
return [32]byte{}, xerrors.Errorf("GetBeaconRandomness not supported")
}

func (b blockStoreAsExterns) VerifyConsensusFault(ctx context.Context, h1, h2, extra []byte) (*cgo.ConsensusFault, int64) {
panic("VerifyConsensusFault not supported")
}

func (b blockStoreAsExterns) TipsetCid(ctx context.Context, epoch abi.ChainEpoch) (cid.Cid, error) {
return cid.Undef, xerrors.Errorf("TipsetCid not supported")
}

func (b blockStoreAsExterns) View(ctx context.Context, cid cid.Cid, callback func([]byte) error) error {
return xerrors.Errorf("View not supported")
}
53 changes: 39 additions & 14 deletions rust/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions rust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ safer-ffi = { version = "0.1.13", features = ["proc_macros"] }
filecoin-proofs-api = { version = "18.1", default-features = false }
yastl = "0.1.2"

[patch.crates-io]
fvm4 = { package = "fvm", path = "/home/rvagg/git/pl/filecoin-project/ref-fvm/fvm" }
fvm4_shared = { package = "fvm_shared", path = "/home/rvagg/git/pl/filecoin-project/ref-fvm/shared" }
fvm_ipld_blockstore = { path = "/home/rvagg/git/pl/filecoin-project/ref-fvm/ipld/blockstore" }
fvm_ipld_encoding = { path = "/home/rvagg/git/pl/filecoin-project/ref-fvm/ipld/encoding" }

[dev-dependencies]
memmap2 = "0.9"
tempfile = "3.12.0"
Expand Down
19 changes: 18 additions & 1 deletion rust/src/fvm/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use super::blockstore::CgoBlockstore;
use super::externs::CgoExterns;
use super::types::*;

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

fn flush(&mut self) -> anyhow::Result<Cid>;

fn dump_cache(&mut self, bs: CgoBlockstore) -> anyhow::Result<()>;
}

pub struct Config {
Expand Down Expand Up @@ -148,6 +150,11 @@ mod v4 {
fn flush(&mut self) -> anyhow::Result<Cid> {
fvm4::executor::Executor::flush(self)
}

fn dump_cache(&mut self, bs: CgoBlockstore) -> anyhow::Result<()> {
log::info!("CgoExecutor4::dump_cache");
fvm4::executor::Executor::dump_cache(self, bs)
}
}

impl AbstractMultiEngine for MultiEngine4 {
Expand Down Expand Up @@ -420,6 +427,11 @@ mod v3 {
fn flush(&mut self) -> anyhow::Result<Cid> {
fvm3::executor::Executor::flush(self)
}

// dump_cache is only implemented in v4
fn dump_cache(&mut self, _: CgoBlockstore) -> anyhow::Result<()> {
Err(anyhow::anyhow!("dump_cache not implemented for fvm v3"))
}
}

impl AbstractMultiEngine for MultiEngine3 {
Expand Down Expand Up @@ -681,6 +693,11 @@ mod v2 {
fn flush(&mut self) -> anyhow::Result<Cid> {
fvm2::executor::Executor::flush(self)
}

// dump_cache is only implemented in v4
fn dump_cache(&mut self, _: CgoBlockstore) -> anyhow::Result<()> {
Err(anyhow::anyhow!("dump_cache not implemented for fvm v2"))
}
}

impl AbstractMultiEngine for MultiEngine2 {
Expand Down
28 changes: 28 additions & 0 deletions rust/src/fvm/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,23 @@ fn fvm_machine_execute_message(
})
}

#[ffi_export]
fn fvm_machine_dump_cache(
executor: &'_ InnerFvmMachine,
blockstore_id: u64,
) -> repr_c::Box<Result<()>> {
catch_panic_response("fvm_machine_dump_cache", || {
let blockstore = CgoBlockstore::new(blockstore_id);
let mut executor = executor
.machine
.as_ref()
.context("missing executor")?
.lock()
.map_err(|e| anyhow!("executor lock poisoned: {e}"))?;
executor.dump_cache(blockstore)
})
}

#[ffi_export]
fn fvm_machine_flush(executor: &'_ InnerFvmMachine) -> repr_c::Box<Result<c_slice::Box<u8>>> {
catch_panic_response("fvm_machine_flush", || {
Expand All @@ -422,6 +439,7 @@ destructor!(
);

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

#[derive(Clone, Debug, PartialEq, Eq, Serialize_tuple, Deserialize_tuple)]
struct LotusGasCharge {
Expand All @@ -439,6 +457,7 @@ struct Trace {
pub msg_invoked: Option<TraceActor>,
pub gas_charges: Vec<LotusGasCharge>,
pub subcalls: Vec<Trace>,
pub logs: Vec<String>,
}

#[derive(Serialize_tuple, Deserialize_tuple, Debug, PartialEq, Eq, Clone)]
Expand Down Expand Up @@ -499,6 +518,7 @@ fn build_lotus_trace(
},
gas_charges: vec![],
subcalls: vec![],
logs: vec![],
};

while let Some(trace) = trace_iter.next() {
Expand Down Expand Up @@ -568,6 +588,9 @@ fn build_lotus_trace(
.unwrap_or(u64::MAX),
});
}
ExecutionEvent::Log(s) => {
new_trace.logs.push(s);
}
_ => (), // ignore unknown events.
};
}
Expand Down Expand Up @@ -605,10 +628,12 @@ mod test {
ExecutionEvent::GasCharge(initial_gas_charge.clone()),
call_event.clone(),
return_result.clone(),
ExecutionEvent::Log("something happened".to_string()),
call_event.clone(),
call_event,
return_result.clone(),
return_result.clone(),
ExecutionEvent::Log("something else happened".to_string()),
return_result,
];

Expand Down Expand Up @@ -648,5 +673,8 @@ mod test {
assert_eq!(lotus_trace.subcalls[0].subcalls.len(), 0);
assert_eq!(lotus_trace.subcalls[1].subcalls.len(), 1);
assert_eq!(lotus_trace.subcalls[1].subcalls[0].subcalls.len(), 0);
assert_eq!(lotus_trace.logs.len(), 2);
assert_eq!(lotus_trace.logs[0], "something happened");
assert_eq!(lotus_trace.logs[1], "something else happened");
}
}

0 comments on commit e08bbe8

Please sign in to comment.