Merge pull request #1495 from filecoin-project/feat/mining-use-base-state

Add GetMiningBaseInfo api and use it for mining
This commit is contained in:
Łukasz Magiera 2020-04-02 04:36:56 +02:00 committed by GitHub
commit f6adbc369a
6 changed files with 94 additions and 74 deletions

View File

@ -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
}

View File

@ -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)
}

View File

@ -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)
}
}

View File

@ -74,8 +74,12 @@ func GetMinerOwner(ctx context.Context, sm *StateManager, st cid.Cid, maddr addr
}
func GetPower(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (types.BigInt, types.BigInt, error) {
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) {
var ps power.State
_, err := sm.LoadActorState(ctx, builtin.StoragePowerActorAddr, &ps, ts)
_, err := sm.LoadActorStateRaw(ctx, builtin.StoragePowerActorAddr, &ps, st)
if err != nil {
return big.Zero(), big.Zero(), xerrors.Errorf("(get sset) failed to load power actor state: %w", err)
}
@ -142,8 +146,12 @@ func SectorSetSizes(ctx context.Context, sm *StateManager, maddr address.Address
}
func GetMinerProvingSet(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) ([]*api.ChainSectorInfo, error) {
return getMinerProvingSetRaw(ctx, sm, ts.ParentState(), maddr)
}
func getMinerProvingSetRaw(ctx context.Context, sm *StateManager, st cid.Cid, maddr address.Address) ([]*api.ChainSectorInfo, error) {
var mas miner.State
_, err := sm.LoadActorState(ctx, maddr, &mas, ts)
_, err := sm.LoadActorStateRaw(ctx, maddr, &mas, st)
if err != nil {
return nil, xerrors.Errorf("(get pset) failed to load miner actor state: %w", err)
}
@ -180,8 +188,12 @@ func GetSectorsForElectionPost(ctx context.Context, sm *StateManager, ts *types.
}
func GetMinerSectorSize(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (abi.SectorSize, error) {
return getMinerSectorSizeRaw(ctx, sm, ts.ParentState(), maddr)
}
func getMinerSectorSizeRaw(ctx context.Context, sm *StateManager, st cid.Cid, maddr address.Address) (abi.SectorSize, error) {
var mas miner.State
_, err := sm.LoadActorState(ctx, maddr, &mas, ts)
_, err := sm.LoadActorStateRaw(ctx, maddr, &mas, st)
if err != nil {
return 0, xerrors.Errorf("(get ssize) failed to load miner actor state: %w", err)
}
@ -357,3 +369,43 @@ 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, _, err := sm.TipSetState(ctx, ts)
if err != nil {
return nil, err
}
provset, err := getMinerProvingSetRaw(ctx, sm, st, maddr)
if err != nil {
return nil, xerrors.Errorf("failed to get proving set: %w", err)
}
mpow, tpow, err := getPowerRaw(ctx, sm, st, maddr)
if err != nil {
return nil, xerrors.Errorf("failed to get power: %w", err)
}
worker, err := GetMinerWorkerRaw(ctx, sm, st, maddr)
if err != nil {
return nil, xerrors.Errorf("failed to get miner worker: %w", err)
}
ssize, err := getMinerSectorSizeRaw(ctx, sm, st, 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
}

View File

@ -635,7 +635,7 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err
})
eproofCheck := async.Err(func() error {
if err := syncer.VerifyElectionPoStProof(ctx, h, baseTs, waddr); err != nil {
if err := syncer.VerifyElectionPoStProof(ctx, h, waddr); err != nil {
return xerrors.Errorf("invalid election post: %w", err)
}
return nil
@ -677,12 +677,17 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err
return merr
}
func (syncer *Syncer) VerifyElectionPoStProof(ctx context.Context, h *types.BlockHeader, baseTs *types.TipSet, waddr address.Address) error {
func (syncer *Syncer) VerifyElectionPoStProof(ctx context.Context, h *types.BlockHeader, waddr address.Address) error {
curTs, err := types.NewTipSet([]*types.BlockHeader{h})
if err != nil {
return err
}
buf := new(bytes.Buffer)
if err := h.Miner.MarshalCBOR(buf); err != nil {
return xerrors.Errorf("failed to marshal miner to cbor: %w", err)
}
rand, err := syncer.sm.ChainStore().GetRandomness(ctx, baseTs.Cids(), crypto.DomainSeparationTag_ElectionPoStChallengeSeed, int64(h.Height-build.EcRandomnessLookback), buf.Bytes())
rand, err := syncer.sm.ChainStore().GetRandomness(ctx, curTs.Cids(), crypto.DomainSeparationTag_ElectionPoStChallengeSeed, int64(h.Height-build.EcRandomnessLookback), buf.Bytes())
if err != nil {
return xerrors.Errorf("failed to get randomness for verifying election proof: %w", err)
}
@ -691,7 +696,7 @@ func (syncer *Syncer) VerifyElectionPoStProof(ctx context.Context, h *types.Bloc
return xerrors.Errorf("checking eproof failed: %w", err)
}
ssize, err := stmgr.GetMinerSectorSize(ctx, syncer.sm, baseTs, h.Miner)
ssize, err := stmgr.GetMinerSectorSize(ctx, syncer.sm, curTs, h.Miner)
if err != nil {
return xerrors.Errorf("failed to get sector size for miner: %w", err)
}
@ -717,7 +722,7 @@ func (syncer *Syncer) VerifyElectionPoStProof(ctx context.Context, h *types.Bloc
return xerrors.Errorf("no candidates")
}
sectorInfo, err := stmgr.GetSectorsForElectionPost(ctx, syncer.sm, baseTs, h.Miner)
sectorInfo, err := stmgr.GetSectorsForElectionPost(ctx, syncer.sm, curTs, h.Miner)
if err != nil {
return xerrors.Errorf("getting election post sector set: %w", err)
}

View File

@ -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)