Merge pull request #7966 from filecoin-project/asr/compute-state-vm
Fix: chain: create a new VM for each epoch
This commit is contained in:
commit
c0f29ea9c6
@ -92,16 +92,16 @@ func (t *TipSetExecutor) ApplyBlocks(ctx context.Context, sm *stmgr.StateManager
|
|||||||
partDone()
|
partDone()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
makeVmWithBaseState := func(base cid.Cid) (*vm.VM, error) {
|
makeVmWithBaseStateAndEpoch := func(base cid.Cid, e abi.ChainEpoch) (*vm.VM, error) {
|
||||||
vmopt := &vm.VMOpts{
|
vmopt := &vm.VMOpts{
|
||||||
StateBase: base,
|
StateBase: base,
|
||||||
Epoch: epoch,
|
Epoch: e,
|
||||||
Rand: r,
|
Rand: r,
|
||||||
Bstore: sm.ChainStore().StateBlockstore(),
|
Bstore: sm.ChainStore().StateBlockstore(),
|
||||||
Actors: NewActorRegistry(),
|
Actors: NewActorRegistry(),
|
||||||
Syscalls: sm.Syscalls,
|
Syscalls: sm.Syscalls,
|
||||||
CircSupplyCalc: sm.GetVMCirculatingSupply,
|
CircSupplyCalc: sm.GetVMCirculatingSupply,
|
||||||
NetworkVersion: sm.GetNetworkVersion(ctx, epoch),
|
NetworkVersion: sm.GetNetworkVersion(ctx, e),
|
||||||
BaseFee: baseFee,
|
BaseFee: baseFee,
|
||||||
LookbackState: stmgr.LookbackStateGetterForTipset(sm, ts),
|
LookbackState: stmgr.LookbackStateGetterForTipset(sm, ts),
|
||||||
}
|
}
|
||||||
@ -109,12 +109,7 @@ func (t *TipSetExecutor) ApplyBlocks(ctx context.Context, sm *stmgr.StateManager
|
|||||||
return sm.VMConstructor()(ctx, vmopt)
|
return sm.VMConstructor()(ctx, vmopt)
|
||||||
}
|
}
|
||||||
|
|
||||||
vmi, err := makeVmWithBaseState(pstate)
|
runCron := func(vmCron *vm.VM, epoch abi.ChainEpoch) error {
|
||||||
if err != nil {
|
|
||||||
return cid.Undef, cid.Undef, xerrors.Errorf("making vm: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
runCron := func(epoch abi.ChainEpoch) error {
|
|
||||||
cronMsg := &types.Message{
|
cronMsg := &types.Message{
|
||||||
To: cron.Address,
|
To: cron.Address,
|
||||||
From: builtin.SystemActorAddr,
|
From: builtin.SystemActorAddr,
|
||||||
@ -126,59 +121,58 @@ func (t *TipSetExecutor) ApplyBlocks(ctx context.Context, sm *stmgr.StateManager
|
|||||||
Method: cron.Methods.EpochTick,
|
Method: cron.Methods.EpochTick,
|
||||||
Params: nil,
|
Params: nil,
|
||||||
}
|
}
|
||||||
ret, err := vmi.ApplyImplicitMessage(ctx, cronMsg)
|
ret, err := vmCron.ApplyImplicitMessage(ctx, cronMsg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return xerrors.Errorf("running cron: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if em != nil {
|
if em != nil {
|
||||||
if err := em.MessageApplied(ctx, ts, cronMsg.Cid(), cronMsg, ret, true); err != nil {
|
if err := em.MessageApplied(ctx, ts, cronMsg.Cid(), cronMsg, ret, true); err != nil {
|
||||||
return xerrors.Errorf("callback failed on cron message: %w", err)
|
return xerrors.Errorf("callback failed on cron message: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ret.ExitCode != 0 {
|
if ret.ExitCode != 0 {
|
||||||
return xerrors.Errorf("CheckProofSubmissions exit was non-zero: %d", ret.ExitCode)
|
return xerrors.Errorf("cron exit was non-zero: %d", ret.ExitCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := parentEpoch; i < epoch; i++ {
|
for i := parentEpoch; i < epoch; i++ {
|
||||||
|
var err error
|
||||||
if i > parentEpoch {
|
if i > parentEpoch {
|
||||||
// run cron for null rounds if any
|
vmCron, err := makeVmWithBaseStateAndEpoch(pstate, i)
|
||||||
if err := runCron(i); err != nil {
|
if err != nil {
|
||||||
return cid.Undef, cid.Undef, err
|
return cid.Undef, cid.Undef, xerrors.Errorf("making cron vm: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
pstate, err = vmi.Flush(ctx)
|
// run cron for null rounds if any
|
||||||
|
if err = runCron(vmCron, i); err != nil {
|
||||||
|
return cid.Undef, cid.Undef, xerrors.Errorf("running cron: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
pstate, err = vmCron.Flush(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cid.Undef, cid.Undef, xerrors.Errorf("flushing vm: %w", err)
|
return cid.Undef, cid.Undef, xerrors.Errorf("flushing cron vm: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle state forks
|
// handle state forks
|
||||||
// XXX: The state tree
|
// XXX: The state tree
|
||||||
newState, err := sm.HandleStateForks(ctx, pstate, i, em, ts)
|
pstate, err = sm.HandleStateForks(ctx, pstate, i, em, ts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cid.Undef, cid.Undef, xerrors.Errorf("error handling state forks: %w", err)
|
return cid.Undef, cid.Undef, xerrors.Errorf("error handling state forks: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if pstate != newState {
|
|
||||||
vmi, err = makeVmWithBaseState(newState)
|
|
||||||
if err != nil {
|
|
||||||
return cid.Undef, cid.Undef, xerrors.Errorf("making vm: %w", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = vmi.SetBlockHeight(ctx, i+1); err != nil {
|
|
||||||
return cid.Undef, cid.Undef, xerrors.Errorf("error advancing vm an epoch: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
pstate = newState
|
|
||||||
}
|
}
|
||||||
|
|
||||||
partDone()
|
partDone()
|
||||||
partDone = metrics.Timer(ctx, metrics.VMApplyMessages)
|
partDone = metrics.Timer(ctx, metrics.VMApplyMessages)
|
||||||
|
|
||||||
|
vmi, err := makeVmWithBaseStateAndEpoch(pstate, epoch)
|
||||||
|
if err != nil {
|
||||||
|
return cid.Undef, cid.Undef, xerrors.Errorf("making vm: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
var receipts []cbg.CBORMarshaler
|
var receipts []cbg.CBORMarshaler
|
||||||
processedMsgs := make(map[cid.Cid]struct{})
|
processedMsgs := make(map[cid.Cid]struct{})
|
||||||
for _, b := range bms {
|
for _, b := range bms {
|
||||||
@ -246,7 +240,7 @@ func (t *TipSetExecutor) ApplyBlocks(ctx context.Context, sm *stmgr.StateManager
|
|||||||
partDone()
|
partDone()
|
||||||
partDone = metrics.Timer(ctx, metrics.VMApplyCron)
|
partDone = metrics.Timer(ctx, metrics.VMApplyCron)
|
||||||
|
|
||||||
if err := runCron(epoch); err != nil {
|
if err := runCron(vmi, epoch); err != nil {
|
||||||
return cid.Cid{}, cid.Cid{}, err
|
return cid.Cid{}, cid.Cid{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -458,7 +458,7 @@ func (filec *FilecoinEC) checkBlockMessages(ctx context.Context, b *types.FullBl
|
|||||||
|
|
||||||
stateroot, _, err := filec.sm.TipSetState(ctx, baseTs)
|
stateroot, _, err := filec.sm.TipSetState(ctx, baseTs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return xerrors.Errorf("failed to compute tipsettate for %s: %w", baseTs.Key(), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
st, err := state.LoadStateTree(filec.store.ActorStore(ctx), stateroot)
|
st, err := state.LoadStateTree(filec.store.ActorStore(ctx), stateroot)
|
||||||
@ -475,7 +475,7 @@ func (filec *FilecoinEC) checkBlockMessages(ctx context.Context, b *types.FullBl
|
|||||||
// Phase 1: syntactic validation, as defined in the spec
|
// Phase 1: syntactic validation, as defined in the spec
|
||||||
minGas := pl.OnChainMessage(msg.ChainLength())
|
minGas := pl.OnChainMessage(msg.ChainLength())
|
||||||
if err := m.ValidForBlockInclusion(minGas.Total(), nv); err != nil {
|
if err := m.ValidForBlockInclusion(minGas.Total(), nv); err != nil {
|
||||||
return err
|
return xerrors.Errorf("msg %s invalid for block inclusion: %w", m.Cid(), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValidForBlockInclusion checks if any single message does not exceed BlockGasLimit
|
// ValidForBlockInclusion checks if any single message does not exceed BlockGasLimit
|
||||||
@ -491,7 +491,7 @@ func (filec *FilecoinEC) checkBlockMessages(ctx context.Context, b *types.FullBl
|
|||||||
if filec.sm.GetNetworkVersion(ctx, b.Header.Height) >= network.Version13 {
|
if filec.sm.GetNetworkVersion(ctx, b.Header.Height) >= network.Version13 {
|
||||||
sender, err = st.LookupID(m.From)
|
sender, err = st.LookupID(m.From)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return xerrors.Errorf("failed to lookup sender %s: %w", m.From, err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sender = m.From
|
sender = m.From
|
||||||
@ -574,12 +574,13 @@ func (filec *FilecoinEC) checkBlockMessages(ctx context.Context, b *types.FullBl
|
|||||||
|
|
||||||
bmroot, err := bmArr.Root()
|
bmroot, err := bmArr.Root()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return xerrors.Errorf("failed to root bls msgs: %w", err)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
smroot, err := smArr.Root()
|
smroot, err := smArr.Root()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return xerrors.Errorf("failed to root secp msgs: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
mrcid, err := tmpstore.Put(ctx, &types.MsgMeta{
|
mrcid, err := tmpstore.Put(ctx, &types.MsgMeta{
|
||||||
@ -587,7 +588,7 @@ func (filec *FilecoinEC) checkBlockMessages(ctx context.Context, b *types.FullBl
|
|||||||
SecpkMessages: smroot,
|
SecpkMessages: smroot,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return xerrors.Errorf("failed to put msg meta: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if b.Header.Messages != mrcid {
|
if b.Header.Messages != mrcid {
|
||||||
@ -595,7 +596,12 @@ func (filec *FilecoinEC) checkBlockMessages(ctx context.Context, b *types.FullBl
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Finally, flush.
|
// Finally, flush.
|
||||||
return vm.Copy(ctx, tmpbs, filec.store.ChainBlockstore(), mrcid)
|
err = vm.Copy(ctx, tmpbs, filec.store.ChainBlockstore(), mrcid)
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("failed to flush:%w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (filec *FilecoinEC) IsEpochBeyondCurrMax(epoch abi.ChainEpoch) bool {
|
func (filec *FilecoinEC) IsEpochBeyondCurrMax(epoch abi.ChainEpoch) bool {
|
||||||
|
@ -824,17 +824,6 @@ func (vm *VM) StateTree() types.StateTree {
|
|||||||
return vm.cstate
|
return vm.cstate
|
||||||
}
|
}
|
||||||
|
|
||||||
func (vm *VM) SetBlockHeight(ctx context.Context, h abi.ChainEpoch) error {
|
|
||||||
vm.blockHeight = h
|
|
||||||
ncirc, err := vm.circSupplyCalc(ctx, vm.blockHeight, vm.cstate)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
vm.baseCircSupply = ncirc
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (vm *VM) Invoke(act *types.Actor, rt *Runtime, method abi.MethodNum, params []byte) ([]byte, aerrors.ActorError) {
|
func (vm *VM) Invoke(act *types.Actor, rt *Runtime, method abi.MethodNum, params []byte) ([]byte, aerrors.ActorError) {
|
||||||
ctx, span := trace.StartSpan(rt.ctx, "vm.Invoke")
|
ctx, span := trace.StartSpan(rt.ctx, "vm.Invoke")
|
||||||
defer span.End()
|
defer span.End()
|
||||||
|
Loading…
Reference in New Issue
Block a user