Skip to content

Commit

Permalink
feat: fvm: add support for looking up past tipset CIDs (#9687)
Browse files Browse the repository at this point in the history
* feat: add support for generating tipset CIDs

(cherry-picked from feat/nv18-fevm)

* feat: fvm: add support for looking up past tipset CIDs

We do this by adding yet another "getter" to the VM that resolves an
epoch into a TipSetKey.

Co-authored-by: Kevin Li <[email protected]>
  • Loading branch information
Stebalien and ychiaoli18 authored Nov 22, 2022
1 parent 64de59a commit e78d130
Show file tree
Hide file tree
Showing 7 changed files with 73 additions and 10 deletions.
1 change: 1 addition & 0 deletions chain/consensus/filcns/compute_state.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ func (t *TipSetExecutor) ApplyBlocks(ctx context.Context,
NetworkVersion: sm.GetNetworkVersion(ctx, e),
BaseFee: baseFee,
LookbackState: stmgr.LookbackStateGetterForTipset(sm, ts),
TipSetGetter: stmgr.TipSetGetterForTipset(sm.ChainStore(), ts),
Tracing: vmTracing,
}

Expand Down
1 change: 1 addition & 0 deletions chain/stmgr/call.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ func (sm *StateManager) callInternal(ctx context.Context, msg *types.Message, pr
NetworkVersion: nvGetter(ctx, vmHeight),
BaseFee: ts.Blocks()[0].ParentBaseFee,
LookbackState: LookbackStateGetterForTipset(sm, ts),
TipSetGetter: TipSetGetterForTipset(sm.cs, ts),
Tracing: true,
}
vmi, err := sm.newVM(ctx, vmopt)
Expand Down
11 changes: 11 additions & 0 deletions chain/stmgr/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ func ComputeState(ctx context.Context, sm *StateManager, height abi.ChainEpoch,
NetworkVersion: sm.GetNetworkVersion(ctx, height),
BaseFee: ts.Blocks()[0].ParentBaseFee,
LookbackState: LookbackStateGetterForTipset(sm, ts),
TipSetGetter: TipSetGetterForTipset(sm.cs, ts),
Tracing: true,
}
vmi, err := sm.newVM(ctx, vmopt)
Expand Down Expand Up @@ -131,6 +132,16 @@ func LookbackStateGetterForTipset(sm *StateManager, ts *types.TipSet) vm.Lookbac
}
}

func TipSetGetterForTipset(cs *store.ChainStore, ts *types.TipSet) vm.TipSetGetter {
return func(ctx context.Context, round abi.ChainEpoch) (types.TipSetKey, error) {
ts, err := cs.GetTipsetByHeight(ctx, round, ts, true)
if err != nil {
return types.EmptyTSK, err
}
return ts.Key(), nil
}
}

