Skip to content

Commit

Permalink
fix: memory leak from policy registration (#1660)
Browse files Browse the repository at this point in the history
  • Loading branch information
rodion-lim-partior committed Dec 13, 2023
1 parent 643b5dc commit 3d95749
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 9 deletions.
14 changes: 13 additions & 1 deletion consensus/istanbul/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
"github.com/naoina/toml"
)
Expand All @@ -35,6 +36,8 @@ const (
Sticky
)

const MaxValidatorSetInRegistry = 128 // Max number of ValidatorSet in the registry

// ProposerPolicy represents the Validator Proposer Policy
type ProposerPolicy struct {
Id ProposerPolicyId // Could be RoundRobin or Sticky
Expand Down Expand Up @@ -111,17 +114,26 @@ func (p *ProposerPolicy) RegisterValidatorSet(valSet ValidatorSet) {
p.registry = []ValidatorSet{valSet}
} else {
p.registry = append(p.registry, valSet)
// Non-validators don't ever call ClearRegistry
// Validators cap the registry to MaxValidatorSetInRegistry length to prevent unexpected leaks
if len(p.registry) > MaxValidatorSetInRegistry {
p.registry = p.registry[1:]
}
}
log.Debug("Validator Policy Registry", "length", p.GetRegistrySize())
}

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

p.registry = nil
}

func (p *ProposerPolicy) GetRegistrySize() int {
return len(p.registry)
}

type Config struct {
RequestTimeout uint64 `toml:",omitempty"` // The timeout for each Istanbul round in milliseconds.
BlockPeriod uint64 `toml:",omitempty"` // Default minimum difference between two consecutive block's timestamps in second
Expand Down
34 changes: 26 additions & 8 deletions consensus/istanbul/validator/proposerpolicy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,19 @@ import (
"github.com/stretchr/testify/assert"
)

var (
addr1 = common.HexToAddress("0xc53f2189bf6d7bf56722731787127f90d319e112")
addr2 = common.HexToAddress("0xed2d479591fe2c5626ce09bca4ed2a62e00e5bc2")
addr3 = common.HexToAddress("0xc8417f834995aaeb35f342a67a4961e19cd4735c")
addr4 = common.HexToAddress("0x784ae51f5013b51c8360afdf91c6bc5a16f586ea")
addr5 = common.HexToAddress("0xecf0974e6f0630fd91ea4da8399cdb3f59e5220f")
addr6 = common.HexToAddress("0x411c4d11acd714b82a5242667e36de14b9e1d10b")
addr7 = common.HexToAddress("0x681381b3D0DaaC179d95aCc9e22E23da2DA670f6")
addrSet = []common.Address{addr1, addr2, addr3, addr4, addr5, addr6}
addrSet2 = []common.Address{addr7, addr1, addr2, addr3, addr4, addr5}
)

func TestProposerPolicy(t *testing.T) {
addr1 := common.HexToAddress("0xc53f2189bf6d7bf56722731787127f90d319e112")
addr2 := common.HexToAddress("0xed2d479591fe2c5626ce09bca4ed2a62e00e5bc2")
addr3 := common.HexToAddress("0xc8417f834995aaeb35f342a67a4961e19cd4735c")
addr4 := common.HexToAddress("0x784ae51f5013b51c8360afdf91c6bc5a16f586ea")
addr5 := common.HexToAddress("0xecf0974e6f0630fd91ea4da8399cdb3f59e5220f")
addr6 := common.HexToAddress("0x411c4d11acd714b82a5242667e36de14b9e1d10b")

addrSet := []common.Address{addr1, addr2, addr3, addr4, addr5, addr6}
addressSortedByByte := []common.Address{addr6, addr4, addr1, addr3, addr5, addr2}
addressSortedByString := []common.Address{addr6, addr4, addr1, addr2, addr5, addr3}

Expand All @@ -51,3 +55,17 @@ func TestProposerPolicy(t *testing.T) {
assert.Equal(t, addressSortedByString[i].Hex(), valList[i].String(), "validatorSet not string sorted")
}
}

func TestProposerPolicyRegistration(t *testing.T) {
// test that registration can't go beyond MaxValidatorSetInRegistry limit
pp := istanbul.NewRoundRobinProposerPolicy()
pp2 := istanbul.NewRoundRobinProposerPolicy()
valSet := NewSet(addrSet, pp)
valSet2 := NewSet(addrSet2, pp2)

for i := 0; i < istanbul.MaxValidatorSetInRegistry+100; i++ {
pp.RegisterValidatorSet(valSet)
}
pp.RegisterValidatorSet(valSet2)
assert.Equal(t, istanbul.MaxValidatorSetInRegistry, pp.GetRegistrySize(), "validator set not dropped")
}

0 comments on commit 3d95749

Please sign in to comment.