diff --git a/build/params_shared.go b/build/params_shared.go index 44b66248d..c101d8db9 100644 --- a/build/params_shared.go +++ b/build/params_shared.go @@ -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 diff --git a/chain/actors/actor_miner.go b/chain/actors/actor_miner.go index c6ab993e3..b1fe46fb7 100644 --- a/chain/actors/actor_miner.go +++ b/chain/actors/actor_miner.go @@ -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") diff --git a/chain/gen/gen.go b/chain/gen/gen.go index 5121bdc7b..9189f76c6 100644 --- a/chain/gen/gen.go +++ b/chain/gen/gen.go @@ -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, diff --git a/chain/sync.go b/chain/sync.go index 4b299f504..abedd2ff0 100644 --- a/chain/sync.go +++ b/chain/sync.go @@ -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) } diff --git a/chain/types/blockheader.go b/chain/types/blockheader.go index 9cac4fd42..79585f1d2 100644 --- a/chain/types/blockheader.go +++ b/chain/types/blockheader.go @@ -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 { diff --git a/chain/types/cbor_gen.go b/chain/types/cbor_gen.go index aa821245c..d2b60f268 100644 --- a/chain/types/cbor_gen.go +++ b/chain/types/cbor_gen.go @@ -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 diff --git a/chain/vm/vm_test.go b/chain/vm/vm_test.go index 7e4dd3e12..862bb4acf 100644 --- a/chain/vm/vm_test.go +++ b/chain/vm/vm_test.go @@ -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) diff --git a/cmd/lotus-bench/main.go b/cmd/lotus-bench/main.go index 03aa60658..cbdaa3048 100644 --- a/cmd/lotus-bench/main.go +++ b/cmd/lotus-bench/main.go @@ -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 } diff --git a/lib/sectorbuilder/sectorbuilder.go b/lib/sectorbuilder/sectorbuilder.go index 53f2a672c..156bf4389 100644 --- a/lib/sectorbuilder/sectorbuilder.go +++ b/lib/sectorbuilder/sectorbuilder.go @@ -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 +} diff --git a/lib/sectorbuilder/sectorbuilder_test.go b/lib/sectorbuilder/sectorbuilder_test.go index b55b6c5bf..17398d482 100644 --- a/lib/sectorbuilder/sectorbuilder_test.go +++ b/lib/sectorbuilder/sectorbuilder_test.go @@ -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) }