Merge pull request #1195 from filecoin-project/test/fork-height-activation
add a test to ensure there are no off-by-one errors in fork activatio…
This commit is contained in:
commit
04c8bca073
@ -27,6 +27,8 @@ const (
|
|||||||
GasCreateActor = 100
|
GasCreateActor = 100
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var BuiltInActors map[cid.Cid]bool
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
||||||
n, err := cbor.WrapObject(map[string]string{}, mh.SHA2_256, -1)
|
n, err := cbor.WrapObject(map[string]string{}, mh.SHA2_256, -1)
|
||||||
@ -160,12 +162,7 @@ func (ia InitActor) Exec(act *types.Actor, vmctx types.VMContext, p *ExecParams)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func IsBuiltinActor(code cid.Cid) bool {
|
func IsBuiltinActor(code cid.Cid) bool {
|
||||||
switch code {
|
return BuiltInActors[code]
|
||||||
case StorageMarketCodeCid, StoragePowerCodeCid, StorageMinerCodeCid, StorageMiner2CodeCid, AccountCodeCid, InitCodeCid, MultisigCodeCid, PaymentChannelCodeCid:
|
|
||||||
return true
|
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsSingletonActor(code cid.Cid) bool {
|
func IsSingletonActor(code cid.Cid) bool {
|
||||||
|
@ -51,4 +51,15 @@ func init() {
|
|||||||
MultisigCodeCid = mustSum("fil/1/multisig")
|
MultisigCodeCid = mustSum("fil/1/multisig")
|
||||||
InitCodeCid = mustSum("fil/1/init")
|
InitCodeCid = mustSum("fil/1/init")
|
||||||
PaymentChannelCodeCid = mustSum("fil/1/paych")
|
PaymentChannelCodeCid = mustSum("fil/1/paych")
|
||||||
|
|
||||||
|
BuiltInActors = map[cid.Cid]bool{
|
||||||
|
StorageMarketCodeCid: true,
|
||||||
|
StoragePowerCodeCid: true,
|
||||||
|
StorageMinerCodeCid: true,
|
||||||
|
StorageMiner2CodeCid: true,
|
||||||
|
AccountCodeCid: true,
|
||||||
|
InitCodeCid: true,
|
||||||
|
MultisigCodeCid: true,
|
||||||
|
PaymentChannelCodeCid: true,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,10 +6,11 @@ import (
|
|||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/filecoin-project/lotus/chain/vm"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/lotus/chain/vm"
|
||||||
|
|
||||||
ffi "github.com/filecoin-project/filecoin-ffi"
|
ffi "github.com/filecoin-project/filecoin-ffi"
|
||||||
|
|
||||||
sectorbuilder "github.com/filecoin-project/go-sectorbuilder"
|
sectorbuilder "github.com/filecoin-project/go-sectorbuilder"
|
||||||
@ -56,6 +57,8 @@ type ChainGen struct {
|
|||||||
|
|
||||||
Timestamper func(*types.TipSet, uint64) uint64
|
Timestamper func(*types.TipSet, uint64) uint64
|
||||||
|
|
||||||
|
GetMessages func(*ChainGen) ([]*types.SignedMessage, error)
|
||||||
|
|
||||||
w *wallet.Wallet
|
w *wallet.Wallet
|
||||||
|
|
||||||
eppProvs map[address.Address]ElectionPoStProver
|
eppProvs map[address.Address]ElectionPoStProver
|
||||||
@ -210,10 +213,11 @@ func NewGenerator() (*ChainGen, error) {
|
|||||||
genesis: genb.Genesis,
|
genesis: genb.Genesis,
|
||||||
w: w,
|
w: w,
|
||||||
|
|
||||||
Miners: minercfg.MinerAddrs,
|
GetMessages: getRandomMessages,
|
||||||
eppProvs: mgen,
|
Miners: minercfg.MinerAddrs,
|
||||||
banker: banker,
|
eppProvs: mgen,
|
||||||
receivers: receievers,
|
banker: banker,
|
||||||
|
receivers: receievers,
|
||||||
|
|
||||||
CurTipset: gents,
|
CurTipset: gents,
|
||||||
|
|
||||||
@ -224,6 +228,14 @@ func NewGenerator() (*ChainGen, error) {
|
|||||||
return gen, nil
|
return gen, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (cg *ChainGen) SetStateManager(sm *stmgr.StateManager) {
|
||||||
|
cg.sm = sm
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cg *ChainGen) ChainStore() *store.ChainStore {
|
||||||
|
return cg.cs
|
||||||
|
}
|
||||||
|
|
||||||
func (cg *ChainGen) Genesis() *types.BlockHeader {
|
func (cg *ChainGen) Genesis() *types.BlockHeader {
|
||||||
return cg.genesis
|
return cg.genesis
|
||||||
}
|
}
|
||||||
@ -295,7 +307,7 @@ func (cg *ChainGen) NextTipSet() (*MinedTipSet, error) {
|
|||||||
func (cg *ChainGen) NextTipSetFromMiners(base *types.TipSet, miners []address.Address) (*MinedTipSet, error) {
|
func (cg *ChainGen) NextTipSetFromMiners(base *types.TipSet, miners []address.Address) (*MinedTipSet, error) {
|
||||||
var blks []*types.FullBlock
|
var blks []*types.FullBlock
|
||||||
|
|
||||||
msgs, err := cg.getRandomMessages()
|
msgs, err := cg.GetMessages(cg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("get random messages: %w", err)
|
return nil, xerrors.Errorf("get random messages: %w", err)
|
||||||
}
|
}
|
||||||
@ -359,7 +371,15 @@ func (cg *ChainGen) ResyncBankerNonce(ts *types.TipSet) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cg *ChainGen) getRandomMessages() ([]*types.SignedMessage, error) {
|
func (cg *ChainGen) Banker() address.Address {
|
||||||
|
return cg.banker
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cg *ChainGen) Wallet() *wallet.Wallet {
|
||||||
|
return cg.w
|
||||||
|
}
|
||||||
|
|
||||||
|
func getRandomMessages(cg *ChainGen) ([]*types.SignedMessage, error) {
|
||||||
msgs := make([]*types.SignedMessage, cg.msgsPerBlock)
|
msgs := make([]*types.SignedMessage, cg.msgsPerBlock)
|
||||||
for m := range msgs {
|
for m := range msgs {
|
||||||
msg := types.Message{
|
msg := types.Message{
|
||||||
|
@ -15,33 +15,50 @@ import (
|
|||||||
"golang.org/x/xerrors"
|
"golang.org/x/xerrors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var ForksAtHeight = map[uint64]func(context.Context, *StateManager, cid.Cid) (cid.Cid, error){
|
||||||
|
build.ForkBlizzardHeight: func(ctx context.Context, sm *StateManager, pstate cid.Cid) (cid.Cid, error) {
|
||||||
|
log.Warnw("Executing blizzard fork logic")
|
||||||
|
nstate, err := fixBlizzardAMTBug(ctx, sm, pstate)
|
||||||
|
if err != nil {
|
||||||
|
return cid.Undef, xerrors.Errorf("blizzard bug fix failed: %w", err)
|
||||||
|
}
|
||||||
|
return nstate, nil
|
||||||
|
},
|
||||||
|
build.ForkFrigidHeight: func(ctx context.Context, sm *StateManager, pstate cid.Cid) (cid.Cid, error) {
|
||||||
|
log.Warnw("Executing frigid fork logic")
|
||||||
|
nstate, err := fixBlizzardAMTBug(ctx, sm, pstate)
|
||||||
|
if err != nil {
|
||||||
|
return cid.Undef, xerrors.Errorf("frigid bug fix failed: %w", err)
|
||||||
|
}
|
||||||
|
return nstate, nil
|
||||||
|
},
|
||||||
|
build.ForkBootyBayHeight: func(ctx context.Context, sm *StateManager, pstate cid.Cid) (cid.Cid, error) {
|
||||||
|
log.Warnw("Executing booty bay fork logic")
|
||||||
|
nstate, err := fixBlizzardAMTBug(ctx, sm, pstate)
|
||||||
|
if err != nil {
|
||||||
|
return cid.Undef, xerrors.Errorf("booty bay bug fix failed: %w", err)
|
||||||
|
}
|
||||||
|
return nstate, nil
|
||||||
|
},
|
||||||
|
build.ForkMissingSnowballs: func(ctx context.Context, sm *StateManager, pstate cid.Cid) (cid.Cid, error) {
|
||||||
|
log.Warnw("Adding more snow to the world")
|
||||||
|
nstate, err := fixTooFewSnowballs(ctx, sm, pstate)
|
||||||
|
if err != nil {
|
||||||
|
return cid.Undef, xerrors.Errorf("missing snowballs bug fix failed: %w", err)
|
||||||
|
}
|
||||||
|
return nstate, nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
func (sm *StateManager) handleStateForks(ctx context.Context, pstate cid.Cid, height, parentH uint64) (_ cid.Cid, err error) {
|
func (sm *StateManager) handleStateForks(ctx context.Context, pstate cid.Cid, height, parentH uint64) (_ cid.Cid, err error) {
|
||||||
for i := parentH; i < height; i++ {
|
for i := parentH; i < height; i++ {
|
||||||
switch i {
|
f, ok := ForksAtHeight[i]
|
||||||
case build.ForkBlizzardHeight:
|
if ok {
|
||||||
log.Warnw("Executing blizzard fork logic", "height", i)
|
nstate, err := f(ctx, sm, pstate)
|
||||||
pstate, err = fixBlizzardAMTBug(ctx, sm, pstate)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cid.Undef, xerrors.Errorf("blizzard bug fix failed: %w", err)
|
return cid.Undef, err
|
||||||
}
|
|
||||||
case build.ForkFrigidHeight:
|
|
||||||
log.Warnw("Executing frigid fork logic", "height", i)
|
|
||||||
pstate, err = fixBlizzardAMTBug(ctx, sm, pstate)
|
|
||||||
if err != nil {
|
|
||||||
return cid.Undef, xerrors.Errorf("frigid bug fix failed: %w", err)
|
|
||||||
}
|
|
||||||
case build.ForkBootyBayHeight:
|
|
||||||
log.Warnw("Executing booty bay fork logic", "height", i)
|
|
||||||
pstate, err = fixBlizzardAMTBug(ctx, sm, pstate)
|
|
||||||
if err != nil {
|
|
||||||
return cid.Undef, xerrors.Errorf("booty bay bug fix failed: %w", err)
|
|
||||||
}
|
|
||||||
case build.ForkMissingSnowballs:
|
|
||||||
log.Warnw("Adding more snow to the world", "height", i)
|
|
||||||
pstate, err = fixTooFewSnowballs(ctx, sm, pstate)
|
|
||||||
if err != nil {
|
|
||||||
return cid.Undef, xerrors.Errorf("missing snowballs bug fix failed: %w", err)
|
|
||||||
}
|
}
|
||||||
|
pstate = nstate
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
231
chain/stmgr/forks_test.go
Normal file
231
chain/stmgr/forks_test.go
Normal file
@ -0,0 +1,231 @@
|
|||||||
|
package stmgr_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/go-address"
|
||||||
|
"github.com/filecoin-project/lotus/build"
|
||||||
|
"github.com/filecoin-project/lotus/chain/actors"
|
||||||
|
"github.com/filecoin-project/lotus/chain/actors/aerrors"
|
||||||
|
"github.com/filecoin-project/lotus/chain/gen"
|
||||||
|
"github.com/filecoin-project/lotus/chain/state"
|
||||||
|
"github.com/filecoin-project/lotus/chain/stmgr"
|
||||||
|
. "github.com/filecoin-project/lotus/chain/stmgr"
|
||||||
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
|
"github.com/filecoin-project/lotus/chain/vm"
|
||||||
|
|
||||||
|
"github.com/ipfs/go-cid"
|
||||||
|
hamt "github.com/ipfs/go-hamt-ipld"
|
||||||
|
blockstore "github.com/ipfs/go-ipfs-blockstore"
|
||||||
|
logging "github.com/ipfs/go-log"
|
||||||
|
mh "github.com/multiformats/go-multihash"
|
||||||
|
cbg "github.com/whyrusleeping/cbor-gen"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
build.SectorSizes = []uint64{1024}
|
||||||
|
build.MinimumMinerPower = 1024
|
||||||
|
}
|
||||||
|
|
||||||
|
const testForkHeight = 40
|
||||||
|
|
||||||
|
type testActor struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
type testActorState struct {
|
||||||
|
HasUpgraded uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tas *testActorState) MarshalCBOR(w io.Writer) error {
|
||||||
|
return cbg.CborWriteHeader(w, cbg.MajUnsignedInt, tas.HasUpgraded)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tas *testActorState) UnmarshalCBOR(r io.Reader) error {
|
||||||
|
t, v, err := cbg.CborReadHeader(r)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if t != cbg.MajUnsignedInt {
|
||||||
|
return fmt.Errorf("wrong type in test actor state")
|
||||||
|
}
|
||||||
|
tas.HasUpgraded = v
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ta *testActor) Exports() []interface{} {
|
||||||
|
return []interface{}{
|
||||||
|
1: ta.Constructor,
|
||||||
|
2: ta.TestMethod,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ta *testActor) Constructor(act *types.Actor, vmctx types.VMContext, params *struct{}) ([]byte, aerrors.ActorError) {
|
||||||
|
c, err := vmctx.Storage().Put(&testActorState{11})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("NEW ACTOR ADDRESS IS: ", vmctx.Message().To.String())
|
||||||
|
|
||||||
|
return nil, vmctx.Storage().Commit(actors.EmptyCBOR, c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ta *testActor) TestMethod(act *types.Actor, vmctx types.VMContext, params *struct{}) ([]byte, aerrors.ActorError) {
|
||||||
|
var st testActorState
|
||||||
|
if err := vmctx.Storage().Get(vmctx.Storage().GetHead(), &st); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if vmctx.BlockHeight() > testForkHeight {
|
||||||
|
if st.HasUpgraded != 55 {
|
||||||
|
return nil, aerrors.Fatal("fork updating applied in wrong order")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if st.HasUpgraded != 11 {
|
||||||
|
return nil, aerrors.Fatal("fork updating happened too early")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestForkHeightTriggers(t *testing.T) {
|
||||||
|
logging.SetAllLoggers(logging.LevelInfo)
|
||||||
|
|
||||||
|
ctx := context.TODO()
|
||||||
|
|
||||||
|
cg, err := gen.NewGenerator()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
sm := NewStateManager(cg.ChainStore())
|
||||||
|
|
||||||
|
inv := vm.NewInvoker()
|
||||||
|
|
||||||
|
pref := cid.NewPrefixV1(cid.Raw, mh.IDENTITY)
|
||||||
|
actcid, err := pref.Sum([]byte("testactor"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
actors.BuiltInActors[actcid] = true
|
||||||
|
|
||||||
|
// predicting the address here... may break if other assumptions change
|
||||||
|
taddr, err := address.NewIDAddress(1000)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
stmgr.ForksAtHeight[testForkHeight] = func(ctx context.Context, sm *StateManager, pstate cid.Cid) (cid.Cid, error) {
|
||||||
|
cst := hamt.CSTFromBstore(sm.ChainStore().Blockstore())
|
||||||
|
st, err := state.LoadStateTree(cst, pstate)
|
||||||
|
if err != nil {
|
||||||
|
return cid.Undef, err
|
||||||
|
}
|
||||||
|
|
||||||
|
act, err := st.GetActor(taddr)
|
||||||
|
if err != nil {
|
||||||
|
return cid.Undef, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var tas testActorState
|
||||||
|
if err := cst.Get(ctx, act.Head, &tas); err != nil {
|
||||||
|
return cid.Undef, err
|
||||||
|
}
|
||||||
|
|
||||||
|
tas.HasUpgraded = 55
|
||||||
|
|
||||||
|
ns, err := cst.Put(ctx, &tas)
|
||||||
|
if err != nil {
|
||||||
|
return cid.Undef, err
|
||||||
|
}
|
||||||
|
|
||||||
|
act.Head = ns
|
||||||
|
|
||||||
|
if err := st.SetActor(taddr, act); err != nil {
|
||||||
|
return cid.Undef, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return st.Flush(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
inv.Register(actcid, &testActor{}, &testActorState{})
|
||||||
|
sm.SetVMConstructor(func(c cid.Cid, h uint64, r vm.Rand, a address.Address, b blockstore.Blockstore, s *types.VMSyscalls) (*vm.VM, error) {
|
||||||
|
nvm, err := vm.NewVM(c, h, r, a, b, s)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
nvm.SetInvoker(inv)
|
||||||
|
return nvm, nil
|
||||||
|
})
|
||||||
|
|
||||||
|
cg.SetStateManager(sm)
|
||||||
|
|
||||||
|
var msgs []*types.SignedMessage
|
||||||
|
|
||||||
|
enc, err := actors.SerializeParams(&actors.ExecParams{Code: actcid})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
m := &types.Message{
|
||||||
|
From: cg.Banker(),
|
||||||
|
To: actors.InitAddress,
|
||||||
|
Method: actors.IAMethods.Exec,
|
||||||
|
Params: enc,
|
||||||
|
GasLimit: types.NewInt(10000),
|
||||||
|
GasPrice: types.NewInt(0),
|
||||||
|
}
|
||||||
|
sig, err := cg.Wallet().Sign(ctx, cg.Banker(), m.Cid().Bytes())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
msgs = append(msgs, &types.SignedMessage{
|
||||||
|
Signature: *sig,
|
||||||
|
Message: *m,
|
||||||
|
})
|
||||||
|
|
||||||
|
nonce := uint64(1)
|
||||||
|
cg.GetMessages = func(cg *gen.ChainGen) ([]*types.SignedMessage, error) {
|
||||||
|
if len(msgs) > 0 {
|
||||||
|
fmt.Println("added construct method")
|
||||||
|
m := msgs
|
||||||
|
msgs = nil
|
||||||
|
return m, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
m := &types.Message{
|
||||||
|
From: cg.Banker(),
|
||||||
|
To: taddr,
|
||||||
|
Method: 2,
|
||||||
|
Params: nil,
|
||||||
|
Nonce: nonce,
|
||||||
|
GasLimit: types.NewInt(10000),
|
||||||
|
GasPrice: types.NewInt(0),
|
||||||
|
}
|
||||||
|
nonce++
|
||||||
|
|
||||||
|
sig, err := cg.Wallet().Sign(ctx, cg.Banker(), m.Cid().Bytes())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return []*types.SignedMessage{
|
||||||
|
&types.SignedMessage{
|
||||||
|
Signature: *sig,
|
||||||
|
Message: *m,
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < 50; i++ {
|
||||||
|
_, err = cg.NextTipSet()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -18,6 +18,7 @@ import (
|
|||||||
bls "github.com/filecoin-project/filecoin-ffi"
|
bls "github.com/filecoin-project/filecoin-ffi"
|
||||||
"github.com/ipfs/go-cid"
|
"github.com/ipfs/go-cid"
|
||||||
hamt "github.com/ipfs/go-hamt-ipld"
|
hamt "github.com/ipfs/go-hamt-ipld"
|
||||||
|
blockstore "github.com/ipfs/go-ipfs-blockstore"
|
||||||
logging "github.com/ipfs/go-log/v2"
|
logging "github.com/ipfs/go-log/v2"
|
||||||
"go.opencensus.io/trace"
|
"go.opencensus.io/trace"
|
||||||
)
|
)
|
||||||
@ -30,10 +31,12 @@ type StateManager struct {
|
|||||||
stCache map[string][]cid.Cid
|
stCache map[string][]cid.Cid
|
||||||
compWait map[string]chan struct{}
|
compWait map[string]chan struct{}
|
||||||
stlk sync.Mutex
|
stlk sync.Mutex
|
||||||
|
newVM func(cid.Cid, uint64, vm.Rand, address.Address, blockstore.Blockstore, *types.VMSyscalls) (*vm.VM, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewStateManager(cs *store.ChainStore) *StateManager {
|
func NewStateManager(cs *store.ChainStore) *StateManager {
|
||||||
return &StateManager{
|
return &StateManager{
|
||||||
|
newVM: vm.NewVM,
|
||||||
cs: cs,
|
cs: cs,
|
||||||
stCache: make(map[string][]cid.Cid),
|
stCache: make(map[string][]cid.Cid),
|
||||||
compWait: make(map[string]chan struct{}),
|
compWait: make(map[string]chan struct{}),
|
||||||
@ -139,7 +142,7 @@ func (sm *StateManager) computeTipSetState(ctx context.Context, blks []*types.Bl
|
|||||||
|
|
||||||
r := store.NewChainRand(sm.cs, cids, blks[0].Height)
|
r := store.NewChainRand(sm.cs, cids, blks[0].Height)
|
||||||
|
|
||||||
vmi, err := vm.NewVM(pstate, blks[0].Height, r, address.Undef, sm.cs.Blockstore(), sm.cs.VMSys())
|
vmi, err := sm.newVM(pstate, blks[0].Height, r, address.Undef, sm.cs.Blockstore(), sm.cs.VMSys())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cid.Undef, cid.Undef, xerrors.Errorf("instantiating VM failed: %w", err)
|
return cid.Undef, cid.Undef, xerrors.Errorf("instantiating VM failed: %w", err)
|
||||||
}
|
}
|
||||||
@ -636,3 +639,7 @@ func (sm *StateManager) ValidateChain(ctx context.Context, ts *types.TipSet) err
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (sm *StateManager) SetVMConstructor(nvm func(cid.Cid, uint64, vm.Rand, address.Address, blockstore.Blockstore, *types.VMSyscalls) (*vm.VM, error)) {
|
||||||
|
sm.newVM = nvm
|
||||||
|
}
|
||||||
|
@ -23,21 +23,21 @@ type invoker struct {
|
|||||||
type invokeFunc func(act *types.Actor, vmctx types.VMContext, params []byte) ([]byte, aerrors.ActorError)
|
type invokeFunc func(act *types.Actor, vmctx types.VMContext, params []byte) ([]byte, aerrors.ActorError)
|
||||||
type nativeCode []invokeFunc
|
type nativeCode []invokeFunc
|
||||||
|
|
||||||
func newInvoker() *invoker {
|
func NewInvoker() *invoker {
|
||||||
inv := &invoker{
|
inv := &invoker{
|
||||||
builtInCode: make(map[cid.Cid]nativeCode),
|
builtInCode: make(map[cid.Cid]nativeCode),
|
||||||
builtInState: make(map[cid.Cid]reflect.Type),
|
builtInState: make(map[cid.Cid]reflect.Type),
|
||||||
}
|
}
|
||||||
|
|
||||||
// add builtInCode using: register(cid, singleton)
|
// add builtInCode using: register(cid, singleton)
|
||||||
inv.register(actors.InitCodeCid, actors.InitActor{}, actors.InitActorState{})
|
inv.Register(actors.InitCodeCid, actors.InitActor{}, actors.InitActorState{})
|
||||||
inv.register(actors.CronCodeCid, actors.CronActor{}, actors.CronActorState{})
|
inv.Register(actors.CronCodeCid, actors.CronActor{}, actors.CronActorState{})
|
||||||
inv.register(actors.StoragePowerCodeCid, actors.StoragePowerActor{}, actors.StoragePowerState{})
|
inv.Register(actors.StoragePowerCodeCid, actors.StoragePowerActor{}, actors.StoragePowerState{})
|
||||||
inv.register(actors.StorageMarketCodeCid, actors.StorageMarketActor{}, actors.StorageMarketState{})
|
inv.Register(actors.StorageMarketCodeCid, actors.StorageMarketActor{}, actors.StorageMarketState{})
|
||||||
inv.register(actors.StorageMinerCodeCid, actors.StorageMinerActor{}, actors.StorageMinerActorState{})
|
inv.Register(actors.StorageMinerCodeCid, actors.StorageMinerActor{}, actors.StorageMinerActorState{})
|
||||||
inv.register(actors.StorageMiner2CodeCid, actors.StorageMinerActor2{}, actors.StorageMinerActorState{})
|
inv.Register(actors.StorageMiner2CodeCid, actors.StorageMinerActor2{}, actors.StorageMinerActorState{})
|
||||||
inv.register(actors.MultisigCodeCid, actors.MultiSigActor{}, actors.MultiSigActorState{})
|
inv.Register(actors.MultisigCodeCid, actors.MultiSigActor{}, actors.MultiSigActorState{})
|
||||||
inv.register(actors.PaymentChannelCodeCid, actors.PaymentChannelActor{}, actors.PaymentChannelActorState{})
|
inv.Register(actors.PaymentChannelCodeCid, actors.PaymentChannelActor{}, actors.PaymentChannelActorState{})
|
||||||
|
|
||||||
return inv
|
return inv
|
||||||
}
|
}
|
||||||
@ -60,7 +60,7 @@ func (inv *invoker) Invoke(act *types.Actor, vmctx types.VMContext, method uint6
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (inv *invoker) register(c cid.Cid, instance Invokee, state interface{}) {
|
func (inv *invoker) Register(c cid.Cid, instance Invokee, state interface{}) {
|
||||||
code, err := inv.transform(instance)
|
code, err := inv.transform(instance)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@ -165,7 +165,7 @@ func DumpActorState(code cid.Cid, b []byte) (interface{}, error) {
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
i := newInvoker() // TODO: register builtins in init block
|
i := NewInvoker() // TODO: register builtins in init block
|
||||||
|
|
||||||
typ, ok := i.builtInState[code]
|
typ, ok := i.builtInState[code]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -327,7 +327,7 @@ func NewVM(base cid.Cid, height uint64, r Rand, maddr address.Address, cbs block
|
|||||||
buf: buf,
|
buf: buf,
|
||||||
blockHeight: height,
|
blockHeight: height,
|
||||||
blockMiner: maddr,
|
blockMiner: maddr,
|
||||||
inv: newInvoker(),
|
inv: NewInvoker(),
|
||||||
rand: r, // TODO: Probably should be a syscall
|
rand: r, // TODO: Probably should be a syscall
|
||||||
Syscalls: syscalls,
|
Syscalls: syscalls,
|
||||||
}, nil
|
}, nil
|
||||||
@ -671,6 +671,10 @@ func Transfer(from, to *types.Actor, amt types.BigInt) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (vm *VM) SetInvoker(i *invoker) {
|
||||||
|
vm.inv = i
|
||||||
|
}
|
||||||
|
|
||||||
func deductFunds(act *types.Actor, amt types.BigInt) error {
|
func deductFunds(act *types.Actor, amt types.BigInt) error {
|
||||||
if act.Balance.LessThan(amt) {
|
if act.Balance.LessThan(amt) {
|
||||||
return fmt.Errorf("not enough funds")
|
return fmt.Errorf("not enough funds")
|
||||||
|
Loading…
Reference in New Issue
Block a user