Merge pull request #2617 from filecoin-project/feat/cron-on-nulls
stmgr: Execute cron tick on null rounds
This commit is contained in:
commit
b7139c38ed
@ -3,23 +3,20 @@ package stmgr
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||||
"github.com/ipfs/go-cid"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var ForksAtHeight = map[abi.ChainEpoch]func(context.Context, *StateManager, cid.Cid) (cid.Cid, error){}
|
var ForksAtHeight = map[abi.ChainEpoch]func(context.Context, *StateManager, types.StateTree) error{}
|
||||||
|
|
||||||
func (sm *StateManager) handleStateForks(ctx context.Context, pstate cid.Cid, height, parentH abi.ChainEpoch) (_ cid.Cid, err error) {
|
func (sm *StateManager) handleStateForks(ctx context.Context, st types.StateTree, height abi.ChainEpoch) (err error) {
|
||||||
for i := parentH; i < height; i++ {
|
f, ok := ForksAtHeight[height]
|
||||||
f, ok := ForksAtHeight[i]
|
if ok {
|
||||||
if ok {
|
err := f(ctx, sm, st)
|
||||||
nstate, err := f(ctx, sm, pstate)
|
if err != nil {
|
||||||
if err != nil {
|
return err
|
||||||
return cid.Undef, err
|
|
||||||
}
|
|
||||||
pstate = nstate
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return pstate, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,6 @@ import (
|
|||||||
"github.com/filecoin-project/lotus/chain/actors"
|
"github.com/filecoin-project/lotus/chain/actors"
|
||||||
"github.com/filecoin-project/lotus/chain/actors/aerrors"
|
"github.com/filecoin-project/lotus/chain/actors/aerrors"
|
||||||
"github.com/filecoin-project/lotus/chain/gen"
|
"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/stmgr"
|
. "github.com/filecoin-project/lotus/chain/stmgr"
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
@ -122,37 +121,33 @@ func TestForkHeightTriggers(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
stmgr.ForksAtHeight[testForkHeight] = func(ctx context.Context, sm *StateManager, pstate cid.Cid) (cid.Cid, error) {
|
stmgr.ForksAtHeight[testForkHeight] = func(ctx context.Context, sm *StateManager, st types.StateTree) error {
|
||||||
cst := cbor.NewCborStore(sm.ChainStore().Blockstore())
|
cst := cbor.NewCborStore(sm.ChainStore().Blockstore())
|
||||||
st, err := state.LoadStateTree(cst, pstate)
|
|
||||||
if err != nil {
|
|
||||||
return cid.Undef, err
|
|
||||||
}
|
|
||||||
|
|
||||||
act, err := st.GetActor(taddr)
|
act, err := st.GetActor(taddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cid.Undef, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var tas testActorState
|
var tas testActorState
|
||||||
if err := cst.Get(ctx, act.Head, &tas); err != nil {
|
if err := cst.Get(ctx, act.Head, &tas); err != nil {
|
||||||
return cid.Undef, xerrors.Errorf("in fork handler, failed to run get: %w", err)
|
return xerrors.Errorf("in fork handler, failed to run get: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
tas.HasUpgraded = 55
|
tas.HasUpgraded = 55
|
||||||
|
|
||||||
ns, err := cst.Put(ctx, &tas)
|
ns, err := cst.Put(ctx, &tas)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cid.Undef, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
act.Head = ns
|
act.Head = ns
|
||||||
|
|
||||||
if err := st.SetActor(taddr, act); err != nil {
|
if err := st.SetActor(taddr, act); err != nil {
|
||||||
return cid.Undef, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return st.Flush(ctx)
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
inv.Register(builtin.PaymentChannelActorCodeID, &testActor{}, &testActorState{})
|
inv.Register(builtin.PaymentChannelActorCodeID, &testActor{}, &testActorState{})
|
||||||
|
@ -146,12 +146,62 @@ type BlockMessages struct {
|
|||||||
|
|
||||||
type ExecCallback func(cid.Cid, *types.Message, *vm.ApplyRet) error
|
type ExecCallback func(cid.Cid, *types.Message, *vm.ApplyRet) error
|
||||||
|
|
||||||
func (sm *StateManager) ApplyBlocks(ctx context.Context, pstate cid.Cid, bms []BlockMessages, epoch abi.ChainEpoch, r vm.Rand, cb ExecCallback) (cid.Cid, cid.Cid, error) {
|
func (sm *StateManager) ApplyBlocks(ctx context.Context, parentEpoch abi.ChainEpoch, pstate cid.Cid, bms []BlockMessages, epoch abi.ChainEpoch, r vm.Rand, cb ExecCallback) (cid.Cid, cid.Cid, error) {
|
||||||
vmi, err := sm.newVM(pstate, epoch, r, sm.cs.Blockstore(), sm.cs.VMSys())
|
vmi, err := sm.newVM(pstate, parentEpoch, r, 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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
runCron := func() error {
|
||||||
|
// TODO: this nonce-getting is a tiny bit ugly
|
||||||
|
ca, err := vmi.StateTree().GetActor(builtin.SystemActorAddr)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
cronMsg := &types.Message{
|
||||||
|
To: builtin.CronActorAddr,
|
||||||
|
From: builtin.SystemActorAddr,
|
||||||
|
Nonce: ca.Nonce,
|
||||||
|
Value: types.NewInt(0),
|
||||||
|
GasPrice: types.NewInt(0),
|
||||||
|
GasLimit: build.BlockGasLimit * 10000, // Make super sure this is never too little
|
||||||
|
Method: builtin.MethodsCron.EpochTick,
|
||||||
|
Params: nil,
|
||||||
|
}
|
||||||
|
ret, err := vmi.ApplyImplicitMessage(ctx, cronMsg)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if cb != nil {
|
||||||
|
if err := cb(cronMsg.Cid(), cronMsg, ret); err != nil {
|
||||||
|
return xerrors.Errorf("callback failed on cron message: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ret.ExitCode != 0 {
|
||||||
|
return xerrors.Errorf("CheckProofSubmissions exit was non-zero: %d", ret.ExitCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := parentEpoch; i < epoch; i++ {
|
||||||
|
// handle state forks
|
||||||
|
err = sm.handleStateForks(ctx, vmi.StateTree(), i)
|
||||||
|
if err != nil {
|
||||||
|
return cid.Undef, cid.Undef, xerrors.Errorf("error handling state forks: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if i > parentEpoch {
|
||||||
|
// run cron for null rounds if any
|
||||||
|
if err := runCron(); err != nil {
|
||||||
|
return cid.Cid{}, cid.Cid{}, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vmi.SetBlockHeight(i + 1)
|
||||||
|
}
|
||||||
|
|
||||||
var receipts []cbg.CBORMarshaler
|
var receipts []cbg.CBORMarshaler
|
||||||
processedMsgs := map[cid.Cid]bool{}
|
processedMsgs := map[cid.Cid]bool{}
|
||||||
for _, b := range bms {
|
for _, b := range bms {
|
||||||
@ -219,36 +269,10 @@ func (sm *StateManager) ApplyBlocks(ctx context.Context, pstate cid.Cid, bms []B
|
|||||||
if ret.ExitCode != 0 {
|
if ret.ExitCode != 0 {
|
||||||
return cid.Undef, cid.Undef, xerrors.Errorf("reward application message failed (exit %d): %s", ret.ExitCode, ret.ActorErr)
|
return cid.Undef, cid.Undef, xerrors.Errorf("reward application message failed (exit %d): %s", ret.ExitCode, ret.ActorErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: this nonce-getting is a tiny bit ugly
|
if err := runCron(); err != nil {
|
||||||
ca, err := vmi.StateTree().GetActor(builtin.SystemActorAddr)
|
return cid.Cid{}, cid.Cid{}, err
|
||||||
if err != nil {
|
|
||||||
return cid.Undef, cid.Undef, err
|
|
||||||
}
|
|
||||||
|
|
||||||
cronMsg := &types.Message{
|
|
||||||
To: builtin.CronActorAddr,
|
|
||||||
From: builtin.SystemActorAddr,
|
|
||||||
Nonce: ca.Nonce,
|
|
||||||
Value: types.NewInt(0),
|
|
||||||
GasPrice: types.NewInt(0),
|
|
||||||
GasLimit: build.BlockGasLimit * 10, // Make super sure this is never too little
|
|
||||||
Method: builtin.MethodsCron.EpochTick,
|
|
||||||
Params: nil,
|
|
||||||
}
|
|
||||||
ret, err := vmi.ApplyImplicitMessage(ctx, cronMsg)
|
|
||||||
if err != nil {
|
|
||||||
return cid.Undef, cid.Undef, err
|
|
||||||
}
|
|
||||||
if cb != nil {
|
|
||||||
if err := cb(cronMsg.Cid(), cronMsg, ret); err != nil {
|
|
||||||
return cid.Undef, cid.Undef, xerrors.Errorf("callback failed on cron message: %w", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ret.ExitCode != 0 {
|
|
||||||
return cid.Undef, cid.Undef, xerrors.Errorf("CheckProofSubmissions exit was non-zero: %d", ret.ExitCode)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rectarr := adt.MakeEmptyArray(sm.cs.Store(ctx))
|
rectarr := adt.MakeEmptyArray(sm.cs.Store(ctx))
|
||||||
@ -284,17 +308,15 @@ func (sm *StateManager) computeTipSetState(ctx context.Context, blks []*types.Bl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var parentEpoch abi.ChainEpoch
|
||||||
pstate := blks[0].ParentStateRoot
|
pstate := blks[0].ParentStateRoot
|
||||||
if len(blks[0].Parents) > 0 { // don't support forks on genesis
|
if len(blks[0].Parents) > 0 {
|
||||||
parent, err := sm.cs.GetBlock(blks[0].Parents[0])
|
parent, err := sm.cs.GetBlock(blks[0].Parents[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cid.Undef, cid.Undef, xerrors.Errorf("getting parent block: %w", err)
|
return cid.Undef, cid.Undef, xerrors.Errorf("getting parent block: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
pstate, err = sm.handleStateForks(ctx, blks[0].ParentStateRoot, blks[0].Height, parent.Height)
|
parentEpoch = parent.Height
|
||||||
if err != nil {
|
|
||||||
return cid.Undef, cid.Undef, xerrors.Errorf("error handling state forks: %w", err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cids := make([]cid.Cid, len(blks))
|
cids := make([]cid.Cid, len(blks))
|
||||||
@ -329,7 +351,7 @@ func (sm *StateManager) computeTipSetState(ctx context.Context, blks []*types.Bl
|
|||||||
blkmsgs = append(blkmsgs, bm)
|
blkmsgs = append(blkmsgs, bm)
|
||||||
}
|
}
|
||||||
|
|
||||||
return sm.ApplyBlocks(ctx, pstate, blkmsgs, blks[0].Height, r, cb)
|
return sm.ApplyBlocks(ctx, parentEpoch, pstate, blkmsgs, blks[0].Height, r, cb)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sm *StateManager) parentState(ts *types.TipSet) cid.Cid {
|
func (sm *StateManager) parentState(ts *types.TipSet) cid.Cid {
|
||||||
|
@ -439,15 +439,20 @@ func ComputeState(ctx context.Context, sm *StateManager, height abi.ChainEpoch,
|
|||||||
return cid.Undef, nil, err
|
return cid.Undef, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
fstate, err := sm.handleStateForks(ctx, base, height, ts.Height())
|
r := store.NewChainRand(sm.cs, ts.Cids(), height)
|
||||||
|
vmi, err := vm.NewVM(base, height, r, sm.cs.Blockstore(), sm.cs.VMSys())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cid.Undef, nil, err
|
return cid.Undef, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
r := store.NewChainRand(sm.cs, ts.Cids(), height)
|
for i := ts.Height(); i < height; i++ {
|
||||||
vmi, err := vm.NewVM(fstate, height, r, sm.cs.Blockstore(), sm.cs.VMSys())
|
// handle state forks
|
||||||
if err != nil {
|
err = sm.handleStateForks(ctx, vmi.StateTree(), i)
|
||||||
return cid.Undef, nil, err
|
if err != nil {
|
||||||
|
return cid.Undef, nil, xerrors.Errorf("error handling state forks: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: should we also run cron here?
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, msg := range msgs {
|
for i, msg := range msgs {
|
||||||
|
@ -88,7 +88,7 @@ func (a *Applier) ApplyTipSetMessages(epoch abi.ChainEpoch, blocks []vtypes.Bloc
|
|||||||
}
|
}
|
||||||
|
|
||||||
var receipts []vtypes.MessageReceipt
|
var receipts []vtypes.MessageReceipt
|
||||||
sroot, _, err := sm.ApplyBlocks(context.TODO(), a.stateWrapper.Root(), bms, epoch, &randWrapper{rnd}, func(c cid.Cid, msg *types.Message, ret *vm.ApplyRet) error {
|
sroot, _, err := sm.ApplyBlocks(context.TODO(), epoch-1, a.stateWrapper.Root(), bms, epoch, &randWrapper{rnd}, func(c cid.Cid, msg *types.Message, ret *vm.ApplyRet) error {
|
||||||
if msg.From == builtin.SystemActorAddr {
|
if msg.From == builtin.SystemActorAddr {
|
||||||
return nil // ignore reward and cron calls
|
return nil // ignore reward and cron calls
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user