fix: stmgr: make the tipset and height agree when estimating gas (#10216)
* fix: stmgr: make the tipset and height agree when estimating gas Specifically re-execute all messages in the current tipset, tacking the new message onto the end. That way, the epoch is the epoch of the current tipset. We could try to "make" a fake block and use that, but that's unlikely to work well. * fix: stmgr: only apply tipset messages for CallWithGas * fix: itest: window post dispute
This commit is contained in:
parent
1996694a2a
commit
01e616f29e
@ -44,12 +44,12 @@ func (sm *StateManager) Call(ctx context.Context, msg *types.Message, ts *types.
|
|||||||
msg.Value = types.NewInt(0)
|
msg.Value = types.NewInt(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
return sm.callInternal(ctx, msg, nil, ts, cid.Undef, sm.GetNetworkVersion, false)
|
return sm.callInternal(ctx, msg, nil, ts, cid.Undef, sm.GetNetworkVersion, false, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CallWithGas calculates the state for a given tipset, and then applies the given message on top of that state.
|
// CallWithGas calculates the state for a given tipset, and then applies the given message on top of that state.
|
||||||
func (sm *StateManager) CallWithGas(ctx context.Context, msg *types.Message, priorMsgs []types.ChainMsg, ts *types.TipSet) (*api.InvocResult, error) {
|
func (sm *StateManager) CallWithGas(ctx context.Context, msg *types.Message, priorMsgs []types.ChainMsg, ts *types.TipSet) (*api.InvocResult, error) {
|
||||||
return sm.callInternal(ctx, msg, priorMsgs, ts, cid.Undef, sm.GetNetworkVersion, true)
|
return sm.callInternal(ctx, msg, priorMsgs, ts, cid.Undef, sm.GetNetworkVersion, true, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CallAtStateAndVersion allows you to specify a message to execute on the given stateCid and network version.
|
// CallAtStateAndVersion allows you to specify a message to execute on the given stateCid and network version.
|
||||||
@ -61,13 +61,13 @@ func (sm *StateManager) CallAtStateAndVersion(ctx context.Context, msg *types.Me
|
|||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
return sm.callInternal(ctx, msg, nil, nil, stateCid, nvGetter, true)
|
return sm.callInternal(ctx, msg, nil, nil, stateCid, nvGetter, true, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// - If no tipset is specified, the first tipset without an expensive migration or one in its parent is used.
|
// - If no tipset is specified, the first tipset without an expensive migration or one in its parent is used.
|
||||||
// - If executing a message at a given tipset or its parent would trigger an expensive migration, the call will
|
// - If executing a message at a given tipset or its parent would trigger an expensive migration, the call will
|
||||||
// fail with ErrExpensiveFork.
|
// fail with ErrExpensiveFork.
|
||||||
func (sm *StateManager) callInternal(ctx context.Context, msg *types.Message, priorMsgs []types.ChainMsg, ts *types.TipSet, stateCid cid.Cid, nvGetter rand.NetworkVersionGetter, checkGas bool) (*api.InvocResult, error) {
|
func (sm *StateManager) callInternal(ctx context.Context, msg *types.Message, priorMsgs []types.ChainMsg, ts *types.TipSet, stateCid cid.Cid, nvGetter rand.NetworkVersionGetter, checkGas, applyTsMessages bool) (*api.InvocResult, error) {
|
||||||
ctx, span := trace.StartSpan(ctx, "statemanager.callInternal")
|
ctx, span := trace.StartSpan(ctx, "statemanager.callInternal")
|
||||||
defer span.End()
|
defer span.End()
|
||||||
|
|
||||||
@ -107,22 +107,18 @@ func (sm *StateManager) callInternal(ctx context.Context, msg *types.Message, pr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var vmHeight abi.ChainEpoch
|
// Unless executing on a specific state cid, apply all the messages from the current tipset
|
||||||
if checkGas {
|
// first. Unfortunately, we can't just execute the tipset, because that will run cron. We
|
||||||
// Since we're simulating a future message, pretend we're applying it in the "next" tipset
|
// don't want to apply miner messages after cron runs in a given epoch.
|
||||||
vmHeight = ts.Height() + 1
|
if stateCid == cid.Undef {
|
||||||
if stateCid == cid.Undef {
|
stateCid = ts.ParentState()
|
||||||
stateCid, _, err = sm.TipSetState(ctx, ts)
|
}
|
||||||
if err != nil {
|
if applyTsMessages {
|
||||||
return nil, xerrors.Errorf("computing tipset state: %w", err)
|
tsMsgs, err := sm.cs.MessagesForTipset(ctx, ts)
|
||||||
}
|
if err != nil {
|
||||||
}
|
return nil, xerrors.Errorf("failed to lookup messages for parent tipset: %w", err)
|
||||||
} else {
|
|
||||||
// If we're not checking gas, we don't want to have to execute the tipset like above. This saves a lot of computation time
|
|
||||||
vmHeight = pts.Height() + 1
|
|
||||||
if stateCid == cid.Undef {
|
|
||||||
stateCid = ts.ParentState()
|
|
||||||
}
|
}
|
||||||
|
priorMsgs = append(tsMsgs, priorMsgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Technically, the tipset we're passing in here should be ts+1, but that may not exist.
|
// Technically, the tipset we're passing in here should be ts+1, but that may not exist.
|
||||||
@ -142,14 +138,14 @@ func (sm *StateManager) callInternal(ctx context.Context, msg *types.Message, pr
|
|||||||
buffStore := blockstore.NewTieredBstore(sm.cs.StateBlockstore(), blockstore.NewMemorySync())
|
buffStore := blockstore.NewTieredBstore(sm.cs.StateBlockstore(), blockstore.NewMemorySync())
|
||||||
vmopt := &vm.VMOpts{
|
vmopt := &vm.VMOpts{
|
||||||
StateBase: stateCid,
|
StateBase: stateCid,
|
||||||
Epoch: vmHeight,
|
Epoch: ts.Height(),
|
||||||
Timestamp: ts.MinTimestamp(),
|
Timestamp: ts.MinTimestamp(),
|
||||||
Rand: rand.NewStateRand(sm.cs, ts.Cids(), sm.beacon, nvGetter),
|
Rand: rand.NewStateRand(sm.cs, ts.Cids(), sm.beacon, nvGetter),
|
||||||
Bstore: buffStore,
|
Bstore: buffStore,
|
||||||
Actors: sm.tsExec.NewActorRegistry(),
|
Actors: sm.tsExec.NewActorRegistry(),
|
||||||
Syscalls: sm.Syscalls,
|
Syscalls: sm.Syscalls,
|
||||||
CircSupplyCalc: sm.GetVMCirculatingSupply,
|
CircSupplyCalc: sm.GetVMCirculatingSupply,
|
||||||
NetworkVersion: nvGetter(ctx, vmHeight),
|
NetworkVersion: nvGetter(ctx, ts.Height()),
|
||||||
BaseFee: ts.Blocks()[0].ParentBaseFee,
|
BaseFee: ts.Blocks()[0].ParentBaseFee,
|
||||||
LookbackState: LookbackStateGetterForTipset(sm, ts),
|
LookbackState: LookbackStateGetterForTipset(sm, ts),
|
||||||
TipSetGetter: TipSetGetterForTipset(sm.cs, ts),
|
TipSetGetter: TipSetGetterForTipset(sm.cs, ts),
|
||||||
|
@ -113,7 +113,7 @@ func TestWindowPostDispute(t *testing.T) {
|
|||||||
//stm: @CHAIN_STATE_MINER_CALCULATE_DEADLINE_001
|
//stm: @CHAIN_STATE_MINER_CALCULATE_DEADLINE_001
|
||||||
di, err = client.StateMinerProvingDeadline(ctx, evilMinerAddr, types.EmptyTSK)
|
di, err = client.StateMinerProvingDeadline(ctx, evilMinerAddr, types.EmptyTSK)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
if di.Index == evilSectorLoc.Deadline && di.CurrentEpoch-di.PeriodStart > 1 {
|
if di.Index == evilSectorLoc.Deadline && di.CurrentEpoch-di.Open > 1 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
build.Clock.Sleep(blocktime)
|
build.Clock.Sleep(blocktime)
|
||||||
@ -217,7 +217,8 @@ func TestWindowPostDispute(t *testing.T) {
|
|||||||
//stm: @CHAIN_STATE_MINER_CALCULATE_DEADLINE_001
|
//stm: @CHAIN_STATE_MINER_CALCULATE_DEADLINE_001
|
||||||
di, err = client.StateMinerProvingDeadline(ctx, evilMinerAddr, types.EmptyTSK)
|
di, err = client.StateMinerProvingDeadline(ctx, evilMinerAddr, types.EmptyTSK)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
if di.Index == evilSectorLoc.Deadline {
|
|
||||||
|
if di.Index == evilSectorLoc.Deadline && di.CurrentEpoch-di.Open > 1 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
build.Clock.Sleep(blocktime)
|
build.Clock.Sleep(blocktime)
|
||||||
|
Loading…
Reference in New Issue
Block a user