feat: drand: refactor round verification

This commit is contained in:
Aayush 2024-01-24 18:35:46 -05:00
parent 13248220a9
commit a967a36445
3 changed files with 20 additions and 14 deletions

View File

@ -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") 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] last := h.BeaconEntries[len(h.BeaconEntries)-1]
if last.Round != maxRound { if last.Round != maxRound {
return xerrors.Errorf("expected final beacon entry in block to be at round %d, got %d", maxRound, last.Round) 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 { for i, e := range h.BeaconEntries {
if err := b.VerifyEntry(e, prevEntry); err != nil { 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) 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 prev.Round = maxRound - 1
} }
cur := maxRound
var out []types.BeaconEntry var out []types.BeaconEntry
for cur > prev.Round { for currEpoch := epoch; currEpoch > parentEpoch; currEpoch-- {
rch := beacon.Entry(ctx, cur) currRound := beacon.MaxBeaconRoundForEpoch(nv, currEpoch)
rch := beacon.Entry(ctx, currRound)
select { select {
case resp := <-rch: case resp := <-rch:
if resp.Err != nil { if resp.Err != nil {
@ -143,7 +153,6 @@ func BeaconEntriesForBlock(ctx context.Context, bSchedule Schedule, nv network.V
} }
out = append(out, resp.Entry) out = append(out, resp.Entry)
cur = resp.Entry.Round - 1
case <-ctx.Done(): case <-ctx.Done():
return nil, xerrors.Errorf("context timed out waiting on beacon entry to come back for epoch %d: %w", epoch, ctx.Err()) return nil, xerrors.Errorf("context timed out waiting on beacon entry to come back for epoch %d: %w", epoch, ctx.Err())
} }

View File

@ -170,10 +170,6 @@ func (db *DrandBeacon) VerifyEntry(curr types.BeaconEntry, prev types.BeaconEntr
return nil 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 be := db.getCachedValue(curr.Round); be != nil {
if !bytes.Equal(curr.Data, be.Data) { if !bytes.Equal(curr.Data, be.Data) {
return xerrors.New("invalid beacon value, does not match cached good value") 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 { if err == nil {
db.cacheValue(curr) db.cacheValue(curr)
} }
return err
return nil
} }
func (db *DrandBeacon) MaxBeaconRoundForEpoch(nv network.Version, filEpoch abi.ChainEpoch) uint64 { func (db *DrandBeacon) MaxBeaconRoundForEpoch(nv network.Version, filEpoch abi.ChainEpoch) uint64 {

View File

@ -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 targetBE := incoming.Blocks()[0].BeaconEntries
sorted := sort.SliceIsSorted(targetBE, func(i, j int) bool { sorted := sort.SliceIsSorted(targetBE, func(i, j int) bool {
return targetBE[i].Round < targetBE[j].Round return targetBE[i].Round < targetBE[j].Round
}) })
if !sorted { if !sorted {
syncer.bad.Add(incoming.Cids()[0], NewBadBlockReason(incoming.Cids(), "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 entires") return nil, xerrors.Errorf("wrong order of beacon entries")
} }
for _, bh := range incoming.Blocks()[1:] { for _, bh := range incoming.Blocks()[1:] {
if len(targetBE) != len(bh.BeaconEntries) { if len(targetBE) != len(bh.BeaconEntries) {
// cannot mark bad, I think @Kubuxu // 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 { for i, be := range bh.BeaconEntries {
if targetBE[i].Round != be.Round || !bytes.Equal(targetBE[i].Data, be.Data) { if targetBE[i].Round != be.Round || !bytes.Equal(targetBE[i].Data, be.Data) {
// cannot mark bad, I think @Kubuxu // cannot mark bad, I think @Kubuxu
return nil, xerrors.Errorf("tipset contained different beacon entires") return nil, xerrors.Errorf("tipset contained different beacon entries")
} }
} }