@@ -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
240251func 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