:Hook up the FVM

This commit is contained in:
Aayush Rajasekaran 2021-12-16 22:38:13 -05:00 committed by Steven Allen
parent d9c763437e
commit 2a669b95fb
5 changed files with 178 additions and 3 deletions

View File

@ -2,6 +2,7 @@ package filcns
import (
"context"
"os"
"sync/atomic"
"github.com/filecoin-project/lotus/chain/rand"
@ -92,7 +93,7 @@ func (t *TipSetExecutor) ApplyBlocks(ctx context.Context, sm *stmgr.StateManager
partDone()
}()
makeVmWithBaseStateAndEpoch := func(base cid.Cid, e abi.ChainEpoch) (*vm.VM, error) {
makeVmWithBaseStateAndEpoch := func(base cid.Cid, e abi.ChainEpoch) (vm.VMI, error) {
vmopt := &vm.VMOpts{
StateBase: base,
Epoch: e,
@ -106,10 +107,14 @@ func (t *TipSetExecutor) ApplyBlocks(ctx context.Context, sm *stmgr.StateManager
LookbackState: stmgr.LookbackStateGetterForTipset(sm, ts),
}
if os.Getenv("LOTUS_USE_FVM_DOESNT_WORK_YET") == "1" {
return vm.NewFVM(ctx, vmopt)
}
return sm.VMConstructor()(ctx, vmopt)
}
runCron := func(vmCron *vm.VM, epoch abi.ChainEpoch) error {
runCron := func(vmCron vm.VMI, epoch abi.ChainEpoch) error {
cronMsg := &types.Message{
To: cron.Address,
From: builtin.SystemActorAddr,

154
chain/vm/fvm.go Normal file
View File

@ -0,0 +1,154 @@
package vm
import (
"context"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/crypto"
"github.com/filecoin-project/lotus/chain/actors/aerrors"
"github.com/filecoin-project/specs-actors/v7/actors/runtime"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/exitcode"
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/blockstore"
"github.com/filecoin-project/lotus/chain/state"
cbor "github.com/ipfs/go-ipld-cbor"
ffi "github.com/filecoin-project/filecoin-ffi"
"github.com/filecoin-project/lotus/chain/types"
"github.com/ipfs/go-cid"
)
var _ VMI = (*FVM)(nil)
type Extern interface {
GetRandomnessFromTickets(personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) abi.Randomness
GetRandomnessFromBeacon(personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) abi.Randomness
VerifyConsensusFault(a, b, extra []byte) (address.Address, abi.ChainEpoch, runtime.ConsensusFaultType)
}
type FvmExtern struct {
rand Rand
}
func (e *FvmExtern) GetRandomnessFromTickets(personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) abi.Randomness {
res, err := e.rand.GetChainRandomness(context.Background(), personalization, randEpoch, entropy)
if err != nil {
panic(aerrors.Fatalf("could not get ticket randomness: %s", err))
}
return res
}
func (e *FvmExtern) GetRandomnessFromBeacon(personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) abi.Randomness {
res, err := e.rand.GetBeaconRandomness(context.Background(), personalization, randEpoch, entropy)
if err != nil {
panic(aerrors.Fatalf("could not get ticket randomness: %s", err))
}
return res
}
type FVM struct {
machineId uint64
extern FvmExtern
}
func NewFVM(ctx context.Context, opts *VMOpts) (*FVM, error) {
buf := blockstore.NewBuffered(opts.Bstore)
cst := cbor.NewCborStore(buf)
state, err := state.LoadStateTree(cst, opts.StateBase)
if err != nil {
return nil, err
}
baseCirc, err := opts.CircSupplyCalc(ctx, opts.Epoch, state)
if err != nil {
return nil, err
}
id, err := ffi.CreateFVM(0, opts.Epoch, opts.BaseFee, baseCirc, opts.NetworkVersion, opts.StateBase)
if err != nil {
return nil, err
}
return &FVM{
extern: FvmExtern{rand: opts.Rand},
machineId: id,
}, nil
}
func (vm *FVM) ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet, error) {
msgBytes, err := cmsg.VMMessage().Serialize()
if err != nil {
return nil, xerrors.Errorf("serializing msg: %w", err)
}
ret, err := ffi.ApplyMessage(vm.machineId, msgBytes)
if err != nil {
return nil, xerrors.Errorf("applying msg: %w", err)
}
return &ApplyRet{
MessageReceipt: types.MessageReceipt{
Return: ret.Return,
ExitCode: exitcode.ExitCode(ret.ExitCode),
GasUsed: ret.GasUsed,
},
GasCosts: &GasOutputs{
// TODO: do the other optional fields eventually
BaseFeeBurn: abi.TokenAmount{},
OverEstimationBurn: abi.TokenAmount{},
MinerPenalty: ret.MinerPenalty,
MinerTip: ret.MinerTip,
Refund: abi.TokenAmount{},
GasRefund: 0,
GasBurned: 0,
},
// TODO: do these eventually, not consensus critical
ActorErr: nil,
ExecutionTrace: types.ExecutionTrace{},
Duration: 0,
}, nil
}
func (vm *FVM) ApplyImplicitMessage(ctx context.Context, cmsg *types.Message) (*ApplyRet, error) {
msgBytes, err := cmsg.VMMessage().Serialize()
if err != nil {
return nil, xerrors.Errorf("serializing msg: %w", err)
}
ret, err := ffi.ApplyMessage(vm.machineId, msgBytes)
if err != nil {
return nil, xerrors.Errorf("applying msg: %w", err)
}
return &ApplyRet{
MessageReceipt: types.MessageReceipt{
Return: ret.Return,
ExitCode: exitcode.ExitCode(ret.ExitCode),
GasUsed: ret.GasUsed,
},
GasCosts: &GasOutputs{
// TODO: do the other optional fields eventually
BaseFeeBurn: abi.TokenAmount{},
OverEstimationBurn: abi.TokenAmount{},
MinerPenalty: ret.MinerPenalty,
MinerTip: ret.MinerTip,
Refund: abi.TokenAmount{},
GasRefund: 0,
GasBurned: 0,
},
// TODO: do these eventually, not consensus critical
ActorErr: nil,
ExecutionTrace: types.ExecutionTrace{},
Duration: 0,
}, nil
}
func (vm *FVM) Flush(ctx context.Context) (cid.Cid, error) {
return cid.Undef, nil
}

View File

@ -201,6 +201,8 @@ type (
LookbackStateGetter func(context.Context, abi.ChainEpoch) (*state.StateTree, error)
)
var _ VMI = (*VM)(nil)
type VM struct {
cstate *state.StateTree
cst *cbor.BasicIpldStore

14
chain/vm/vmi.go Normal file
View File

@ -0,0 +1,14 @@
package vm
import (
"context"
"github.com/filecoin-project/lotus/chain/types"
"github.com/ipfs/go-cid"
)
type VMI interface {
ApplyMessage(ctx context.Context, cmsg types.ChainMsg) (*ApplyRet, error)
ApplyImplicitMessage(ctx context.Context, msg *types.Message) (*ApplyRet, error)
Flush(ctx context.Context) (cid.Cid, error)
}

2
extern/filecoin-ffi vendored

@ -1 +1 @@
Subproject commit e660df5616e397b2d8ac316f45ddfa7a44637971
Subproject commit 7e1f3a991e410a71ed9ef33becee8d56d5cb9d26