2019-09-06 06:26:02 +00:00
|
|
|
package stmgr
|
|
|
|
|
|
|
|
import (
|
2020-04-30 22:11:14 +00:00
|
|
|
"bytes"
|
2019-09-06 06:26:02 +00:00
|
|
|
"context"
|
2020-09-04 03:28:42 +00:00
|
|
|
"fmt"
|
2020-04-20 17:43:02 +00:00
|
|
|
"os"
|
2020-07-03 16:57:58 +00:00
|
|
|
"reflect"
|
2020-09-04 03:28:42 +00:00
|
|
|
"runtime"
|
|
|
|
"strings"
|
2020-04-17 23:36:54 +00:00
|
|
|
|
2020-09-17 06:34:15 +00:00
|
|
|
v0miner "github.com/filecoin-project/specs-actors/actors/builtin/miner"
|
|
|
|
|
2020-09-07 06:08:53 +00:00
|
|
|
saruntime "github.com/filecoin-project/specs-actors/actors/runtime"
|
|
|
|
"github.com/filecoin-project/specs-actors/actors/runtime/proof"
|
|
|
|
|
2020-04-20 17:43:02 +00:00
|
|
|
cid "github.com/ipfs/go-cid"
|
|
|
|
cbg "github.com/whyrusleeping/cbor-gen"
|
|
|
|
"golang.org/x/xerrors"
|
|
|
|
|
|
|
|
"github.com/filecoin-project/go-address"
|
2020-07-01 04:57:49 +00:00
|
|
|
"github.com/filecoin-project/go-bitfield"
|
2020-09-07 03:49:10 +00:00
|
|
|
"github.com/filecoin-project/go-state-types/abi"
|
|
|
|
"github.com/filecoin-project/go-state-types/crypto"
|
2020-09-14 22:43:12 +00:00
|
|
|
"github.com/filecoin-project/lotus/chain/actors/builtin/power"
|
2020-08-17 13:26:18 +00:00
|
|
|
"github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper"
|
2020-02-19 20:39:10 +00:00
|
|
|
"github.com/filecoin-project/specs-actors/actors/builtin"
|
2020-07-03 16:57:58 +00:00
|
|
|
"github.com/filecoin-project/specs-actors/actors/builtin/account"
|
|
|
|
"github.com/filecoin-project/specs-actors/actors/builtin/cron"
|
2020-09-17 06:50:59 +00:00
|
|
|
v0msig "github.com/filecoin-project/specs-actors/actors/builtin/multisig"
|
2020-07-03 16:57:58 +00:00
|
|
|
"github.com/filecoin-project/specs-actors/actors/builtin/paych"
|
2020-09-17 06:42:39 +00:00
|
|
|
v0reward "github.com/filecoin-project/specs-actors/actors/builtin/reward"
|
2020-07-03 16:57:58 +00:00
|
|
|
"github.com/filecoin-project/specs-actors/actors/builtin/verifreg"
|
2020-02-08 02:18:32 +00:00
|
|
|
|
2019-10-18 04:47:41 +00:00
|
|
|
"github.com/filecoin-project/lotus/api"
|
2020-04-17 23:36:54 +00:00
|
|
|
"github.com/filecoin-project/lotus/build"
|
2020-09-14 22:43:12 +00:00
|
|
|
init_ "github.com/filecoin-project/lotus/chain/actors/builtin/init"
|
2020-09-15 13:29:25 +00:00
|
|
|
"github.com/filecoin-project/lotus/chain/actors/builtin/market"
|
2020-09-14 22:43:12 +00:00
|
|
|
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
|
2020-04-30 22:11:14 +00:00
|
|
|
"github.com/filecoin-project/lotus/chain/beacon"
|
2020-03-31 23:13:37 +00:00
|
|
|
"github.com/filecoin-project/lotus/chain/state"
|
2020-01-17 02:33:43 +00:00
|
|
|
"github.com/filecoin-project/lotus/chain/store"
|
2019-10-18 04:47:41 +00:00
|
|
|
"github.com/filecoin-project/lotus/chain/types"
|
2020-01-17 02:33:43 +00:00
|
|
|
"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-06 06:26:02 +00:00
|
|
|
)
|
|
|
|
|
2020-03-31 23:13:37 +00:00
|
|
|
func GetNetworkName(ctx context.Context, sm *StateManager, st cid.Cid) (dtypes.NetworkName, error) {
|
2020-09-14 22:43:12 +00:00
|
|
|
act, err := sm.LoadActorRaw(ctx, init_.Address, st)
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
ias, err := init_.Load(sm.cs.Store(ctx), act)
|
2020-03-31 23:13:37 +00:00
|
|
|
if err != nil {
|
2020-07-14 11:45:45 +00:00
|
|
|
return "", err
|
2020-03-31 23:13:37 +00:00
|
|
|
}
|
|
|
|
|
2020-09-15 04:55:49 +00:00
|
|
|
return ias.NetworkName()
|
2020-03-31 23:13:37 +00:00
|
|
|
}
|
|
|
|
|
2019-10-23 17:39:14 +00:00
|
|
|
func GetMinerWorkerRaw(ctx context.Context, sm *StateManager, st cid.Cid, maddr address.Address) (address.Address, error) {
|
2020-09-15 04:55:49 +00:00
|
|
|
state, err := sm.StateTree(st)
|
2019-09-06 06:26:02 +00:00
|
|
|
if err != nil {
|
2020-09-15 04:55:49 +00:00
|
|
|
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)
|
2019-09-06 06:26:02 +00:00
|
|
|
}
|
2020-09-14 22:43:12 +00:00
|
|
|
mas, err := miner.Load(sm.cs.Store(ctx), act)
|
2020-02-21 16:57:40 +00:00
|
|
|
if err != nil {
|
2020-09-15 04:55:49 +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
|
|
|
}
|
|
|
|
|
2020-09-14 22:43:12 +00:00
|
|
|
info, err := mas.Info()
|
2020-07-01 11:47:40 +00:00
|
|
|
if err != nil {
|
2020-09-14 22:43:12 +00:00
|
|
|
return address.Undef, xerrors.Errorf("failed to load actor info: %w", err)
|
2020-07-01 11:47:40 +00:00
|
|
|
}
|
|
|
|
|
2020-09-15 04:55:49 +00:00
|
|
|
return vm.ResolveToKeyAddr(state, sm.cs.Store(ctx), info.Worker)
|
2019-09-06 06:26:02 +00:00
|
|
|
}
|
|
|
|
|
2020-09-16 05:47:24 +00:00
|
|
|
func GetPower(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (power.Claim, power.Claim, bool, error) {
|
2020-04-17 23:36:54 +00:00
|
|
|
return GetPowerRaw(ctx, sm, ts.ParentState(), maddr)
|
2020-04-02 01:25:58 +00:00
|
|
|
}
|
|
|
|
|
2020-09-16 05:47:24 +00:00
|
|
|
func GetPowerRaw(ctx context.Context, sm *StateManager, st cid.Cid, maddr address.Address) (power.Claim, power.Claim, bool, error) {
|
2020-09-14 22:43:12 +00:00
|
|
|
act, err := sm.LoadActorRaw(ctx, builtin.StoragePowerActorAddr, st)
|
2020-02-11 02:33:27 +00:00
|
|
|
if err != nil {
|
2020-09-16 05:47:24 +00:00
|
|
|
return power.Claim{}, power.Claim{}, false, 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-09-16 05:47:24 +00:00
|
|
|
pas, err := power.Load(sm.cs.Store(ctx), act)
|
2020-09-14 22:43:12 +00:00
|
|
|
if err != nil {
|
2020-09-16 05:47:24 +00:00
|
|
|
return power.Claim{}, power.Claim{}, false, err
|
2020-09-14 22:43:12 +00:00
|
|
|
}
|
|
|
|
|
2020-09-16 05:47:24 +00:00
|
|
|
tpow, err := pas.TotalPower()
|
2020-09-14 22:43:12 +00:00
|
|
|
if err != nil {
|
2020-09-16 05:47:24 +00:00
|
|
|
return power.Claim{}, power.Claim{}, false, err
|
2020-09-14 22:43:12 +00:00
|
|
|
}
|
|
|
|
|
2020-04-17 22:02:04 +00:00
|
|
|
var mpow power.Claim
|
2019-09-09 20:03:10 +00:00
|
|
|
if maddr != address.Undef {
|
2020-09-15 19:13:13 +00:00
|
|
|
var found bool
|
2020-09-16 05:47:24 +00:00
|
|
|
mpow, found, err = pas.MinerPower(maddr)
|
2020-09-15 19:13:13 +00:00
|
|
|
if err != nil || !found {
|
|
|
|
// TODO: return an error when not found?
|
2020-09-16 05:47:24 +00:00
|
|
|
return power.Claim{}, power.Claim{}, false, err
|
2020-04-13 21:05:34 +00:00
|
|
|
}
|
2019-09-09 20:03:10 +00:00
|
|
|
}
|
|
|
|
|
2020-09-16 05:47:24 +00:00
|
|
|
minpow, err := pas.MinerNominalPowerMeetsConsensusMinimum(maddr)
|
|
|
|
if err != nil {
|
|
|
|
return power.Claim{}, power.Claim{}, false, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return mpow, tpow, minpow, nil
|
2019-09-09 20:03:10 +00:00
|
|
|
}
|
2019-09-17 08:00:38 +00:00
|
|
|
|
2020-09-15 04:55:49 +00:00
|
|
|
func PreCommitInfo(ctx context.Context, sm *StateManager, maddr address.Address, sid abi.SectorNumber, ts *types.TipSet) (*miner.SectorPreCommitOnChainInfo, error) {
|
2020-09-14 22:43:12 +00:00
|
|
|
act, err := sm.LoadActor(ctx, maddr, ts)
|
2020-04-04 02:55:19 +00:00
|
|
|
if err != nil {
|
2020-09-15 04:55:49 +00:00
|
|
|
return nil, xerrors.Errorf("(get sset) failed to load miner actor: %w", err)
|
2020-04-04 02:55:19 +00:00
|
|
|
}
|
|
|
|
|
2020-09-15 04:55:49 +00:00
|
|
|
mas, err := miner.Load(sm.cs.Store(ctx), act)
|
2020-04-04 02:55:19 +00:00
|
|
|
if err != nil {
|
2020-09-15 04:55:49 +00:00
|
|
|
return nil, xerrors.Errorf("(get sset) failed to load miner actor state: %w", err)
|
2020-04-04 02:55:19 +00:00
|
|
|
}
|
|
|
|
|
2020-09-15 04:55:49 +00:00
|
|
|
return mas.GetPrecommittedSector(sid)
|
2020-04-04 02:55:19 +00:00
|
|
|
}
|
|
|
|
|
2020-05-28 00:06:29 +00:00
|
|
|
func MinerSectorInfo(ctx context.Context, sm *StateManager, maddr address.Address, sid abi.SectorNumber, ts *types.TipSet) (*miner.SectorOnChainInfo, error) {
|
2020-09-15 04:55:49 +00:00
|
|
|
act, err := sm.LoadActor(ctx, maddr, ts)
|
2020-05-28 00:06:29 +00:00
|
|
|
if err != nil {
|
2020-09-15 04:55:49 +00:00
|
|
|
return nil, xerrors.Errorf("(get sset) failed to load miner actor: %w", err)
|
2020-05-28 00:06:29 +00:00
|
|
|
}
|
|
|
|
|
2020-09-15 04:55:49 +00:00
|
|
|
mas, err := miner.Load(sm.cs.Store(ctx), act)
|
2020-05-28 00:06:29 +00:00
|
|
|
if err != nil {
|
2020-09-15 04:55:49 +00:00
|
|
|
return nil, xerrors.Errorf("(get sset) failed to load miner actor state: %w", err)
|
2020-05-28 00:06:29 +00:00
|
|
|
}
|
|
|
|
|
2020-09-15 04:55:49 +00:00
|
|
|
return mas.GetSector(sid)
|
2020-05-28 00:06:29 +00:00
|
|
|
}
|
|
|
|
|
2020-09-15 11:04:45 +00:00
|
|
|
func GetMinerSectorSet(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address, filter *bitfield.BitField, filterOut bool) ([]*miner.ChainSectorInfo, 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)
|
2019-09-18 02:55:51 +00:00
|
|
|
if err != nil {
|
2019-11-30 04:31:16 +00:00
|
|
|
return nil, xerrors.Errorf("(get sset) failed to load miner actor state: %w", err)
|
2019-09-18 02:55:51 +00:00
|
|
|
}
|
|
|
|
|
2020-09-17 06:34:15 +00:00
|
|
|
sectors, err := mas.LoadSectorsFromSet(filter, filterOut)
|
|
|
|
if err != nil {
|
|
|
|
return nil, xerrors.Errorf("(get sset) failed to load sectors: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
var sset []*miner.ChainSectorInfo
|
|
|
|
var v cbg.Deferred
|
|
|
|
if err := sectors.ForEach(&v, func(i int64) error {
|
|
|
|
var oci v0miner.SectorOnChainInfo
|
|
|
|
if err := oci.UnmarshalCBOR(bytes.NewReader(v.Raw)); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
sset = append(sset, &miner.ChainSectorInfo{
|
|
|
|
Info: oci,
|
|
|
|
ID: abi.SectorNumber(i),
|
|
|
|
})
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return sset, nil
|
2019-09-18 02:55:51 +00:00
|
|
|
}
|
|
|
|
|
2020-09-07 03:49:10 +00:00
|
|
|
func GetSectorsForWinningPoSt(ctx context.Context, pv ffiwrapper.Verifier, sm *StateManager, st cid.Cid, maddr address.Address, rand abi.PoStRandomness) ([]proof.SectorInfo, error) {
|
2020-09-15 11:04:45 +00:00
|
|
|
act, err := sm.LoadActorRaw(ctx, maddr, st)
|
|
|
|
if err != nil {
|
|
|
|
return nil, xerrors.Errorf("failed to load miner actor: %w", err)
|
|
|
|
}
|
2020-07-14 11:45:45 +00:00
|
|
|
|
2020-09-15 11:04:45 +00:00
|
|
|
mas, err := miner.Load(sm.cs.Store(ctx), act)
|
2020-07-01 04:57:49 +00:00
|
|
|
if err != nil {
|
2020-09-15 11:04:45 +00:00
|
|
|
return nil, xerrors.Errorf("failed to load miner actor state: %w", err)
|
2020-07-01 04:57:49 +00:00
|
|
|
}
|
|
|
|
|
2020-09-15 11:04:45 +00:00
|
|
|
// TODO (!!): This was partition.Sectors-partition.Faults originally, which was likely very wrong, and will need to be an upgrade
|
|
|
|
// ^ THE CURRENT THING HERE WON'T SYNC v
|
|
|
|
|
|
|
|
provingSectors, err := miner.AllPartSectors(mas, miner.Partition.ActiveSectors)
|
2020-07-01 04:57:49 +00:00
|
|
|
if err != nil {
|
2020-07-14 11:45:45 +00:00
|
|
|
return nil, xerrors.Errorf("merge partition proving sets: %w", err)
|
2020-07-01 04:57:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
numProvSect, err := provingSectors.Count()
|
2020-04-17 14:47:19 +00:00
|
|
|
if err != nil {
|
2020-07-01 04:57:49 +00:00
|
|
|
return nil, xerrors.Errorf("failed to count bits: %w", err)
|
2020-04-17 14:47:19 +00:00
|
|
|
}
|
|
|
|
|
2020-07-01 04:57:49 +00:00
|
|
|
// TODO(review): is this right? feels fishy to me
|
|
|
|
if numProvSect == 0 {
|
2020-04-23 21:12:42 +00:00
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
2020-09-15 11:04:45 +00:00
|
|
|
info, err := mas.Info()
|
|
|
|
if err != nil {
|
|
|
|
return nil, xerrors.Errorf("getting miner info: %w", err)
|
|
|
|
}
|
|
|
|
|
2020-07-01 11:47:40 +00:00
|
|
|
spt, err := ffiwrapper.SealProofTypeFromSectorSize(info.SectorSize)
|
2020-04-17 14:47:19 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, xerrors.Errorf("getting seal proof type: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
wpt, err := spt.RegisteredWinningPoStProof()
|
|
|
|
if err != nil {
|
|
|
|
return nil, xerrors.Errorf("getting window proof type: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
mid, err := address.IDFromAddress(maddr)
|
|
|
|
if err != nil {
|
|
|
|
return nil, xerrors.Errorf("getting miner ID: %w", err)
|
|
|
|
}
|
|
|
|
|
2020-07-01 04:57:49 +00:00
|
|
|
ids, err := pv.GenerateWinningPoStSectorChallenge(ctx, wpt, abi.ActorID(mid), rand, numProvSect)
|
2020-04-17 14:47:19 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, xerrors.Errorf("generating winning post challenges: %w", err)
|
|
|
|
}
|
|
|
|
|
2020-09-15 11:04:45 +00:00
|
|
|
sectors, err := mas.LoadSectorsFromSet(&provingSectors, false)
|
2020-07-01 04:57:49 +00:00
|
|
|
if err != nil {
|
2020-09-15 11:04:45 +00:00
|
|
|
return nil, xerrors.Errorf("loading proving sectors: %w", err)
|
2020-07-01 04:57:49 +00:00
|
|
|
}
|
|
|
|
|
2020-09-07 03:49:10 +00:00
|
|
|
out := make([]proof.SectorInfo, len(ids))
|
2020-04-17 14:47:19 +00:00
|
|
|
for i, n := range ids {
|
2020-09-17 06:34:15 +00:00
|
|
|
var sinfo miner.SectorOnChainInfo
|
|
|
|
found, err := sectors.Get(n, &sinfo)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return nil, xerrors.Errorf("loading sector info: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if !found {
|
|
|
|
return nil, xerrors.Errorf("didn't find sector info for sector %d", n)
|
|
|
|
}
|
2020-07-01 04:57:49 +00:00
|
|
|
|
2020-09-07 03:49:10 +00:00
|
|
|
out[i] = proof.SectorInfo{
|
2020-06-15 16:30:49 +00:00
|
|
|
SealProof: spt,
|
2020-09-17 06:34:15 +00:00
|
|
|
SectorNumber: sinfo.SectorNumber,
|
|
|
|
SealedCID: sinfo.SealedCID,
|
2020-04-17 14:47:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return out, nil
|
2020-04-17 05:39:55 +00:00
|
|
|
}
|
|
|
|
|
2020-07-01 11:47:40 +00:00
|
|
|
func StateMinerInfo(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (*miner.MinerInfo, error) {
|
2020-09-15 11:04:45 +00:00
|
|
|
act, err := sm.LoadActor(ctx, maddr, ts)
|
2020-04-16 17:36:36 +00:00
|
|
|
if err != nil {
|
2020-09-15 11:04:45 +00:00
|
|
|
return nil, xerrors.Errorf("failed to load miner actor: %w", err)
|
2020-04-16 17:36:36 +00:00
|
|
|
}
|
|
|
|
|
2020-09-15 11:04:45 +00:00
|
|
|
mas, err := miner.Load(sm.cs.Store(ctx), act)
|
|
|
|
if err != nil {
|
|
|
|
return nil, xerrors.Errorf("failed to load miner actor state: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
mi, err := mas.Info()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return &mi, err
|
2020-04-02 01:25:58 +00:00
|
|
|
}
|
|
|
|
|
2020-03-02 01:09:38 +00:00
|
|
|
func GetMinerSlashed(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (bool, error) {
|
2020-09-15 11:04:45 +00:00
|
|
|
act, err := sm.LoadActor(ctx, builtin.StoragePowerActorAddr, ts)
|
|
|
|
if err != nil {
|
|
|
|
return false, xerrors.Errorf("failed to load power actor: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
spas, err := power.Load(sm.cs.Store(ctx), act)
|
2020-03-02 01:09:38 +00:00
|
|
|
if err != nil {
|
2020-09-15 11:04:45 +00:00
|
|
|
return false, xerrors.Errorf("failed to load power actor state: %w", err)
|
2020-03-02 01:09:38 +00:00
|
|
|
}
|
|
|
|
|
2020-09-15 13:29:25 +00:00
|
|
|
_, ok, err := spas.MinerPower(maddr)
|
2020-04-21 14:32:17 +00:00
|
|
|
if err != nil {
|
2020-09-15 13:29:25 +00:00
|
|
|
return false, xerrors.Errorf("getting miner power: %w", err)
|
2020-03-02 01:09:38 +00:00
|
|
|
}
|
2020-04-16 20:52:40 +00:00
|
|
|
|
2020-04-21 14:32:17 +00:00
|
|
|
if !ok {
|
|
|
|
return true, nil
|
2020-03-02 01:09:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return false, nil
|
2019-11-15 01:01:53 +00:00
|
|
|
}
|
|
|
|
|
2020-06-02 14:29:39 +00:00
|
|
|
func GetStorageDeal(ctx context.Context, sm *StateManager, dealID abi.DealID, ts *types.TipSet) (*api.MarketDeal, error) {
|
2020-09-15 11:04:45 +00:00
|
|
|
act, err := sm.LoadActor(ctx, builtin.StorageMarketActorAddr, ts)
|
|
|
|
if err != nil {
|
|
|
|
return nil, xerrors.Errorf("failed to load market actor: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
state, err := market.Load(sm.cs.Store(ctx), act)
|
|
|
|
if err != nil {
|
|
|
|
return nil, xerrors.Errorf("failed to load market actor state: %w", err)
|
2019-11-07 07:57:10 +00:00
|
|
|
}
|
2020-09-15 11:04:45 +00:00
|
|
|
|
2020-09-17 07:32:10 +00:00
|
|
|
proposals, err := state.Proposals()
|
2019-11-07 07:57:10 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2020-09-17 07:32:10 +00:00
|
|
|
proposal, found, err := proposals.Get(dealID)
|
|
|
|
|
|
|
|
if err != nil {
|
2019-11-07 07:57:10 +00:00
|
|
|
return nil, err
|
2020-07-23 00:14:54 +00:00
|
|
|
} else if !found {
|
|
|
|
return nil, xerrors.Errorf("deal %d not found", dealID)
|
2019-11-07 07:57:10 +00:00
|
|
|
}
|
|
|
|
|
2020-09-17 07:32:10 +00:00
|
|
|
states, err := state.States()
|
2020-04-13 21:05:34 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2020-09-17 07:32:10 +00:00
|
|
|
st, found, err := states.Get(dealID)
|
2020-02-09 06:06:32 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2020-05-06 00:04:25 +00:00
|
|
|
if !found {
|
2020-09-17 07:32:10 +00:00
|
|
|
st = market.EmptyDealState()
|
2020-05-06 00:04:25 +00:00
|
|
|
}
|
|
|
|
|
2020-02-09 06:06:32 +00:00
|
|
|
return &api.MarketDeal{
|
2020-09-17 07:32:10 +00:00
|
|
|
Proposal: *proposal,
|
2020-02-23 15:50:36 +00:00
|
|
|
State: *st,
|
2020-02-09 06:06:32 +00:00
|
|
|
}, nil
|
2019-11-07 07:57:10 +00:00
|
|
|
}
|
|
|
|
|
2019-12-17 06:51:41 +00:00
|
|
|
func ListMinerActors(ctx context.Context, sm *StateManager, ts *types.TipSet) ([]address.Address, error) {
|
2020-09-15 11:04:45 +00:00
|
|
|
act, err := sm.LoadActor(ctx, builtin.StoragePowerActorAddr, ts)
|
|
|
|
if err != nil {
|
|
|
|
return nil, xerrors.Errorf("failed to load power actor: %w", err)
|
|
|
|
}
|
|
|
|
|
2020-09-16 05:00:00 +00:00
|
|
|
powState, err := power.Load(sm.cs.Store(ctx), act)
|
2020-09-15 11:04:45 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, xerrors.Errorf("failed to load power actor state: %w", err)
|
2019-12-17 06:51:41 +00:00
|
|
|
}
|
|
|
|
|
2020-09-16 05:00:00 +00:00
|
|
|
return powState.ListAllMiners()
|
2019-09-17 22:43:47 +00:00
|
|
|
}
|
2020-01-17 02:33:43 +00:00
|
|
|
|
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) {
|
2020-01-17 02:33:43 +00:00
|
|
|
if ts == nil {
|
|
|
|
ts = sm.cs.GetHeaviestTipSet()
|
|
|
|
}
|
|
|
|
|
2020-03-08 02:31:36 +00:00
|
|
|
base, trace, err := sm.ExecutionTrace(ctx, ts)
|
2020-01-17 02:33:43 +00:00
|
|
|
if err != nil {
|
2020-03-08 02:31:36 +00:00
|
|
|
return cid.Undef, nil, err
|
2020-01-17 02:33:43 +00:00
|
|
|
}
|
|
|
|
|
2020-09-01 19:48:16 +00:00
|
|
|
r := store.NewChainRand(sm.cs, ts.Cids())
|
2020-08-06 17:09:03 +00:00
|
|
|
vmopt := &vm.VMOpts{
|
2020-08-09 22:49:38 +00:00
|
|
|
StateBase: base,
|
|
|
|
Epoch: height,
|
|
|
|
Rand: r,
|
|
|
|
Bstore: sm.cs.Blockstore(),
|
|
|
|
Syscalls: sm.cs.VMSys(),
|
|
|
|
CircSupplyCalc: sm.GetCirculatingSupply,
|
2020-09-07 20:01:09 +00:00
|
|
|
NtwkVersion: sm.GetNtwkVersion,
|
2020-08-09 22:49:38 +00:00
|
|
|
BaseFee: ts.Blocks()[0].ParentBaseFee,
|
2020-08-06 17:09:03 +00:00
|
|
|
}
|
2020-09-15 11:04:45 +00:00
|
|
|
vmi, err := vm.NewVM(ctx, vmopt)
|
2020-01-17 02:33:43 +00:00
|
|
|
if err != nil {
|
2020-03-08 02:31:36 +00:00
|
|
|
return cid.Undef, nil, err
|
2020-01-17 02:33:43 +00:00
|
|
|
}
|
|
|
|
|
2020-07-28 12:31:13 +00:00
|
|
|
for i := ts.Height(); i < height; i++ {
|
|
|
|
// handle state forks
|
2020-09-08 20:45:44 +00:00
|
|
|
err = sm.handleStateForks(ctx, vmi.StateTree(), i, ts)
|
2020-07-28 12:31:13 +00:00
|
|
|
if err != nil {
|
|
|
|
return cid.Undef, nil, xerrors.Errorf("error handling state forks: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: should we also run cron here?
|
2020-01-17 02:33:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
2020-01-17 02:33:43 +00:00
|
|
|
if err != nil {
|
2020-03-08 02:31:36 +00:00
|
|
|
return cid.Undef, nil, xerrors.Errorf("applying message %s: %w", msg.Cid(), err)
|
2020-01-17 02:33:43 +00:00
|
|
|
}
|
|
|
|
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-01-17 02:33:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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
|
2020-01-17 02:33:43 +00:00
|
|
|
}
|
2020-04-02 01:10:28 +00:00
|
|
|
|
2020-04-17 23:36:54 +00:00
|
|
|
func GetLookbackTipSetForRound(ctx context.Context, sm *StateManager, ts *types.TipSet, round abi.ChainEpoch) (*types.TipSet, error) {
|
|
|
|
var lbr abi.ChainEpoch
|
|
|
|
if round > build.WinningPoStSectorSetLookback {
|
|
|
|
lbr = round - build.WinningPoStSectorSetLookback
|
|
|
|
}
|
|
|
|
|
|
|
|
// more null blocks than our lookback
|
|
|
|
if lbr > ts.Height() {
|
|
|
|
return ts, nil
|
|
|
|
}
|
|
|
|
|
2020-05-05 17:06:05 +00:00
|
|
|
lbts, err := sm.ChainStore().GetTipsetByHeight(ctx, lbr, ts, true)
|
2020-04-17 23:36:54 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, xerrors.Errorf("failed to get lookback tipset: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return lbts, nil
|
|
|
|
}
|
|
|
|
|
2020-09-08 20:28:06 +00:00
|
|
|
func MinerGetBaseInfo(ctx context.Context, sm *StateManager, bcs beacon.Schedule, tsk types.TipSetKey, round abi.ChainEpoch, maddr address.Address, pv ffiwrapper.Verifier) (*api.MiningBaseInfo, error) {
|
2020-04-02 01:10:28 +00:00
|
|
|
ts, err := sm.ChainStore().LoadTipSet(tsk)
|
|
|
|
if err != nil {
|
|
|
|
return nil, xerrors.Errorf("failed to load tipset for mining base: %w", err)
|
|
|
|
}
|
|
|
|
|
2020-04-30 22:11:14 +00:00
|
|
|
prev, err := sm.ChainStore().GetLatestBeaconEntry(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{}
|
|
|
|
}
|
|
|
|
|
2020-09-08 20:28:06 +00:00
|
|
|
entries, err := beacon.BeaconEntriesForBlock(ctx, bcs, round, ts.Height(), *prev)
|
2020-04-30 22:11:14 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
rbase := *prev
|
|
|
|
if len(entries) > 0 {
|
|
|
|
rbase = entries[len(entries)-1]
|
|
|
|
}
|
|
|
|
|
2020-04-17 23:36:54 +00:00
|
|
|
lbts, err := GetLookbackTipSetForRound(ctx, sm, ts, round)
|
|
|
|
if err != nil {
|
|
|
|
return nil, xerrors.Errorf("getting lookback miner actor state: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
lbst, _, err := sm.TipSetState(ctx, lbts)
|
2020-04-02 01:10:28 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2020-09-15 11:04:45 +00:00
|
|
|
act, err := sm.LoadActorRaw(ctx, maddr, lbst)
|
|
|
|
if err != nil {
|
|
|
|
return nil, xerrors.Errorf("failed to load miner actor: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
mas, err := miner.Load(sm.cs.Store(ctx), act)
|
|
|
|
if err != nil {
|
|
|
|
return nil, xerrors.Errorf("failed to load miner actor state: %w", err)
|
2020-04-17 23:36:54 +00:00
|
|
|
}
|
|
|
|
|
2020-04-30 22:11:14 +00:00
|
|
|
buf := new(bytes.Buffer)
|
|
|
|
if err := maddr.MarshalCBOR(buf); err != nil {
|
|
|
|
return nil, xerrors.Errorf("failed to marshal miner address: %w", err)
|
|
|
|
}
|
|
|
|
|
2020-05-01 19:42:59 +00:00
|
|
|
prand, err := store.DrawRandomness(rbase.Data, crypto.DomainSeparationTag_WinningPoStChallengeSeed, round, buf.Bytes())
|
2020-04-02 01:10:28 +00:00
|
|
|
if err != nil {
|
2020-04-17 23:36:54 +00:00
|
|
|
return nil, xerrors.Errorf("failed to get randomness for winning post: %w", err)
|
2020-04-02 01:10:28 +00:00
|
|
|
}
|
|
|
|
|
2020-04-17 23:36:54 +00:00
|
|
|
sectors, err := GetSectorsForWinningPoSt(ctx, pv, sm, lbst, maddr, prand)
|
2020-04-02 01:10:28 +00:00
|
|
|
if err != nil {
|
2020-04-17 23:36:54 +00:00
|
|
|
return nil, xerrors.Errorf("getting wpost proving set: %w", err)
|
2020-04-02 01:10:28 +00:00
|
|
|
}
|
|
|
|
|
2020-04-23 21:12:42 +00:00
|
|
|
if len(sectors) == 0 {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
2020-09-16 05:47:24 +00:00
|
|
|
mpow, tpow, hmp, err := GetPowerRaw(ctx, sm, lbst, maddr)
|
2020-04-02 01:10:28 +00:00
|
|
|
if err != nil {
|
2020-04-15 19:59:11 +00:00
|
|
|
return nil, xerrors.Errorf("failed to get power: %w", err)
|
2020-04-02 01:10:28 +00:00
|
|
|
}
|
|
|
|
|
2020-09-15 11:04:45 +00:00
|
|
|
info, err := mas.Info()
|
2020-07-01 11:47:40 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
worker, err := sm.ResolveToKeyAddress(ctx, info.Worker, ts)
|
2020-04-16 17:17:56 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, xerrors.Errorf("resolving worker address: %w", err)
|
|
|
|
}
|
|
|
|
|
2020-04-02 01:10:28 +00:00
|
|
|
return &api.MiningBaseInfo{
|
2020-04-17 22:02:04 +00:00
|
|
|
MinerPower: mpow.QualityAdjPower,
|
|
|
|
NetworkPower: tpow.QualityAdjPower,
|
2020-04-17 23:36:54 +00:00
|
|
|
Sectors: sectors,
|
2020-04-16 17:17:56 +00:00
|
|
|
WorkerKey: worker,
|
2020-07-01 11:47:40 +00:00
|
|
|
SectorSize: info.SectorSize,
|
2020-04-09 17:13:09 +00:00
|
|
|
PrevBeaconEntry: *prev,
|
2020-04-30 22:11:14 +00:00
|
|
|
BeaconEntries: entries,
|
2020-07-27 23:51:30 +00:00
|
|
|
HasMinPower: hmp,
|
2020-04-02 01:10:28 +00:00
|
|
|
}, nil
|
|
|
|
}
|
2020-06-26 13:49:39 +00:00
|
|
|
|
2020-09-04 03:28:42 +00:00
|
|
|
type MethodMeta struct {
|
2020-07-03 16:57:58 +00:00
|
|
|
Name string
|
|
|
|
|
|
|
|
Params reflect.Type
|
|
|
|
Ret reflect.Type
|
|
|
|
}
|
|
|
|
|
2020-09-04 03:28:42 +00:00
|
|
|
var MethodsMap = map[cid.Cid]map[abi.MethodNum]MethodMeta{}
|
2020-07-03 16:57:58 +00:00
|
|
|
|
|
|
|
func init() {
|
|
|
|
cidToMethods := map[cid.Cid][2]interface{}{
|
|
|
|
// builtin.SystemActorCodeID: {builtin.MethodsSystem, system.Actor{} }- apparently it doesn't have methods
|
|
|
|
builtin.InitActorCodeID: {builtin.MethodsInit, init_.Actor{}},
|
|
|
|
builtin.CronActorCodeID: {builtin.MethodsCron, cron.Actor{}},
|
|
|
|
builtin.AccountActorCodeID: {builtin.MethodsAccount, account.Actor{}},
|
|
|
|
builtin.StoragePowerActorCodeID: {builtin.MethodsPower, power.Actor{}},
|
|
|
|
builtin.StorageMinerActorCodeID: {builtin.MethodsMiner, miner.Actor{}},
|
|
|
|
builtin.StorageMarketActorCodeID: {builtin.MethodsMarket, market.Actor{}},
|
|
|
|
builtin.PaymentChannelActorCodeID: {builtin.MethodsPaych, paych.Actor{}},
|
2020-09-17 06:50:59 +00:00
|
|
|
builtin.MultisigActorCodeID: {builtin.MethodsMultisig, v0msig.Actor{}},
|
2020-09-17 06:42:39 +00:00
|
|
|
builtin.RewardActorCodeID: {builtin.MethodsReward, v0reward.Actor{}},
|
2020-07-03 16:57:58 +00:00
|
|
|
builtin.VerifiedRegistryActorCodeID: {builtin.MethodsVerifiedRegistry, verifreg.Actor{}},
|
|
|
|
}
|
|
|
|
|
|
|
|
for c, m := range cidToMethods {
|
2020-09-07 03:49:10 +00:00
|
|
|
exports := m[1].(saruntime.Invokee).Exports()
|
2020-09-04 03:28:42 +00:00
|
|
|
methods := make(map[abi.MethodNum]MethodMeta, len(exports))
|
2020-07-03 16:57:58 +00:00
|
|
|
|
2020-09-04 03:28:42 +00:00
|
|
|
// Explicitly add send, it's special.
|
|
|
|
methods[builtin.MethodSend] = MethodMeta{
|
2020-07-03 16:57:58 +00:00
|
|
|
Name: "Send",
|
2020-09-10 06:21:38 +00:00
|
|
|
Params: reflect.TypeOf(new(abi.EmptyValue)),
|
|
|
|
Ret: reflect.TypeOf(new(abi.EmptyValue)),
|
2020-09-04 03:28:42 +00:00
|
|
|
}
|
2020-07-03 16:57:58 +00:00
|
|
|
|
2020-09-04 03:28:42 +00:00
|
|
|
// Learn method names from the builtin.Methods* structs.
|
|
|
|
rv := reflect.ValueOf(m[0])
|
|
|
|
rt := rv.Type()
|
|
|
|
nf := rt.NumField()
|
|
|
|
methodToName := make([]string, len(exports))
|
2020-07-03 16:57:58 +00:00
|
|
|
for i := 0; i < nf; i++ {
|
2020-09-04 03:28:42 +00:00
|
|
|
name := rt.Field(i).Name
|
|
|
|
number := rv.Field(i).Interface().(abi.MethodNum)
|
|
|
|
methodToName[number] = name
|
|
|
|
}
|
2020-07-03 16:57:58 +00:00
|
|
|
|
2020-09-04 03:28:42 +00:00
|
|
|
// Iterate over exported methods. Some of these _may_ be nil and
|
|
|
|
// must be skipped.
|
|
|
|
for number, export := range exports {
|
|
|
|
if export == nil {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
ev := reflect.ValueOf(export)
|
|
|
|
et := ev.Type()
|
|
|
|
|
|
|
|
// Make sure the method name is correct.
|
|
|
|
// This is just a nice sanity check.
|
|
|
|
fnName := runtime.FuncForPC(ev.Pointer()).Name()
|
|
|
|
fnName = strings.TrimSuffix(fnName[strings.LastIndexByte(fnName, '.')+1:], "-fm")
|
|
|
|
mName := methodToName[number]
|
|
|
|
if mName != fnName {
|
|
|
|
panic(fmt.Sprintf(
|
|
|
|
"actor method name is %s but exported method name is %s",
|
|
|
|
fnName, mName,
|
|
|
|
))
|
|
|
|
}
|
|
|
|
|
|
|
|
switch abi.MethodNum(number) {
|
|
|
|
case builtin.MethodSend:
|
|
|
|
panic("method 0 is reserved for Send")
|
|
|
|
case builtin.MethodConstructor:
|
|
|
|
if fnName != "Constructor" {
|
|
|
|
panic("method 1 is reserved for Constructor")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
methods[abi.MethodNum(number)] = MethodMeta{
|
|
|
|
Name: fnName,
|
|
|
|
Params: et.In(1),
|
|
|
|
Ret: et.Out(0),
|
|
|
|
}
|
2020-07-03 16:57:58 +00:00
|
|
|
}
|
2020-09-04 03:28:42 +00:00
|
|
|
MethodsMap[c] = methods
|
2020-07-03 16:57:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func GetReturnType(ctx context.Context, sm *StateManager, to address.Address, method abi.MethodNum, ts *types.TipSet) (cbg.CBORUnmarshaler, error) {
|
2020-09-15 11:04:45 +00:00
|
|
|
act, err := sm.LoadActor(ctx, to, ts)
|
|
|
|
if err != nil {
|
|
|
|
return nil, xerrors.Errorf("(get sset) failed to load miner actor: %w", err)
|
2020-07-03 16:57:58 +00:00
|
|
|
}
|
|
|
|
|
2020-09-04 03:28:42 +00:00
|
|
|
m, found := MethodsMap[act.Code][method]
|
|
|
|
if !found {
|
|
|
|
return nil, fmt.Errorf("unknown method %d for actor %s", method, act.Code)
|
|
|
|
}
|
2020-07-03 16:57:58 +00:00
|
|
|
return reflect.New(m.Ret.Elem()).Interface().(cbg.CBORUnmarshaler), nil
|
|
|
|
}
|
2020-07-27 23:51:30 +00:00
|
|
|
|
|
|
|
func MinerHasMinPower(ctx context.Context, sm *StateManager, addr address.Address, ts *types.TipSet) (bool, error) {
|
2020-09-14 12:17:45 +00:00
|
|
|
pact, err := sm.LoadActor(ctx, builtin.StoragePowerActorAddr, ts)
|
2020-07-27 23:51:30 +00:00
|
|
|
if err != nil {
|
|
|
|
return false, xerrors.Errorf("loading power actor state: %w", err)
|
|
|
|
}
|
|
|
|
|
2020-09-14 22:43:12 +00:00
|
|
|
ps, err := power.Load(sm.cs.Store(ctx), pact)
|
2020-09-14 12:17:45 +00:00
|
|
|
if err != nil {
|
|
|
|
return false, err
|
|
|
|
}
|
|
|
|
|
2020-09-14 22:43:12 +00:00
|
|
|
return ps.MinerNominalPowerMeetsConsensusMinimum(addr)
|
2020-07-27 23:51:30 +00:00
|
|
|
}
|
2020-08-12 22:20:32 +00:00
|
|
|
|
|
|
|
func CheckTotalFIL(ctx context.Context, sm *StateManager, ts *types.TipSet) (abi.TokenAmount, error) {
|
2020-09-14 22:43:12 +00:00
|
|
|
str, err := state.LoadStateTree(sm.ChainStore().Store(ctx), ts.ParentState())
|
2020-08-12 22:20:32 +00:00
|
|
|
if err != nil {
|
|
|
|
return abi.TokenAmount{}, err
|
|
|
|
}
|
|
|
|
|
|
|
|
sum := types.NewInt(0)
|
|
|
|
err = str.ForEach(func(a address.Address, act *types.Actor) error {
|
|
|
|
sum = types.BigAdd(sum, act.Balance)
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return abi.TokenAmount{}, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return sum, nil
|
|
|
|
}
|