Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: drand: refactor round verification #11598

Merged
merged 1 commit into from
Jan 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 {
Stebalien marked this conversation as resolved.
Show resolved Hide resolved
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