Skip to content
Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
698cffa
pull changes
noot Apr 20, 2021
03651b8
add primary proposal sending
noot Apr 20, 2021
7a0f9b9
lint
noot Apr 20, 2021
9b3ae8e
fix decoding CommitMessage error
noot Apr 21, 2021
0cced87
readd code
noot Apr 21, 2021
45e67c6
create GrandpaState for managing authorities
noot Apr 21, 2021
0687988
begin updating DigestHandler to use GrandpaState
noot Apr 21, 2021
d81b5eb
fix some tests
noot Apr 22, 2021
864e231
merge w development
noot Apr 22, 2021
98cafe9
add go.mod
noot Apr 22, 2021
3f4310c
Merge branch 'development' of github.com:ChainSafe/gossamer into noot…
noot Apr 22, 2021
115faa5
Merge branch 'development' of github.com:ChainSafe/gossamer into noot…
noot Apr 22, 2021
0a1f6a5
move grandpa.Voter to types.GrandpaVoter
noot Apr 22, 2021
45d16fe
Merge branch 'noot/update-grandpa-messages' of github.com:ChainSafe/g…
noot Apr 22, 2021
04ebee8
update DigestHandler to set grandpaState
noot Apr 22, 2021
81b1886
fix tests, update DigestHandler
noot Apr 23, 2021
f6ef369
remove grandpa interface from core; update grandpa.Service to get nex…
noot Apr 23, 2021
7a90491
fix grandpa tests
noot Apr 23, 2021
4c96abf
cleanup, add tests
noot Apr 23, 2021
6ede432
cleanup
noot Apr 23, 2021
b96fd85
add grandpa pause, resume functionality
noot Apr 23, 2021
af5aa2e
merge w development
noot Apr 26, 2021
017222d
fix deepsource issue
noot Apr 26, 2021
71b4123
address comments
noot Apr 26, 2021
3d3f054
lint
noot Apr 26, 2021
971ea44
address comments
noot Apr 27, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
206 changes: 89 additions & 117 deletions dot/core/digest.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,11 @@ type DigestHandler struct {
cancel context.CancelFunc

// interfaces
blockState BlockState
epochState EpochState
grandpa FinalityGadget
babe BlockProducer
verifier Verifier
isFinalityAuthority bool
isBlockProducer bool
blockState BlockState
epochState EpochState
grandpaState GrandpaState
babe BlockProducer
verifier Verifier

// block notification channels
imported chan *types.Block
Expand All @@ -52,7 +50,6 @@ type DigestHandler struct {
grandpaForcedChange *grandpaChange
grandpaPause *pause
grandpaResume *resume
grandpaAuths []*types.Authority // saved in case of pause
}

type grandpaChange struct {
Expand All @@ -69,7 +66,7 @@ type resume struct {
}

// NewDigestHandler returns a new DigestHandler
func NewDigestHandler(blockState BlockState, epochState EpochState, babe BlockProducer, grandpa FinalityGadget, verifier Verifier) (*DigestHandler, error) {
func NewDigestHandler(blockState BlockState, epochState EpochState, grandpaState GrandpaState, babe BlockProducer, verifier Verifier) (*DigestHandler, error) {
imported := make(chan *types.Block, 16)
finalised := make(chan *types.Header, 16)
iid, err := blockState.RegisterImportedChannel(imported)
Expand All @@ -82,32 +79,27 @@ func NewDigestHandler(blockState BlockState, epochState EpochState, babe BlockPr
return nil, err
}

isFinalityAuthority := grandpa != nil
isBlockProducer := babe != nil

ctx, cancel := context.WithCancel(context.Background())

return &DigestHandler{
ctx: ctx,
cancel: cancel,
blockState: blockState,
epochState: epochState,
grandpa: grandpa,
babe: babe,
verifier: verifier,
isFinalityAuthority: isFinalityAuthority,
isBlockProducer: isBlockProducer,
imported: imported,
importedID: iid,
finalised: finalised,
finalisedID: fid,
ctx: ctx,
cancel: cancel,
blockState: blockState,
epochState: epochState,
grandpaState: grandpaState,
babe: babe,
verifier: verifier,
imported: imported,
importedID: iid,
finalised: finalised,
finalisedID: fid,
}, nil
}

// Start starts the DigestHandler
func (h *DigestHandler) Start() {
go h.handleBlockImport(h.ctx)
go h.handleBlockFinalization(h.ctx)
go h.handleBlockFinalisation(h.ctx)
}

// Stop stops the DigestHandler
Expand All @@ -119,11 +111,6 @@ func (h *DigestHandler) Stop() {
close(h.finalised)
}

// SetFinalityGadget sets the digest handler's grandpa instance
func (h *DigestHandler) SetFinalityGadget(grandpa FinalityGadget) {
h.grandpa = grandpa
}

// NextGrandpaAuthorityChange returns the block number of the next upcoming grandpa authorities change.
// It returns 0 if no change is scheduled.
func (h *DigestHandler) NextGrandpaAuthorityChange() uint64 {
Expand Down Expand Up @@ -155,11 +142,9 @@ func (h *DigestHandler) HandleConsensusDigest(d *types.ConsensusDigest, header *
if d.ConsensusEngineID == types.GrandpaEngineID {
switch t {
case types.GrandpaScheduledChangeType:
return h.handleScheduledChange(d)
return h.handleScheduledChange(d, header)
case types.GrandpaForcedChangeType:
return h.handleForcedChange(d)
case types.GrandpaOnDisabledType:
return h.handleGrandpaOnDisabled(d, header)
return h.handleForcedChange(d, header)
case types.GrandpaPauseType:
return h.handlePause(d)
case types.GrandpaResumeType:
Expand Down Expand Up @@ -193,163 +178,150 @@ func (h *DigestHandler) handleBlockImport(ctx context.Context) {
continue
}

if h.isFinalityAuthority {
h.handleGrandpaChangesOnImport(block.Header.Number)
err := h.handleGrandpaChangesOnImport(block.Header.Number)
if err != nil {
logger.Error("failed to handle grandpa changes on block import", "error", err)
}
case <-ctx.Done():
return
}
}
}

func (h *DigestHandler) handleBlockFinalization(ctx context.Context) {
func (h *DigestHandler) handleBlockFinalisation(ctx context.Context) {
for {
select {
case header := <-h.finalised:
if header == nil {
continue
}

if h.isFinalityAuthority {
h.handleGrandpaChangesOnFinalization(header.Number)
err := h.handleGrandpaChangesOnFinalization(header.Number)
if err != nil {
logger.Error("failed to handle grandpa changes on block finalisation", "error", err)
}

// TODO: check if there's a NextEpochData or NextConfigData digest, if there is,
// make sure it matches what's in the EpochState for the upcoming epoch
case <-ctx.Done():
return
}
}
}

func (h *DigestHandler) handleGrandpaChangesOnImport(num *big.Int) {
func (h *DigestHandler) handleGrandpaChangesOnImport(num *big.Int) error {
resume := h.grandpaResume
if resume != nil && num.Cmp(resume.atBlock) == 0 {
h.grandpa.UpdateAuthorities(h.grandpaAuths)
h.grandpaResume = nil
}

fc := h.grandpaForcedChange
if fc != nil && num.Cmp(fc.atBlock) == 0 {
h.grandpa.UpdateAuthorities(fc.auths)
err := h.grandpaState.IncrementSetID()
if err != nil {
return err
}

h.grandpaForcedChange = nil
}

return nil
}

func (h *DigestHandler) handleGrandpaChangesOnFinalization(num *big.Int) {
func (h *DigestHandler) handleGrandpaChangesOnFinalization(num *big.Int) error {
pause := h.grandpaPause
if pause != nil && num.Cmp(pause.atBlock) == 0 {
// save authority data for Resume
h.grandpaAuths = h.grandpa.Authorities()
h.grandpa.UpdateAuthorities([]*types.Authority{})
h.grandpaPause = nil
}

sc := h.grandpaScheduledChange
if sc != nil && num.Cmp(sc.atBlock) == 0 {
h.grandpa.UpdateAuthorities(sc.auths)
err := h.grandpaState.IncrementSetID()
if err != nil {
return err
}

h.grandpaScheduledChange = nil
}

// if blocks get finalised before forced change takes place, disregard it
h.grandpaForcedChange = nil
return nil
}

func (h *DigestHandler) handleScheduledChange(d *types.ConsensusDigest) error {
func (h *DigestHandler) handleScheduledChange(d *types.ConsensusDigest, header *types.Header) error {
curr, err := h.blockState.BestBlockHeader()
if err != nil {
return err
}

if d.ConsensusEngineID == types.GrandpaEngineID {
if h.grandpaScheduledChange != nil {
return nil
}
if d.ConsensusEngineID != types.GrandpaEngineID {
return nil
}

sc := &types.GrandpaScheduledChange{}
dec, err := scale.Decode(d.Data[1:], sc)
if err != nil {
return err
}
sc = dec.(*types.GrandpaScheduledChange)
if h.grandpaScheduledChange != nil {
return nil
}

logger.Debug("handling GrandpaScheduledChange", "data", sc)
sc := &types.GrandpaScheduledChange{}
dec, err := scale.Decode(d.Data[1:], sc)
if err != nil {
return err
}
sc = dec.(*types.GrandpaScheduledChange)

if h.grandpa == nil {
// this should never happen
return nil
}
logger.Debug("handling GrandpaScheduledChange", "data", sc)

c, err := newGrandpaChange(sc.Auths, sc.Delay, curr.Number)
if err != nil {
return err
}

h.grandpaScheduledChange = c
c, err := newGrandpaChange(sc.Auths, sc.Delay, curr.Number)
if err != nil {
return err
}

return nil
}
h.grandpaScheduledChange = c

func (h *DigestHandler) handleForcedChange(d *types.ConsensusDigest) error {
curr, err := h.blockState.BestBlockHeader()
auths, err := types.GrandpaAuthoritiesRawToAuthorities(sc.Auths)
if err != nil {
return err
}

if d.ConsensusEngineID == types.GrandpaEngineID {
if h.grandpaForcedChange != nil {
return errors.New("already have forced change scheduled")
}

fc := &types.GrandpaForcedChange{}
dec, err := scale.Decode(d.Data[1:], fc)
if err != nil {
return err
}
fc = dec.(*types.GrandpaForcedChange)
return h.grandpaState.SetNextChange(types.NewGrandpaVotersFromAuthorities(auths), big.NewInt(0).Add(header.Number, big.NewInt(int64(sc.Delay))))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we institute max column in linting?

Suggested change
return h.grandpaState.SetNextChange(types.NewGrandpaVotersFromAuthorities(auths), big.NewInt(0).Add(header.Number, big.NewInt(int64(sc.Delay))))
return h.grandpaState.SetNextChange(
types.NewGrandpaVotersFromAuthorities(auths),
big.NewInt(0).Add(header.Number, big.NewInt(int64(sc.Delay))),
)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good idea, @dutterbutter is there a way to add max column size to the linter?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can take a look!

}

c, err := newGrandpaChange(fc.Auths, fc.Delay, curr.Number)
if err != nil {
return err
}
func (h *DigestHandler) handleForcedChange(d *types.ConsensusDigest, header *types.Header) error {
if d.ConsensusEngineID != types.GrandpaEngineID {
return nil
}

h.grandpaForcedChange = c
if header == nil {
return errors.New("header is nil")
}

return nil
}
if h.grandpaForcedChange != nil {
return errors.New("already have forced change scheduled")
}

func (h *DigestHandler) handleGrandpaOnDisabled(d *types.ConsensusDigest, _ *types.Header) error {
od := &types.GrandpaOnDisabled{}
dec, err := scale.Decode(d.Data[1:], od)
fc := &types.GrandpaForcedChange{}
dec, err := scale.Decode(d.Data[1:], fc)
if err != nil {
return err
}
od = dec.(*types.GrandpaOnDisabled)
fc = dec.(*types.GrandpaForcedChange)

logger.Debug("handling GrandpaOnDisabled", "data", od)
logger.Debug("handling GrandpaForcedChange", "data", fc)

if h.grandpa == nil {
// this should never happen
return nil
c, err := newGrandpaChange(fc.Auths, fc.Delay, header.Number)
if err != nil {
return err
}

curr := h.grandpa.Authorities()
next := []*types.Authority{}
h.grandpaForcedChange = c

for _, auth := range curr {
if auth.Weight != od.ID {
next = append(next, auth)
}
auths, err := types.GrandpaAuthoritiesRawToAuthorities(fc.Auths)
if err != nil {
return err
}

// TODO: this needs to be updated not to remove the authority from the list,
// but to flag them as disabled. thus, if we are disabled, we should stop voting.
// if we receive vote or finalisation messages, we should ignore anything signed by the
// disabled authority
h.grandpa.UpdateAuthorities(next)
return nil
return h.grandpaState.SetNextChange(
types.NewGrandpaVotersFromAuthorities(auths),
big.NewInt(0).Add(header.Number, big.NewInt(int64(fc.Delay))),
)
}

func (h *DigestHandler) handlePause(d *types.ConsensusDigest) error {
Expand All @@ -371,7 +343,7 @@ func (h *DigestHandler) handlePause(d *types.ConsensusDigest) error {
atBlock: big.NewInt(-1).Add(curr.Number, delay),
}

return nil
return h.grandpaState.SetNextPause(h.grandpaPause.atBlock)
}

func (h *DigestHandler) handleResume(d *types.ConsensusDigest) error {
Expand All @@ -393,7 +365,7 @@ func (h *DigestHandler) handleResume(d *types.ConsensusDigest) error {
atBlock: big.NewInt(-1).Add(curr.Number, delay),
}

return nil
return h.grandpaState.SetNextResume(h.grandpaResume.atBlock)
}

func newGrandpaChange(raw []*types.GrandpaAuthoritiesRaw, delay uint32, currBlock *big.Int) (*grandpaChange, error) {
Expand Down
Loading