bd10bdf99a
* build: Bump version to v1.17.3-dev * build: set version to v1.18.0-dev * chore: actors: Allow builtin-actors to return a map of methods (#9342) * Allow builtin-actors to return a map of methods * go mod * Fix tests * Fix tests, check carefully please * Delete lotus-pond (#9352) * feat: add StateNetworkVersion to mpool API * chore: refactor: rename NewestNetworkVersion * feat: actors: Integrate datacap actor into lotus (#9348) * Integrate datacap actor * Implement datacap actor in chain/builtin * feat: support typed errors over RPC * chore: deps: update to go-jsonrpc 0.1.8 * remove duplicate import * fix: itest: check for closed connection * chore: refactor: move retry test to API * address magik supernit * Add ability to only have single partition per msg for partitions with recovery sectors * doc gen * Address comments * Return beneficiary info from miner state Info() * Update builtin-actors to dev/20220922-v9 which includes FIP-0045 changes in progress * Integrate verifreg changes to lotus * Setup datacap actor * Update builtin-actors to dev/20220922-v9-1 * Update datacap actor to query datacap instead of verifreg * update gst * update markets * update actors with hamt fix * update gst * Update datacap to parse tokens * Update bundles * datacap and verifreg actors use ID addresses without protocol byte * update builtin-actors to rc1 * update go-fil-markets * Update bundles to rc2 * Integrate the v9 migration * Add api for getting allocation * Add upgrade epoch for butterfly * Tweak PreSeal struct to be infra-friendly * docsgen * More tweaking of PreSeal for genesis * review fixes * Use fake cid for test * add butterfly artifacts for oct 5 upgrade * check datacaps for v8 verifreg match v9 datacap actor * Remove print statements * Update to go-state-types master * Update to go-state-types v0.9.0-rc1 * review fixes * use go-fil-markets v1.24.0-v17 * Add accessors for allocations and claims maps * fix: missing permissions tag * butterfly * update butterfly artifacts * sealing pipeline: Prepare deal assigning logic for FIP-45 * sealing pipeline: Get allocationId with StateApi * use NoAllocationID instead of nil AllocationId * address review * Add datacap actor to registry.go * Add cli for listing allocations and removing expired allocations * Update to go-state-types master * deps: upgrade go-merkledag to 0.8.0 * shark params * Update cli/filplus.go Co-authored-by: Aayush Rajasekaran <arajasek94@gmail.com> * revert change to verifreg util * docsgen-cli * miss the stuff * Update FFI * Update go-state-types to v0.9.0 * Update builtin-actors to v9.0.0 * add calib upgrade epcoh * update the upgrade envvar * kill shark * Remove fvm splash banner from nv17 upgrade * check invariance for pending deals and allocations * check pending verified deal proposal migrated to allocation * Add check for unsealed CID in precommit sectors * Fix counting of allocations in nv17 migration test * make gen * pass state trees as pointers * Add assertion that migrations with & without cache are the same * compare allocation to verified deal proposal * Fix miner state precommit info * fix migration test tool * add changelog * Update to go-state-types v0.9.1 * Integrate builtin-actors v9.0.1 * chore: ver: bump version for rc3 (#9512) * Bump version to 1.18.0-rc3 * Update CHANGELOG.md * Update CHANGELOG.md Co-authored-by: Aayush Rajasekaran <arajasek94@gmail.com> * Update CHANGELOG.md Co-authored-by: Aayush Rajasekaran <arajasek94@gmail.com> Co-authored-by: Jiaying Wang <42981373+jennijuju@users.noreply.github.com> Co-authored-by: Aayush Rajasekaran <arajasek94@gmail.com> * Migration: Use autobatch bs * Fix autobatch Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai> * Invoker: Use MethodMeta from go-state-types * Add a second premigration for nv17 * Add more shed tools for migration checking * address review * Lotus release v1.18.0-rc4 * fix: ci: fix app-image build on ci (#9527) * Remove old go version first * Add GO_VERSION file * Use GO_VERSION to set / verify go version * mv GO_VERSION GO_VERSION_MIN * Use GO_VERSION_MIN in Makefile check Co-authored-by: Ian Davis <jungziege@gmail.com> * Update to latest go-state-types for migration fixes * go mod tidy * fix: use api.ErrActorNotFound instead of types.ErrActorNotFound * fix: add fields to ForkUpgradeParams * docs: update actors_version_checklist.md * chore: fix lint * update to go state type v0.9.6 with market migration fix (#9545) * update go-state-types to v-0.9.7 * Add invariant checks to migration * fix invariant check: number of entries in datacap actor should include verifreg * Invariant checks: Only include not-activated deals * test: nv17 migration * Address review * add lotus-shed invariance method * Migration cli takes a stateroot cid and a height * make gen * Update to builtin-actors v9.0.2 * Failing test that shows that notaries can remove datacap from the verifreg actor * Test that should pass when the problem is solved * make gen * Review fixes * statemanager call function will return call information even if call errors * update go-state-types * update builtin-actors * bubble up errors properly from ApplyImplicitMessage * bump to rc5 * set new upgrade heights for calibnet * set new upgrade height for butterfly * tweak calibnet upgrade schedule * clarify changelog note about calibnet * butterfly * update calibnet artifacts * Allow setting local bundles for Debug FVM for av 9+ * fix: autobatch: remove potential deadlock when a block is missing Check the _underlying_ blockstore instead of recursing. Also, drop the lock before we do that. * fix imports * build: set shark mainnet epoch (#9640) * chore: build: Lotus release v1.18.0 (#9641) * Lotus release v1.18.0 * add changelog * address review * changelog improvement Co-authored-by: Jennifer Wang <jiayingw703@gmail.com> Co-authored-by: Jiaying Wang <42981373+jennijuju@users.noreply.github.com> Signed-off-by: Jakub Sztandera <kubuxu@protocol.ai> Co-authored-by: Łukasz Magiera <magik6k@gmail.com> Co-authored-by: Łukasz Magiera <magik6k@users.noreply.github.com> Co-authored-by: Aayush <arajasek94@gmail.com> Co-authored-by: Geoff Stuart <geoff.vball@gmail.com> Co-authored-by: Shrenuj Bansal <shrenuj.bansal@protocol.ai> Co-authored-by: simlecode <69969590+simlecode@users.noreply.github.com> Co-authored-by: Rod Vagg <rod@vagg.org> Co-authored-by: Jakub Sztandera <kubuxu@protocol.ai> Co-authored-by: Ian Davis <jungziege@gmail.com> Co-authored-by: zenground0 <ZenGround0@users.noreply.github.com> Co-authored-by: Steven Allen <steven@stebalien.com>
573 lines
16 KiB
Go
573 lines
16 KiB
Go
package stmgr
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"os"
|
|
|
|
"github.com/ipfs/go-cid"
|
|
"golang.org/x/xerrors"
|
|
|
|
"github.com/filecoin-project/go-address"
|
|
"github.com/filecoin-project/go-bitfield"
|
|
"github.com/filecoin-project/go-state-types/abi"
|
|
"github.com/filecoin-project/go-state-types/big"
|
|
"github.com/filecoin-project/go-state-types/crypto"
|
|
"github.com/filecoin-project/go-state-types/network"
|
|
|
|
"github.com/filecoin-project/lotus/api"
|
|
"github.com/filecoin-project/lotus/chain/actors/builtin"
|
|
"github.com/filecoin-project/lotus/chain/actors/builtin/market"
|
|
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
|
|
"github.com/filecoin-project/lotus/chain/actors/builtin/paych"
|
|
"github.com/filecoin-project/lotus/chain/actors/builtin/power"
|
|
"github.com/filecoin-project/lotus/chain/actors/builtin/verifreg"
|
|
"github.com/filecoin-project/lotus/chain/beacon"
|
|
"github.com/filecoin-project/lotus/chain/rand"
|
|
"github.com/filecoin-project/lotus/chain/types"
|
|
"github.com/filecoin-project/lotus/chain/vm"
|
|
"github.com/filecoin-project/lotus/storage/sealer/storiface"
|
|
)
|
|
|
|
func GetMinerWorkerRaw(ctx context.Context, sm *StateManager, st cid.Cid, maddr address.Address) (address.Address, error) {
|
|
state, err := sm.StateTree(st)
|
|
if err != nil {
|
|
return address.Undef, xerrors.Errorf("(get sset) failed to load state tree: %w", err)
|
|
}
|
|
act, err := state.GetActor(maddr)
|
|
if err != nil {
|
|
return address.Undef, xerrors.Errorf("(get sset) failed to load miner actor: %w", err)
|
|
}
|
|
mas, err := miner.Load(sm.cs.ActorStore(ctx), act)
|
|
if err != nil {
|
|
return address.Undef, xerrors.Errorf("(get sset) failed to load miner actor state: %w", err)
|
|
}
|
|
|
|
info, err := mas.Info()
|
|
if err != nil {
|
|
return address.Undef, xerrors.Errorf("failed to load actor info: %w", err)
|
|
}
|
|
|
|
return vm.ResolveToKeyAddr(state, sm.cs.ActorStore(ctx), info.Worker)
|
|
}
|
|
|
|
func GetPower(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (power.Claim, power.Claim, bool, error) {
|
|
return GetPowerRaw(ctx, sm, ts.ParentState(), maddr)
|
|
}
|
|
|
|
func GetPowerRaw(ctx context.Context, sm *StateManager, st cid.Cid, maddr address.Address) (power.Claim, power.Claim, bool, error) {
|
|
act, err := sm.LoadActorRaw(ctx, power.Address, st)
|
|
if err != nil {
|
|
return power.Claim{}, power.Claim{}, false, xerrors.Errorf("(get sset) failed to load power actor state: %w", err)
|
|
}
|
|
|
|
pas, err := power.Load(sm.cs.ActorStore(ctx), act)
|
|
if err != nil {
|
|
return power.Claim{}, power.Claim{}, false, err
|
|
}
|
|
|
|
tpow, err := pas.TotalPower()
|
|
if err != nil {
|
|
return power.Claim{}, power.Claim{}, false, err
|
|
}
|
|
|
|
var mpow power.Claim
|
|
var minpow bool
|
|
if maddr != address.Undef {
|
|
var found bool
|
|
mpow, found, err = pas.MinerPower(maddr)
|
|
if err != nil || !found {
|
|
return power.Claim{}, tpow, false, err
|
|
}
|
|
|
|
minpow, err = pas.MinerNominalPowerMeetsConsensusMinimum(maddr)
|
|
if err != nil {
|
|
return power.Claim{}, power.Claim{}, false, err
|
|
}
|
|
}
|
|
|
|
return mpow, tpow, minpow, nil
|
|
}
|
|
|
|
func PreCommitInfo(ctx context.Context, sm *StateManager, maddr address.Address, sid abi.SectorNumber, ts *types.TipSet) (*miner.SectorPreCommitOnChainInfo, 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.ActorStore(ctx), act)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("(get sset) failed to load miner actor state: %w", err)
|
|
}
|
|
|
|
return mas.GetPrecommittedSector(sid)
|
|
}
|
|
|
|
func MinerSectorInfo(ctx context.Context, sm *StateManager, maddr address.Address, sid abi.SectorNumber, ts *types.TipSet) (*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.ActorStore(ctx), act)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("(get sset) failed to load miner actor state: %w", err)
|
|
}
|
|
|
|
return mas.GetSector(sid)
|
|
}
|
|
|
|
func GetSectorsForWinningPoSt(ctx context.Context, nv network.Version, pv storiface.Verifier, sm *StateManager, st cid.Cid, maddr address.Address, rand abi.PoStRandomness) ([]builtin.ExtendedSectorInfo, error) {
|
|
act, err := sm.LoadActorRaw(ctx, maddr, st)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("failed to load miner actor: %w", err)
|
|
}
|
|
|
|
mas, err := miner.Load(sm.cs.ActorStore(ctx), act)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("failed to load miner actor state: %w", err)
|
|
}
|
|
|
|
var provingSectors bitfield.BitField
|
|
if nv < network.Version7 {
|
|
allSectors, err := miner.AllPartSectors(mas, miner.Partition.AllSectors)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("get all sectors: %w", err)
|
|
}
|
|
|
|
faultySectors, err := miner.AllPartSectors(mas, miner.Partition.FaultySectors)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("get faulty sectors: %w", err)
|
|
}
|
|
|
|
provingSectors, err = bitfield.SubtractBitField(allSectors, faultySectors)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("calc proving sectors: %w", err)
|
|
}
|
|
} else {
|
|
provingSectors, err = miner.AllPartSectors(mas, miner.Partition.ActiveSectors)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("get active sectors sectors: %w", err)
|
|
}
|
|
}
|
|
|
|
numProvSect, err := provingSectors.Count()
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("failed to count bits: %w", err)
|
|
}
|
|
|
|
// TODO(review): is this right? feels fishy to me
|
|
if numProvSect == 0 {
|
|
return nil, nil
|
|
}
|
|
|
|
info, err := mas.Info()
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("getting miner info: %w", err)
|
|
}
|
|
|
|
mid, err := address.IDFromAddress(maddr)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("getting miner ID: %w", err)
|
|
}
|
|
|
|
proofType, err := miner.WinningPoStProofTypeFromWindowPoStProofType(nv, info.WindowPoStProofType)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("determining winning post proof type: %w", err)
|
|
}
|
|
|
|
ids, err := pv.GenerateWinningPoStSectorChallenge(ctx, proofType, abi.ActorID(mid), rand, numProvSect)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("generating winning post challenges: %w", err)
|
|
}
|
|
|
|
iter, err := provingSectors.BitIterator()
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("iterating over proving sectors: %w", err)
|
|
}
|
|
|
|
// Select winning sectors by _index_ in the all-sectors bitfield.
|
|
selectedSectors := bitfield.New()
|
|
prev := uint64(0)
|
|
for _, n := range ids {
|
|
sno, err := iter.Nth(n - prev)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("iterating over proving sectors: %w", err)
|
|
}
|
|
selectedSectors.Set(sno)
|
|
prev = n
|
|
}
|
|
|
|
sectors, err := mas.LoadSectors(&selectedSectors)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("loading proving sectors: %w", err)
|
|
}
|
|
|
|
out := make([]builtin.ExtendedSectorInfo, len(sectors))
|
|
for i, sinfo := range sectors {
|
|
out[i] = builtin.ExtendedSectorInfo{
|
|
SealProof: sinfo.SealProof,
|
|
SectorNumber: sinfo.SectorNumber,
|
|
SealedCID: sinfo.SealedCID,
|
|
SectorKey: sinfo.SectorKeyCID,
|
|
}
|
|
}
|
|
|
|
return out, nil
|
|
}
|
|
|
|
func GetMinerSlashed(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (bool, error) {
|
|
act, err := sm.LoadActor(ctx, power.Address, ts)
|
|
if err != nil {
|
|
return false, xerrors.Errorf("failed to load power actor: %w", err)
|
|
}
|
|
|
|
spas, err := power.Load(sm.cs.ActorStore(ctx), act)
|
|
if err != nil {
|
|
return false, xerrors.Errorf("failed to load power actor state: %w", err)
|
|
}
|
|
|
|
_, ok, err := spas.MinerPower(maddr)
|
|
if err != nil {
|
|
return false, xerrors.Errorf("getting miner power: %w", err)
|
|
}
|
|
|
|
if !ok {
|
|
return true, nil
|
|
}
|
|
|
|
return false, nil
|
|
}
|
|
|
|
func GetStorageDeal(ctx context.Context, sm *StateManager, dealID abi.DealID, ts *types.TipSet) (*api.MarketDeal, error) {
|
|
act, err := sm.LoadActor(ctx, market.Address, ts)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("failed to load market actor: %w", err)
|
|
}
|
|
|
|
state, err := market.Load(sm.cs.ActorStore(ctx), act)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("failed to load market actor state: %w", err)
|
|
}
|
|
|
|
proposals, err := state.Proposals()
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("failed to get proposals from state : %w", err)
|
|
}
|
|
|
|
proposal, found, err := proposals.Get(dealID)
|
|
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("failed to get proposal : %w", err)
|
|
} else if !found {
|
|
return nil, xerrors.Errorf(
|
|
"deal %d not found "+
|
|
"- deal may not have completed sealing before deal proposal "+
|
|
"start epoch, or deal may have been slashed",
|
|
dealID)
|
|
}
|
|
|
|
states, err := state.States()
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("failed to get states : %w", err)
|
|
}
|
|
|
|
st, found, err := states.Get(dealID)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("failed to get state : %w", err)
|
|
}
|
|
|
|
if !found {
|
|
st = market.EmptyDealState()
|
|
}
|
|
|
|
return &api.MarketDeal{
|
|
Proposal: *proposal,
|
|
State: *st,
|
|
}, nil
|
|
}
|
|
|
|
func ListMinerActors(ctx context.Context, sm *StateManager, ts *types.TipSet) ([]address.Address, error) {
|
|
act, err := sm.LoadActor(ctx, power.Address, ts)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("failed to load power actor: %w", err)
|
|
}
|
|
|
|
powState, err := power.Load(sm.cs.ActorStore(ctx), act)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("failed to load power actor state: %w", err)
|
|
}
|
|
|
|
return powState.ListAllMiners()
|
|
}
|
|
|
|
func MinerGetBaseInfo(ctx context.Context, sm *StateManager, bcs beacon.Schedule, tsk types.TipSetKey, round abi.ChainEpoch, maddr address.Address, pv storiface.Verifier) (*api.MiningBaseInfo, error) {
|
|
ts, err := sm.ChainStore().LoadTipSet(ctx, tsk)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("failed to load tipset for mining base: %w", err)
|
|
}
|
|
|
|
prev, err := sm.ChainStore().GetLatestBeaconEntry(ctx, ts)
|
|
if err != nil {
|
|
if os.Getenv("LOTUS_IGNORE_DRAND") != "_yes_" {
|
|
return nil, xerrors.Errorf("failed to get latest beacon entry: %w", err)
|
|
}
|
|
|
|
prev = &types.BeaconEntry{}
|
|
}
|
|
|
|
entries, err := beacon.BeaconEntriesForBlock(ctx, bcs, sm.GetNetworkVersion(ctx, round), round, ts.Height(), *prev)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
rbase := *prev
|
|
if len(entries) > 0 {
|
|
rbase = entries[len(entries)-1]
|
|
}
|
|
|
|
lbts, lbst, err := GetLookbackTipSetForRound(ctx, sm, ts, round)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("getting lookback miner actor state: %w", err)
|
|
}
|
|
|
|
act, err := sm.LoadActorRaw(ctx, maddr, lbst)
|
|
if xerrors.Is(err, types.ErrActorNotFound) {
|
|
_, err := sm.LoadActor(ctx, maddr, ts)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("loading miner in current state: %w", err)
|
|
}
|
|
|
|
return nil, nil
|
|
}
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("failed to load miner actor: %w", err)
|
|
}
|
|
|
|
mas, err := miner.Load(sm.cs.ActorStore(ctx), act)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("failed to load miner actor state: %w", err)
|
|
}
|
|
|
|
buf := new(bytes.Buffer)
|
|
if err := maddr.MarshalCBOR(buf); err != nil {
|
|
return nil, xerrors.Errorf("failed to marshal miner address: %w", err)
|
|
}
|
|
|
|
prand, err := rand.DrawRandomness(rbase.Data, crypto.DomainSeparationTag_WinningPoStChallengeSeed, round, buf.Bytes())
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("failed to get randomness for winning post: %w", err)
|
|
}
|
|
|
|
nv := sm.GetNetworkVersion(ctx, ts.Height())
|
|
|
|
sectors, err := GetSectorsForWinningPoSt(ctx, nv, pv, sm, lbst, maddr, prand)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("getting winning post proving set: %w", err)
|
|
}
|
|
|
|
if len(sectors) == 0 {
|
|
return nil, nil
|
|
}
|
|
|
|
mpow, tpow, _, err := GetPowerRaw(ctx, sm, lbst, maddr)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("failed to get power: %w", err)
|
|
}
|
|
|
|
info, err := mas.Info()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
worker, err := sm.ResolveToKeyAddress(ctx, info.Worker, ts)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("resolving worker address: %w", err)
|
|
}
|
|
|
|
// TODO: Not ideal performance...This method reloads miner and power state (already looked up here and in GetPowerRaw)
|
|
eligible, err := MinerEligibleToMine(ctx, sm, maddr, ts, lbts)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("determining miner eligibility: %w", err)
|
|
}
|
|
|
|
return &api.MiningBaseInfo{
|
|
MinerPower: mpow.QualityAdjPower,
|
|
NetworkPower: tpow.QualityAdjPower,
|
|
Sectors: sectors,
|
|
WorkerKey: worker,
|
|
SectorSize: info.SectorSize,
|
|
PrevBeaconEntry: *prev,
|
|
BeaconEntries: entries,
|
|
EligibleForMining: eligible,
|
|
}, nil
|
|
}
|
|
|
|
func minerHasMinPower(ctx context.Context, sm *StateManager, addr address.Address, ts *types.TipSet) (bool, error) {
|
|
pact, err := sm.LoadActor(ctx, power.Address, ts)
|
|
if err != nil {
|
|
return false, xerrors.Errorf("loading power actor state: %w", err)
|
|
}
|
|
|
|
ps, err := power.Load(sm.cs.ActorStore(ctx), pact)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
return ps.MinerNominalPowerMeetsConsensusMinimum(addr)
|
|
}
|
|
|
|
func MinerEligibleToMine(ctx context.Context, sm *StateManager, addr address.Address, baseTs *types.TipSet, lookbackTs *types.TipSet) (bool, error) {
|
|
hmp, err := minerHasMinPower(ctx, sm, addr, lookbackTs)
|
|
|
|
// TODO: We're blurring the lines between a "runtime network version" and a "Lotus upgrade epoch", is that unavoidable?
|
|
if sm.GetNetworkVersion(ctx, baseTs.Height()) <= network.Version3 {
|
|
return hmp, err
|
|
}
|
|
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
if !hmp {
|
|
return false, nil
|
|
}
|
|
|
|
// Post actors v2, also check MinerEligibleForElection with base ts
|
|
|
|
pact, err := sm.LoadActor(ctx, power.Address, baseTs)
|
|
if err != nil {
|
|
return false, xerrors.Errorf("loading power actor state: %w", err)
|
|
}
|
|
|
|
pstate, err := power.Load(sm.cs.ActorStore(ctx), pact)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
mact, err := sm.LoadActor(ctx, addr, baseTs)
|
|
if err != nil {
|
|
return false, xerrors.Errorf("loading miner actor state: %w", err)
|
|
}
|
|
|
|
mstate, err := miner.Load(sm.cs.ActorStore(ctx), mact)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
// Non-empty power claim.
|
|
if claim, found, err := pstate.MinerPower(addr); err != nil {
|
|
return false, err
|
|
} else if !found {
|
|
return false, err
|
|
} else if claim.QualityAdjPower.LessThanEqual(big.Zero()) {
|
|
return false, err
|
|
}
|
|
|
|
// No fee debt.
|
|
if debt, err := mstate.FeeDebt(); err != nil {
|
|
return false, err
|
|
} else if !debt.IsZero() {
|
|
return false, err
|
|
}
|
|
|
|
// No active consensus faults.
|
|
if mInfo, err := mstate.Info(); err != nil {
|
|
return false, err
|
|
} else if baseTs.Height() <= mInfo.ConsensusFaultElapsed {
|
|
return false, nil
|
|
}
|
|
|
|
return true, nil
|
|
}
|
|
|
|
func (sm *StateManager) GetPaychState(ctx context.Context, addr address.Address, ts *types.TipSet) (*types.Actor, paych.State, error) {
|
|
st, err := sm.ParentState(ts)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
act, err := st.GetActor(addr)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
actState, err := paych.Load(sm.cs.ActorStore(ctx), act)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
return act, actState, nil
|
|
}
|
|
|
|
func (sm *StateManager) GetMarketState(ctx context.Context, ts *types.TipSet) (market.State, error) {
|
|
st, err := sm.ParentState(ts)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
act, err := st.GetActor(market.Address)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
actState, err := market.Load(sm.cs.ActorStore(ctx), act)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return actState, nil
|
|
}
|
|
|
|
func (sm *StateManager) GetVerifregState(ctx context.Context, ts *types.TipSet) (verifreg.State, error) {
|
|
st, err := sm.ParentState(ts)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
act, err := st.GetActor(verifreg.Address)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
actState, err := verifreg.Load(sm.cs.ActorStore(ctx), act)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return actState, nil
|
|
}
|
|
|
|
func (sm *StateManager) MarketBalance(ctx context.Context, addr address.Address, ts *types.TipSet) (api.MarketBalance, error) {
|
|
mstate, err := sm.GetMarketState(ctx, ts)
|
|
if err != nil {
|
|
return api.MarketBalance{}, err
|
|
}
|
|
|
|
addr, err = sm.LookupID(ctx, addr, ts)
|
|
if err != nil {
|
|
return api.MarketBalance{}, err
|
|
}
|
|
|
|
var out api.MarketBalance
|
|
|
|
et, err := mstate.EscrowTable()
|
|
if err != nil {
|
|
return api.MarketBalance{}, err
|
|
}
|
|
out.Escrow, err = et.Get(addr)
|
|
if err != nil {
|
|
return api.MarketBalance{}, xerrors.Errorf("getting escrow balance: %w", err)
|
|
}
|
|
|
|
lt, err := mstate.LockedTable()
|
|
if err != nil {
|
|
return api.MarketBalance{}, err
|
|
}
|
|
out.Locked, err = lt.Get(addr)
|
|
if err != nil {
|
|
return api.MarketBalance{}, xerrors.Errorf("getting locked balance: %w", err)
|
|
}
|
|
|
|
return out, nil
|
|
}
|
|
|
|
var _ StateManagerAPI = (*StateManager)(nil)
|