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 // 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) MinerCreateBlock(context.Context, address.Address, types.TipSetKey, *types.Ticket, *types.EPostProof, []*types.SignedMessage, abi.ChainEpoch, uint64) (*types.BlockMsg, error)
// // UX ? // // UX ?
@ -376,3 +377,11 @@ type ComputeStateOutput struct {
Root cid.Cid Root cid.Cid
Trace []*InvocResult 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/store"
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/node/modules/dtypes" "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/sealtasks"
"github.com/filecoin-project/sector-storage/stores" "github.com/filecoin-project/sector-storage/stores"
) )
@ -87,6 +87,7 @@ type FullNodeStruct struct {
MpoolGetNonce func(context.Context, address.Address) (uint64, error) `perm:"read"` MpoolGetNonce func(context.Context, address.Address) (uint64, error) `perm:"read"`
MpoolSub func(context.Context) (<-chan api.MpoolUpdate, 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"` 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"` 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) 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) { 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) 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 { type MiningCheckAPI interface {
ChainGetRandomness(ctx context.Context, tsk types.TipSetKey, personalization crypto.DomainSeparationTag, randEpoch abi.ChainEpoch, entropy []byte) (abi.Randomness, error) 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) MinerGetBaseInfo(context.Context, address.Address, types.TipSetKey) (*api.MiningBaseInfo, 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)
WalletSign(context.Context, address.Address, []byte) (*crypto.Signature, 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) 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) { func (mca mca) MinerGetBaseInfo(ctx context.Context, maddr address.Address, tsk types.TipSetKey) (*api.MiningBaseInfo, error) {
ts, err := mca.sm.ChainStore().LoadTipSet(tsk) return stmgr.MinerGetBaseInfo(ctx, mca.sm, tsk, maddr)
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) WalletSign(ctx context.Context, a address.Address, v []byte) (*crypto.Signature, error) { 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) 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 { 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 { if err != nil {
return nil, xerrors.Errorf("failed to compute VRF: %w", err) return nil, xerrors.Errorf("failed to compute VRF: %w", err)
} }
pset, err := a.StateMinerProvingSet(ctx, miner, ts.Key()) if len(mbi.Sectors) == 0 {
if err != nil {
return nil, xerrors.Errorf("failed to load proving set for miner: %w", err)
}
if len(pset) == 0 {
return nil, nil return nil, nil
} }
var sinfos []abi.SectorInfo var sinfos []abi.SectorInfo
for _, s := range pset { for _, s := range mbi.Sectors {
if s.Info.Info.RegisteredProof == 0 { if s.Info.Info.RegisteredProof == 0 {
return nil, xerrors.Errorf("sector %d in proving set had registered type of zero", s.ID) 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) 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 var winners []storage.PoStCandidateWithTicket
for _, c := range candidates { 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) 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) { 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 var ps power.State
_, err := sm.LoadActorState(ctx, builtin.StoragePowerActorAddr, &ps, ts) _, err := sm.LoadActorStateRaw(ctx, builtin.StoragePowerActorAddr, &ps, st)
if err != nil { if err != nil {
return big.Zero(), big.Zero(), xerrors.Errorf("(get sset) failed to load power actor state: %w", err) 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) { 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 var mas miner.State
_, err := sm.LoadActorState(ctx, maddr, &mas, ts) _, err := sm.LoadActorStateRaw(ctx, maddr, &mas, st)
if err != nil { if err != nil {
return nil, xerrors.Errorf("(get pset) failed to load miner actor state: %w", err) 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) { 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 var mas miner.State
_, err := sm.LoadActorState(ctx, maddr, &mas, ts) _, err := sm.LoadActorStateRaw(ctx, maddr, &mas, st)
if err != nil { if err != nil {
return 0, xerrors.Errorf("(get ssize) failed to load miner actor state: %w", err) 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 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 { 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 xerrors.Errorf("invalid election post: %w", err)
} }
return nil return nil
@ -677,12 +677,17 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err
return merr 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) buf := new(bytes.Buffer)
if err := h.Miner.MarshalCBOR(buf); err != nil { if err := h.Miner.MarshalCBOR(buf); err != nil {
return xerrors.Errorf("failed to marshal miner to cbor: %w", err) 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 { if err != nil {
return xerrors.Errorf("failed to get randomness for verifying election proof: %w", err) 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) 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 { if err != nil {
return xerrors.Errorf("failed to get sector size for miner: %w", err) 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") 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 { if err != nil {
return xerrors.Errorf("getting election post sector set: %w", err) 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 }, 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 // 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) { 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) parents, err := a.Chain.GetTipSetFromKey(parentsTSK)