actors: Fallback post progress

This commit is contained in:
Łukasz Magiera 2019-11-28 13:46:56 +01:00
parent 7afc0d4dbe
commit aefd432422
10 changed files with 84 additions and 60 deletions

View File

@ -31,7 +31,7 @@ func SupportedSectorSize(ssize uint64) bool {
// /////
// Payments
// Blocks
// Epochs
const PaymentChannelClosingDelay = 6 * 60 * 2 // six hours
// /////
@ -40,13 +40,13 @@ const PaymentChannelClosingDelay = 6 * 60 * 2 // six hours
// Seconds
const AllowableClockDrift = BlockDelay * 2
// Blocks
// Epochs
const ForkLengthThreshold = Finality
// Blocks (e)
const BlocksPerEpoch = 5
// Blocks
// Epochs
const Finality = 500
// constants for Weight calculation
@ -57,40 +57,45 @@ const WRatioDen = 2
// /////
// Proofs
// PoStChallangeTime sets the window in which post computation should happen
// Blocks
const PoStChallangeTime = ProvingPeriodDuration - 6
// PoStRandomnessLookback is additional randomness lookback for PoSt computation
// To compute randomness epoch in a given proving period:
// RandH = PPE - PoStChallangeTime - PoStRandomnessLookback
//
// Blocks
// Epochs
const PoStRandomnessLookback = 1
// Blocks
// Epochs
const SealRandomnessLookback = Finality
// Blocks
// Epochs
const SealRandomnessLookbackLimit = SealRandomnessLookback + 2000
// 1 / n
const SectorChallengeRatioDiv = 25
const MaxFallbackPostChallengeCount = 10
// FallbackPoStBegin is the number of epochs the miner needs to wait after
// ElectionPeriodStart before starting fallback post computation
//
// Epochs
const FallbackPoStBegin = 1000
// SlashablePowerDelay is the number of epochs
// Epochs
const SlashablePowerDelay = 2000
// /////
// Mining
// Blocks
// Epochs
const EcRandomnessLookback = 300
const FallbackPoStBegin = 1000
const SlashablePowerDelay = 2000
const PowerCollateralProportion = 5
const PerCapitaCollateralProportion = 1
const CollateralPrecision = 1000
// Blocks
// Epochs
const InteractivePoRepDelay = 10
// /////
@ -106,8 +111,8 @@ var InitialReward *big.Int
const FilecoinPrecision = 1_000_000_000_000_000_000
// six years
// Blocks
const HalvingPeriodBlocks = 6 * 365 * 24 * 60 * 2
// Epochs
const HalvingPeriodEpochs = 6 * 365 * 24 * 60 * 2
// TODO: Move other important consts here
@ -125,6 +130,6 @@ func init() {
// Sync
const BadBlockCacheSize = 1 << 15
// assuming 4000 blocks per round, this lets us not lose any messages across a
// assuming 4000 messages per round, this lets us not lose any messages across a
// 10 block reorg.
const BlsSignatureCacheSize = 40000

View File

@ -366,7 +366,7 @@ func (sma StorageMinerActor) ProveCommitSector(act *types.Actor, vmctx types.VMC
if pss.Count == 0 {
self.ProvingSet = self.Sectors
// TODO: probably want to wait until the miner is above a certain
// threshold before starting this
// threshold before starting this
self.ElectionPeriodStart = vmctx.BlockHeight()
}
@ -390,15 +390,8 @@ func (sma StorageMinerActor) ProveCommitSector(act *types.Actor, vmctx types.VMC
}
type SubmitPoStParams struct {
Proof []byte
}
func ProvingPeriodEnd(setPeriodEnd, height uint64) (uint64, uint64) {
offset := setPeriodEnd % build.ProvingPeriodDuration
period := ((height - offset - 1) / build.ProvingPeriodDuration) + 1
end := (period * build.ProvingPeriodDuration) + offset
return end, period
Proof []byte
Candidates []types.EPostTicket
}
func (sma StorageMinerActor) SubmitFallbackPoSt(act *types.Actor, vmctx types.VMContext, params *SubmitPoStParams) ([]byte, ActorError) {
@ -482,13 +475,21 @@ func (sma StorageMinerActor) SubmitFallbackPoSt(act *types.Actor, vmctx types.VM
faults := self.CurrentFaultSet.All()
_ = faults
_ = seed
//VerifyPoStRandomness()
proverID := vmctx.Message().To // TODO: normalize to ID address
if ok, lerr := sectorbuilder.VerifyPost(vmctx.Context(), mi.SectorSize,
sectorbuilder.NewSortedPublicSectorInfo(sectorInfos), params.Proof.PostRand, params.Proof.Proof, winners, proverID); !ok || lerr != nil {
var candidates []sectorbuilder.EPostCandidate
for _, t := range params.Candidates {
var partial [32]byte
copy(partial[:], t.Partial)
candidates = append(candidates, sectorbuilder.EPostCandidate{
PartialTicket: partial,
SectorID: t.SectorID,
SectorChallengeIndex: t.ChallengeIndex,
})
}
if ok, lerr := sectorbuilder.VerifyFallbackPost(vmctx.Context(), mi.SectorSize,
sectorbuilder.NewSortedPublicSectorInfo(sectorInfos), seed[:], params.Proof, candidates, proverID); !ok || lerr != nil {
if lerr != nil {
// TODO: study PoST errors
return nil, aerrors.Absorb(lerr, 4, "PoST error")

View File

@ -506,7 +506,7 @@ func IsRoundWinner(ctx context.Context, ts *types.TipSet, round int64, miner add
PostRand: vrfout,
}
for _, win := range winners {
ept.Winners = append(ept.Winners, types.EPostTicket{
ept.Candidates = append(ept.Candidates, types.EPostTicket{
Partial: win.PartialTicket[:],
SectorID: win.SectorID,
ChallengeIndex: win.SectorChallengeIndex,

View File

@ -555,7 +555,7 @@ func (syncer *Syncer) ValidateBlock(ctx context.Context, b *types.FullBlock) err
return xerrors.Errorf("failed to get sector size for block miner: %w", err)
}
for _, t := range h.EPostProof.Winners {
for _, t := range h.EPostProof.Candidates {
if !types.IsTicketWinner(t.Partial, ssize, tpow, 1) {
return xerrors.Errorf("miner created a block but was not a winner")
}
@ -667,7 +667,7 @@ func (syncer *Syncer) VerifyElectionPoStProof(ctx context.Context, h *types.Bloc
}
var winners []sectorbuilder.EPostCandidate
for _, t := range h.EPostProof.Winners {
for _, t := range h.EPostProof.Candidates {
var partial [32]byte
copy(partial[:], t.Partial)
winners = append(winners, sectorbuilder.EPostCandidate{
@ -689,7 +689,7 @@ func (syncer *Syncer) VerifyElectionPoStProof(ctx context.Context, h *types.Bloc
return xerrors.Errorf("[TESTING] election post was invalid")
}
hvrf := sha256.Sum256(h.EPostProof.PostRand)
ok, err := sectorbuilder.VerifyPost(ctx, ssize, *sectorInfo, hvrf[:], h.EPostProof.Proof, winners, h.Miner)
ok, err := sectorbuilder.VerifyElectionPost(ctx, ssize, *sectorInfo, hvrf[:], h.EPostProof.Proof, winners, h.Miner)
if err != nil {
return xerrors.Errorf("failed to verify election post: %w", err)
}

View File

@ -27,9 +27,9 @@ type EPostTicket struct {
}
type EPostProof struct {
Proof []byte
PostRand []byte
Winners []EPostTicket
Proof []byte
PostRand []byte
Candidates []EPostTicket
}
type BlockHeader struct {

View File

@ -349,11 +349,11 @@ func (t *EPostProof) MarshalCBOR(w io.Writer) error {
return err
}
// t.t.Winners ([]types.EPostTicket) (slice)
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajArray, uint64(len(t.Winners)))); err != nil {
// t.t.Candidates ([]types.EPostTicket) (slice)
if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajArray, uint64(len(t.Candidates)))); err != nil {
return err
}
for _, v := range t.Winners {
for _, v := range t.Candidates {
if err := v.MarshalCBOR(w); err != nil {
return err
}
@ -410,21 +410,21 @@ func (t *EPostProof) UnmarshalCBOR(r io.Reader) error {
if _, err := io.ReadFull(br, t.PostRand); err != nil {
return err
}
// t.t.Winners ([]types.EPostTicket) (slice)
// t.t.Candidates ([]types.EPostTicket) (slice)
maj, extra, err = cbg.CborReadHeader(br)
if err != nil {
return err
}
if extra > 8192 {
return fmt.Errorf("t.Winners: array too large (%d)", extra)
return fmt.Errorf("t.Candidates: array too large (%d)", extra)
}
if maj != cbg.MajArray {
return fmt.Errorf("expected cbor array")
}
if extra > 0 {
t.Winners = make([]EPostTicket, extra)
t.Candidates = make([]EPostTicket, extra)
}
for i := 0; i < int(extra); i++ {
@ -433,7 +433,7 @@ func (t *EPostProof) UnmarshalCBOR(r io.Reader) error {
return err
}
t.Winners[i] = v
t.Candidates[i] = v
}
return nil

View File

@ -12,7 +12,7 @@ import (
func TestBlockReward(t *testing.T) {
coffer := types.FromFil(build.MiningRewardTotal).Int
sum := new(big.Int)
N := build.HalvingPeriodBlocks
N := build.HalvingPeriodEpochs
for i := 0; i < N; i++ {
a := MiningReward(types.BigInt{coffer})
sum = sum.Add(sum, a.Int)

View File

@ -192,7 +192,7 @@ func main() {
epost := time.Now()
ok, err := sectorbuilder.VerifyPost(context.TODO(), sectorSize, sinfos, challenge[:], proof, candidates[:1], maddr)
ok, err := sectorbuilder.VerifyElectionPost(context.TODO(), sectorSize, sinfos, challenge[:], proof, candidates[:1], maddr)
if err != nil {
return err
}

View File

@ -299,7 +299,7 @@ func (sb *SectorBuilder) GenerateEPostCandidates(sectorInfo SortedPublicSectorIn
return nil, err
}
challengeCount := challengeCount(uint64(len(sectorInfo.Values())))
challengeCount := electionPostChallengeCount(uint64(len(sectorInfo.Values())))
proverID := addressToProverID(sb.Miner)
return sectorbuilder.GenerateCandidates(sb.ssize, proverID, challengeSeed, challengeCount, privsectors)
@ -334,10 +334,7 @@ func (sb *SectorBuilder) GenerateFallbackPoSt(sectorInfo SortedPublicSectorInfo,
return nil, err
}
challengeCount := challengeCount(uint64(len(sectorInfo.Values())))
if challengeCount > 10 {
challengeCount = 10
}
challengeCount := fallbackPostChallengeCount(uint64(len(sectorInfo.Values())))
proverID := addressToProverID(sb.Miner)
candidates, err := sectorbuilder.GenerateCandidates(sb.ssize, proverID, challengeSeed, challengeCount, privsectors)
@ -369,16 +366,29 @@ func NewSortedPublicSectorInfo(sectors []sectorbuilder.PublicSectorInfo) SortedP
return sectorbuilder.NewSortedPublicSectorInfo(sectors...)
}
func VerifyPost(ctx context.Context, sectorSize uint64, sectorInfo SortedPublicSectorInfo, challengeSeed []byte, proof []byte, winners []EPostCandidate, proverID address.Address) (bool, error) {
func VerifyElectionPost(ctx context.Context, sectorSize uint64, sectorInfo SortedPublicSectorInfo, challengeSeed []byte, proof []byte, candidates []EPostCandidate, proverID address.Address) (bool, error) {
challengeCount := electionPostChallengeCount(uint64(len(sectorInfo.Values())))
return verifyPost(ctx, sectorSize, sectorInfo, challengeCount, challengeSeed, proof, candidates, proverID)
}
func VerifyFallbackPost(ctx context.Context, sectorSize uint64, sectorInfo SortedPublicSectorInfo, challengeSeed []byte, proof []byte, candidates []EPostCandidate, proverID address.Address) (bool, error) {
challengeCount := fallbackPostChallengeCount(uint64(len(sectorInfo.Values())))
return verifyPost(ctx, sectorSize, sectorInfo, challengeCount, challengeSeed, proof, candidates, proverID)
}
func verifyPost(ctx context.Context, sectorSize uint64, sectorInfo SortedPublicSectorInfo, challengeCount uint64, challengeSeed []byte, proof []byte, candidates []EPostCandidate, proverID address.Address) (bool, error) {
if challengeCount != uint64(len(candidates)) {
log.Warnf("verifyPost with wrong candidate count: expected %d, got %d", challengeCount, len(candidates))
return false, nil // user input, dont't error
}
var challengeSeeda [CommLen]byte
copy(challengeSeeda[:], challengeSeed)
challengeCount := challengeCount(uint64(len(sectorInfo.Values())))
_, span := trace.StartSpan(ctx, "VerifyPoSt")
defer span.End()
prover := addressToProverID(proverID)
return sectorbuilder.VerifyPoSt(sectorSize, sectorInfo, challengeSeeda, challengeCount, proof, winners, prover)
return sectorbuilder.VerifyPoSt(sectorSize, sectorInfo, challengeSeeda, challengeCount, proof, candidates, prover)
}
func GeneratePieceCommitment(piece io.Reader, pieceSize uint64) (commP [CommLen]byte, err error) {
@ -399,7 +409,15 @@ func GenerateDataCommitment(ssize uint64, pieces []PublicPieceInfo) ([CommLen]by
return sectorbuilder.GenerateDataCommitment(ssize, pieces)
}
func challengeCount(sectors uint64) uint64 {
func electionPostChallengeCount(sectors uint64) uint64 {
// ceil(sectors / build.SectorChallengeRatioDiv)
return (sectors + build.SectorChallengeRatioDiv - 1) / build.SectorChallengeRatioDiv
}
func fallbackPostChallengeCount(sectors uint64) uint64 {
challengeCount := electionPostChallengeCount(sectors)
if challengeCount > build.MaxFallbackPostChallengeCount {
return build.MaxFallbackPostChallengeCount
}
return challengeCount
}

View File

@ -102,7 +102,7 @@ func (s *seal) post(t *testing.T, sb *sectorbuilder.SectorBuilder) time.Time {
t.Fatalf("%+v", err)
}
ok, err := sectorbuilder.VerifyPost(context.TODO(), sb.SectorSize(), ssi, cSeed[:], postProof, candndates, sb.Miner)
ok, err := sectorbuilder.VerifyElectionPost(context.TODO(), sb.SectorSize(), ssi, cSeed[:], postProof, candndates, sb.Miner)
if err != nil {
t.Fatalf("%+v", err)
}