From 32055731b0f6a60b061ccd66a2af30e1407d1474 Mon Sep 17 00:00:00 2001 From: ZenGround0 <5515260+ZenGround0@users.noreply.github.com> Date: Tue, 21 Apr 2020 16:26:19 -0400 Subject: [PATCH] Feat/winning post prep (#4005) * WIP * WIP * Complete with failing tests * Fix broken header and tests * Please linter * Remove car files Co-authored-by: ZenGround0 --- internal/pkg/block/block.go | 8 +- internal/pkg/block/block_test.go | 21 ++++- internal/pkg/block/epost_info.go | 52 ++-------- internal/pkg/consensus/election.go | 131 ++++++++++++-------------- internal/pkg/consensus/expected.go | 10 +- internal/pkg/consensus/testing.go | 60 ++---------- internal/pkg/mining/block_generate.go | 2 + internal/pkg/mining/worker.go | 21 +++-- internal/pkg/mining/worker_test.go | 12 +-- 9 files changed, 131 insertions(+), 186 deletions(-) diff --git a/internal/pkg/block/block.go b/internal/pkg/block/block.go index 5d2ca16429..d5bd2757ef 100644 --- a/internal/pkg/block/block.go +++ b/internal/pkg/block/block.go @@ -33,6 +33,9 @@ type Block struct { // ElectionProof is the vrf proof giving this block's miner authoring rights ElectionProof crypto.ElectionProof + // PoStProofs are the winning post proofs + PoStProofs []PoStProof `json:"PoStProofs"` + // DrandEntries contain the verifiable oracle randomness used to elect // this block's author leader DrandEntries []*drand.Entry @@ -77,10 +80,10 @@ type Block struct { } // IndexMessagesField is the message field position in the encoded block -const IndexMessagesField = 9 +const IndexMessagesField = 10 // IndexParentsField is the parents field position in the encoded block -const IndexParentsField = 4 +const IndexParentsField = 5 // Cid returns the content id of this block. func (b *Block) Cid() cid.Cid { @@ -165,6 +168,7 @@ func (b *Block) SignatureData() []byte { Messages: b.Messages, StateRoot: b.StateRoot, MessageReceipts: b.MessageReceipts, + PoStProofs: b.PoStProofs, DrandEntries: b.DrandEntries, Timestamp: b.Timestamp, BLSAggregateSig: b.BLSAggregateSig, diff --git a/internal/pkg/block/block_test.go b/internal/pkg/block/block_test.go index afb0a86845..1cc61146bf 100644 --- a/internal/pkg/block/block_test.go +++ b/internal/pkg/block/block_test.go @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/require" blk "github.com/filecoin-project/go-filecoin/internal/pkg/block" + "github.com/filecoin-project/go-filecoin/internal/pkg/constants" "github.com/filecoin-project/go-filecoin/internal/pkg/crypto" "github.com/filecoin-project/go-filecoin/internal/pkg/drand" e "github.com/filecoin-project/go-filecoin/internal/pkg/enccid" @@ -61,6 +62,7 @@ func TestTriangleEncoding(t *testing.T) { t.Run("encoding block with nonzero fields works", func(t *testing.T) { // We should ensure that every field is set -- zero values might // pass when non-zero values do not due to nil/null encoding. + posts := []blk.PoStProof{blk.NewPoStProof(constants.DevRegisteredPoStProof, []byte{0x07})} b := &blk.Block{ Miner: newAddress(), Ticket: blk.Ticket{VRFProof: []byte{0x01, 0x02, 0x03}}, @@ -86,6 +88,7 @@ func TestTriangleEncoding(t *testing.T) { Type: crypto.SigTypeBLS, Data: []byte{0x3}, }, + PoStProofs: posts, ForkSignaling: 6, } s := reflect.TypeOf(*b) @@ -94,7 +97,7 @@ func TestTriangleEncoding(t *testing.T) { // Also please add non zero fields to "b" and "diff" in TestSignatureData // and add a new check that different values of the new field result in // different output data. - require.Equal(t, 17, s.NumField()) // Note: this also counts private fields + require.Equal(t, 18, s.NumField()) // Note: this also counts private fields testRoundTrip(t, b) }) } @@ -223,6 +226,7 @@ func TestBlockJsonMarshal(t *testing.T) { func TestSignatureData(t *testing.T) { tf.UnitTest(t) newAddress := vmaddr.NewForTestGetter() + posts := []blk.PoStProof{blk.NewPoStProof(constants.DevRegisteredPoStProof, []byte{0x07})} b := &blk.Block{ Miner: newAddress(), @@ -242,12 +246,15 @@ func TestSignatureData(t *testing.T) { ForkSignaling: 3, StateRoot: e.NewCid(types.CidFromString(t, "somecid")), Timestamp: 1, + PoStProofs: posts, BlockSig: &crypto.Signature{ Type: crypto.SigTypeBLS, Data: []byte{0x3}, }, } + diffPoSts := []blk.PoStProof{blk.NewPoStProof(constants.DevRegisteredPoStProof, []byte{0x17})} + diff := &blk.Block{ Miner: newAddress(), Ticket: blk.Ticket{VRFProof: []byte{0x03, 0x01, 0x02}}, @@ -266,6 +273,7 @@ func TestSignatureData(t *testing.T) { ForkSignaling: 2, StateRoot: e.NewCid(types.CidFromString(t, "someothercid")), Timestamp: 4, + PoStProofs: diffPoSts, BlockSig: &crypto.Signature{ Type: crypto.SigTypeBLS, Data: []byte{0x4}, @@ -408,6 +416,17 @@ func TestSignatureData(t *testing.T) { assert.False(t, bytes.Equal(before, after)) }() + func() { + before := b.SignatureData() + + cpy := b.PoStProofs + defer func() { b.PoStProofs = cpy }() + + b.PoStProofs = diff.PoStProofs + after := b.SignatureData() + assert.False(t, bytes.Equal(before, after)) + }() + func() { before := b.SignatureData() cpy := b.DrandEntries diff --git a/internal/pkg/block/epost_info.go b/internal/pkg/block/epost_info.go index 90cedcef1e..91c8bf50b3 100644 --- a/internal/pkg/block/epost_info.go +++ b/internal/pkg/block/epost_info.go @@ -4,63 +4,27 @@ import ( "github.com/filecoin-project/specs-actors/actors/abi" ) -// EPoStCandidate wraps the input data needed to verify an election PoSt -type EPoStCandidate struct { - _ struct{} `cbor:",toarray"` - PartialTicket abi.PartialTicket - SectorID abi.SectorNumber - SectorChallengeIndex int64 -} - -type EPoStProof struct { +// PoStProof is a winning post proof included in a block header +type PoStProof struct { _ struct{} `cbor:",toarray"` RegisteredProof abi.RegisteredProof ProofBytes []byte } -// NewEPoStCandidate constructs an epost candidate from data -func NewEPoStCandidate(sID uint64, pt []byte, sci int64) EPoStCandidate { - return EPoStCandidate{ - SectorID: abi.SectorNumber(sID), - PartialTicket: pt, - SectorChallengeIndex: sci, - } -} - -// NewEPoStProof constructs an epost proof from registered proof and bytes -func NewEPoStProof(rpp abi.RegisteredProof, bs []byte) EPoStProof { - return EPoStProof{ +// NewPoStProof constructs an epost proof from registered proof and bytes +func NewPoStProof(rpp abi.RegisteredProof, bs []byte) PoStProof { + return PoStProof{ RegisteredProof: rpp, ProofBytes: bs, } } -// FromFFICandidate converts a Candidate to an EPoStCandidate -func FromFFICandidate(candidate abi.PoStCandidate) EPoStCandidate { - return EPoStCandidate{ - PartialTicket: candidate.PartialTicket[:], - SectorID: candidate.SectorID.Number, - SectorChallengeIndex: candidate.ChallengeIndex, - } -} - -// FromFFICandidates converts a variable number of Candidate to a slice of -// EPoStCandidate -func FromFFICandidates(candidates ...abi.PoStCandidate) []EPoStCandidate { - out := make([]EPoStCandidate, len(candidates)) - for idx, c := range candidates { - out[idx] = FromFFICandidate(c) - } - - return out -} - // FromABIPoStProofs converts the abi post proof type to a local type for // serialization purposes -func FromABIPoStProofs(postProofs ...abi.PoStProof) []EPoStProof { - out := make([]EPoStProof, len(postProofs)) +func FromABIPoStProofs(postProofs ...abi.PoStProof) []PoStProof { + out := make([]PoStProof, len(postProofs)) for i, p := range postProofs { - out[i] = EPoStProof{RegisteredProof: p.RegisteredProof, ProofBytes: p.ProofBytes} + out[i] = PoStProof{RegisteredProof: p.RegisteredProof, ProofBytes: p.ProofBytes} } return out diff --git a/internal/pkg/consensus/election.go b/internal/pkg/consensus/election.go index dad6260192..2a982a4449 100644 --- a/internal/pkg/consensus/election.go +++ b/internal/pkg/consensus/election.go @@ -5,9 +5,9 @@ import ( "math/big" address "github.com/filecoin-project/go-address" - "github.com/filecoin-project/sector-storage/ffiwrapper" "github.com/filecoin-project/specs-actors/actors/abi" acrypto "github.com/filecoin-project/specs-actors/actors/crypto" + "github.com/minio/blake2b-simd" "github.com/pkg/errors" @@ -26,12 +26,10 @@ type EPoStVerifier interface { } // ElectionMachine generates and validates PoSt partial tickets and PoSt proofs. -type ElectionMachine struct { - chain ChainRandomness -} +type ElectionMachine struct{} func NewElectionMachine(chain ChainRandomness) *ElectionMachine { - return &ElectionMachine{chain: chain} + return &ElectionMachine{} } func (em ElectionMachine) GenerateElectionProof(ctx context.Context, entry *drand.Entry, @@ -47,47 +45,29 @@ func (em ElectionMachine) GenerateElectionProof(ctx context.Context, entry *dran return vrfProof.Data, nil } -// GenerateCandidates creates candidate partial tickets for consideration in -// block reward election -func (em ElectionMachine) GenerateCandidates(poStRand abi.PoStRandomness, sectorInfos []abi.SectorInfo, ep postgenerator.PoStGenerator, maddr address.Address) ([]abi.PoStCandidate, error) { - dummyFaults := []abi.SectorNumber{} - proofTypeBySectorNumber := make(map[abi.SectorNumber]abi.RegisteredProof, len(sectorInfos)) - for _, s := range sectorInfos { - p, err := s.RegisteredPoStProof() - if err != nil { - return nil, err - } - proofTypeBySectorNumber[s.SectorNumber] = p - } - +// GenerateWinningPoSt creates a PoSt proof over the input miner ID and sector infos. +func (em ElectionMachine) GenerateWinningPoSt(allSectorInfos []abi.SectorInfo, entry *drand.Entry, epoch abi.ChainEpoch, ep postgenerator.PoStGenerator, maddr address.Address) ([]abi.PoStProof, error) { minerID, err := address.IDFromAddress(maddr) if err != nil { return nil, err } + _ = minerID - candidatesWithTicket, err := ep.GenerateEPostCandidates(context.TODO(), abi.ActorID(minerID), sectorInfos, poStRand, dummyFaults) + seed := blake2b.Sum256(entry.Signature) + randomness, err := crypto.BlendEntropy(acrypto.DomainSeparationTag_ElectionPoStChallengeSeed, seed[:], epoch, []byte{}) if err != nil { return nil, err } + _ = randomness - candidates := make([]abi.PoStCandidate, len(candidatesWithTicket)) - for i, candidateWithTicket := range candidatesWithTicket { - candidates[i] = candidateWithTicket.Candidate - candidates[i].RegisteredProof = proofTypeBySectorNumber[candidates[i].SectorID.Number] - candidates[i].SectorID.Miner = abi.ActorID(minerID) - } - return candidates, nil -} - -// GenerateEPoSt creates a PoSt proof over the input PoSt candidates. Should -// only be called on winning candidates. -func (em ElectionMachine) GenerateEPoSt(allSectorInfos []abi.SectorInfo, challengeSeed abi.PoStRandomness, winners []abi.PoStCandidate, ep postgenerator.PoStGenerator, maddr address.Address) ([]abi.PoStProof, error) { - minerID, err := address.IDFromAddress(maddr) - if err != nil { - return nil, err - } + // challengeIndexes, err := ep.GenerateWinningPoStSectorChallenge(proofs[0].RegisteredProof, minerID, randomness, len(allPrivateSectorInfos)) + // if err != nil { + // return nil, err + // } + // challengedSectorInfos := filterSectorInfosByIndex(allSectorInfos, challengeIndexes) + // return ep.GenerateWinningPoSt(minerID, challengedSectorInfos, randomness) - return ep.ComputeElectionPoSt(context.TODO(), abi.ActorID(minerID), allSectorInfos, challengeSeed, winners) + return nil, nil } func (em ElectionMachine) VerifyElectionProof(ctx context.Context, entry *drand.Entry, epoch abi.ChainEpoch, miner address.Address, workerSigner address.Address, vrfProof crypto.VRFPi) error { @@ -113,39 +93,31 @@ func (em ElectionMachine) IsWinner(challengeTicket []byte, sectorNum, networkPow return lhs.Cmp(rhs) == -1 } -// VerifyPoSt verifies a PoSt proof. -func (em ElectionMachine) VerifyPoSt(ctx context.Context, ep EPoStVerifier, allSectorInfos []abi.SectorInfo, challengeSeed abi.PoStRandomness, proofs []block.EPoStProof, candidates []block.EPoStCandidate, mIDAddr address.Address) (bool, error) { - // filter down sector infos to only those referenced by candidates - // TODO: pass an actual faults count to this challenge count. https://github.com/filecoin-project/go-filecoin/issues/3875 - challengeCount := ffiwrapper.ElectionPostChallengeCount(uint64(len(allSectorInfos)), 0) - minerID, err := address.IDFromAddress(mIDAddr) +// VerifyWinningPoSt verifies a Winning PoSt proof. +func (em ElectionMachine) VerifyWinningPoSt(ctx context.Context, ep EPoStVerifier, allSectorInfos []abi.SectorInfo, entry *drand.Entry, epoch abi.ChainEpoch, proofs []block.PoStProof, mIDAddr address.Address) (bool, error) { + if len(proofs) == 0 { + return false, nil + } + + seed := blake2b.Sum256(entry.Signature) + randomness, err := crypto.BlendEntropy(acrypto.DomainSeparationTag_ElectionPoStChallengeSeed, seed[:], epoch, []byte{}) if err != nil { return false, err } + _ = randomness - sectorNumToRegisteredProof := make(map[abi.SectorNumber]abi.RegisteredProof) - for _, si := range allSectorInfos { - rpp, err := si.RegisteredPoStProof() - if err != nil { - return false, err - } - sectorNumToRegisteredProof[si.SectorNumber] = rpp + minerID, err := address.IDFromAddress(mIDAddr) + if err != nil { + return false, err } + _ = minerID - // map inputs to abi.PoStVerifyInfo - var ffiCandidates []abi.PoStCandidate - for _, candidate := range candidates { - c := abi.PoStCandidate{ - RegisteredProof: sectorNumToRegisteredProof[candidate.SectorID], - PartialTicket: candidate.PartialTicket, - SectorID: abi.SectorID{ - Miner: abi.ActorID(minerID), - Number: candidate.SectorID, - }, - ChallengeIndex: candidate.SectorChallengeIndex, - } - ffiCandidates = append(ffiCandidates, c) - } + // Gather sector inputs for each proof + // challengeIndexes, err := ep.GenerateWinningPoStSectorChallenge(proofs[0].RegisteredProof, minerID, randomness, len(allSectorInfos)) + // if err != nil { + // return false, nil + // } + // challengedSectorsInfos := filterSectorInfosByIndex(allSectorInfos, challengeIndexes) proofsPrime := make([]abi.PoStProof, len(proofs)) for idx := range proofsPrime { @@ -155,16 +127,14 @@ func (em ElectionMachine) VerifyPoSt(ctx context.Context, ep EPoStVerifier, allS } } - poStVerifyInfo := abi.PoStVerifyInfo{ - Randomness: challengeSeed, - Candidates: ffiCandidates, - Proofs: proofsPrime, - EligibleSectors: allSectorInfos, - Prover: abi.ActorID(minerID), - ChallengeCount: challengeCount, - } - - return ep.VerifyElectionPost(ctx, poStVerifyInfo) + return true, nil + // verifyInfo := abi.WinningPoStVerifyInfo{ + // Randomness: randomness, + // Proofs: proofsPrime, + // EligibleSectors: challengedSectorInfos, + // Prover: abi.ActorID(minerID), + // } + // return ep.VerifyWinningPost(ctx, poStVerifyInfo) } // TicketMachine uses a VRF and VDF to generate deterministic, unpredictable @@ -220,3 +190,18 @@ func electionVRFRandomness(entry *drand.Entry, miner address.Address, epoch abi. seed := blake2b.Sum256(entry.Signature) return crypto.BlendEntropy(acrypto.DomainSeparationTag_ElectionPoStChallengeSeed, seed[:], epoch, entropy) } + +// func filterSectorInfosByIndex(allSectorInfos []abi.SectorInfo, challengeIDs []uint64) []abi.SectorInfo { +// idSet := make(map[uint64]struct{}) +// for _, id := range challengeIDs { +// idSet[id] = struct{}{} +// } + +// var filteredSectorInfos []abi.SectorInfo +// for _, si := range allSectorInfos { +// if _, ok := idSet[uint64(si.SectorNumber)]; ok { +// filteredSectorInfos = append(filteredSectorInfos, si) +// } +// } +// return filteredSectorInfos +// } diff --git a/internal/pkg/consensus/expected.go b/internal/pkg/consensus/expected.go index be9efff666..14c23ccc32 100644 --- a/internal/pkg/consensus/expected.go +++ b/internal/pkg/consensus/expected.go @@ -79,9 +79,9 @@ type TicketValidator interface { // ElectionValidator validates that an election fairly produced a winner. type ElectionValidator interface { - VerifyPoSt(ctx context.Context, ep EPoStVerifier, allSectorInfos []abi.SectorInfo, challengeSeed abi.PoStRandomness, proofs []block.EPoStProof, candidates []block.EPoStCandidate, mIDAddr address.Address) (bool, error) IsWinner(challengeTicket []byte, sectorNum, networkPower, sectorSize uint64) bool VerifyElectionProof(ctx context.Context, entry *drand.Entry, epoch abi.ChainEpoch, miner address.Address, workerSigner address.Address, vrfProof crypto.VRFPi) error + VerifyWinningPoSt(ctx context.Context, ep EPoStVerifier, allSectorInfos []abi.SectorInfo, seedEntry *drand.Entry, epoch abi.ChainEpoch, proofs []block.PoStProof, mIDAddr address.Address) (bool, error) } // StateViewer provides views into the chain state. @@ -310,12 +310,18 @@ func (c *Expected) validateMining(ctx context.Context, return errors.Errorf("Block did not win election") } - // TODO #3989 validate winning post allSectorInfos, err := sectorSetPowerTable.SortedSectorInfos(ctx, blk.Miner) if err != nil { return errors.Wrapf(err, "failed to read sector infos from power table") } _ = allSectorInfos + // valid, err := c.VerifyWinningPoSt(ctx, c.postVerifier, allSectorInfos, electionEntry, blk.Height, blk.PoStProofs, blk.Miner) + // if err != nil { + // return errors.Wrapf(err, "failed verifying winning post") + // } + // if !valid { + // return errors.Errorf("Invalid winning post") + // } // Ticket was correctly generated by miner sampleEpoch := blk.Height - miner.ElectionLookback diff --git a/internal/pkg/consensus/testing.go b/internal/pkg/consensus/testing.go index 4187fee833..bf2ffba6aa 100644 --- a/internal/pkg/consensus/testing.go +++ b/internal/pkg/consensus/testing.go @@ -57,52 +57,20 @@ type FakeElectionMachine struct{} var _ ElectionValidator = new(FakeElectionMachine) -// GenerateEPoStVrfProof returns a fake post randomness byte array -func (fem *FakeElectionMachine) GenerateEPoStVrfProof(ctx context.Context, base block.TipSetKey, epoch abi.ChainEpoch, miner address.Address, worker address.Address, signer types.Signer) (crypto.VRFPi, error) { - return MakeFakeVRFProofForTest(), nil -} - // GenerateElectionProof returns a fake randomness func (fem *FakeElectionMachine) GenerateElectionProof(_ context.Context, _ *drand.Entry, _ abi.ChainEpoch, _ address.Address, _ address.Address, _ types.Signer) (crypto.VRFPi, error) { return MakeFakeVRFProofForTest(), nil } -// GenerateCandidates returns one fake election post candidate -func (fem *FakeElectionMachine) GenerateCandidates(poStRand abi.PoStRandomness, sectorInfos []abi.SectorInfo, ep postgenerator.PoStGenerator, minerAddr address.Address) ([]abi.PoStCandidate, error) { - return []abi.PoStCandidate{ - { - - SectorID: abi.SectorID{Miner: abi.ActorID(1), Number: 0}, - PartialTicket: []byte{0xf}, - ChallengeIndex: 0, - }, - }, nil -} - // GenerateEPoSt returns a fake post proof -func (fem *FakeElectionMachine) GenerateEPoSt(_ []abi.SectorInfo, _ abi.PoStRandomness, _ []abi.PoStCandidate, _ postgenerator.PoStGenerator, _ address.Address) ([]abi.PoStProof, error) { +func (fem *FakeElectionMachine) GenerateWinningPoSt(allSectorInfos []abi.SectorInfo, entry *drand.Entry, epoch abi.ChainEpoch, ep postgenerator.PoStGenerator, maddr address.Address) ([]abi.PoStProof, error) { return []abi.PoStProof{{ RegisteredProof: constants.DevRegisteredPoStProof, ProofBytes: []byte{0xe}, }}, nil } -// VerifyEPoStVrfProof returns true -func (fem *FakeElectionMachine) VerifyEPoStVrfProof(context.Context, block.TipSetKey, abi.ChainEpoch, address.Address, address.Address, abi.PoStRandomness) error { - return nil -} - -// CandidateWins returns true -func (fem *FakeElectionMachine) CandidateWins(_ []byte, _ uint64, _ uint64, _ uint64, _ uint64) bool { - return true -} - -// VerifyPoSt return true -func (fem *FakeElectionMachine) VerifyPoSt(_ context.Context, _ EPoStVerifier, _ []abi.SectorInfo, _ abi.PoStRandomness, _ []block.EPoStProof, _ []block.EPoStCandidate, _ address.Address) (bool, error) { - return true, nil -} - func (fem *FakeElectionMachine) IsWinner(_ []byte, _, _, _ uint64) bool { return true } @@ -111,6 +79,10 @@ func (fem *FakeElectionMachine) VerifyElectionProof(_ context.Context, _ *drand. return nil } +func (fem *FakeElectionMachine) VerifyWinningPoSt(_ context.Context, _ EPoStVerifier, _ []abi.SectorInfo, _ *drand.Entry, _ abi.ChainEpoch, _ []block.PoStProof, _ address.Address) (bool, error) { + return true, nil +} + // FakeTicketMachine generates fake tickets and verifies all tickets type FakeTicketMachine struct{} @@ -137,11 +109,6 @@ type FailingElectionValidator struct{} var _ ElectionValidator = new(FailingElectionValidator) -// CandidateWins always returns false -func (fev *FailingElectionValidator) CandidateWins(_ []byte, _, _, _, _ uint64) bool { - return false -} - func (fev *FailingElectionValidator) IsWinner(_ []byte, _, _, _ uint64) bool { return false } @@ -150,16 +117,10 @@ func (fev *FailingElectionValidator) VerifyElectionProof(_ context.Context, _ *d return nil } -// VerifyPoSt returns true without error -func (fev *FailingElectionValidator) VerifyPoSt(ctx context.Context, ep EPoStVerifier, allSectorInfos []abi.SectorInfo, challengeSeed abi.PoStRandomness, proofs []block.EPoStProof, candidates []block.EPoStCandidate, mIDAddr address.Address) (bool, error) { +func (fev *FailingElectionValidator) VerifyWinningPoSt(_ context.Context, _ EPoStVerifier, _ []abi.SectorInfo, _ *drand.Entry, _ abi.ChainEpoch, _ []block.PoStProof, _ address.Address) (bool, error) { return true, nil } -// VerifyEPoStVrfProof return true -func (fev *FailingElectionValidator) VerifyEPoStVrfProof(context.Context, block.TipSetKey, abi.ChainEpoch, address.Address, address.Address, abi.PoStRandomness) error { - return nil -} - // MakeFakeTicketForTest creates a fake ticket func MakeFakeTicketForTest() block.Ticket { val := make([]byte, 65) @@ -177,18 +138,13 @@ func MakeFakeVRFProofForTest() []byte { } // MakeFakePoStForTest creates a fake post -func MakeFakePoStsForTest() []block.EPoStProof { - return []block.EPoStProof{{ +func MakeFakePoStsForTest() []block.PoStProof { + return []block.PoStProof{{ RegisteredProof: constants.DevRegisteredPoStProof, ProofBytes: []byte{0xe}, }} } -// MakeFakeWinnersForTest creats an empty winners array -func MakeFakeWinnersForTest() []block.EPoStCandidate { - return []block.EPoStCandidate{} -} - // NFakeSectorInfos returns numSectors fake sector infos func RequireFakeSectorInfos(t *testing.T, numSectors uint64) []abi.SectorInfo { var infos []abi.SectorInfo diff --git a/internal/pkg/mining/block_generate.go b/internal/pkg/mining/block_generate.go index 4ff8b1c087..ea7da48d9a 100644 --- a/internal/pkg/mining/block_generate.go +++ b/internal/pkg/mining/block_generate.go @@ -28,6 +28,7 @@ func (w *DefaultWorker) Generate( ticket block.Ticket, electionProof crypto.VRFPi, nullBlockCount abi.ChainEpoch, + posts []block.PoStProof, drandEntries []*drand.Entry, ) Output { @@ -104,6 +105,7 @@ func (w *DefaultWorker) Generate( MessageReceipts: e.NewCid(baseReceiptRoot), Parents: baseTipSet.Key(), ParentWeight: weight, + PoStProofs: posts, StateRoot: e.NewCid(baseStateRoot), Ticket: ticket, Timestamp: uint64(epochStartTime.Unix()), diff --git a/internal/pkg/mining/worker.go b/internal/pkg/mining/worker.go index 61dde00242..874156ead7 100644 --- a/internal/pkg/mining/worker.go +++ b/internal/pkg/mining/worker.go @@ -88,7 +88,7 @@ type workerPorcelainAPI interface { type electionUtil interface { GenerateElectionProof(ctx context.Context, entry *drand.Entry, epoch abi.ChainEpoch, miner address.Address, worker address.Address, signer types.Signer) (crypto.VRFPi, error) IsWinner(challengeTicket []byte, sectorNum, networkPower, sectorSize uint64) bool - // TODO: GenerateWinningPoSt (maybe also winning post candidates?) + GenerateWinningPoSt(allSectorInfos []abi.SectorInfo, entry *drand.Entry, epoch abi.ChainEpoch, ep postgenerator.PoStGenerator, maddr address.Address) ([]abi.PoStProof, error) } // ticketGenerator creates tickets. @@ -192,6 +192,7 @@ func (w *DefaultWorker) Mine(ctx context.Context, base block.TipSet, nullBlkCoun outCh <- NewOutputErr(err) return } + currEpoch := baseEpoch + abi.ChainEpoch(1) + abi.ChainEpoch(nullBlkCount) log.Debugf("Mining on tipset %s, at epoch %d with %d null blocks.", base.String(), baseEpoch, nullBlkCount) if ctx.Err() != nil { @@ -215,7 +216,7 @@ func (w *DefaultWorker) Mine(ctx context.Context, base block.TipSet, nullBlkCoun // The parameter is interpreted as: lookback=1 means parent tipset. Subtract one here because the base from // which the lookback is counted is already the parent, rather than "current" tipset. // The sampling code will handle this underflowing past the genesis. - lookbackEpoch := baseEpoch - (miner.ElectionLookback - 1) + abi.ChainEpoch(nullBlkCount) + lookbackEpoch := currEpoch - miner.ElectionLookback workerSignerAddr, err := keyView.AccountSignerAddress(ctx, workerAddr) if err != nil { @@ -245,7 +246,7 @@ func (w *DefaultWorker) Mine(ctx context.Context, base block.TipSet, nullBlkCoun return } - electionVRFProof, err := w.election.GenerateElectionProof(ctx, electionEntry, baseEpoch+1+abi.ChainEpoch(nullBlkCount), w.minerAddr, workerSignerAddr, w.workerSigner) + electionVRFProof, err := w.election.GenerateElectionProof(ctx, electionEntry, currEpoch, w.minerAddr, workerSignerAddr, w.workerSigner) if err != nil { log.Errorf("Worker.Mine failed to generate electionVRFProof %s", err) } @@ -309,9 +310,17 @@ func (w *DefaultWorker) Mine(ctx context.Context, base block.TipSet, nullBlkCoun outCh <- NewOutputErr(err) return } - _ = sortedSectorInfos // TODO use for winning post - - next := w.Generate(ctx, base, nextTicket, electionVRFProof, abi.ChainEpoch(nullBlkCount), drandEntries) + _ = sortedSectorInfos + posts := []block.PoStProof{} + // be able to get the cachedir and the sectordir to fill out private sector info + // posts, err := w.election.GenerateWinningPoSt(sortedSectorInfos, electionEntry, currEpoch, w.poster, w.minerAddr) + // if err != nil { + // log.Warnf("Worker.Mine failed to generate post") + // outCh <- NewOutputErr(err) + // return + // } + + next := w.Generate(ctx, base, nextTicket, electionVRFProof, abi.ChainEpoch(nullBlkCount), posts, drandEntries) if next.Err == nil { log.Debugf("Worker.Mine generates new winning block! %s", next.Header.Cid().String()) } diff --git a/internal/pkg/mining/worker_test.go b/internal/pkg/mining/worker_test.go index 28fec60106..e9ad3b0478 100644 --- a/internal/pkg/mining/worker_test.go +++ b/internal/pkg/mining/worker_test.go @@ -473,7 +473,7 @@ func TestGenerateMultiBlockTipSet(t *testing.T) { baseTipset := builder.AppendOn(parentTipset, 2) assert.Equal(t, 2, baseTipset.Len()) - out := worker.Generate(ctx, baseTipset, block.Ticket{VRFProof: []byte{2}}, consensus.MakeFakeVRFProofForTest(), 0, nil) + out := worker.Generate(ctx, baseTipset, block.Ticket{VRFProof: []byte{2}}, consensus.MakeFakeVRFProofForTest(), 0, consensus.MakeFakePoStsForTest(), nil) assert.NoError(t, out.Err) txMeta, err := messages.LoadTxMeta(ctx, out.Header.Messages.Cid) @@ -577,7 +577,7 @@ func TestGeneratePoolBlockResults(t *testing.T) { StateRoot: e.NewCid(stateRoot), } - out := worker.Generate(ctx, block.RequireNewTipSet(t, &baseBlock), block.Ticket{VRFProof: []byte{0}}, consensus.MakeFakeVRFProofForTest(), 0, nil) + out := worker.Generate(ctx, block.RequireNewTipSet(t, &baseBlock), block.Ticket{VRFProof: []byte{0}}, consensus.MakeFakeVRFProofForTest(), 0, consensus.MakeFakePoStsForTest(), nil) assert.NoError(t, out.Err) // This is the temporary failure + the good message, @@ -642,14 +642,14 @@ func TestGenerateSetsBasicFields(t *testing.T) { } baseTipSet := block.RequireNewTipSet(t, &baseBlock) ticket := mining.NthTicket(7) - out := worker.Generate(ctx, baseTipSet, ticket, consensus.MakeFakeVRFProofForTest(), 0, nil) + out := worker.Generate(ctx, baseTipSet, ticket, consensus.MakeFakeVRFProofForTest(), 0, consensus.MakeFakePoStsForTest(), nil) assert.NoError(t, out.Err) assert.Equal(t, h+1, out.Header.Height) assert.Equal(t, minerAddr, out.Header.Miner) assert.Equal(t, ticket, out.Header.Ticket) - out = worker.Generate(ctx, baseTipSet, block.Ticket{VRFProof: []byte{0}}, consensus.MakeFakeVRFProofForTest(), 1, nil) + out = worker.Generate(ctx, baseTipSet, block.Ticket{VRFProof: []byte{0}}, consensus.MakeFakeVRFProofForTest(), 1, consensus.MakeFakePoStsForTest(), nil) assert.NoError(t, out.Err) assert.Equal(t, h+2, out.Header.Height) @@ -698,7 +698,7 @@ func TestGenerateWithoutMessages(t *testing.T) { Height: 100, StateRoot: e.NewCid(newCid()), } - out := worker.Generate(ctx, block.RequireNewTipSet(t, &baseBlock), block.Ticket{VRFProof: []byte{0}}, consensus.MakeFakeVRFProofForTest(), 0, nil) + out := worker.Generate(ctx, block.RequireNewTipSet(t, &baseBlock), block.Ticket{VRFProof: []byte{0}}, consensus.MakeFakeVRFProofForTest(), 0, consensus.MakeFakePoStsForTest(), nil) assert.NoError(t, out.Err) assert.Len(t, pool.Pending(), 0) // This is the temporary failure. @@ -759,7 +759,7 @@ func TestGenerateError(t *testing.T) { StateRoot: e.NewCid(newCid()), } baseTipSet := block.RequireNewTipSet(t, &baseBlock) - out := worker.Generate(ctx, baseTipSet, block.Ticket{VRFProof: []byte{0}}, consensus.MakeFakeVRFProofForTest(), 0, nil) + out := worker.Generate(ctx, baseTipSet, block.Ticket{VRFProof: []byte{0}}, consensus.MakeFakeVRFProofForTest(), 0, consensus.MakeFakePoStsForTest(), nil) assert.Error(t, out.Err, "boom") assert.Nil(t, out.Header)