Skip to content

Commit

Permalink
feat: drand: refactor round verification
Browse files Browse the repository at this point in the history
  • Loading branch information
arajasek committed Jan 25, 2024
1 parent 1324822 commit a967a36
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 14 deletions.
17 changes: 13 additions & 4 deletions chain/beacon/beacon.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -132,18 +142,17 @@ 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 {
return nil, xerrors.Errorf("beacon entry request returned error: %w", resp.Err)
}

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())
}
Expand Down
7 changes: 2 additions & 5 deletions chain/beacon/drand/drand.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand All @@ -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 {
Expand Down
10 changes: 5 additions & 5 deletions chain/sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
}
}

Expand Down

0 comments on commit a967a36

Please sign in to comment.