lotus/chain/stmgr/utils.go

437 lines
13 KiB
Go
Raw Normal View History

package stmgr
import (
"context"
2020-04-09 17:13:09 +00:00
amt "github.com/filecoin-project/go-amt-ipld/v2"
2020-02-08 02:18:32 +00:00
"github.com/filecoin-project/specs-actors/actors/abi"
2020-02-11 02:33:27 +00:00
"github.com/filecoin-project/specs-actors/actors/abi/big"
2020-02-19 20:39:10 +00:00
"github.com/filecoin-project/specs-actors/actors/builtin"
2020-03-31 23:13:37 +00:00
init_ "github.com/filecoin-project/specs-actors/actors/builtin/init"
2020-02-08 02:18:32 +00:00
"github.com/filecoin-project/specs-actors/actors/builtin/market"
2020-02-11 02:33:27 +00:00
"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"
2020-02-08 02:18:32 +00:00
"github.com/filecoin-project/go-address"
2020-01-07 16:23:12 +00:00
"github.com/filecoin-project/lotus/api"
2020-03-31 23:13:37 +00:00
"github.com/filecoin-project/lotus/chain/actors/aerrors"
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm"
2020-03-31 23:13:37 +00:00
"github.com/filecoin-project/lotus/node/modules/dtypes"
2019-09-17 22:43:47 +00:00
cid "github.com/ipfs/go-cid"
2019-09-18 02:55:51 +00:00
blockstore "github.com/ipfs/go-ipfs-blockstore"
2019-09-17 22:43:47 +00:00
cbor "github.com/ipfs/go-ipld-cbor"
"github.com/libp2p/go-libp2p-core/peer"
cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors"
)
2020-03-31 23:13:37 +00:00
func GetNetworkName(ctx context.Context, sm *StateManager, st cid.Cid) (dtypes.NetworkName, error) {
var state init_.State
_, err := sm.LoadActorStateRaw(ctx, builtin.InitActorAddr, &state, st)
if err != nil {
return "", xerrors.Errorf("(get sset) failed to load miner actor state: %w", err)
}
return dtypes.NetworkName(state.NetworkName), nil
}
func GetMinerWorkerRaw(ctx context.Context, sm *StateManager, st cid.Cid, maddr address.Address) (address.Address, error) {
2020-02-11 02:33:27 +00:00
var mas miner.State
_, err := sm.LoadActorStateRaw(ctx, maddr, &mas, st)
if err != nil {
2020-02-11 02:33:27 +00:00
return address.Undef, xerrors.Errorf("(get sset) failed to load miner actor state: %w", err)
}
2020-02-21 16:57:40 +00:00
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) {
2020-02-11 02:33:27 +00:00
var mas miner.State
_, err := sm.LoadActorStateRaw(ctx, maddr, &mas, st)
if err != nil {
2020-02-11 02:33:27 +00:00
return address.Undef, xerrors.Errorf("(get sset) failed to load miner actor state: %w", err)
}
2020-02-21 16:57:40 +00:00
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)
}
2019-09-09 20:03:10 +00:00
func GetPower(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (types.BigInt, types.BigInt, error) {
2020-04-02 01:25:58 +00:00
return getPowerRaw(ctx, sm, ts.ParentState(), maddr)
}
func getPowerRaw(ctx context.Context, sm *StateManager, st cid.Cid, maddr address.Address) (types.BigInt, types.BigInt, error) {
2020-02-11 02:33:27 +00:00
var ps power.State
2020-04-02 01:25:58 +00:00
_, err := sm.LoadActorStateRaw(ctx, builtin.StoragePowerActorAddr, &ps, st)
2020-02-11 02:33:27 +00:00
if err != nil {
2020-02-19 20:39:10 +00:00
return big.Zero(), big.Zero(), xerrors.Errorf("(get sset) failed to load power actor state: %w", err)
2020-02-11 02:33:27 +00:00
}
2019-09-09 20:03:10 +00:00
2020-02-11 02:33:27 +00:00
var mpow big.Int
2019-09-09 20:03:10 +00:00
if maddr != address.Undef {
2020-04-13 21:05:34 +00:00
cm, err := adt.AsMap(sm.cs.Store(ctx), ps.Claims)
if err != nil {
return types.BigInt{}, types.BigInt{}, err
}
2020-02-11 02:33:27 +00:00
var claim power.Claim
2020-04-13 21:05:34 +00:00
if _, err := cm.Get(adt.AddrKey(maddr), &claim); err != nil {
2020-02-11 02:33:27 +00:00
return big.Zero(), big.Zero(), err
2019-09-09 20:03:10 +00:00
}
2020-04-10 12:19:06 +00:00
mpow = claim.QualityAdjPower // TODO: is quality adjusted power what we want here?
2019-09-09 20:03:10 +00:00
}
2020-04-10 12:19:06 +00:00
return mpow, ps.TotalQualityAdjPower, nil
2019-09-09 20:03:10 +00:00
}
2019-09-17 08:00:38 +00:00
func GetMinerPeerID(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (peer.ID, error) {
2020-02-11 02:33:27 +00:00
var mas miner.State
_, err := sm.LoadActorState(ctx, maddr, &mas, ts)
2019-09-17 08:00:38 +00:00
if err != nil {
2020-02-11 02:33:27 +00:00
return "", xerrors.Errorf("(get sset) failed to load miner actor state: %w", err)
2019-09-17 08:00:38 +00:00
}
2020-02-11 02:33:27 +00:00
return mas.Info.PeerId, nil
2019-09-17 08:00:38 +00:00
}
2019-09-17 22:43:47 +00:00
func GetMinerWorker(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (address.Address, error) {
2020-02-11 02:33:27 +00:00
return GetMinerWorkerRaw(ctx, sm, sm.parentState(ts), maddr)
}
2020-02-11 02:33:27 +00:00
func GetMinerPostState(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (*miner.PoStState, error) {
2020-02-25 20:35:15 +00:00
var mas miner.State
2019-09-17 22:43:47 +00:00
_, err := sm.LoadActorState(ctx, maddr, &mas, ts)
if err != nil {
2020-02-11 02:33:27 +00:00
return nil, xerrors.Errorf("(get eps) failed to load miner actor state: %w", err)
2019-09-17 22:43:47 +00:00
}
2020-02-11 02:33:27 +00:00
return &mas.PoStState, nil
2019-09-17 22:43:47 +00:00
}
2019-12-11 23:31:59 +00:00
func SectorSetSizes(ctx context.Context, sm *StateManager, maddr address.Address, ts *types.TipSet) (api.MinerSectors, error) {
2020-02-25 20:35:15 +00:00
var mas miner.State
2019-12-11 23:31:59 +00:00
_, 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)
2019-12-11 23:31:59 +00:00
if err != nil {
return api.MinerSectors{}, err
}
ps, err := amt.LoadAMT(ctx, blks, mas.ProvingSet)
2019-12-11 23:31:59 +00:00
if err != nil {
return api.MinerSectors{}, err
}
return api.MinerSectors{
Pset: ps.Count,
Sset: ss.Count,
}, nil
}
func PreCommitInfo(ctx context.Context, sm *StateManager, maddr address.Address, sid abi.SectorNumber, ts *types.TipSet) (miner.SectorPreCommitOnChainInfo, error) {
var mas miner.State
_, err := sm.LoadActorState(ctx, maddr, &mas, ts)
if err != nil {
return miner.SectorPreCommitOnChainInfo{}, xerrors.Errorf("(get sset) failed to load miner actor state: %w", err)
}
i, ok, err := mas.GetPrecommittedSector(sm.cs.Store(ctx), sid)
if err != nil {
return miner.SectorPreCommitOnChainInfo{}, err
}
if !ok {
return miner.SectorPreCommitOnChainInfo{}, xerrors.New("precommit not found")
}
return *i, nil
}
2019-11-08 18:15:13 +00:00
func GetMinerProvingSet(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) ([]*api.ChainSectorInfo, error) {
2020-04-02 01:25:58 +00:00
return getMinerProvingSetRaw(ctx, sm, ts.ParentState(), maddr)
}
func getMinerProvingSetRaw(ctx context.Context, sm *StateManager, st cid.Cid, maddr address.Address) ([]*api.ChainSectorInfo, error) {
2020-02-25 20:35:15 +00:00
var mas miner.State
2020-04-02 01:25:58 +00:00
_, err := sm.LoadActorStateRaw(ctx, maddr, &mas, st)
2019-09-17 22:43:47 +00:00
if err != nil {
return nil, xerrors.Errorf("(get pset) failed to load miner actor state: %w", err)
2019-09-17 22:43:47 +00:00
}
2019-09-18 02:55:51 +00:00
return LoadSectorsFromSet(ctx, sm.ChainStore().Blockstore(), mas.ProvingSet)
}
2019-11-08 18:15:13 +00:00
func GetMinerSectorSet(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) ([]*api.ChainSectorInfo, error) {
2020-02-25 20:35:15 +00:00
var mas miner.State
2019-09-18 02:55:51 +00:00
_, err := sm.LoadActorState(ctx, maddr, &mas, ts)
if err != nil {
return nil, xerrors.Errorf("(get sset) failed to load miner actor state: %w", err)
2019-09-18 02:55:51 +00:00
}
return LoadSectorsFromSet(ctx, sm.ChainStore().Blockstore(), mas.Sectors)
}
2020-02-08 02:18:32 +00:00
func GetMinerSectorSize(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (abi.SectorSize, error) {
2020-04-02 01:25:58 +00:00
return getMinerSectorSizeRaw(ctx, sm, ts.ParentState(), maddr)
}
func getMinerSectorSizeRaw(ctx context.Context, sm *StateManager, st cid.Cid, maddr address.Address) (abi.SectorSize, error) {
2020-02-25 20:35:15 +00:00
var mas miner.State
2020-04-02 01:25:58 +00:00
_, err := sm.LoadActorStateRaw(ctx, maddr, &mas, st)
if err != nil {
return 0, xerrors.Errorf("(get ssize) failed to load miner actor state: %w", err)
}
2020-02-11 02:33:27 +00:00
return mas.Info.SectorSize, nil
}
2020-03-02 01:09:38 +00:00
func GetMinerSlashed(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (bool, error) {
var mas miner.State
_, err := sm.LoadActorState(ctx, maddr, &mas, ts)
if err != nil {
return false, xerrors.Errorf("(get miner slashed) failed to load miner actor state")
}
if mas.PoStState.HasFailedPost() {
return true, nil
}
var spas power.State
_, err = sm.LoadActorState(ctx, builtin.StoragePowerActorAddr, &spas, ts)
if err != nil {
return false, xerrors.Errorf("(get miner slashed) failed to load power actor state")
}
store := sm.cs.Store(ctx)
2020-04-13 21:05:34 +00:00
claims, err := adt.AsMap(store, spas.Claims)
if err != nil {
return false, err
}
2020-03-02 01:09:38 +00:00
ok, err := claims.Get(power.AddrKey(maddr), nil)
if err != nil {
return false, err
}
if !ok {
return true, nil
}
return false, nil
}
func GetMinerFaults(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) ([]abi.SectorNumber, error) {
2020-02-25 20:35:15 +00:00
var mas miner.State
2020-01-30 00:50:58 +00:00
_, 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)
2020-01-30 00:50:58 +00:00
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
2020-01-30 00:50:58 +00:00
}
func GetStorageDeal(ctx context.Context, sm *StateManager, dealId abi.DealID, ts *types.TipSet) (*api.MarketDeal, error) {
2020-02-23 15:50:36 +00:00
var state market.State
2020-02-25 20:54:58 +00:00
if _, err := sm.LoadActorState(ctx, builtin.StorageMarketActorAddr, &state, ts); err != nil {
return nil, err
}
2020-02-08 02:18:32 +00:00
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
}
2020-04-13 21:05:34 +00:00
sa, err := market.AsDealStateArray(sm.ChainStore().Store(ctx), state.States)
if err != nil {
return nil, err
}
2020-02-23 15:50:36 +00:00
st, err := sa.Get(dealId)
if err != nil {
return nil, err
}
return &api.MarketDeal{
Proposal: dp,
2020-02-23 15:50:36 +00:00
State: *st,
}, nil
}
func ListMinerActors(ctx context.Context, sm *StateManager, ts *types.TipSet) ([]address.Address, error) {
2020-02-25 20:35:15 +00:00
var state power.State
2020-02-25 20:54:58 +00:00
if _, err := sm.LoadActorState(ctx, builtin.StoragePowerActorAddr, &state, ts); err != nil {
return nil, err
}
2020-04-13 21:05:34 +00:00
m, err := adt.AsMap(sm.cs.Store(ctx), state.Claims)
if err != nil {
return nil, err
}
2020-02-11 02:33:27 +00:00
var miners []address.Address
2020-04-13 21:05:34 +00:00
err = m.ForEach(nil, func(k string) error {
2020-02-11 02:33:27 +00:00
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
}
2019-11-08 18:15:13 +00:00
func LoadSectorsFromSet(ctx context.Context, bs blockstore.Blockstore, ssc cid.Cid) ([]*api.ChainSectorInfo, error) {
a, err := amt.LoadAMT(ctx, cbor.NewCborStore(bs), ssc)
2019-09-17 22:43:47 +00:00
if err != nil {
return nil, err
}
2019-11-08 18:15:13 +00:00
var sset []*api.ChainSectorInfo
if err := a.ForEach(ctx, func(i uint64, v *cbg.Deferred) error {
2020-02-19 19:26:11 +00:00
var oci miner.SectorOnChainInfo
if err := cbor.DecodeInto(v.Raw, &oci); err != nil {
2019-09-17 22:43:47 +00:00
return err
}
2019-11-08 18:15:13 +00:00
sset = append(sset, &api.ChainSectorInfo{
2020-02-19 20:34:21 +00:00
Info: oci,
2020-02-21 19:28:20 +00:00
ID: abi.SectorNumber(i),
2019-09-17 22:43:47 +00:00
})
return nil
}); err != nil {
return nil, err
}
return sset, nil
}
2020-03-08 02:31:36 +00:00
func ComputeState(ctx context.Context, sm *StateManager, height abi.ChainEpoch, msgs []*types.Message, ts *types.TipSet) (cid.Cid, []*api.InvocResult, error) {
if ts == nil {
ts = sm.cs.GetHeaviestTipSet()
}
2020-03-08 02:31:36 +00:00
base, trace, err := sm.ExecutionTrace(ctx, ts)
if err != nil {
2020-03-08 02:31:36 +00:00
return cid.Undef, nil, err
}
fstate, err := sm.handleStateForks(ctx, base, height, ts.Height())
if err != nil {
2020-03-08 02:31:36 +00:00
return cid.Undef, nil, err
}
r := store.NewChainRand(sm.cs, ts.Cids(), height)
2020-02-25 20:54:58 +00:00
vmi, err := vm.NewVM(fstate, height, r, builtin.SystemActorAddr, sm.cs.Blockstore(), sm.cs.VMSys())
if err != nil {
2020-03-08 02:31:36 +00:00
return cid.Undef, nil, err
}
for i, msg := range msgs {
2020-03-25 11:29:35 +00:00
// TODO: Use the signed message length for secp messages
2020-03-25 19:13:09 +00:00
ret, err := vmi.ApplyMessage(ctx, msg)
if err != nil {
2020-03-08 02:31:36 +00:00
return cid.Undef, nil, xerrors.Errorf("applying message %s: %w", msg.Cid(), err)
}
if ret.ExitCode != 0 {
2020-01-17 06:14:00 +00:00
log.Infof("compute state apply message %d failed (exit: %d): %s", i, ret.ExitCode, ret.ActorErr)
}
}
2020-03-08 02:31:36 +00:00
root, err := vmi.Flush(ctx)
if err != nil {
return cid.Undef, nil, err
}
return root, trace, nil
}
func MinerGetBaseInfo(ctx context.Context, sm *StateManager, tsk types.TipSetKey, maddr address.Address) (*api.MiningBaseInfo, error) {
ts, err := sm.ChainStore().LoadTipSet(tsk)
if err != nil {
return nil, xerrors.Errorf("failed to load tipset for mining base: %w", err)
}
2020-04-02 01:25:58 +00:00
st, _, err := sm.TipSetState(ctx, ts)
if err != nil {
return nil, err
}
2020-04-02 01:25:58 +00:00
provset, err := getMinerProvingSetRaw(ctx, sm, st, maddr)
if err != nil {
return nil, xerrors.Errorf("failed to get proving set: %w", err)
}
2020-04-02 01:25:58 +00:00
mpow, tpow, err := getPowerRaw(ctx, sm, st, maddr)
if err != nil {
return nil, xerrors.Errorf("failed to get power: %w", err)
}
2020-04-02 01:25:58 +00:00
worker, err := GetMinerWorkerRaw(ctx, sm, st, maddr)
if err != nil {
return nil, xerrors.Errorf("failed to get miner worker: %w", err)
}
2020-04-02 01:25:58 +00:00
ssize, err := getMinerSectorSizeRaw(ctx, sm, st, maddr)
if err != nil {
return nil, xerrors.Errorf("failed to get miner sector size: %w", err)
}
2020-04-09 17:13:09 +00:00
prev, err := sm.ChainStore().GetLatestBeaconEntry(ts)
if err != nil {
return nil, xerrors.Errorf("failed to get latest beacon entry: %w", err)
}
return &api.MiningBaseInfo{
2020-04-09 17:13:09 +00:00
MinerPower: mpow,
NetworkPower: tpow,
Sectors: provset,
Worker: worker,
SectorSize: ssize,
PrevBeaconEntry: *prev,
}, nil
}