diff --git a/api/api_full.go b/api/api_full.go index b91ecd3e7..74857ab9b 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -331,10 +331,14 @@ type FullNode interface { // MethodGroup: State // The State methods are used to query, inspect, and interact with chain state. - // Most methods take a TipSetKey as a parameter. The state looked up is the state at that tipset. + // Most methods take a TipSetKey as a parameter. The state looked up is the parent state of the tipset. // A nil TipSetKey can be provided as a param, this will cause the heaviest tipset in the chain to be used. // StateCall runs the given message and returns its result without any persisted changes. + // + // StateCall applies the message to the tipset's parent state. The + // message is not applied on-top-of the messages in the passed-in + // tipset. StateCall(context.Context, *types.Message, types.TipSetKey) (*InvocResult, error) // StateReplay replays a given message, assuming it was included in a block in the specified tipset. // If no tipset key is provided, the appropriate tipset is looked up. diff --git a/chain/stmgr/utils.go b/chain/stmgr/utils.go index 1e29e72d8..ff821eb2f 100644 --- a/chain/stmgr/utils.go +++ b/chain/stmgr/utils.go @@ -144,20 +144,6 @@ func MinerSectorInfo(ctx context.Context, sm *StateManager, maddr address.Addres return mas.GetSector(sid) } -func GetMinerSectorSet(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address, snos *bitfield.BitField) ([]*miner.SectorOnChainInfo, error) { - act, err := sm.LoadActor(ctx, maddr, ts) - if err != nil { - return nil, xerrors.Errorf("(get sset) failed to load miner actor: %w", err) - } - - mas, err := miner.Load(sm.cs.Store(ctx), act) - if err != nil { - return nil, xerrors.Errorf("(get sset) failed to load miner actor state: %w", err) - } - - return mas.LoadSectors(snos) -} - func GetSectorsForWinningPoSt(ctx context.Context, nv network.Version, pv ffiwrapper.Verifier, sm *StateManager, st cid.Cid, maddr address.Address, rand abi.PoStRandomness) ([]builtin.SectorInfo, error) { act, err := sm.LoadActorRaw(ctx, maddr, st) if err != nil { diff --git a/miner/miner.go b/miner/miner.go index 4075c8cc6..efdbe4896 100644 --- a/miner/miner.go +++ b/miner/miner.go @@ -21,7 +21,6 @@ import ( "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/gen" - "github.com/filecoin-project/lotus/chain/messagepool/gasguess" "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/journal" @@ -506,33 +505,3 @@ func (m *Miner) createBlock(base *MiningBase, addr address.Address, ticket *type WinningPoStProof: wpostProof, }) } - -type actCacheEntry struct { - act *types.Actor - err error -} - -type cachedActorLookup struct { - tsk types.TipSetKey - cache map[address.Address]actCacheEntry - fallback gasguess.ActorLookup -} - -func (c *cachedActorLookup) StateGetActor(ctx context.Context, a address.Address, tsk types.TipSetKey) (*types.Actor, error) { - if c.tsk == tsk { - e, has := c.cache[a] - if has { - return e.act, e.err - } - } - - e, err := c.fallback(ctx, a, tsk) - if c.tsk == tsk { - c.cache[a] = actCacheEntry{ - act: e, err: err, - } - } - return e, err -} - -type ActorLookup func(context.Context, address.Address, types.TipSetKey) (*types.Actor, error) diff --git a/node/impl/full/state.go b/node/impl/full/state.go index 957cf0b5b..71399b27e 100644 --- a/node/impl/full/state.go +++ b/node/impl/full/state.go @@ -6,7 +6,6 @@ import ( "strconv" cid "github.com/ipfs/go-cid" - cbor "github.com/ipfs/go-ipld-cbor" "go.uber.org/fx" "golang.org/x/xerrors" @@ -35,7 +34,6 @@ import ( "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/vm" "github.com/filecoin-project/lotus/chain/wallet" - "github.com/filecoin-project/lotus/lib/bufbstore" "github.com/filecoin-project/lotus/node/modules/dtypes" ) @@ -92,19 +90,20 @@ func (a *StateAPI) StateNetworkName(ctx context.Context) (dtypes.NetworkName, er } func (a *StateAPI) StateMinerSectors(ctx context.Context, addr address.Address, sectorNos *bitfield.BitField, tsk types.TipSetKey) ([]*miner.SectorOnChainInfo, error) { - ts, err := a.Chain.GetTipSetFromKey(tsk) + act, err := a.StateManager.LoadActorTsk(ctx, addr, tsk) if err != nil { - return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err) + return nil, xerrors.Errorf("failed to load miner actor: %w", err) } - return stmgr.GetMinerSectorSet(ctx, a.StateManager, ts, addr, sectorNos) + + mas, err := miner.Load(a.StateManager.ChainStore().Store(ctx), act) + if err != nil { + return nil, xerrors.Errorf("failed to load miner actor state: %w", err) + } + + return mas.LoadSectors(sectorNos) } func (a *StateAPI) StateMinerActiveSectors(ctx context.Context, maddr address.Address, tsk types.TipSetKey) ([]*miner.SectorOnChainInfo, error) { // TODO: only used in cli - ts, err := a.Chain.GetTipSetFromKey(tsk) - if err != nil { - return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err) - } - act, err := a.StateManager.LoadActorTsk(ctx, maddr, tsk) if err != nil { return nil, xerrors.Errorf("failed to load miner actor: %w", err) @@ -120,7 +119,7 @@ func (a *StateAPI) StateMinerActiveSectors(ctx context.Context, maddr address.Ad return nil, xerrors.Errorf("merge partition active sets: %w", err) } - return stmgr.GetMinerSectorSet(ctx, a.StateManager, ts, maddr, &activeSectors) + return mas.LoadSectors(&activeSectors) } func (m *StateModule) StateMinerInfo(ctx context.Context, actor address.Address, tsk types.TipSetKey) (miner.MinerInfo, error) { @@ -423,38 +422,12 @@ func (a *StateAPI) StateReplay(ctx context.Context, tsk types.TipSetKey, mc cid. }, nil } -func stateForTs(ctx context.Context, ts *types.TipSet, cstore *store.ChainStore, smgr *stmgr.StateManager) (*state.StateTree, error) { - if ts == nil { - ts = cstore.GetHeaviestTipSet() - } - - st, _, err := smgr.TipSetState(ctx, ts) - if err != nil { - return nil, err - } - - buf := bufbstore.NewBufferedBstore(cstore.Blockstore()) - cst := cbor.NewCborStore(buf) - return state.LoadStateTree(cst, st) -} -func (a *StateAPI) stateForTs(ctx context.Context, ts *types.TipSet) (*state.StateTree, error) { - return stateForTs(ctx, ts, a.Chain, a.StateManager) -} -func (m *StateModule) stateForTs(ctx context.Context, ts *types.TipSet) (*state.StateTree, error) { - return stateForTs(ctx, ts, m.Chain, m.StateManager) -} - func (m *StateModule) StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error) { ts, err := m.Chain.GetTipSetFromKey(tsk) if err != nil { return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err) } - state, err := m.stateForTs(ctx, ts) - if err != nil { - return nil, xerrors.Errorf("computing tipset state failed: %w", err) - } - - return state.GetActor(actor) + return m.StateManager.LoadActor(ctx, actor, ts) } func (m *StateModule) StateLookupID(ctx context.Context, addr address.Address, tsk types.TipSetKey) (address.Address, error) { @@ -480,17 +453,12 @@ func (a *StateAPI) StateReadState(ctx context.Context, actor address.Address, ts if err != nil { return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err) } - state, err := a.stateForTs(ctx, ts) - if err != nil { - return nil, xerrors.Errorf("getting state for tipset: %w", err) - } - - act, err := state.GetActor(actor) + act, err := a.StateManager.LoadActor(ctx, actor, ts) if err != nil { return nil, xerrors.Errorf("getting actor: %w", err) } - blk, err := state.Store.(*cbor.BasicIpldStore).Blocks.Get(act.Head) + blk, err := a.Chain.Blockstore().Get(act.Head) if err != nil { return nil, xerrors.Errorf("getting actor head: %w", err) } @@ -526,6 +494,7 @@ func (a *StateAPI) StateDecodeParams(ctx context.Context, toAddr address.Address // This is on StateAPI because miner.Miner requires this, and MinerAPI requires miner.Miner func (a *StateAPI) MinerGetBaseInfo(ctx context.Context, maddr address.Address, epoch abi.ChainEpoch, tsk types.TipSetKey) (*api.MiningBaseInfo, error) { + // XXX: Gets the state by computing the tipset state, instead of looking at the parent. return stmgr.MinerGetBaseInfo(ctx, a.StateManager, a.Beacon, tsk, epoch, maddr, a.ProofVerifier) } @@ -1329,11 +1298,11 @@ func (a *StateAPI) StateCirculatingSupply(ctx context.Context, tsk types.TipSetK return types.EmptyInt, xerrors.Errorf("loading tipset %s: %w", tsk, err) } - sTree, err := a.stateForTs(ctx, ts) + sTree, err := a.StateManager.ParentState(ts) if err != nil { return types.EmptyInt, err } - return a.StateManager.GetCirculatingSupply(ctx, ts.Height(), sTree) + return a.StateManager.GetCirculatingSupply(ctx, ts.Height()-1, sTree) } func (a *StateAPI) StateVMCirculatingSupplyInternal(ctx context.Context, tsk types.TipSetKey) (api.CirculatingSupply, error) { @@ -1350,7 +1319,7 @@ func stateVMCirculatingSupplyInternal( return api.CirculatingSupply{}, xerrors.Errorf("loading tipset %s: %w", tsk, err) } - sTree, err := stateForTs(ctx, ts, cstore, smgr) + sTree, err := smgr.ParentState(ts) if err != nil { return api.CirculatingSupply{}, err } @@ -1364,5 +1333,7 @@ func (m *StateModule) StateNetworkVersion(ctx context.Context, tsk types.TipSetK return network.VersionMax, xerrors.Errorf("loading tipset %s: %w", tsk, err) } + // TODO: Height-1 to be consistent with the rest of the APIs? + // But that's likely going to break a bunch of stuff. return m.StateManager.GetNtwkVersion(ctx, ts.Height()), nil }