Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Protect ProposerPolicy Registry using Mutex #1242

Merged
merged 4 commits into from
Aug 25, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion consensus/istanbul/backend/engine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,14 +169,14 @@ func TestSealStopChannel(t *testing.T) {
stop <- struct{}{}
eventSub.Unsubscribe()
}
go eventLoop()
resultCh := make(chan *types.Block, 10)
go func() {
err := engine.Seal(chain, block, resultCh, stop)
if err != nil {
t.Errorf("error mismatch: have %v, want nil", err)
}
}()
go eventLoop()
ricardolyn marked this conversation as resolved.
Show resolved Hide resolved

finalBlock := <-resultCh
if finalBlock != nil {
Expand Down
2 changes: 1 addition & 1 deletion consensus/istanbul/backend/snapshot.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ func (s *Snapshot) UnmarshalJSON(b []byte) error {
s.Tally = j.Tally

// Setting the By function to ValidatorSortByStringFunc should be fine, as the validator do not change only the order changes
pp := &istanbul.ProposerPolicy{Id: j.Policy, By: istanbul.ValidatorSortByString()}
pp := istanbul.NewProposerPolicyByIdAndSortFunc(j.Policy, istanbul.ValidatorSortByString())
s.ValSet = validator.NewSet(j.Validators, pp)
return nil
}
Expand Down
30 changes: 21 additions & 9 deletions consensus/istanbul/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package istanbul

import (
"math/big"
"sync"

"github.com/naoina/toml"
)
Expand All @@ -31,9 +32,10 @@ const (

// ProposerPolicy represents the Validator Proposer Policy
type ProposerPolicy struct {
Id ProposerPolicyId // Could be RoundRobin or Sticky
Registry []ValidatorSet // Holds the ValidatorSet for a given block height
By ValidatorSortByFunc // func that defines how the ValidatorSet should be sorted
Id ProposerPolicyId // Could be RoundRobin or Sticky
By ValidatorSortByFunc // func that defines how the ValidatorSet should be sorted
registry []ValidatorSet // Holds the ValidatorSet for a given block height
registryMU *sync.Mutex // Mutex to lock access to changes to Registry
}

// NewRoundRobinProposerPolicy returns a RoundRobin ProposerPolicy with ValidatorSortByString as default sort function
Expand All @@ -47,7 +49,11 @@ func NewStickyProposerPolicy() *ProposerPolicy {
}

func NewProposerPolicy(id ProposerPolicyId) *ProposerPolicy {
return &ProposerPolicy{Id: id, By: ValidatorSortByString()}
return NewProposerPolicyByIdAndSortFunc(id, ValidatorSortByString())
}

func NewProposerPolicyByIdAndSortFunc(id ProposerPolicyId, by ValidatorSortByFunc) *ProposerPolicy {
return &ProposerPolicy{Id: id, By: by, registryMU: new(sync.Mutex)}
}

type proposerPolicyToml struct {
Expand All @@ -74,23 +80,29 @@ func (p *ProposerPolicy) UnmarshalTOML(input []byte) error {
func (p *ProposerPolicy) Use(v ValidatorSortByFunc) {
p.By = v

for _, validatorSet := range p.Registry {
for _, validatorSet := range p.registry {
validatorSet.SortValidators()
}
}

// RegisterValidatorSet stores the given ValidatorSet in the policy registry
func (p *ProposerPolicy) RegisterValidatorSet(valSet ValidatorSet) {
if len(p.Registry) == 0 {
p.Registry = []ValidatorSet{valSet}
p.registryMU.Lock()
defer p.registryMU.Unlock()

if len(p.registry) == 0 {
p.registry = []ValidatorSet{valSet}
} else {
p.Registry = append(p.Registry, valSet)
p.registry = append(p.registry, valSet)
}
}

// ClearRegistry removes any ValidatorSet from the ProposerPolicy registry
func (p *ProposerPolicy) ClearRegistry() {
p.Registry = nil
p.registryMU.Lock()
defer p.registryMU.Unlock()

p.registry = nil
}

type Config struct {
Expand Down