func GetLookbackTipSetForRound(ctx context.Context, sm *StateManager, ts *types.TipSet, round abi.ChainEpoch) (*types.TipSet, cid.Cid, error) {
var lbr abi.ChainEpoch
lb := policy.GetWinningPoStSectorSetLookback(sm.GetNetworkVersion(ctx, round))
Expand Down
23 changes: 23 additions & 0 deletions chain/types/tipset_key.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"io"
"strings"

block "github.com/ipfs/go-block-format"
"github.com/ipfs/go-cid"
typegen "github.com/whyrusleeping/cbor-gen"

Expand Down Expand Up @@ -98,6 +99,28 @@ func (k *TipSetKey) UnmarshalJSON(b []byte) error {
return nil
}

func (k TipSetKey) Cid() (cid.Cid, error) {
blk, err := k.ToStorageBlock()
if err != nil {
return cid.Cid{}, err
}
return blk.Cid(), nil
}

func (k TipSetKey) ToStorageBlock() (block.Block, error) {
buf := new(bytes.Buffer)
if err := k.MarshalCBOR(buf); err != nil {
log.Errorf("failed to marshal ts key as CBOR: %s", k)
}

cid, err := abi.CidBuilder.Sum(buf.Bytes())
if err != nil {
return nil, err
}

return block.NewBlockWithCid(buf.Bytes(), cid)
}

func (k TipSetKey) MarshalCBOR(writer io.Writer) error {
if err := typegen.WriteMajorTypeHeader(writer, typegen.MajByteString, uint64(len(k.Bytes()))); err != nil {
return err
Expand Down
10 changes: 10 additions & 0 deletions chain/vm/fvm.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ type FvmExtern struct {
blockstore.Blockstore
epoch abi.ChainEpoch
lbState LookbackStateGetter
tsGet TipSetGetter
base cid.Cid
}

Expand Down Expand Up @@ -99,6 +100,14 @@ func (t *FvmExecutionTrace) ToExecutionTrace() types.ExecutionTrace {
return ret
}

func (x *FvmExtern) TipsetCid(ctx context.Context, epoch abi.ChainEpoch) (cid.Cid, error) {
tsk, err := x.tsGet(ctx, epoch)
if err != nil {
return cid.Undef, err
}
return tsk.Cid()
}

// VerifyConsensusFault is similar to the one in syscalls.go used by the Lotus VM, except it never errors
// Errors are logged and "no fault" is returned, which is functionally what go-actors does anyway
func (x *FvmExtern) VerifyConsensusFault(ctx context.Context, a, b, extra []byte) (*ffi_cgo.ConsensusFault, int64) {
Expand Down Expand Up @@ -294,6 +303,7 @@ func defaultFVMOpts(ctx context.Context, opts *VMOpts) (*ffi.FVMOpts, error) {
Rand: opts.Rand,
Blockstore: opts.Bstore,
lbState: opts.LookbackState,
tsGet: opts.TipSetGetter,
base: opts.StateBase,
epoch: opts.Epoch,
},
Expand Down
2 changes: 2 additions & 0 deletions chain/vm/vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ type (
CircSupplyCalculator func(context.Context, abi.ChainEpoch, *state.StateTree) (abi.TokenAmount, error)
NtwkVersionGetter func(context.Context, abi.ChainEpoch) network.Version
LookbackStateGetter func(context.Context, abi.ChainEpoch) (*state.StateTree, error)
TipSetGetter func(context.Context, abi.ChainEpoch) (types.TipSetKey, error)
)

var _ Interface = (*LegacyVM)(nil)
Expand Down Expand Up @@ -223,6 +224,7 @@ type VMOpts struct {
NetworkVersion network.Version
BaseFee abi.TokenAmount
LookbackState LookbackStateGetter
TipSetGetter TipSetGetter
Tracing bool
}

Expand Down
35 changes: 25 additions & 10 deletions conformance/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,9 @@ type ExecuteMessageParams struct {

// Lookback is the LookbackStateGetter; returns the state tree at a given epoch.
Lookback vm.LookbackStateGetter

// TipSetGetter returns the tipset key at any given epoch.
TipSetGetter vm.TipSetGetter
}

// ExecuteMessage executes a conformance test vector message in a temporary VM.
Expand All @@ -217,15 +220,26 @@ func (d *Driver) ExecuteMessage(bs blockstore.Blockstore, params ExecuteMessageP
params.Rand = NewFixedRand()
}

// TODO: This lookback state returns the supplied precondition state tree, unconditionally.
// This is obviously not correct, but the lookback state tree is only used to validate the
// worker key when verifying a consensus fault. If the worker key hasn't changed in the
// current finality window, this workaround is enough.
// The correct solutions are documented in https://github.com/filecoin-project/ref-fvm/issues/381,
// but they're much harder to implement, and the tradeoffs aren't clear.
var lookback vm.LookbackStateGetter = func(ctx context.Context, epoch abi.ChainEpoch) (*state.StateTree, error) {
cst := cbor.NewCborStore(bs)
return state.LoadStateTree(cst, params.Preroot)
if params.TipSetGetter == nil {
// TODO: If/when we start writing conformance tests against the EVM, we'll need to
// actually implement this and (unfortunately) capture any tipsets looked up by
// messages.
params.TipSetGetter = func(context.Context, abi.ChainEpoch) (types.TipSetKey, error) {
return types.EmptyTSK, nil
}
}

if params.Lookback == nil {
// TODO: This lookback state returns the supplied precondition state tree, unconditionally.
// This is obviously not correct, but the lookback state tree is only used to validate the
// worker key when verifying a consensus fault. If the worker key hasn't changed in the
// current finality window, this workaround is enough.
// The correct solutions are documented in https://github.com/filecoin-project/ref-fvm/issues/381,
// but they're much harder to implement, and the tradeoffs aren't clear.
params.Lookback = func(ctx context.Context, epoch abi.ChainEpoch) (*state.StateTree, error) {
cst := cbor.NewCborStore(bs)
return state.LoadStateTree(cst, params.Preroot)
}
}

vmOpts := &vm.VMOpts{
Expand All @@ -239,7 +253,8 @@ func (d *Driver) ExecuteMessage(bs blockstore.Blockstore, params ExecuteMessageP
Rand: params.Rand,
BaseFee: params.BaseFee,
NetworkVersion: params.NetworkVersion,
LookbackState: lookback,
LookbackState: params.Lookback,
TipSetGetter: params.TipSetGetter,
}

var vmi vm.Interface
Expand Down

0 comments on commit e78d130

Please sign in to comment.