Add comments, re-select messages if refreshing base

This commit is contained in:
Aayush 2023-08-11 10:31:18 -04:00
parent 91d2c02765
commit 668d615be6

View File

@ -555,7 +555,7 @@ func (m *Miner) mineOne(ctx context.Context, base *MiningBase) (minedBlock *type
tProof := build.Clock.Now() tProof := build.Clock.Now()
// get pending messages early, // get pending messages early,
msgs, err := m.api.MpoolSelect(context.TODO(), base.TipSet.Key(), ticket.Quality()) msgs, err := m.api.MpoolSelect(ctx, base.TipSet.Key(), ticket.Quality())
if err != nil { if err != nil {
err = xerrors.Errorf("failed to select messages for block: %w", err) err = xerrors.Errorf("failed to select messages for block: %w", err)
return nil, err return nil, err
@ -563,6 +563,11 @@ func (m *Miner) mineOne(ctx context.Context, base *MiningBase) (minedBlock *type
tEquivocateWait := build.Clock.Now() tEquivocateWait := build.Clock.Now()
// This next block exists to "catch" equivocating miners,
// who submit 2 blocks at the same height at different times in order to split the network.
// To safeguard against this, we make sure it's been EquivocationDelaySecs since our base was calculated,
// then re-calculate it.
// If the daemon detected equivocated blocks, those blocks will no longer be in the new base.
// TODO: make param // TODO: make param
m.niceSleep(time.Until(base.ComputeTime.Add(2 * time.Second))) m.niceSleep(time.Until(base.ComputeTime.Add(2 * time.Second)))
newBase, err := m.GetBestMiningCandidate(ctx) newBase, err := m.GetBestMiningCandidate(ctx)
@ -571,24 +576,38 @@ func (m *Miner) mineOne(ctx context.Context, base *MiningBase) (minedBlock *type
return nil, err return nil, err
} }
// Only factor in equivocated blocks if doing so will not risk us missing a block // If the MinTicket is still the same, we take the _intersection_ of our old base and new base,
if newBase.TipSet.Height() == base.TipSet.Height() && newBase.TipSet.MinTicket().Equals(base.TipSet.MinTicket()) { // thus ejecting blocks from any equivocating miners, without taking any new blocks.
// If the MinTicket is not the same, then the work we've done so far is no longer valid.
// Instead of choosing to miss a block, we submit our best-effort block anyway.
if !newBase.TipSet.Equals(base.TipSet) && newBase.TipSet.MinTicket().Equals(base.TipSet.MinTicket()) {
newBaseMap := map[cid.Cid]struct{}{} newBaseMap := map[cid.Cid]struct{}{}
for _, newBaseBlk := range newBase.TipSet.Cids() { for _, newBaseBlk := range newBase.TipSet.Cids() {
newBaseMap[newBaseBlk] = struct{}{} newBaseMap[newBaseBlk] = struct{}{}
} }
refreshedBase := make([]*types.BlockHeader, 0, len(base.TipSet.Cids())) refreshedBaseBlocks := make([]*types.BlockHeader, 0, len(base.TipSet.Cids()))
for _, baseBlk := range base.TipSet.Blocks() { for _, baseBlk := range base.TipSet.Blocks() {
if _, ok := newBaseMap[baseBlk.Cid()]; ok { if _, ok := newBaseMap[baseBlk.Cid()]; ok {
refreshedBase = append(refreshedBase, baseBlk) refreshedBaseBlocks = append(refreshedBaseBlocks, baseBlk)
} }
} }
base.TipSet, err = types.NewTipSet(refreshedBase) if len(refreshedBaseBlocks) != len(base.TipSet.Blocks()) {
if err != nil { refreshedBase, err := types.NewTipSet(refreshedBaseBlocks)
err = xerrors.Errorf("failed to create new tipset when refreshing: %w", err) if err != nil {
return nil, err err = xerrors.Errorf("failed to create new tipset when refreshing: %w", err)
return nil, err
}
base.TipSet = refreshedBase
// refresh messages, as the selected messages may no longer be valid
msgs, err = m.api.MpoolSelect(ctx, base.TipSet.Key(), ticket.Quality())
if err != nil {
err = xerrors.Errorf("failed to re-select messages for block: %w", err)
return nil, err
}
} }
} }