330 lines
9.9 KiB
Go
330 lines
9.9 KiB
Go
package stmgr
|
|
|
|
import (
|
|
"context"
|
|
"github.com/filecoin-project/lotus/chain/state"
|
|
|
|
amt "github.com/filecoin-project/go-amt-ipld/v2"
|
|
commcid "github.com/filecoin-project/go-fil-commcid"
|
|
"github.com/filecoin-project/specs-actors/actors/abi"
|
|
"github.com/filecoin-project/specs-actors/actors/abi/big"
|
|
"github.com/filecoin-project/specs-actors/actors/builtin"
|
|
"github.com/filecoin-project/specs-actors/actors/builtin/market"
|
|
"github.com/filecoin-project/specs-actors/actors/builtin/miner"
|
|
"github.com/filecoin-project/specs-actors/actors/builtin/power"
|
|
"github.com/filecoin-project/specs-actors/actors/util/adt"
|
|
|
|
"github.com/filecoin-project/lotus/chain/actors/aerrors"
|
|
|
|
sectorbuilder "github.com/filecoin-project/go-sectorbuilder"
|
|
|
|
ffi "github.com/filecoin-project/filecoin-ffi"
|
|
|
|
"github.com/filecoin-project/go-address"
|
|
|
|
"github.com/filecoin-project/lotus/api"
|
|
"github.com/filecoin-project/lotus/chain/actors"
|
|
"github.com/filecoin-project/lotus/chain/store"
|
|
"github.com/filecoin-project/lotus/chain/types"
|
|
"github.com/filecoin-project/lotus/chain/vm"
|
|
|
|
cid "github.com/ipfs/go-cid"
|
|
blockstore "github.com/ipfs/go-ipfs-blockstore"
|
|
cbor "github.com/ipfs/go-ipld-cbor"
|
|
"github.com/libp2p/go-libp2p-core/peer"
|
|
cbg "github.com/whyrusleeping/cbor-gen"
|
|
"golang.org/x/xerrors"
|
|
)
|
|
|
|
func GetMinerWorkerRaw(ctx context.Context, sm *StateManager, st cid.Cid, maddr address.Address) (address.Address, error) {
|
|
var mas miner.State
|
|
_, err := sm.LoadActorStateRaw(ctx, maddr, &mas, st)
|
|
if err != nil {
|
|
return address.Undef, xerrors.Errorf("(get sset) failed to load miner actor state: %w", err)
|
|
}
|
|
|
|
cst := cbor.NewCborStore(sm.cs.Blockstore())
|
|
state, err := state.LoadStateTree(cst, st)
|
|
if err != nil {
|
|
return address.Undef, xerrors.Errorf("load state tree: %w", err)
|
|
}
|
|
|
|
return vm.ResolveToKeyAddr(state, cst, mas.Info.Worker)
|
|
}
|
|
|
|
func GetMinerOwner(ctx context.Context, sm *StateManager, st cid.Cid, maddr address.Address) (address.Address, error) {
|
|
var mas miner.State
|
|
_, err := sm.LoadActorStateRaw(ctx, maddr, &mas, st)
|
|
if err != nil {
|
|
return address.Undef, xerrors.Errorf("(get sset) failed to load miner actor state: %w", err)
|
|
}
|
|
|
|
cst := cbor.NewCborStore(sm.cs.Blockstore())
|
|
state, err := state.LoadStateTree(cst, st)
|
|
if err != nil {
|
|
return address.Undef, xerrors.Errorf("load state tree: %w", err)
|
|
}
|
|
|
|
return vm.ResolveToKeyAddr(state, cst, mas.Info.Owner)
|
|
}
|
|
|
|
func GetPower(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (types.BigInt, types.BigInt, error) {
|
|
var ps power.State
|
|
_, err := sm.LoadActorState(ctx, builtin.StoragePowerActorAddr, &ps, ts)
|
|
if err != nil {
|
|
return big.Zero(), big.Zero(), xerrors.Errorf("(get sset) failed to load power actor state: %w", err)
|
|
}
|
|
|
|
var mpow big.Int
|
|
if maddr != address.Undef {
|
|
var claim power.Claim
|
|
if _, err := adt.AsMap(sm.cs.Store(ctx), ps.Claims).Get(adt.AddrKey(maddr), &claim); err != nil {
|
|
return big.Zero(), big.Zero(), err
|
|
}
|
|
|
|
mpow = claim.Power
|
|
}
|
|
|
|
return mpow, ps.TotalNetworkPower, nil
|
|
}
|
|
|
|
func GetMinerPeerID(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (peer.ID, error) {
|
|
var mas miner.State
|
|
_, err := sm.LoadActorState(ctx, maddr, &mas, ts)
|
|
if err != nil {
|
|
return "", xerrors.Errorf("(get sset) failed to load miner actor state: %w", err)
|
|
}
|
|
|
|
return mas.Info.PeerId, nil
|
|
}
|
|
|
|
func GetMinerWorker(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (address.Address, error) {
|
|
return GetMinerWorkerRaw(ctx, sm, sm.parentState(ts), maddr)
|
|
}
|
|
|
|
func GetMinerPostState(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (*miner.PoStState, error) {
|
|
var mas miner.State
|
|
_, err := sm.LoadActorState(ctx, maddr, &mas, ts)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("(get eps) failed to load miner actor state: %w", err)
|
|
}
|
|
|
|
return &mas.PoStState, nil
|
|
}
|
|
|
|
func SectorSetSizes(ctx context.Context, sm *StateManager, maddr address.Address, ts *types.TipSet) (api.MinerSectors, error) {
|
|
var mas miner.State
|
|
_, err := sm.LoadActorState(ctx, maddr, &mas, ts)
|
|
if err != nil {
|
|
return api.MinerSectors{}, xerrors.Errorf("(get sset) failed to load miner actor state: %w", err)
|
|
}
|
|
|
|
blks := cbor.NewCborStore(sm.ChainStore().Blockstore())
|
|
ss, err := amt.LoadAMT(ctx, blks, mas.Sectors)
|
|
if err != nil {
|
|
return api.MinerSectors{}, err
|
|
}
|
|
|
|
ps, err := amt.LoadAMT(ctx, blks, mas.ProvingSet)
|
|
if err != nil {
|
|
return api.MinerSectors{}, err
|
|
}
|
|
|
|
return api.MinerSectors{
|
|
Pset: ps.Count,
|
|
Sset: ss.Count,
|
|
}, nil
|
|
}
|
|
|
|
func GetMinerProvingSet(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) ([]*api.ChainSectorInfo, error) {
|
|
var mas miner.State
|
|
_, err := sm.LoadActorState(ctx, maddr, &mas, ts)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("(get pset) failed to load miner actor state: %w", err)
|
|
}
|
|
|
|
return LoadSectorsFromSet(ctx, sm.ChainStore().Blockstore(), mas.ProvingSet)
|
|
}
|
|
|
|
func GetMinerSectorSet(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) ([]*api.ChainSectorInfo, error) {
|
|
var mas miner.State
|
|
_, err := sm.LoadActorState(ctx, maddr, &mas, ts)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("(get sset) failed to load miner actor state: %w", err)
|
|
}
|
|
|
|
return LoadSectorsFromSet(ctx, sm.ChainStore().Blockstore(), mas.Sectors)
|
|
}
|
|
|
|
func GetSectorsForElectionPost(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (*sectorbuilder.SortedPublicSectorInfo, error) {
|
|
sectors, err := GetMinerProvingSet(ctx, sm, ts, maddr)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("failed to get sector set for miner: %w", err)
|
|
}
|
|
|
|
var uselessOtherArray []ffi.PublicSectorInfo
|
|
for _, s := range sectors {
|
|
cr, err := commcid.CIDToReplicaCommitmentV1(s.Info.Info.SealedCID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var uselessBuffer [32]byte
|
|
copy(uselessBuffer[:], cr)
|
|
uselessOtherArray = append(uselessOtherArray, ffi.PublicSectorInfo{
|
|
SectorNum: s.ID,
|
|
CommR: uselessBuffer,
|
|
})
|
|
}
|
|
|
|
ssi := sectorbuilder.NewSortedPublicSectorInfo(uselessOtherArray)
|
|
return &ssi, nil
|
|
}
|
|
|
|
func GetMinerSectorSize(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (abi.SectorSize, error) {
|
|
var mas miner.State
|
|
_, err := sm.LoadActorState(ctx, maddr, &mas, ts)
|
|
if err != nil {
|
|
return 0, xerrors.Errorf("(get ssize) failed to load miner actor state: %w", err)
|
|
}
|
|
|
|
return mas.Info.SectorSize, nil
|
|
}
|
|
|
|
func GetMinerSlashed(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (uint64, error) {
|
|
log.Warn("stub GetMinerSlashed")
|
|
return 0, nil
|
|
}
|
|
|
|
func GetMinerFaults(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) ([]abi.SectorNumber, error) {
|
|
var mas miner.State
|
|
_, err := sm.LoadActorState(ctx, maddr, &mas, ts)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("(get ssize) failed to load miner actor state: %w", err)
|
|
}
|
|
|
|
ss, lerr := amt.LoadAMT(ctx, cbor.NewCborStore(sm.cs.Blockstore()), mas.Sectors)
|
|
if lerr != nil {
|
|
return nil, aerrors.HandleExternalError(lerr, "could not load proving set node")
|
|
}
|
|
|
|
faults, err := mas.FaultSet.All(2 * ss.Count)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("reading fault bit set: %w", err)
|
|
}
|
|
|
|
out := make([]abi.SectorNumber, len(faults))
|
|
for i, fault := range faults {
|
|
out[i] = abi.SectorNumber(fault)
|
|
}
|
|
|
|
return out, nil
|
|
}
|
|
|
|
func GetStorageDeal(ctx context.Context, sm *StateManager, dealId abi.DealID, ts *types.TipSet) (*api.MarketDeal, error) {
|
|
var state market.State
|
|
if _, err := sm.LoadActorState(ctx, actors.StorageMarketAddress, &state, ts); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
da, err := amt.LoadAMT(ctx, cbor.NewCborStore(sm.ChainStore().Blockstore()), state.Proposals)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var dp market.DealProposal
|
|
if err := da.Get(ctx, uint64(dealId), &dp); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
sa := market.AsDealStateArray(sm.ChainStore().Store(ctx), state.States)
|
|
st, err := sa.Get(dealId)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &api.MarketDeal{
|
|
Proposal: dp,
|
|
State: *st,
|
|
}, nil
|
|
}
|
|
|
|
func ListMinerActors(ctx context.Context, sm *StateManager, ts *types.TipSet) ([]address.Address, error) {
|
|
var state power.State
|
|
if _, err := sm.LoadActorState(ctx, actors.StoragePowerAddress, &state, ts); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var miners []address.Address
|
|
err := adt.AsMap(sm.cs.Store(ctx), state.Claims).ForEach(nil, func(k string) error {
|
|
a, err := address.NewFromBytes([]byte(k))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
miners = append(miners, a)
|
|
return nil
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return miners, nil
|
|
}
|
|
|
|
func LoadSectorsFromSet(ctx context.Context, bs blockstore.Blockstore, ssc cid.Cid) ([]*api.ChainSectorInfo, error) {
|
|
a, err := amt.LoadAMT(ctx, cbor.NewCborStore(bs), ssc)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var sset []*api.ChainSectorInfo
|
|
if err := a.ForEach(ctx, func(i uint64, v *cbg.Deferred) error {
|
|
var oci miner.SectorOnChainInfo
|
|
if err := cbor.DecodeInto(v.Raw, &oci); err != nil {
|
|
return err
|
|
}
|
|
sset = append(sset, &api.ChainSectorInfo{
|
|
Info: oci,
|
|
ID: abi.SectorNumber(i),
|
|
})
|
|
return nil
|
|
}); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return sset, nil
|
|
}
|
|
|
|
func ComputeState(ctx context.Context, sm *StateManager, height abi.ChainEpoch, msgs []*types.Message, ts *types.TipSet) (cid.Cid, error) {
|
|
if ts == nil {
|
|
ts = sm.cs.GetHeaviestTipSet()
|
|
}
|
|
|
|
base, _, err := sm.TipSetState(ctx, ts)
|
|
if err != nil {
|
|
return cid.Undef, err
|
|
}
|
|
|
|
fstate, err := sm.handleStateForks(ctx, base, height, ts.Height())
|
|
if err != nil {
|
|
return cid.Undef, err
|
|
}
|
|
|
|
r := store.NewChainRand(sm.cs, ts.Cids(), height)
|
|
vmi, err := vm.NewVM(fstate, height, r, actors.SystemAddress, sm.cs.Blockstore(), sm.cs.VMSys())
|
|
if err != nil {
|
|
return cid.Undef, err
|
|
}
|
|
|
|
for i, msg := range msgs {
|
|
ret, err := vmi.ApplyMessage(ctx, msg)
|
|
if err != nil {
|
|
return cid.Undef, xerrors.Errorf("applying message %s: %w", msg.Cid(), err)
|
|
}
|
|
if ret.ExitCode != 0 {
|
|
log.Infof("compute state apply message %d failed (exit: %d): %s", i, ret.ExitCode, ret.ActorErr)
|
|
}
|
|
}
|
|
|
|
return vmi.Flush(ctx)
|
|
}
|