diff --git a/api/api_full.go b/api/api_full.go index 05cffc05f..a1c21344c 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -72,6 +72,7 @@ type FullNode interface { // miner + MinerGetBaseInfo(context.Context, address.Address, types.TipSetKey) (*MiningBaseInfo, error) MinerCreateBlock(context.Context, address.Address, types.TipSetKey, *types.Ticket, *types.EPostProof, []*types.SignedMessage, abi.ChainEpoch, uint64) (*types.BlockMsg, error) // // UX ? @@ -376,3 +377,11 @@ type ComputeStateOutput struct { Root cid.Cid Trace []*InvocResult } + +type MiningBaseInfo struct { + MinerPower types.BigInt + NetworkPower types.BigInt + Sectors []*ChainSectorInfo + Worker address.Address + SectorSize abi.SectorSize +} diff --git a/api/apistruct/struct.go b/api/apistruct/struct.go index 563afcfd7..d809c8a25 100644 --- a/api/apistruct/struct.go +++ b/api/apistruct/struct.go @@ -22,7 +22,7 @@ import ( "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/node/modules/dtypes" - "github.com/filecoin-project/sector-storage" + sectorstorage "github.com/filecoin-project/sector-storage" "github.com/filecoin-project/sector-storage/sealtasks" "github.com/filecoin-project/sector-storage/stores" ) @@ -87,6 +87,7 @@ type FullNodeStruct struct { MpoolGetNonce func(context.Context, address.Address) (uint64, error) `perm:"read"` MpoolSub func(context.Context) (<-chan api.MpoolUpdate, error) `perm:"read"` + MinerGetBaseInfo func(context.Context, address.Address, types.TipSetKey) (*api.MiningBaseInfo, error) `perm:"read"` MinerCreateBlock func(context.Context, address.Address, types.TipSetKey, *types.Ticket, *types.EPostProof, []*types.SignedMessage, abi.ChainEpoch, uint64) (*types.BlockMsg, error) `perm:"write"` WalletNew func(context.Context, crypto.SigType) (address.Address, error) `perm:"write"` @@ -323,6 +324,10 @@ func (c *FullNodeStruct) MpoolSub(ctx context.Context) (<-chan api.MpoolUpdate, return c.Internal.MpoolSub(ctx) } +func (c *FullNodeStruct) MinerGetBaseInfo(ctx context.Context, maddr address.Address, tsk types.TipSetKey) (*api.MiningBaseInfo, error) { + return c.Internal.MinerGetBaseInfo(ctx, maddr, tsk) +} + func (c *FullNodeStruct) MinerCreateBlock(ctx context.Context, addr address.Address, base types.TipSetKey, ticket *types.Ticket, eproof *types.EPostProof, msgs []*types.SignedMessage, height abi.ChainEpoch, ts uint64) (*types.BlockMsg, error) { return c.Internal.MinerCreateBlock(ctx, addr, base, ticket, eproof, msgs, height, ts) } diff --git a/chain/gen/gen.go b/chain/gen/gen.go index a8eeb54f0..9becb17d4 100644 --- a/chain/gen/gen.go +++ b/chain/gen/gen.go @@ -446,13 +446,7 @@ func (cg *ChainGen) YieldRepo() (repo.Repo, error) { type MiningCheckAPI interface { ChainGetRandomness(ctx context.Context, tsk types.TipSetKey, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) (abi.Randomness, error) - StateMinerPower(context.Context, address.Address, types.TipSetKey) (*api.MinerPower, error) - - StateMinerWorker(context.Context, address.Address, types.TipSetKey) (address.Address, error) - - StateMinerSectorSize(context.Context, address.Address, types.TipSetKey) (abi.SectorSize, error) - - StateMinerProvingSet(context.Context, address.Address, types.TipSetKey) ([]*api.ChainSectorInfo, error) + MinerGetBaseInfo(context.Context, address.Address, types.TipSetKey) (*api.MiningBaseInfo, error) WalletSign(context.Context, address.Address, []byte) (*crypto.Signature, error) } @@ -471,44 +465,8 @@ func (mca mca) ChainGetRandomness(ctx context.Context, tsk types.TipSetKey, pers return mca.sm.ChainStore().GetRandomness(ctx, pts.Cids(), personalization, int64(randEpoch), entropy) } -func (mca mca) StateMinerPower(ctx context.Context, maddr address.Address, tsk types.TipSetKey) (*api.MinerPower, error) { - ts, err := mca.sm.ChainStore().LoadTipSet(tsk) - if err != nil { - return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err) - } - mpow, tpow, err := stmgr.GetPower(ctx, mca.sm, ts, maddr) - if err != nil { - return nil, err - } - - return &api.MinerPower{ - MinerPower: mpow, - TotalPower: tpow, - }, err -} - -func (mca mca) StateMinerWorker(ctx context.Context, maddr address.Address, tsk types.TipSetKey) (address.Address, error) { - ts, err := mca.sm.ChainStore().LoadTipSet(tsk) - if err != nil { - return address.Undef, xerrors.Errorf("loading tipset %s: %w", tsk, err) - } - return stmgr.GetMinerWorkerRaw(ctx, mca.sm, ts.ParentState(), maddr) -} - -func (mca mca) StateMinerSectorSize(ctx context.Context, maddr address.Address, tsk types.TipSetKey) (abi.SectorSize, error) { - ts, err := mca.sm.ChainStore().LoadTipSet(tsk) - if err != nil { - return 0, xerrors.Errorf("loading tipset %s: %w", tsk, err) - } - return stmgr.GetMinerSectorSize(ctx, mca.sm, ts, maddr) -} - -func (mca mca) StateMinerProvingSet(ctx context.Context, maddr address.Address, tsk types.TipSetKey) ([]*api.ChainSectorInfo, error) { - ts, err := mca.sm.ChainStore().LoadTipSet(tsk) - if err != nil { - return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err) - } - return stmgr.GetMinerProvingSet(ctx, mca.sm, ts, maddr) +func (mca mca) MinerGetBaseInfo(ctx context.Context, maddr address.Address, tsk types.TipSetKey) (*api.MiningBaseInfo, error) { + return stmgr.MinerGetBaseInfo(ctx, mca.sm, tsk, maddr) } func (mca mca) WalletSign(ctx context.Context, a address.Address, v []byte) (*crypto.Signature, error) { @@ -560,26 +518,22 @@ func IsRoundWinner(ctx context.Context, ts *types.TipSet, round int64, miner add return nil, xerrors.Errorf("chain get randomness: %w", err) } - mworker, err := a.StateMinerWorker(ctx, miner, ts.Key()) + mbi, err := a.MinerGetBaseInfo(ctx, miner, ts.Key()) if err != nil { - return nil, xerrors.Errorf("failed to get miner worker: %w", err) + return nil, xerrors.Errorf("failed to get mining base info: %w", err) } - vrfout, err := ComputeVRF(ctx, a.WalletSign, mworker, epostRand) + vrfout, err := ComputeVRF(ctx, a.WalletSign, mbi.Worker, epostRand) if err != nil { return nil, xerrors.Errorf("failed to compute VRF: %w", err) } - pset, err := a.StateMinerProvingSet(ctx, miner, ts.Key()) - if err != nil { - return nil, xerrors.Errorf("failed to load proving set for miner: %w", err) - } - if len(pset) == 0 { + if len(mbi.Sectors) == 0 { return nil, nil } var sinfos []abi.SectorInfo - for _, s := range pset { + for _, s := range mbi.Sectors { if s.Info.Info.RegisteredProof == 0 { return nil, xerrors.Errorf("sector %d in proving set had registered type of zero", s.ID) } @@ -596,19 +550,9 @@ func IsRoundWinner(ctx context.Context, ts *types.TipSet, round int64, miner add return nil, xerrors.Errorf("failed to generate electionPoSt candidates: %w", err) } - pow, err := a.StateMinerPower(ctx, miner, ts.Key()) - if err != nil { - return nil, xerrors.Errorf("failed to check power: %w", err) - } - - ssize, err := a.StateMinerSectorSize(ctx, miner, ts.Key()) - if err != nil { - return nil, xerrors.Errorf("failed to look up miners sector size: %w", err) - } - var winners []storage.PoStCandidateWithTicket for _, c := range candidates { - if types.IsTicketWinner(c.Candidate.PartialTicket, ssize, uint64(len(sinfos)), pow.TotalPower) { + if types.IsTicketWinner(c.Candidate.PartialTicket, mbi.SectorSize, uint64(len(sinfos)), mbi.NetworkPower) { winners = append(winners, c) } } diff --git a/chain/stmgr/utils.go b/chain/stmgr/utils.go index d4b2ff5b5..b4af548f8 100644 --- a/chain/stmgr/utils.go +++ b/chain/stmgr/utils.go @@ -357,3 +357,58 @@ func ComputeState(ctx context.Context, sm *StateManager, height abi.ChainEpoch, 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) + } + + st, mr, err := sm.TipSetState(ctx, ts) + if err != nil { + return nil, err + } + + // HAXX: we want to use this tipsets evaluated state for all the information + nb := &types.BlockHeader{ + Miner: maddr, + Parents: ts.Cids(), + ParentStateRoot: st, + ParentMessageReceipts: mr, + Messages: ts.Blocks()[0].Messages, // TODO: horribly wrong, can't take a cid without it though + Height: ts.Height() + 1, + } + + nts, err := types.NewTipSet([]*types.BlockHeader{nb}) + if err != nil { + return nil, xerrors.Errorf("failed to make 'next' tipset for getting base info: %w", err) + } + + provset, err := GetMinerProvingSet(ctx, sm, nts, maddr) + if err != nil { + return nil, xerrors.Errorf("failed to get proving set: %w", err) + } + + mpow, tpow, err := GetPower(ctx, sm, nts, maddr) + if err != nil { + return nil, xerrors.Errorf("failed to get power: %w", err) + } + + worker, err := GetMinerWorker(ctx, sm, nts, maddr) + if err != nil { + return nil, xerrors.Errorf("failed to get miner worker: %w", err) + } + + ssize, err := GetMinerSectorSize(ctx, sm, nts, maddr) + if err != nil { + return nil, xerrors.Errorf("failed to get miner sector size: %w", err) + } + + return &api.MiningBaseInfo{ + MinerPower: mpow, + NetworkPower: tpow, + Sectors: provset, + Worker: worker, + SectorSize: ssize, + }, nil +} diff --git a/node/impl/full/state.go b/node/impl/full/state.go index 407ea2767..023faa3b2 100644 --- a/node/impl/full/state.go +++ b/node/impl/full/state.go @@ -263,6 +263,11 @@ func (a *StateAPI) StateReadState(ctx context.Context, act *types.Actor, tsk typ }, nil } +// This is on StateAPI because miner.Miner requires this, and MinerAPI requires miner.Miner +func (a *StateAPI) MinerGetBaseInfo(ctx context.Context, maddr address.Address, tsk types.TipSetKey) (*api.MiningBaseInfo, error) { + return stmgr.MinerGetBaseInfo(ctx, a.StateManager, tsk, maddr) +} + // This is on StateAPI because miner.Miner requires this, and MinerAPI requires miner.Miner func (a *StateAPI) MinerCreateBlock(ctx context.Context, addr address.Address, parentsTSK types.TipSetKey, ticket *types.Ticket, proof *types.EPostProof, msgs []*types.SignedMessage, height abi.ChainEpoch, ts uint64) (*types.BlockMsg, error) { parents, err := a.Chain.GetTipSetFromKey(parentsTSK)