From 6a6b03ef4071eebf0e777d3ba6ae0cfb34dc7d99 Mon Sep 17 00:00:00 2001 From: Aayush Date: Wed, 24 Jan 2024 18:35:46 -0500 Subject: [PATCH] feat: drand: refactor round verification --- chain/beacon/beacon.go | 17 +++++++++++++---- chain/beacon/drand/drand.go | 7 ++----- chain/sync.go | 10 +++++----- 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/chain/beacon/beacon.go b/chain/beacon/beacon.go index aa76bcffe..ff75b8579 100644 --- a/chain/beacon/beacon.go +++ b/chain/beacon/beacon.go @@ -79,11 +79,21 @@ func ValidateBlockValues(bSchedule Schedule, nv network.Version, h *types.BlockH return xerrors.Errorf("expected to have beacon entries in this block, but didn't find any") } + // Verify that the last beacon entry's round corresponds to the round we expect last := h.BeaconEntries[len(h.BeaconEntries)-1] if last.Round != maxRound { return xerrors.Errorf("expected final beacon entry in block to be at round %d, got %d", maxRound, last.Round) } + // Verify that all other entries' rounds are as expected for the epochs in between parentEpoch and h.Height + for i, e := range h.BeaconEntries { + correctRound := b.MaxBeaconRoundForEpoch(nv, parentEpoch+abi.ChainEpoch(i)+1) + if e.Round != correctRound { + return xerrors.Errorf("unexpected beacon round %d, expected %d for epoch %d", e.Round, correctRound, parentEpoch+abi.ChainEpoch(i)) + } + } + + // Verify the beacon entries themselves for i, e := range h.BeaconEntries { if err := b.VerifyEntry(e, prevEntry); err != nil { return xerrors.Errorf("beacon entry %d (%d - %x (%d)) was invalid: %w", i, e.Round, e.Data, len(e.Data), err) @@ -132,10 +142,10 @@ func BeaconEntriesForBlock(ctx context.Context, bSchedule Schedule, nv network.V prev.Round = maxRound - 1 } - cur := maxRound var out []types.BeaconEntry - for cur > prev.Round { - rch := beacon.Entry(ctx, cur) + for currEpoch := epoch; currEpoch > parentEpoch; currEpoch-- { + currRound := beacon.MaxBeaconRoundForEpoch(nv, currEpoch) + rch := beacon.Entry(ctx, currRound) select { case resp := <-rch: if resp.Err != nil { @@ -143,7 +153,6 @@ func BeaconEntriesForBlock(ctx context.Context, bSchedule Schedule, nv network.V } out = append(out, resp.Entry) - cur = resp.Entry.Round - 1 case <-ctx.Done(): return nil, xerrors.Errorf("context timed out waiting on beacon entry to come back for epoch %d: %w", epoch, ctx.Err()) } diff --git a/chain/beacon/drand/drand.go b/chain/beacon/drand/drand.go index 5825fa691..1b78daadd 100644 --- a/chain/beacon/drand/drand.go +++ b/chain/beacon/drand/drand.go @@ -170,10 +170,6 @@ func (db *DrandBeacon) VerifyEntry(curr types.BeaconEntry, prev types.BeaconEntr return nil } - if curr.Round != prev.Round+1 { - return xerrors.Errorf("invalid beacon entry: cur (%d) != prev (%d) + 1", curr.Round, prev.Round) - } - if be := db.getCachedValue(curr.Round); be != nil { if !bytes.Equal(curr.Data, be.Data) { return xerrors.New("invalid beacon value, does not match cached good value") @@ -190,7 +186,8 @@ func (db *DrandBeacon) VerifyEntry(curr types.BeaconEntry, prev types.BeaconEntr if err == nil { db.cacheValue(curr) } - return err + + return nil } func (db *DrandBeacon) MaxBeaconRoundForEpoch(nv network.Version, filEpoch abi.ChainEpoch) uint64 { diff --git a/chain/sync.go b/chain/sync.go index 4dccc2036..ded6ab1b5 100644 --- a/chain/sync.go +++ b/chain/sync.go @@ -704,25 +704,25 @@ func (syncer *Syncer) collectHeaders(ctx context.Context, incoming *types.TipSet } { - // ensure consistency of beacon entires + // ensure consistency of beacon entries targetBE := incoming.Blocks()[0].BeaconEntries sorted := sort.SliceIsSorted(targetBE, func(i, j int) bool { return targetBE[i].Round < targetBE[j].Round }) if !sorted { - syncer.bad.Add(incoming.Cids()[0], NewBadBlockReason(incoming.Cids(), "wrong order of beacon entires")) - return nil, xerrors.Errorf("wrong order of beacon entires") + syncer.bad.Add(incoming.Cids()[0], NewBadBlockReason(incoming.Cids(), "wrong order of beacon entries")) + return nil, xerrors.Errorf("wrong order of beacon entries") } for _, bh := range incoming.Blocks()[1:] { if len(targetBE) != len(bh.BeaconEntries) { // cannot mark bad, I think @Kubuxu - return nil, xerrors.Errorf("tipset contained different number for beacon entires") + return nil, xerrors.Errorf("tipset contained different number for beacon entries") } for i, be := range bh.BeaconEntries { if targetBE[i].Round != be.Round || !bytes.Equal(targetBE[i].Data, be.Data) { // cannot mark bad, I think @Kubuxu - return nil, xerrors.Errorf("tipset contained different beacon entires") + return nil, xerrors.Errorf("tipset contained different beacon entries") } }