Skip to content

Commit 7613cdf

Browse files
committed
feat: implement FIP-0063
1 parent 9e03fca commit 7613cdf

13 files changed

+127
-95
lines changed

build/drand.go

+17
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ const (
2727
DrandDevnet
2828
DrandLocalnet
2929
DrandIncentinet
30+
DrandQuicknet
3031
)
3132

3233
var DrandConfigs = map[DrandEnum]dtypes.DrandConfig{
@@ -36,6 +37,7 @@ var DrandConfigs = map[DrandEnum]dtypes.DrandConfig{
3637
"https://api2.drand.sh",
3738
"https://api3.drand.sh",
3839
"https://drand.cloudflare.com",
40+
"https://api.drand.secureweb3.com:6875", // Storswift
3941
},
4042
Relays: []string{
4143
"/dnsaddr/api.drand.sh/",
@@ -44,6 +46,21 @@ var DrandConfigs = map[DrandEnum]dtypes.DrandConfig{
4446
},
4547
ChainInfoJSON: `{"public_key":"868f005eb8e6e4ca0a47c8a77ceaa5309a47978a7c71bc5cce96366b5d7a569937c529eeda66c7293784a9402801af31","period":30,"genesis_time":1595431050,"hash":"8990e7a9aaed2ffed73dbd7092123d6f289930540d7651336225dc172e51b2ce","groupHash":"176f93498eac9ca337150b46d21dd58673ea4e3581185f869672e59fa4cb390a"}`,
4648
},
49+
DrandQuicknet: {
50+
Servers: []string{
51+
"https://api.drand.sh",
52+
"https://api2.drand.sh",
53+
"https://api3.drand.sh",
54+
"https://drand.cloudflare.com",
55+
"https://api.drand.secureweb3.com:6875", // Storswift
56+
},
57+
Relays: []string{
58+
"/dnsaddr/api.drand.sh/",
59+
"/dnsaddr/api2.drand.sh/",
60+
"/dnsaddr/api3.drand.sh/",
61+
},
62+
ChainInfoJSON: `{"public_key":"83cf0f2896adee7eb8b5f01fcad3912212c437e0073e911fb90022d3e760183c8c4b450b6a0a6c3ac6a5776a2d1064510d1fec758c921cc22b0e17e63aaf4bcb5ed66304de9cf809bd274ca73bab4af5a6e9c76a4bc09e76eae8991ef5ece45a","period":3,"genesis_time":1692803367,"hash":"52db9ba70e0cc0f6eaf7803dd07447a1f5477735fd3f661792ba94600c84e971","groupHash":"f477d5c89f21a17c863a7f937c6a6d15859414d2be09cd448d4279af331c5d3e","schemeID":"bls-unchained-g1-rfc9380","metadata":{"beaconID":"quicknet"}}`,
63+
},
4764
DrandTestnet: {
4865
Servers: []string{
4966
"https://pl-eu.testnet.drand.sh",

build/params_2k.go

+5-2
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,9 @@ var UpgradeThunderHeight = abi.ChainEpoch(-23)
6767

6868
var UpgradeWatermelonHeight = abi.ChainEpoch(-24)
6969

70-
var UpgradePineappleHeight = abi.ChainEpoch(200)
70+
var UpgradePineappleHeight = abi.ChainEpoch(20)
71+
72+
var UpgradeMangoHeight = UpgradePineappleHeight + 10
7173

7274
// This fix upgrade only ran on calibrationnet
7375
const UpgradeWatermelonFixHeight = -100
@@ -76,7 +78,8 @@ const UpgradeWatermelonFixHeight = -100
7678
const UpgradeWatermelonFix2Height = -101
7779

7880
var DrandSchedule = map[abi.ChainEpoch]DrandEnum{
79-
0: DrandMainnet,
81+
0: DrandMainnet,
82+
UpgradeMangoHeight: DrandQuicknet,
8083
}
8184

8285
var SupportedProofTypes = []abi.RegisteredSealProof{

build/params_butterfly.go

+4-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ import (
1616
)
1717

1818
var DrandSchedule = map[abi.ChainEpoch]DrandEnum{
19-
0: DrandMainnet,
19+
0: DrandMainnet,
20+
UpgradeMangoHeight: DrandQuicknet,
2021
}
2122

2223
const GenesisNetworkVersion = network.Version20
@@ -59,6 +60,8 @@ const UpgradeWatermelonHeight = -24
5960
// ??????
6061
const UpgradePineappleHeight = 999999999999999
6162

63+
const UpgradeMangoHeight = UpgradePineappleHeight + 10
64+
6265
// This fix upgrade only ran on calibrationnet
6366
const UpgradeWatermelonFixHeight = -100
6467

build/params_calibnet.go

+4-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ import (
1919
)
2020

2121
var DrandSchedule = map[abi.ChainEpoch]DrandEnum{
22-
0: DrandMainnet,
22+
0: DrandMainnet,
23+
UpgradeMangoHeight: DrandQuicknet,
2324
}
2425

2526
const GenesisNetworkVersion = network.Version0
@@ -91,6 +92,8 @@ const UpgradeWatermelonFix2Height = 1108174
9192
// ??????
9293
const UpgradePineappleHeight = 999999999999999
9394

95+
const UpgradeMangoHeight = UpgradePineappleHeight + 10
96+
9497
var SupportedProofTypes = []abi.RegisteredSealProof{
9598
abi.RegisteredSealProof_StackedDrg32GiBV1,
9699
abi.RegisteredSealProof_StackedDrg64GiBV1,

build/params_interop.go

+4-1
Original file line numberDiff line numberDiff line change
@@ -57,14 +57,17 @@ var UpgradeWatermelonHeight = abi.ChainEpoch(-24)
5757

5858
const UpgradePineappleHeight = 50
5959

60+
const UpgradeMangoHeight = UpgradePineappleHeight + 10
61+
6062
// This fix upgrade only ran on calibrationnet
6163
const UpgradeWatermelonFixHeight = -1
6264

6365
// This fix upgrade only ran on calibrationnet
6466
const UpgradeWatermelonFix2Height = -2
6567

6668
var DrandSchedule = map[abi.ChainEpoch]DrandEnum{
67-
0: DrandMainnet,
69+
0: DrandMainnet,
70+
UpgradeMangoHeight: DrandQuicknet,
6871
}
6972

7073
var SupportedProofTypes = []abi.RegisteredSealProof{

build/params_mainnet.go

+7-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
var DrandSchedule = map[abi.ChainEpoch]DrandEnum{
1919
0: DrandIncentinet,
2020
UpgradeSmokeHeight: DrandMainnet,
21+
UpgradeMangoHeight: DrandQuicknet,
2122
}
2223

2324
var NetworkBundle = "mainnet"
@@ -101,6 +102,10 @@ const UpgradeWatermelonHeight = 3469380
101102
// ??????
102103
var UpgradePineappleHeight = abi.ChainEpoch(999999999999999)
103104

105+
// This epoch, 10 epochs after the "rest" of the nv22 upgrade, is when we switch to Drand quicknet
106+
// ??????
107+
var UpgradeMangoHeight = UpgradePineappleHeight + 10
108+
104109
// This fix upgrade only ran on calibrationnet
105110
const UpgradeWatermelonFixHeight = -1
106111

@@ -123,7 +128,8 @@ func init() {
123128
}
124129

125130
if os.Getenv("LOTUS_DISABLE_PINEAPPLE") == "1" {
126-
UpgradePineappleHeight = math.MaxInt64
131+
UpgradePineappleHeight = math.MaxInt64 - 1
132+
UpgradeMangoHeight = math.MaxInt64
127133
}
128134

129135
// NOTE: DO NOT change this unless you REALLY know what you're doing. This is not consensus critical, however,

build/params_testground.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -113,9 +113,11 @@ var (
113113
UpgradeWatermelonFixHeight abi.ChainEpoch = -24
114114
UpgradeWatermelonFix2Height abi.ChainEpoch = -25
115115
UpgradePineappleHeight abi.ChainEpoch = -26
116+
UpgradeMangoHeight abi.ChainEpoch = -27
116117

117118
DrandSchedule = map[abi.ChainEpoch]DrandEnum{
118-
0: DrandMainnet,
119+
0: DrandMainnet,
120+
UpgradeMangoHeight: DrandQuicknet,
119121
}
120122

121123
GenesisNetworkVersion = network.Version0

chain/beacon/beacon.go

+14-7
Original file line numberDiff line numberDiff line change
@@ -43,20 +43,21 @@ type BeaconPoint struct {
4343
// been posted on chain.
4444
type RandomBeacon interface {
4545
Entry(context.Context, uint64) <-chan Response
46-
VerifyEntry(types.BeaconEntry, types.BeaconEntry) error
46+
VerifyEntry(entry types.BeaconEntry, prevEntrySig []byte) error
4747
MaxBeaconRoundForEpoch(network.Version, abi.ChainEpoch) uint64
4848
}
4949

5050
func ValidateBlockValues(bSchedule Schedule, nv network.Version, h *types.BlockHeader, parentEpoch abi.ChainEpoch,
5151
prevEntry types.BeaconEntry) error {
52-
{
52+
// Before nv22 we had "chained" beacons, and so required two entries at a fork
53+
if nv < network.Version22 {
5354
parentBeacon := bSchedule.BeaconForEpoch(parentEpoch)
5455
currBeacon := bSchedule.BeaconForEpoch(h.Height)
5556
if parentBeacon != currBeacon {
5657
if len(h.BeaconEntries) != 2 {
5758
return xerrors.Errorf("expected two beacon entries at beacon fork, got %d", len(h.BeaconEntries))
5859
}
59-
err := currBeacon.VerifyEntry(h.BeaconEntries[1], h.BeaconEntries[0])
60+
err := currBeacon.VerifyEntry(h.BeaconEntries[1], h.BeaconEntries[0].Data)
6061
if err != nil {
6162
return xerrors.Errorf("beacon at fork point invalid: (%v, %v): %w",
6263
h.BeaconEntries[1], h.BeaconEntries[0], err)
@@ -65,9 +66,9 @@ func ValidateBlockValues(bSchedule Schedule, nv network.Version, h *types.BlockH
6566
}
6667
}
6768

68-
// TODO: fork logic
6969
b := bSchedule.BeaconForEpoch(h.Height)
7070
maxRound := b.MaxBeaconRoundForEpoch(nv, h.Height)
71+
// We don't expect to ever actually meet this condition
7172
if maxRound == prevEntry.Round {
7273
if len(h.BeaconEntries) != 0 {
7374
return xerrors.Errorf("expected not to have any beacon entries in this block, got %d", len(h.BeaconEntries))
@@ -79,7 +80,11 @@ func ValidateBlockValues(bSchedule Schedule, nv network.Version, h *types.BlockH
7980
return xerrors.Errorf("expected to have beacon entries in this block, but didn't find any")
8081
}
8182

82-
// Verify that the last beacon entry's round corresponds to the round we expect
83+
if nv < network.Version22 && prevEntry.Round == 0 {
84+
// We skip verifying the genesis entry before nv22, since that was "chained" randomness.
85+
return nil
86+
}
87+
8388
last := h.BeaconEntries[len(h.BeaconEntries)-1]
8489
if last.Round != maxRound {
8590
return xerrors.Errorf("expected final beacon entry in block to be at round %d, got %d", maxRound, last.Round)
@@ -95,7 +100,7 @@ func ValidateBlockValues(bSchedule Schedule, nv network.Version, h *types.BlockH
95100

96101
// Verify the beacon entries themselves
97102
for i, e := range h.BeaconEntries {
98-
if err := b.VerifyEntry(e, prevEntry); err != nil {
103+
if err := b.VerifyEntry(e, prevEntry.Data); err != nil {
99104
return xerrors.Errorf("beacon entry %d (%d - %x (%d)) was invalid: %w", i, e.Round, e.Data, len(e.Data), err)
100105
}
101106
prevEntry = e
@@ -105,7 +110,8 @@ func ValidateBlockValues(bSchedule Schedule, nv network.Version, h *types.BlockH
105110
}
106111

107112
func BeaconEntriesForBlock(ctx context.Context, bSchedule Schedule, nv network.Version, epoch abi.ChainEpoch, parentEpoch abi.ChainEpoch, prev types.BeaconEntry) ([]types.BeaconEntry, error) {
108-
{
113+
// Before nv22 we had "chained" beacons, and so required two entries at a fork
114+
if nv < network.Version22 {
109115
parentBeacon := bSchedule.BeaconForEpoch(parentEpoch)
110116
currBeacon := bSchedule.BeaconForEpoch(epoch)
111117
if parentBeacon != currBeacon {
@@ -133,6 +139,7 @@ func BeaconEntriesForBlock(ctx context.Context, bSchedule Schedule, nv network.V
133139
start := build.Clock.Now()
134140

135141
maxRound := beacon.MaxBeaconRoundForEpoch(nv, epoch)
142+
// We don't expect this to ever be the case
136143
if maxRound == prev.Round {
137144
return nil, nil
138145
}

chain/beacon/drand/drand.go

+23-15
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import (
88
dchain "github.com/drand/drand/chain"
99
dclient "github.com/drand/drand/client"
1010
hclient "github.com/drand/drand/client/http"
11-
"github.com/drand/drand/common/scheme"
11+
dcrypto "github.com/drand/drand/crypto"
1212
dlog "github.com/drand/drand/log"
1313
gclient "github.com/drand/drand/lp2p/client"
1414
"github.com/drand/kyber"
@@ -47,6 +47,7 @@ type DrandBeacon struct {
4747
drandGenTime uint64
4848
filGenTime uint64
4949
filRoundTime uint64
50+
scheme *dcrypto.Scheme
5051

5152
localCache *lru.Cache[uint64, *types.BeaconEntry]
5253
}
@@ -68,6 +69,10 @@ func (l *logger) Named(s string) dlog.Logger {
6869
return &logger{l.SugaredLogger.Named(s)}
6970
}
7071

72+
func (l *logger) AddCallerSkip(skip int) dlog.Logger {
73+
return &logger{l.SugaredLogger.With(zap.AddCallerSkip(skip))}
74+
}
75+
7176
func NewDrandBeacon(genesisTs, interval uint64, ps *pubsub.PubSub, config dtypes.DrandConfig) (*DrandBeacon, error) {
7277
if genesisTs == 0 {
7378
panic("what are you doing this cant be zero")
@@ -116,6 +121,11 @@ func NewDrandBeacon(genesisTs, interval uint64, ps *pubsub.PubSub, config dtypes
116121
localCache: lc,
117122
}
118123

124+
sch, err := dcrypto.GetSchemeByIDWithDefault(drandChain.Scheme)
125+
if err != nil {
126+
return nil, err
127+
}
128+
db.scheme = sch
119129
db.pubkey = drandChain.PublicKey
120130
db.interval = drandChain.Period
121131
db.drandGenTime = uint64(drandChain.GenesisTime)
@@ -164,29 +174,27 @@ func (db *DrandBeacon) getCachedValue(round uint64) *types.BeaconEntry {
164174
return v
165175
}
166176

167-
func (db *DrandBeacon) VerifyEntry(curr types.BeaconEntry, prev types.BeaconEntry) error {
168-
if prev.Round == 0 {
169-
// TODO handle genesis better
170-
return nil
171-
}
172-
173-
if be := db.getCachedValue(curr.Round); be != nil {
174-
if !bytes.Equal(curr.Data, be.Data) {
177+
func (db *DrandBeacon) VerifyEntry(entry types.BeaconEntry, prevEntrySig []byte) error {
178+
if be := db.getCachedValue(entry.Round); be != nil {
179+
if !bytes.Equal(entry.Data, be.Data) {
175180
return xerrors.New("invalid beacon value, does not match cached good value")
176181
}
177182
// return no error if the value is in the cache already
178183
return nil
179184
}
180185
b := &dchain.Beacon{
181-
PreviousSig: prev.Data,
182-
Round: curr.Round,
183-
Signature: curr.Data,
186+
PreviousSig: prevEntrySig,
187+
Round: entry.Round,
188+
Signature: entry.Data,
184189
}
185-
err := dchain.NewVerifier(scheme.GetSchemeFromEnv()).VerifyBeacon(*b, db.pubkey)
186-
if err == nil {
187-
db.cacheValue(curr)
190+
191+
err := db.scheme.VerifyBeacon(b, db.pubkey)
192+
if err != nil {
193+
return xerrors.Errorf("failed to verify beacon: %w", err)
188194
}
189195

196+
db.cacheValue(entry)
197+
190198
return nil
191199
}
192200

chain/beacon/mock.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ func (mb *mockBeacon) Entry(ctx context.Context, index uint64) <-chan Response {
4747
return out
4848
}
4949

50-
func (mb *mockBeacon) VerifyEntry(from types.BeaconEntry, to types.BeaconEntry) error {
50+
func (mb *mockBeacon) VerifyEntry(from types.BeaconEntry, _prevEntrySig []byte) error {
5151
// TODO: cache this, especially for bls
5252
oe := mb.entryForIndex(from.Round)
5353
if !bytes.Equal(from.Data, oe.Data) {

chain/consensus/filcns/filecoin.go

+1
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ func (filec *FilecoinEC) ValidateBlock(ctx context.Context, b *types.FullBlock)
129129
return xerrors.Errorf("failed to get lookback tipset for block: %w", err)
130130
}
131131

132+
// TODO: Optimization: See https://github.com/filecoin-project/lotus/issues/11597
132133
prevBeacon, err := filec.store.GetLatestBeaconEntry(ctx, baseTs)
133134
if err != nil {
134135
return xerrors.Errorf("failed to get latest beacon entry: %w", err)

0 commit comments

Comments
 (0)