Skip to content

Commit 69d1a8b

Browse files
committed
fix(drand): add null HistoricalBeaconClient for old beacons
Fixes: #11802 Ref: #11802 (comment)
1 parent 97dc186 commit 69d1a8b

File tree

1 file changed

+42
-3
lines changed

1 file changed

+42
-3
lines changed

chain/beacon/drand/drand.go

+42-3
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,6 @@ func NewDrandBeacon(genesisTs, interval uint64, ps *pubsub.PubSub, config dtypes
100100
}
101101
hc.(DrandHTTPClient).SetUserAgent("drand-client-lotus/" + build.NodeBuildVersion)
102102
clients = append(clients, hc)
103-
104103
}
105104

106105
opts := []dclient.Option{
@@ -113,6 +112,18 @@ func NewDrandBeacon(genesisTs, interval uint64, ps *pubsub.PubSub, config dtypes
113112
opts = append(opts, gclient.WithPubsub(ps))
114113
} else {
115114
log.Info("drand beacon without pubsub")
115+
if len(clients) == 0 {
116+
// This hack is necessary to convince a drand beacon to start without any clients. For
117+
// historical becaons we need them to be able to verify old entries but we don't need to fetch
118+
// new ones. With pubsub enabled, it acts as a client so drand is happy, but if we don't have
119+
// pubsub then drand will complain about old beacons withotu clients. So we make one that
120+
// it'll think is a valid client and that it won't speed test (hence the need to mark it as
121+
// as "watcher").
122+
historicalClient := &historicalBeaconClient{}
123+
opts = append(opts, dclient.WithWatcher(func(chainInfo *dchain.Info, cache dclient.Cache) (dclient.Watcher, error) {
124+
return historicalClient, nil
125+
}))
126+
}
116127
}
117128

118129
client, err := dclient.Wrap(clients, opts...)
@@ -239,13 +250,41 @@ var _ beacon.RandomBeacon = (*DrandBeacon)(nil)
239250

240251
func BeaconScheduleFromDrandSchedule(dcs dtypes.DrandSchedule, genesisTime uint64, ps *pubsub.PubSub) (beacon.Schedule, error) {
241252
shd := beacon.Schedule{}
242-
for _, dc := range dcs {
253+
for i, dc := range dcs {
243254
bc, err := NewDrandBeacon(genesisTime, buildconstants.BlockDelaySecs, ps, dc.Config)
244255
if err != nil {
245-
return nil, xerrors.Errorf("creating drand beacon: %w", err)
256+
return nil, xerrors.Errorf("%d creating drand beacon: %w", i, err)
246257
}
247258
shd = append(shd, beacon.BeaconPoint{Start: dc.Start, Beacon: bc})
248259
}
249260

250261
return shd, nil
251262
}
263+
264+
var _ dclient.Client = historicalBeaconClient{}
265+
266+
// historicalBeaconClient is a drand client that doesn't actually do anything. It's used when
267+
// we don't have a drand network to connect to but still need to provide a beacon client.
268+
// We don't expect calls through to the client to be made since we should only be verifying old
269+
// randomness, not fetching it.
270+
type historicalBeaconClient struct{}
271+
272+
func (h historicalBeaconClient) Get(ctx context.Context, round uint64) (dclient.Result, error) {
273+
return nil, xerrors.Errorf("no historical randomness available")
274+
}
275+
276+
func (h historicalBeaconClient) Watch(ctx context.Context) <-chan dclient.Result {
277+
return nil
278+
}
279+
280+
func (h historicalBeaconClient) Info(ctx context.Context) (*dchain.Info, error) {
281+
return nil, xerrors.Errorf("no historical randomness available")
282+
}
283+
284+
func (h historicalBeaconClient) RoundAt(time.Time) uint64 {
285+
return 0
286+
}
287+
288+
func (h historicalBeaconClient) Close() error {
289+
return nil
290+
}

0 commit comments

Comments
 (0)