Merge pull request #11632 from hanabi1224/hm/drand-test
feat: drand quicknet: allow scheduling drand quicknet upgrade before nv22 on 2k devnet
This commit is contained in:
parent
fc6229abf7
commit
f2bca588b2
@ -10,8 +10,8 @@ type DrandEnum int
|
|||||||
|
|
||||||
func DrandConfigSchedule() dtypes.DrandSchedule {
|
func DrandConfigSchedule() dtypes.DrandSchedule {
|
||||||
out := dtypes.DrandSchedule{}
|
out := dtypes.DrandSchedule{}
|
||||||
for start, config := range DrandSchedule {
|
for start, network := range DrandSchedule {
|
||||||
out = append(out, dtypes.DrandPoint{Start: start, Config: DrandConfigs[config]})
|
out = append(out, dtypes.DrandPoint{Start: start, Config: DrandConfigs[network]})
|
||||||
}
|
}
|
||||||
|
|
||||||
sort.Slice(out, func(i, j int) bool {
|
sort.Slice(out, func(i, j int) bool {
|
||||||
@ -44,6 +44,7 @@ var DrandConfigs = map[DrandEnum]dtypes.DrandConfig{
|
|||||||
"/dnsaddr/api2.drand.sh/",
|
"/dnsaddr/api2.drand.sh/",
|
||||||
"/dnsaddr/api3.drand.sh/",
|
"/dnsaddr/api3.drand.sh/",
|
||||||
},
|
},
|
||||||
|
IsChained: true,
|
||||||
ChainInfoJSON: `{"public_key":"868f005eb8e6e4ca0a47c8a77ceaa5309a47978a7c71bc5cce96366b5d7a569937c529eeda66c7293784a9402801af31","period":30,"genesis_time":1595431050,"hash":"8990e7a9aaed2ffed73dbd7092123d6f289930540d7651336225dc172e51b2ce","groupHash":"176f93498eac9ca337150b46d21dd58673ea4e3581185f869672e59fa4cb390a"}`,
|
ChainInfoJSON: `{"public_key":"868f005eb8e6e4ca0a47c8a77ceaa5309a47978a7c71bc5cce96366b5d7a569937c529eeda66c7293784a9402801af31","period":30,"genesis_time":1595431050,"hash":"8990e7a9aaed2ffed73dbd7092123d6f289930540d7651336225dc172e51b2ce","groupHash":"176f93498eac9ca337150b46d21dd58673ea4e3581185f869672e59fa4cb390a"}`,
|
||||||
},
|
},
|
||||||
DrandQuicknet: {
|
DrandQuicknet: {
|
||||||
@ -59,6 +60,7 @@ var DrandConfigs = map[DrandEnum]dtypes.DrandConfig{
|
|||||||
"/dnsaddr/api2.drand.sh/",
|
"/dnsaddr/api2.drand.sh/",
|
||||||
"/dnsaddr/api3.drand.sh/",
|
"/dnsaddr/api3.drand.sh/",
|
||||||
},
|
},
|
||||||
|
IsChained: false,
|
||||||
ChainInfoJSON: `{"public_key":"83cf0f2896adee7eb8b5f01fcad3912212c437e0073e911fb90022d3e760183c8c4b450b6a0a6c3ac6a5776a2d1064510d1fec758c921cc22b0e17e63aaf4bcb5ed66304de9cf809bd274ca73bab4af5a6e9c76a4bc09e76eae8991ef5ece45a","period":3,"genesis_time":1692803367,"hash":"52db9ba70e0cc0f6eaf7803dd07447a1f5477735fd3f661792ba94600c84e971","groupHash":"f477d5c89f21a17c863a7f937c6a6d15859414d2be09cd448d4279af331c5d3e","schemeID":"bls-unchained-g1-rfc9380","metadata":{"beaconID":"quicknet"}}`,
|
ChainInfoJSON: `{"public_key":"83cf0f2896adee7eb8b5f01fcad3912212c437e0073e911fb90022d3e760183c8c4b450b6a0a6c3ac6a5776a2d1064510d1fec758c921cc22b0e17e63aaf4bcb5ed66304de9cf809bd274ca73bab4af5a6e9c76a4bc09e76eae8991ef5ece45a","period":3,"genesis_time":1692803367,"hash":"52db9ba70e0cc0f6eaf7803dd07447a1f5477735fd3f661792ba94600c84e971","groupHash":"f477d5c89f21a17c863a7f937c6a6d15859414d2be09cd448d4279af331c5d3e","schemeID":"bls-unchained-g1-rfc9380","metadata":{"beaconID":"quicknet"}}`,
|
||||||
},
|
},
|
||||||
DrandTestnet: {
|
DrandTestnet: {
|
||||||
@ -72,6 +74,7 @@ var DrandConfigs = map[DrandEnum]dtypes.DrandConfig{
|
|||||||
"/dnsaddr/pl-us.testnet.drand.sh/",
|
"/dnsaddr/pl-us.testnet.drand.sh/",
|
||||||
"/dnsaddr/pl-sin.testnet.drand.sh/",
|
"/dnsaddr/pl-sin.testnet.drand.sh/",
|
||||||
},
|
},
|
||||||
|
IsChained: true,
|
||||||
ChainInfoJSON: `{"public_key":"922a2e93828ff83345bae533f5172669a26c02dc76d6bf59c80892e12ab1455c229211886f35bb56af6d5bea981024df","period":25,"genesis_time":1590445175,"hash":"84b2234fb34e835dccd048255d7ad3194b81af7d978c3bf157e3469592ae4e02","groupHash":"4dd408e5fdff9323c76a9b6f087ba8fdc5a6da907bd9217d9d10f2287d081957"}`,
|
ChainInfoJSON: `{"public_key":"922a2e93828ff83345bae533f5172669a26c02dc76d6bf59c80892e12ab1455c229211886f35bb56af6d5bea981024df","period":25,"genesis_time":1590445175,"hash":"84b2234fb34e835dccd048255d7ad3194b81af7d978c3bf157e3469592ae4e02","groupHash":"4dd408e5fdff9323c76a9b6f087ba8fdc5a6da907bd9217d9d10f2287d081957"}`,
|
||||||
},
|
},
|
||||||
DrandDevnet: {
|
DrandDevnet: {
|
||||||
@ -83,9 +86,11 @@ var DrandConfigs = map[DrandEnum]dtypes.DrandConfig{
|
|||||||
"/dnsaddr/dev1.drand.sh/",
|
"/dnsaddr/dev1.drand.sh/",
|
||||||
"/dnsaddr/dev2.drand.sh/",
|
"/dnsaddr/dev2.drand.sh/",
|
||||||
},
|
},
|
||||||
|
IsChained: true,
|
||||||
ChainInfoJSON: `{"public_key":"8cda589f88914aa728fd183f383980b35789ce81b274e5daee1f338b77d02566ef4d3fb0098af1f844f10f9c803c1827","period":25,"genesis_time":1595348225,"hash":"e73b7dc3c4f6a236378220c0dd6aa110eb16eed26c11259606e07ee122838d4f","groupHash":"567d4785122a5a3e75a9bc9911d7ea807dd85ff76b78dc4ff06b075712898607"}`,
|
ChainInfoJSON: `{"public_key":"8cda589f88914aa728fd183f383980b35789ce81b274e5daee1f338b77d02566ef4d3fb0098af1f844f10f9c803c1827","period":25,"genesis_time":1595348225,"hash":"e73b7dc3c4f6a236378220c0dd6aa110eb16eed26c11259606e07ee122838d4f","groupHash":"567d4785122a5a3e75a9bc9911d7ea807dd85ff76b78dc4ff06b075712898607"}`,
|
||||||
},
|
},
|
||||||
DrandIncentinet: {
|
DrandIncentinet: {
|
||||||
|
IsChained: true,
|
||||||
ChainInfoJSON: `{"public_key":"8cad0c72c606ab27d36ee06de1d5b2db1faf92e447025ca37575ab3a8aac2eaae83192f846fc9e158bc738423753d000","period":30,"genesis_time":1595873820,"hash":"80c8b872c714f4c00fdd3daa465d5514049f457f01f85a4caf68cdcd394ba039","groupHash":"d9406aaed487f7af71851b4399448e311f2328923d454e971536c05398ce2d9b"}`,
|
ChainInfoJSON: `{"public_key":"8cad0c72c606ab27d36ee06de1d5b2db1faf92e447025ca37575ab3a8aac2eaae83192f846fc9e158bc738423753d000","period":30,"genesis_time":1595873820,"hash":"80c8b872c714f4c00fdd3daa465d5514049f457f01f85a4caf68cdcd394ba039","groupHash":"d9406aaed487f7af71851b4399448e311f2328923d454e971536c05398ce2d9b"}`,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ var NetworkBundle = "devnet"
|
|||||||
var BundleOverrides map[actorstypes.Version]string
|
var BundleOverrides map[actorstypes.Version]string
|
||||||
var ActorDebugging = true
|
var ActorDebugging = true
|
||||||
|
|
||||||
const GenesisNetworkVersion = network.Version21
|
var GenesisNetworkVersion = network.Version21
|
||||||
|
|
||||||
var UpgradeBreezeHeight = abi.ChainEpoch(-1)
|
var UpgradeBreezeHeight = abi.ChainEpoch(-1)
|
||||||
|
|
||||||
@ -96,6 +96,22 @@ func init() {
|
|||||||
policy.SetMinVerifiedDealSize(MinVerifiedDealSize)
|
policy.SetMinVerifiedDealSize(MinVerifiedDealSize)
|
||||||
policy.SetPreCommitChallengeDelay(PreCommitChallengeDelay)
|
policy.SetPreCommitChallengeDelay(PreCommitChallengeDelay)
|
||||||
|
|
||||||
|
getGenesisNetworkVersion := func(ev string, def network.Version) network.Version {
|
||||||
|
hs, found := os.LookupEnv(ev)
|
||||||
|
if found {
|
||||||
|
h, err := strconv.Atoi(hs)
|
||||||
|
if err != nil {
|
||||||
|
log.Panicf("failed to parse %s env var", ev)
|
||||||
|
}
|
||||||
|
|
||||||
|
return network.Version(h)
|
||||||
|
}
|
||||||
|
|
||||||
|
return def
|
||||||
|
}
|
||||||
|
|
||||||
|
GenesisNetworkVersion = getGenesisNetworkVersion("LOTUS_GENESIS_NETWORK_VERSION", GenesisNetworkVersion)
|
||||||
|
|
||||||
getUpgradeHeight := func(ev string, def abi.ChainEpoch) abi.ChainEpoch {
|
getUpgradeHeight := func(ev string, def abi.ChainEpoch) abi.ChainEpoch {
|
||||||
hs, found := os.LookupEnv(ev)
|
hs, found := os.LookupEnv(ev)
|
||||||
if found {
|
if found {
|
||||||
@ -136,6 +152,12 @@ func init() {
|
|||||||
UpgradeWatermelonHeight = getUpgradeHeight("LOTUS_WATERMELON_HEIGHT", UpgradeWatermelonHeight)
|
UpgradeWatermelonHeight = getUpgradeHeight("LOTUS_WATERMELON_HEIGHT", UpgradeWatermelonHeight)
|
||||||
UpgradeDragonHeight = getUpgradeHeight("LOTUS_DRAGON_HEIGHT", UpgradeDragonHeight)
|
UpgradeDragonHeight = getUpgradeHeight("LOTUS_DRAGON_HEIGHT", UpgradeDragonHeight)
|
||||||
|
|
||||||
|
UpgradePhoenixHeight = getUpgradeHeight("LOTUS_PHOENIX_HEIGHT", UpgradePhoenixHeight)
|
||||||
|
DrandSchedule = map[abi.ChainEpoch]DrandEnum{
|
||||||
|
0: DrandMainnet,
|
||||||
|
UpgradePhoenixHeight: DrandQuicknet,
|
||||||
|
}
|
||||||
|
|
||||||
BuildType |= Build2k
|
BuildType |= Build2k
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -45,15 +45,16 @@ type RandomBeacon interface {
|
|||||||
Entry(context.Context, uint64) <-chan Response
|
Entry(context.Context, uint64) <-chan Response
|
||||||
VerifyEntry(entry types.BeaconEntry, prevEntrySig []byte) error
|
VerifyEntry(entry types.BeaconEntry, prevEntrySig []byte) error
|
||||||
MaxBeaconRoundForEpoch(network.Version, abi.ChainEpoch) uint64
|
MaxBeaconRoundForEpoch(network.Version, abi.ChainEpoch) uint64
|
||||||
|
IsChained() bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func ValidateBlockValues(bSchedule Schedule, nv network.Version, h *types.BlockHeader, parentEpoch abi.ChainEpoch,
|
func ValidateBlockValues(bSchedule Schedule, nv network.Version, h *types.BlockHeader, parentEpoch abi.ChainEpoch,
|
||||||
prevEntry types.BeaconEntry) error {
|
prevEntry types.BeaconEntry) error {
|
||||||
// Before nv22 we had "chained" beacons, and so required two entries at a fork
|
|
||||||
if nv < network.Version22 {
|
|
||||||
parentBeacon := bSchedule.BeaconForEpoch(parentEpoch)
|
parentBeacon := bSchedule.BeaconForEpoch(parentEpoch)
|
||||||
currBeacon := bSchedule.BeaconForEpoch(h.Height)
|
currBeacon := bSchedule.BeaconForEpoch(h.Height)
|
||||||
if parentBeacon != currBeacon {
|
// When we have "chained" beacons, two entries at a fork are required.
|
||||||
|
if parentBeacon != currBeacon && currBeacon.IsChained() {
|
||||||
if len(h.BeaconEntries) != 2 {
|
if len(h.BeaconEntries) != 2 {
|
||||||
return xerrors.Errorf("expected two beacon entries at beacon fork, got %d", len(h.BeaconEntries))
|
return xerrors.Errorf("expected two beacon entries at beacon fork, got %d", len(h.BeaconEntries))
|
||||||
}
|
}
|
||||||
@ -64,10 +65,8 @@ func ValidateBlockValues(bSchedule Schedule, nv network.Version, h *types.BlockH
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
b := bSchedule.BeaconForEpoch(h.Height)
|
maxRound := currBeacon.MaxBeaconRoundForEpoch(nv, h.Height)
|
||||||
maxRound := b.MaxBeaconRoundForEpoch(nv, h.Height)
|
|
||||||
// We don't expect to ever actually meet this condition
|
// We don't expect to ever actually meet this condition
|
||||||
if maxRound == prevEntry.Round {
|
if maxRound == prevEntry.Round {
|
||||||
if len(h.BeaconEntries) != 0 {
|
if len(h.BeaconEntries) != 0 {
|
||||||
@ -80,8 +79,8 @@ 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")
|
||||||
}
|
}
|
||||||
|
|
||||||
if nv < network.Version22 && prevEntry.Round == 0 {
|
// We skip verifying the genesis entry when randomness is "chained".
|
||||||
// We skip verifying the genesis entry before nv22, since that was "chained" randomness.
|
if currBeacon.IsChained() && prevEntry.Round == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,7 +91,7 @@ func ValidateBlockValues(bSchedule Schedule, nv network.Version, h *types.BlockH
|
|||||||
|
|
||||||
// Verify that all other entries' rounds are as expected for the epochs in between parentEpoch and h.Height
|
// Verify that all other entries' rounds are as expected for the epochs in between parentEpoch and h.Height
|
||||||
for i, e := range h.BeaconEntries {
|
for i, e := range h.BeaconEntries {
|
||||||
correctRound := b.MaxBeaconRoundForEpoch(nv, parentEpoch+abi.ChainEpoch(i)+1)
|
correctRound := currBeacon.MaxBeaconRoundForEpoch(nv, parentEpoch+abi.ChainEpoch(i)+1)
|
||||||
if e.Round != correctRound {
|
if e.Round != correctRound {
|
||||||
return xerrors.Errorf("unexpected beacon round %d, expected %d for epoch %d", e.Round, correctRound, parentEpoch+abi.ChainEpoch(i))
|
return xerrors.Errorf("unexpected beacon round %d, expected %d for epoch %d", e.Round, correctRound, parentEpoch+abi.ChainEpoch(i))
|
||||||
}
|
}
|
||||||
@ -100,7 +99,7 @@ func ValidateBlockValues(bSchedule Schedule, nv network.Version, h *types.BlockH
|
|||||||
|
|
||||||
// Verify the beacon entries themselves
|
// Verify the beacon entries themselves
|
||||||
for i, e := range h.BeaconEntries {
|
for i, e := range h.BeaconEntries {
|
||||||
if err := b.VerifyEntry(e, prevEntry.Data); err != nil {
|
if err := currBeacon.VerifyEntry(e, prevEntry.Data); 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)
|
||||||
}
|
}
|
||||||
prevEntry = e
|
prevEntry = e
|
||||||
@ -110,11 +109,10 @@ func ValidateBlockValues(bSchedule Schedule, nv network.Version, h *types.BlockH
|
|||||||
}
|
}
|
||||||
|
|
||||||
func BeaconEntriesForBlock(ctx context.Context, bSchedule Schedule, nv network.Version, epoch abi.ChainEpoch, parentEpoch abi.ChainEpoch, prev types.BeaconEntry) ([]types.BeaconEntry, error) {
|
func BeaconEntriesForBlock(ctx context.Context, bSchedule Schedule, nv network.Version, epoch abi.ChainEpoch, parentEpoch abi.ChainEpoch, prev types.BeaconEntry) ([]types.BeaconEntry, error) {
|
||||||
// Before nv22 we had "chained" beacons, and so required two entries at a fork
|
// When we have "chained" beacons, two entries at a fork are required.
|
||||||
if nv < network.Version22 {
|
|
||||||
parentBeacon := bSchedule.BeaconForEpoch(parentEpoch)
|
parentBeacon := bSchedule.BeaconForEpoch(parentEpoch)
|
||||||
currBeacon := bSchedule.BeaconForEpoch(epoch)
|
currBeacon := bSchedule.BeaconForEpoch(epoch)
|
||||||
if parentBeacon != currBeacon {
|
if parentBeacon != currBeacon && currBeacon.IsChained() {
|
||||||
// Fork logic
|
// Fork logic
|
||||||
round := currBeacon.MaxBeaconRoundForEpoch(nv, epoch)
|
round := currBeacon.MaxBeaconRoundForEpoch(nv, epoch)
|
||||||
out := make([]types.BeaconEntry, 2)
|
out := make([]types.BeaconEntry, 2)
|
||||||
@ -132,13 +130,10 @@ func BeaconEntriesForBlock(ctx context.Context, bSchedule Schedule, nv network.V
|
|||||||
out[1] = res.Entry
|
out[1] = res.Entry
|
||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
beacon := bSchedule.BeaconForEpoch(epoch)
|
|
||||||
|
|
||||||
start := build.Clock.Now()
|
start := build.Clock.Now()
|
||||||
|
|
||||||
maxRound := beacon.MaxBeaconRoundForEpoch(nv, epoch)
|
maxRound := currBeacon.MaxBeaconRoundForEpoch(nv, epoch)
|
||||||
// We don't expect this to ever be the case
|
// We don't expect this to ever be the case
|
||||||
if maxRound == prev.Round {
|
if maxRound == prev.Round {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
@ -151,8 +146,8 @@ func BeaconEntriesForBlock(ctx context.Context, bSchedule Schedule, nv network.V
|
|||||||
|
|
||||||
var out []types.BeaconEntry
|
var out []types.BeaconEntry
|
||||||
for currEpoch := epoch; currEpoch > parentEpoch; currEpoch-- {
|
for currEpoch := epoch; currEpoch > parentEpoch; currEpoch-- {
|
||||||
currRound := beacon.MaxBeaconRoundForEpoch(nv, currEpoch)
|
currRound := currBeacon.MaxBeaconRoundForEpoch(nv, currEpoch)
|
||||||
rch := beacon.Entry(ctx, currRound)
|
rch := currBeacon.Entry(ctx, currRound)
|
||||||
select {
|
select {
|
||||||
case resp := <-rch:
|
case resp := <-rch:
|
||||||
if resp.Err != nil {
|
if resp.Err != nil {
|
||||||
|
@ -37,6 +37,7 @@ var log = logging.Logger("drand")
|
|||||||
//
|
//
|
||||||
// The root trust for the Drand chain is configured from build.DrandChain.
|
// The root trust for the Drand chain is configured from build.DrandChain.
|
||||||
type DrandBeacon struct {
|
type DrandBeacon struct {
|
||||||
|
isChained bool
|
||||||
client dclient.Client
|
client dclient.Client
|
||||||
|
|
||||||
pubkey kyber.Point
|
pubkey kyber.Point
|
||||||
@ -52,6 +53,10 @@ type DrandBeacon struct {
|
|||||||
localCache *lru.Cache[uint64, *types.BeaconEntry]
|
localCache *lru.Cache[uint64, *types.BeaconEntry]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (db *DrandBeacon) IsChained() bool {
|
||||||
|
return db.isChained
|
||||||
|
}
|
||||||
|
|
||||||
// DrandHTTPClient interface overrides the user agent used by drand
|
// DrandHTTPClient interface overrides the user agent used by drand
|
||||||
type DrandHTTPClient interface {
|
type DrandHTTPClient interface {
|
||||||
SetUserAgent(string)
|
SetUserAgent(string)
|
||||||
@ -117,6 +122,7 @@ func NewDrandBeacon(genesisTs, interval uint64, ps *pubsub.PubSub, config dtypes
|
|||||||
}
|
}
|
||||||
|
|
||||||
db := &DrandBeacon{
|
db := &DrandBeacon{
|
||||||
|
isChained: config.IsChained,
|
||||||
client: client,
|
client: client,
|
||||||
localCache: lc,
|
localCache: lc,
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,15 @@ func TestMaxBeaconRoundForEpoch(t *testing.T) {
|
|||||||
todayTs := uint64(1652222222)
|
todayTs := uint64(1652222222)
|
||||||
db, err := NewDrandBeacon(todayTs, build.BlockDelaySecs, nil, build.DrandConfigs[build.DrandTestnet])
|
db, err := NewDrandBeacon(todayTs, build.BlockDelaySecs, nil, build.DrandConfigs[build.DrandTestnet])
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
assert.True(t, db.IsChained())
|
||||||
mbr15 := db.MaxBeaconRoundForEpoch(network.Version15, 100)
|
mbr15 := db.MaxBeaconRoundForEpoch(network.Version15, 100)
|
||||||
mbr16 := db.MaxBeaconRoundForEpoch(network.Version16, 100)
|
mbr16 := db.MaxBeaconRoundForEpoch(network.Version16, 100)
|
||||||
assert.Equal(t, mbr15+1, mbr16)
|
assert.Equal(t, mbr15+1, mbr16)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestQuicknetIsChained(t *testing.T) {
|
||||||
|
todayTs := uint64(1652222222)
|
||||||
|
db, err := NewDrandBeacon(todayTs, build.BlockDelaySecs, nil, build.DrandConfigs[build.DrandQuicknet])
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.False(t, db.IsChained())
|
||||||
|
}
|
||||||
|
@ -20,6 +20,10 @@ type mockBeacon struct {
|
|||||||
interval time.Duration
|
interval time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (mb *mockBeacon) IsChained() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func NewMockBeacon(interval time.Duration) RandomBeacon {
|
func NewMockBeacon(interval time.Duration) RandomBeacon {
|
||||||
mb := &mockBeacon{interval: interval}
|
mb := &mockBeacon{interval: interval}
|
||||||
|
|
||||||
|
@ -13,4 +13,5 @@ type DrandConfig struct {
|
|||||||
Servers []string
|
Servers []string
|
||||||
Relays []string
|
Relays []string
|
||||||
ChainInfoJSON string
|
ChainInfoJSON string
|
||||||
|
IsChained bool
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user