From 9c6e9212a242692605f5c70397dc5e0f5faa01f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Tue, 3 Dec 2019 19:25:56 +0100 Subject: [PATCH] mining: get pending messages early --- chain/gen/gen.go | 34 +++++++++++++++++++++++++++------- miner/miner.go | 40 ++++++++++++++++++++++++++++++---------- 2 files changed, 57 insertions(+), 17 deletions(-) diff --git a/chain/gen/gen.go b/chain/gen/gen.go index c35ca5ce9..a823c1250 100644 --- a/chain/gen/gen.go +++ b/chain/gen/gen.go @@ -261,13 +261,17 @@ func (cg *ChainGen) nextBlockProof(ctx context.Context, pts *types.TipSet, m add VRFProof: vrfout, } - win, eproof, err := IsRoundWinner(ctx, pts, round, m, cg.eppProvs[m], &mca{w: cg.w, sm: cg.sm}) + win, eproofin, err := IsRoundWinner(ctx, pts, round, m, cg.eppProvs[m], &mca{w: cg.w, sm: cg.sm}) if err != nil { return nil, nil, xerrors.Errorf("checking round winner failed: %w", err) } if !win { return nil, tick, nil } + eproof, err := ComputeProof(ctx, cg.eppProvs[m], eproofin) + if err != nil { + return nil, nil, xerrors.Errorf("computing proof: %w", err) + } return eproof, tick, nil } @@ -466,7 +470,14 @@ func (epp *eppProvider) ComputeProof(ctx context.Context, _ sectorbuilder.Sorted return []byte("valid proof"), nil } -func IsRoundWinner(ctx context.Context, ts *types.TipSet, round int64, miner address.Address, epp ElectionPoStProver, a MiningCheckAPI) (bool, *types.EPostProof, error) { +type ProofInput struct { + sectors sectorbuilder.SortedPublicSectorInfo + hvrf []byte + winners []sectorbuilder.EPostCandidate + vrfout []byte +} + +func IsRoundWinner(ctx context.Context, ts *types.TipSet, round int64, miner address.Address, epp ElectionPoStProver, a MiningCheckAPI) (bool, *ProofInput, error) { r, err := a.ChainGetRandomness(ctx, ts.Key(), round-build.EcRandomnessLookback) if err != nil { return false, nil, xerrors.Errorf("chain get randomness: %w", err) @@ -529,16 +540,25 @@ func IsRoundWinner(ctx context.Context, ts *types.TipSet, round int64, miner add return false, nil, nil } - proof, err := epp.ComputeProof(ctx, sectors, hvrf[:], winners) + return true, &ProofInput{ + sectors: sectors, + hvrf: hvrf[:], + winners: winners, + vrfout: vrfout, + }, nil +} + +func ComputeProof(ctx context.Context, epp ElectionPoStProver, pi *ProofInput) (*types.EPostProof, error) { + proof, err := epp.ComputeProof(ctx, pi.sectors, pi.hvrf, pi.winners) if err != nil { - return false, nil, xerrors.Errorf("failed to compute snark for election proof: %w", err) + return nil, xerrors.Errorf("failed to compute snark for election proof: %w", err) } ept := types.EPostProof{ Proof: proof, - PostRand: vrfout, + PostRand: pi.vrfout, } - for _, win := range winners { + for _, win := range pi.winners { ept.Candidates = append(ept.Candidates, types.EPostTicket{ Partial: win.PartialTicket[:], SectorID: win.SectorID, @@ -546,7 +566,7 @@ func IsRoundWinner(ctx context.Context, ts *types.TipSet, round int64, miner add }) } - return true, &ept, nil + return &ept, nil } type SignFunc func(context.Context, address.Address, []byte) (*types.Signature, error) diff --git a/miner/miner.go b/miner/miner.go index 03f0f98c8..461cf7c86 100644 --- a/miner/miner.go +++ b/miner/miner.go @@ -265,7 +265,7 @@ func (m *Miner) mineOne(ctx context.Context, addr address.Address, base *MiningB return nil, xerrors.Errorf("scratching ticket failed: %w", err) } - win, proof, err := gen.IsRoundWinner(ctx, base.ts, int64(base.ts.Height()+base.nullRounds+1), addr, m.epp, m.api) + win, proofin, err := gen.IsRoundWinner(ctx, base.ts, int64(base.ts.Height()+base.nullRounds+1), addr, m.epp, m.api) if err != nil { return nil, xerrors.Errorf("failed to check if we win next round: %w", err) } @@ -275,7 +275,18 @@ func (m *Miner) mineOne(ctx context.Context, addr address.Address, base *MiningB return nil, nil } - b, err := m.createBlock(base, addr, ticket, proof) + // get pending messages early, + pending, err := m.api.MpoolPending(context.TODO(), base.ts) + if err != nil { + return nil, xerrors.Errorf("failed to get pending messages: %w", err) + } + + proof, err := gen.ComputeProof(ctx, m.epp, proofin) + if err != nil { + return nil, xerrors.Errorf("computing election proof: %w", err) + } + + b, err := m.createBlock(base, addr, ticket, proof, pending) if err != nil { return nil, xerrors.Errorf("failed to create block: %w", err) } @@ -372,12 +383,7 @@ func (m *Miner) actorLookup(ctx context.Context, addr address.Address, ts *types return curnonce, &balance, nil } -func (m *Miner) createBlock(base *MiningBase, addr address.Address, ticket *types.Ticket, proof *types.EPostProof) (*types.BlockMsg, error) { - pending, err := m.api.MpoolPending(context.TODO(), base.ts) - if err != nil { - return nil, xerrors.Errorf("failed to get pending messages: %w", err) - } - +func (m *Miner) createBlock(base *MiningBase, addr address.Address, ticket *types.Ticket, proof *types.EPostProof, pending []*types.SignedMessage) (*types.BlockMsg, error) { msgs, err := selectMessages(context.TODO(), m.actorLookup, base, pending) if err != nil { return nil, xerrors.Errorf("message filtering failed: %w", err) @@ -393,10 +399,24 @@ func (m *Miner) createBlock(base *MiningBase, addr address.Address, ticket *type type actorLookup func(context.Context, address.Address, *types.TipSet) (uint64, *types.BigInt, error) +func countFrom(msgs []*types.SignedMessage, from address.Address) (out int) { + for _, msg := range msgs { + if msg.Message.From == from { + out++ + } + } + return out +} + func selectMessages(ctx context.Context, al actorLookup, base *MiningBase, msgs []*types.SignedMessage) ([]*types.SignedMessage, error) { out := make([]*types.SignedMessage, 0, len(msgs)) inclNonces := make(map[address.Address]uint64) inclBalances := make(map[address.Address]types.BigInt) + + sort.Slice(msgs, func(i, j int) bool { // TODO: is this actually needed? + return msgs[i].Message.Nonce < msgs[j].Message.Nonce + }) + for _, msg := range msgs { if msg.Message.To == address.Undef { log.Warnf("message in mempool had bad 'To' address") @@ -421,12 +441,12 @@ func selectMessages(ctx context.Context, al actorLookup, base *MiningBase, msgs } if msg.Message.Nonce > inclNonces[from] { - log.Warnf("message in mempool has too high of a nonce (%d > %d) %s", msg.Message.Nonce, inclNonces[from], msg.Cid()) + log.Warnf("message in mempool has too high of a nonce (%d > %d) %s (%d pending for orig)", msg.Message.Nonce, inclNonces[from], msg.Cid(), countFrom(msgs, from)) continue } if msg.Message.Nonce < inclNonces[from] { - log.Warnf("message in mempool has already used nonce (%d < %d), from %s, to %s, %s", msg.Message.Nonce, inclNonces[from], msg.Message.From, msg.Message.To, msg.Cid()) + log.Warnf("message in mempool has already used nonce (%d < %d), from %s, to %s, %s (%d pending for)", msg.Message.Nonce, inclNonces[from], msg.Message.From, msg.Message.To, msg.Cid(), countFrom(msgs, from)) continue }