Skip to content

Commit

Permalink
Fix check and apply forced auth changes
Browse files Browse the repository at this point in the history
  • Loading branch information
dimartiro committed Dec 5, 2024
1 parent 8a83ac2 commit 2d8968e
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 65 deletions.
65 changes: 1 addition & 64 deletions dot/digest/block_import.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@ func NewBlockImportHandler(epochState EpochState, grandpaState GrandpaState) *Bl

// HandleDigests handles consensus digests for an imported block
func (h *BlockImportHandler) HandleDigests(header *types.Header) error {
consensusDigests := toConsensusDigests(header.Digest)
consensusDigests, err := checkForGRANDPAForcedChanges(consensusDigests)
consensusDigests, err := types.FilterGRANDPAForcedChanges(header.Digest.ToConsensusDigests())
if err != nil {
return fmt.Errorf("failed while checking GRANDPA digests: %w", err)
}
Expand Down Expand Up @@ -74,65 +73,3 @@ func (h *BlockImportHandler) handleConsensusDigest(d *types.ConsensusDigest, hea

return nil
}

// toConsensusDigests converts a slice of scale.VaryingDataType to a slice of types.ConsensusDigest.
func toConsensusDigests(scaleVaryingTypes types.Digest) []types.ConsensusDigest {
consensusDigests := make([]types.ConsensusDigest, 0, len(scaleVaryingTypes))

for _, d := range scaleVaryingTypes {
digestValue, err := d.Value()
if err != nil {
logger.Error(err.Error())
continue
}
digest, ok := digestValue.(types.ConsensusDigest)
if !ok {
continue
}

switch digest.ConsensusEngineID {
case types.GrandpaEngineID, types.BabeEngineID:
consensusDigests = append(consensusDigests, digest)
}
}

return consensusDigests
}

// checkForGRANDPAForcedChanges removes any GrandpaScheduledChange in the presence of a
// GrandpaForcedChange in the same block digest, returning a new slice of types.ConsensusDigest
func checkForGRANDPAForcedChanges(digests []types.ConsensusDigest) ([]types.ConsensusDigest, error) {
var hasForcedChange bool
digestsWithoutScheduled := make([]types.ConsensusDigest, 0, len(digests))
for i, digest := range digests {
if digest.ConsensusEngineID != types.GrandpaEngineID {
digestsWithoutScheduled = append(digestsWithoutScheduled, digest)
continue
}

data := types.NewGrandpaConsensusDigest()
err := scale.Unmarshal(digest.Data, &data)
if err != nil {
return nil, fmt.Errorf("cannot unmarshal GRANDPA consensus digest: %w", err)
}

dataValue, err := data.Value()
if err != nil {
return nil, fmt.Errorf("getting value of digest type at index %d: %w", i, err)
}
switch dataValue.(type) {
case types.GrandpaScheduledChange:
case types.GrandpaForcedChange:
hasForcedChange = true
digestsWithoutScheduled = append(digestsWithoutScheduled, digest)
default:
digestsWithoutScheduled = append(digestsWithoutScheduled, digest)
}
}

if hasForcedChange {
return digestsWithoutScheduled, nil
}

return digests, nil
}
34 changes: 33 additions & 1 deletion dot/sync/block_importer.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/ChainSafe/gossamer/internal/database"
"github.com/ChainSafe/gossamer/lib/common"
rtstorage "github.com/ChainSafe/gossamer/lib/runtime/storage"
"github.com/ChainSafe/gossamer/pkg/scale"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
)
Expand Down Expand Up @@ -54,6 +55,7 @@ type (

// GrandpaState is the interface for the state.GrandpaState
GrandpaState interface {
HandleGRANDPADigest(header *types.Header, digest types.GrandpaConsensusDigest) error
ApplyForcedChanges(importedHeader *types.Header) error
}

Expand Down Expand Up @@ -106,6 +108,36 @@ func (b *blockImporter) importBlock(bd *types.BlockData, origin BlockOrigin) (im
return true, nil
}

func (b *blockImporter) checkAndApplyForcedAuthChanges(blockData types.BlockData) error {
header := blockData.Header
consensusDigests, err := types.FilterGRANDPAForcedChanges(header.Digest.ToConsensusDigests())
if err != nil {
return fmt.Errorf("failed while checking GRANDPA digests: %w", err)
}

for i := range consensusDigests {
digest := consensusDigests[i]
switch digest.ConsensusEngineID {
case types.GrandpaEngineID:
data := types.NewGrandpaConsensusDigest()
err := scale.Unmarshal(digest.Data, &data)
if err != nil {
return fmt.Errorf("unmarshaling grandpa consensus digest: %w", err)
}

err = b.grandpaState.HandleGRANDPADigest(header, data)
if err != nil {
return fmt.Errorf("handling grandpa digest: %w", err)
}
default:
// Will be handle by the block importer
continue
}
}

return b.grandpaState.ApplyForcedChanges(header)
}

// processBlockData processes the BlockData from a BlockResponse and
// returns the index of the last BlockData it handled on success,
// or the index of the block data that errored on failure.
Expand All @@ -117,7 +149,7 @@ func (b *blockImporter) processBlockData(blockData types.BlockData, origin Block
setID uint64
)

err := b.grandpaState.ApplyForcedChanges(blockData.Header)
err := b.checkAndApplyForcedAuthChanges(blockData)
if err != nil {
return fmt.Errorf("applying forced changes: %w", err)
}
Expand Down
60 changes: 60 additions & 0 deletions dot/types/digest.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,28 @@ func (d *Digest) Add(values ...any) (err error) {
return nil
}

func (d *Digest) ToConsensusDigests() []ConsensusDigest {
consensusDigests := make([]ConsensusDigest, 0, len(*d))

for _, d := range *d {
digestValue, err := d.Value()
if err != nil {
continue
}
digest, ok := digestValue.(ConsensusDigest)
if !ok {
continue
}

switch digest.ConsensusEngineID {
case GrandpaEngineID, BabeEngineID:
consensusDigests = append(consensusDigests, digest)
}
}

return consensusDigests
}

func (d *Digest) String() string {
stringTypes := make([]string, len(*d))
for i, vdt := range *d {
Expand Down Expand Up @@ -182,3 +204,41 @@ type RuntimeEnvironmentUpdated struct{}
func (RuntimeEnvironmentUpdated) String() string {
return "RuntimeEnvironmentUpdated"
}

// FilterGRANDPAForcedChanges removes any GrandpaScheduledChange in the presence of a
// GrandpaForcedChange in the same block digest, returning a new slice of ConsensusDigest
func FilterGRANDPAForcedChanges(digests []ConsensusDigest) ([]ConsensusDigest, error) {
var hasForcedChange bool
digestsWithoutScheduled := make([]ConsensusDigest, 0, len(digests))
for i, digest := range digests {
if digest.ConsensusEngineID != GrandpaEngineID {
digestsWithoutScheduled = append(digestsWithoutScheduled, digest)
continue
}

data := NewGrandpaConsensusDigest()
err := scale.Unmarshal(digest.Data, &data)
if err != nil {
return nil, fmt.Errorf("cannot unmarshal GRANDPA consensus digest: %w", err)
}

dataValue, err := data.Value()
if err != nil {
return nil, fmt.Errorf("getting value of digest type at index %d: %w", i, err)
}
switch dataValue.(type) {
case GrandpaScheduledChange:
case GrandpaForcedChange:
hasForcedChange = true
digestsWithoutScheduled = append(digestsWithoutScheduled, digest)
default:
digestsWithoutScheduled = append(digestsWithoutScheduled, digest)
}
}

if hasForcedChange {
return digestsWithoutScheduled, nil
}

return digests, nil
}

0 comments on commit 2d8968e

Please sign in to comment.