Skip to content

Commit 3296fa7

Browse files
Merge branch 'development' into eclesio/update-mock-checks
2 parents d5810bb + 3ab76bc commit 3296fa7

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+3493
-1442
lines changed

dot/core/service.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ import (
2222
"github.com/ChainSafe/gossamer/lib/runtime/wasmer"
2323
"github.com/ChainSafe/gossamer/lib/services"
2424
"github.com/ChainSafe/gossamer/lib/transaction"
25-
cscale "github.com/centrifuge/go-substrate-rpc-client/v3/scale"
26-
ctypes "github.com/centrifuge/go-substrate-rpc-client/v3/types"
25+
cscale "github.com/centrifuge/go-substrate-rpc-client/v4/scale"
26+
ctypes "github.com/centrifuge/go-substrate-rpc-client/v4/types"
2727
)
2828

2929
var (

dot/digest/digest.go

Lines changed: 79 additions & 223 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ var (
1818
_ services.Service = &Handler{}
1919
)
2020

21+
var (
22+
ErrUnknownConsensusEngineID = errors.New("unknown consensus engine ID")
23+
)
24+
2125
// Handler is used to handle consensus messages and relevant authority updates to BABE and GRANDPA
2226
type Handler struct {
2327
ctx context.Context
@@ -32,28 +36,9 @@ type Handler struct {
3236
imported chan *types.Block
3337
finalised chan *types.FinalisationInfo
3438

35-
// GRANDPA changes
36-
grandpaScheduledChange *grandpaChange
37-
grandpaForcedChange *grandpaChange
38-
grandpaPause *pause
39-
grandpaResume *resume
40-
4139
logger log.LeveledLogger
4240
}
4341

44-
type grandpaChange struct {
45-
auths []types.Authority
46-
atBlock uint
47-
}
48-
49-
type pause struct {
50-
atBlock uint
51-
}
52-
53-
type resume struct {
54-
atBlock uint
55-
}
56-
5742
// NewHandler returns a new Handler
5843
func NewHandler(lvl log.Level, blockState BlockState, epochState EpochState,
5944
grandpaState GrandpaState) (*Handler, error) {
@@ -91,44 +76,80 @@ func (h *Handler) Stop() error {
9176
return nil
9277
}
9378

94-
// NextGrandpaAuthorityChange returns the block number of the next upcoming grandpa authorities change.
95-
// It returns 0 if no change is scheduled.
96-
func (h *Handler) NextGrandpaAuthorityChange() (next uint) {
97-
next = ^uint(0)
98-
99-
if h.grandpaScheduledChange != nil {
100-
next = h.grandpaScheduledChange.atBlock
79+
// HandleDigests handles consensus digests for an imported block
80+
func (h *Handler) HandleDigests(header *types.Header) error {
81+
consensusDigests := h.toConsensusDigests(header.Digest.Types)
82+
consensusDigests, err := checkForGRANDPAForcedChanges(consensusDigests)
83+
if err != nil {
84+
return fmt.Errorf("failed while checking GRANDPA digests: %w", err)
10185
}
10286

103-
if h.grandpaForcedChange != nil && h.grandpaForcedChange.atBlock < next {
104-
next = h.grandpaForcedChange.atBlock
87+
for i := range consensusDigests {
88+
// avoiding implicit memory aliasing in for loop, since:
89+
// for _, digest := range consensusDigests { &digest }
90+
// is using the address of a loop variable
91+
digest := consensusDigests[i]
92+
err := h.handleConsensusDigest(&digest, header)
93+
if err != nil {
94+
h.logger.Errorf("cannot handle consensus digest: %w", err)
95+
}
10596
}
10697

107-
if h.grandpaPause != nil && h.grandpaPause.atBlock < next {
108-
next = h.grandpaPause.atBlock
109-
}
98+
return nil
99+
}
100+
101+
// toConsensusDigests converts a slice of scale.VaryingDataType to a slice of types.ConsensusDigest.
102+
func (h *Handler) toConsensusDigests(scaleVaryingTypes []scale.VaryingDataType) []types.ConsensusDigest {
103+
consensusDigests := make([]types.ConsensusDigest, 0, len(scaleVaryingTypes))
104+
105+
for _, d := range scaleVaryingTypes {
106+
digest, ok := d.Value().(types.ConsensusDigest)
107+
if !ok {
108+
h.logger.Debugf("digest type not supported: %T", d.Value())
109+
continue
110+
}
110111

111-
if h.grandpaResume != nil && h.grandpaResume.atBlock < next {
112-
next = h.grandpaResume.atBlock
112+
switch digest.ConsensusEngineID {
113+
case types.GrandpaEngineID, types.BabeEngineID:
114+
consensusDigests = append(consensusDigests, digest)
115+
}
113116
}
114117

115-
return next
118+
return consensusDigests
116119
}
117120

118-
// HandleDigests handles consensus digests for an imported block
119-
func (h *Handler) HandleDigests(header *types.Header) {
120-
for i, d := range header.Digest.Types {
121-
val, ok := d.Value().(types.ConsensusDigest)
122-
if !ok {
121+
// checkForGRANDPAForcedChanges removes any GrandpaScheduledChange in the presence of a
122+
// GrandpaForcedChange in the same block digest, returning a new slice of types.ConsensusDigest
123+
func checkForGRANDPAForcedChanges(digests []types.ConsensusDigest) ([]types.ConsensusDigest, error) {
124+
var hasForcedChange bool
125+
digestsWithoutScheduled := make([]types.ConsensusDigest, 0, len(digests))
126+
for _, digest := range digests {
127+
if digest.ConsensusEngineID != types.GrandpaEngineID {
128+
digestsWithoutScheduled = append(digestsWithoutScheduled, digest)
123129
continue
124130
}
125131

126-
err := h.handleConsensusDigest(&val, header)
132+
data := types.NewGrandpaConsensusDigest()
133+
err := scale.Unmarshal(digest.Data, &data)
127134
if err != nil {
128-
h.logger.Errorf("cannot handle digest for block number %d, index %d, digest %s: %s",
129-
header.Number, i, d.Value(), err)
135+
return nil, fmt.Errorf("cannot unmarshal GRANDPA consensus digest: %w", err)
136+
}
137+
138+
switch data.Value().(type) {
139+
case types.GrandpaScheduledChange:
140+
case types.GrandpaForcedChange:
141+
hasForcedChange = true
142+
digestsWithoutScheduled = append(digestsWithoutScheduled, digest)
143+
default:
144+
digestsWithoutScheduled = append(digestsWithoutScheduled, digest)
130145
}
131146
}
147+
148+
if hasForcedChange {
149+
return digestsWithoutScheduled, nil
150+
}
151+
152+
return digests, nil
132153
}
133154

134155
func (h *Handler) handleConsensusDigest(d *types.ConsensusDigest, header *types.Header) error {
@@ -139,42 +160,19 @@ func (h *Handler) handleConsensusDigest(d *types.ConsensusDigest, header *types.
139160
if err != nil {
140161
return err
141162
}
142-
err = h.handleGrandpaConsensusDigest(data, header)
143-
if err != nil {
144-
return err
145-
}
146-
return nil
163+
164+
return h.grandpaState.HandleGRANDPADigest(header, data)
147165
case types.BabeEngineID:
148166
data := types.NewBabeConsensusDigest()
149167
err := scale.Unmarshal(d.Data, &data)
150168
if err != nil {
151169
return err
152170
}
153-
err = h.handleBabeConsensusDigest(data, header)
154-
if err != nil {
155-
return err
156-
}
157-
return nil
158-
}
159-
160-
return errors.New("unknown consensus engine ID")
161-
}
162171

163-
func (h *Handler) handleGrandpaConsensusDigest(digest scale.VaryingDataType, header *types.Header) error {
164-
switch val := digest.Value().(type) {
165-
case types.GrandpaScheduledChange:
166-
return h.handleScheduledChange(val, header)
167-
case types.GrandpaForcedChange:
168-
return h.handleForcedChange(val, header)
169-
case types.GrandpaOnDisabled:
170-
return nil // do nothing, as this is not implemented in substrate
171-
case types.GrandpaPause:
172-
return h.handlePause(val)
173-
case types.GrandpaResume:
174-
return h.handleResume(val)
172+
return h.handleBabeConsensusDigest(data, header)
173+
default:
174+
return fmt.Errorf("%w: 0x%x", ErrUnknownConsensusEngineID, d.ConsensusEngineID.ToBytes())
175175
}
176-
177-
return errors.New("invalid consensus digest data")
178176
}
179177

180178
func (h *Handler) handleBabeConsensusDigest(digest scale.VaryingDataType, header *types.Header) error {
@@ -194,7 +192,7 @@ func (h *Handler) handleBabeConsensusDigest(digest scale.VaryingDataType, header
194192
return nil
195193

196194
case types.BABEOnDisabled:
197-
return h.handleBABEOnDisabled(val, header)
195+
return nil
198196

199197
case types.NextConfigData:
200198
currEpoch, err := h.epochState.GetEpochForBlock(header)
@@ -220,10 +218,14 @@ func (h *Handler) handleBlockImport(ctx context.Context) {
220218
continue
221219
}
222220

223-
h.HandleDigests(&block.Header)
224-
err := h.handleGrandpaChangesOnImport(block.Header.Number)
221+
err := h.HandleDigests(&block.Header)
225222
if err != nil {
226-
h.logger.Errorf("failed to handle grandpa changes on block import: %s", err)
223+
h.logger.Errorf("failed to handle digests: %s", err)
224+
}
225+
226+
err = h.grandpaState.ApplyForcedChanges(&block.Header)
227+
if err != nil {
228+
h.logger.Errorf("failed to apply forced changes: %s", err)
227229
}
228230
case <-ctx.Done():
229231
return
@@ -249,159 +251,13 @@ func (h *Handler) handleBlockFinalisation(ctx context.Context) {
249251
h.logger.Errorf("failed to persist babe next epoch config: %s", err)
250252
}
251253

252-
err = h.handleGrandpaChangesOnFinalization(info.Header.Number)
254+
err = h.grandpaState.ApplyScheduledChanges(&info.Header)
253255
if err != nil {
254-
h.logger.Errorf("failed to handle grandpa changes on block finalisation: %s", err)
256+
h.logger.Errorf("failed to apply scheduled change: %s", err)
255257
}
258+
256259
case <-ctx.Done():
257260
return
258261
}
259262
}
260263
}
261-
262-
func (h *Handler) handleGrandpaChangesOnImport(num uint) error {
263-
resume := h.grandpaResume
264-
if resume != nil && num >= resume.atBlock {
265-
h.grandpaResume = nil
266-
}
267-
268-
fc := h.grandpaForcedChange
269-
if fc != nil && num >= fc.atBlock {
270-
curr, err := h.grandpaState.IncrementSetID()
271-
if err != nil {
272-
return err
273-
}
274-
275-
h.grandpaForcedChange = nil
276-
h.logger.Debugf("incremented grandpa set id %d", curr)
277-
}
278-
279-
return nil
280-
}
281-
282-
func (h *Handler) handleGrandpaChangesOnFinalization(num uint) error {
283-
pause := h.grandpaPause
284-
if pause != nil && num >= pause.atBlock {
285-
h.grandpaPause = nil
286-
}
287-
288-
sc := h.grandpaScheduledChange
289-
if sc != nil && num >= sc.atBlock {
290-
curr, err := h.grandpaState.IncrementSetID()
291-
if err != nil {
292-
return err
293-
}
294-
295-
h.grandpaScheduledChange = nil
296-
h.logger.Debugf("incremented grandpa set id %d", curr)
297-
}
298-
299-
// if blocks get finalised before forced change takes place, disregard it
300-
h.grandpaForcedChange = nil
301-
return nil
302-
}
303-
304-
func (h *Handler) handleScheduledChange(sc types.GrandpaScheduledChange, header *types.Header) error {
305-
curr, err := h.blockState.BestBlockHeader()
306-
if err != nil {
307-
return err
308-
}
309-
310-
if h.grandpaScheduledChange != nil {
311-
return nil
312-
}
313-
314-
h.logger.Debugf("handling GrandpaScheduledChange data: %v", sc)
315-
316-
c, err := newGrandpaChange(sc.Auths, sc.Delay, curr.Number)
317-
if err != nil {
318-
return err
319-
}
320-
321-
h.grandpaScheduledChange = c
322-
323-
auths, err := types.GrandpaAuthoritiesRawToAuthorities(sc.Auths)
324-
if err != nil {
325-
return err
326-
}
327-
h.logger.Debugf("setting GrandpaScheduledChange at block %d",
328-
header.Number+uint(sc.Delay))
329-
return h.grandpaState.SetNextChange(
330-
types.NewGrandpaVotersFromAuthorities(auths),
331-
header.Number+uint(sc.Delay),
332-
)
333-
}
334-
335-
func (h *Handler) handleForcedChange(fc types.GrandpaForcedChange, header *types.Header) error {
336-
if header == nil {
337-
return errors.New("header is nil")
338-
}
339-
340-
if h.grandpaForcedChange != nil {
341-
return errors.New("already have forced change scheduled")
342-
}
343-
344-
h.logger.Debugf("handling GrandpaForcedChange with data %v", fc)
345-
346-
c, err := newGrandpaChange(fc.Auths, fc.Delay, header.Number)
347-
if err != nil {
348-
return err
349-
}
350-
351-
h.grandpaForcedChange = c
352-
353-
auths, err := types.GrandpaAuthoritiesRawToAuthorities(fc.Auths)
354-
if err != nil {
355-
return err
356-
}
357-
358-
h.logger.Debugf("setting GrandpaForcedChange at block %d",
359-
header.Number+uint(fc.Delay))
360-
return h.grandpaState.SetNextChange(
361-
types.NewGrandpaVotersFromAuthorities(auths),
362-
header.Number+uint(fc.Delay),
363-
)
364-
}
365-
366-
func (h *Handler) handlePause(p types.GrandpaPause) error {
367-
curr, err := h.blockState.BestBlockHeader()
368-
if err != nil {
369-
return err
370-
}
371-
372-
h.grandpaPause = &pause{
373-
atBlock: curr.Number + uint(p.Delay),
374-
}
375-
376-
return h.grandpaState.SetNextPause(h.grandpaPause.atBlock)
377-
}
378-
379-
func (h *Handler) handleResume(r types.GrandpaResume) error {
380-
curr, err := h.blockState.BestBlockHeader()
381-
if err != nil {
382-
return err
383-
}
384-
385-
h.grandpaResume = &resume{
386-
atBlock: curr.Number + uint(r.Delay),
387-
}
388-
389-
return h.grandpaState.SetNextResume(h.grandpaResume.atBlock)
390-
}
391-
392-
func newGrandpaChange(raw []types.GrandpaAuthoritiesRaw, delay uint32, currBlock uint) (*grandpaChange, error) {
393-
auths, err := types.GrandpaAuthoritiesRawToAuthorities(raw)
394-
if err != nil {
395-
return nil, err
396-
}
397-
398-
return &grandpaChange{
399-
auths: auths,
400-
atBlock: currBlock + uint(delay),
401-
}, nil
402-
}
403-
404-
func (h *Handler) handleBABEOnDisabled(_ types.BABEOnDisabled, _ *types.Header) error {
405-
h.logger.Debug("handling BABEOnDisabled")
406-
return nil
407-
}

0 commit comments

Comments
 (0)