-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
26 changed files
with
281 additions
and
134 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
// +build !libfuzzer | ||
|
||
package cache | ||
|
||
import ( | ||
"sync" | ||
|
||
"github.com/prometheus/client_golang/prometheus" | ||
"github.com/prometheus/client_golang/prometheus/promauto" | ||
"k8s.io/client-go/tools/cache" | ||
) | ||
|
||
var ( | ||
// maxProposerIndicesCacheSize defines the max number of proposer indices on per block root basis can cache. | ||
// Due to reorgs and long finality, it's good to keep the old cache around for quickly switch over. | ||
maxProposerIndicesCacheSize = uint64(8) | ||
|
||
// ProposerIndicesCacheMiss tracks the number of proposerIndices requests that aren't present in the cache. | ||
ProposerIndicesCacheMiss = promauto.NewCounter(prometheus.CounterOpts{ | ||
Name: "proposer_indices_cache_miss", | ||
Help: "The number of proposer indices requests that aren't present in the cache.", | ||
}) | ||
// ProposerIndicesCacheHit tracks the number of proposerIndices requests that are in the cache. | ||
ProposerIndicesCacheHit = promauto.NewCounter(prometheus.CounterOpts{ | ||
Name: "proposer_indices_cache_hit", | ||
Help: "The number of proposer indices requests that are present in the cache.", | ||
}) | ||
) | ||
|
||
// ProposerIndicesCache is a struct with 1 queue for looking up proposer indices by root. | ||
type ProposerIndicesCache struct { | ||
ProposerIndicesCache *cache.FIFO | ||
lock sync.RWMutex | ||
} | ||
|
||
// proposerIndicesKeyFn takes the block root as the key to retrieve proposer indices in a given epoch. | ||
func proposerIndicesKeyFn(obj interface{}) (string, error) { | ||
info, ok := obj.(*ProposerIndices) | ||
if !ok { | ||
return "", ErrNotProposerIndices | ||
} | ||
|
||
return key(info.BlockRoot), nil | ||
} | ||
|
||
// NewProposerIndicesCache creates a new proposer indices cache for storing/accessing proposer index assignments of an epoch. | ||
func NewProposerIndicesCache() *ProposerIndicesCache { | ||
return &ProposerIndicesCache{ | ||
ProposerIndicesCache: cache.NewFIFO(proposerIndicesKeyFn), | ||
} | ||
} | ||
|
||
// AddProposerIndices adds ProposerIndices object to the cache. | ||
// This method also trims the least recently list if the cache size has ready the max cache size limit. | ||
func (c *ProposerIndicesCache) AddProposerIndices(p *ProposerIndices) error { | ||
c.lock.Lock() | ||
defer c.lock.Unlock() | ||
|
||
if err := c.ProposerIndicesCache.AddIfNotPresent(p); err != nil { | ||
return err | ||
} | ||
trim(c.ProposerIndicesCache, maxProposerIndicesCacheSize) | ||
return nil | ||
} | ||
|
||
// ProposerIndices returns the proposer indices of a block root seed. | ||
func (c *ProposerIndicesCache) ProposerIndices(r [32]byte) ([]uint64, error) { | ||
c.lock.RLock() | ||
defer c.lock.RUnlock() | ||
obj, exists, err := c.ProposerIndicesCache.GetByKey(key(r)) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
if exists { | ||
ProposerIndicesCacheHit.Inc() | ||
} else { | ||
ProposerIndicesCacheMiss.Inc() | ||
return nil, nil | ||
} | ||
|
||
item, ok := obj.(*ProposerIndices) | ||
if !ok { | ||
return nil, ErrNotProposerIndices | ||
} | ||
|
||
return item.ProposerIndices, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
// +build libfuzzer | ||
|
||
// This file is used in fuzzer builds to bypass proposer indices caches. | ||
package cache | ||
|
||
// FakeProposerIndicesCache is a struct with 1 queue for looking up proposer indices by root. | ||
type FakeProposerIndicesCache struct { | ||
} | ||
|
||
// NewProposerIndicesCache creates a new proposer indices cache for storing/accessing proposer index assignments of an epoch. | ||
func NewProposerIndicesCache() *FakeProposerIndicesCache { | ||
return &FakeProposerIndicesCache{} | ||
} | ||
|
||
// AddProposerIndices adds ProposerIndices object to the cache. | ||
// This method also trims the least recently list if the cache size has ready the max cache size limit. | ||
func (c *FakeProposerIndicesCache) AddProposerIndices(p *ProposerIndices) error { | ||
return nil | ||
} | ||
|
||
// ProposerIndices returns the proposer indices of a block root seed. | ||
func (c *FakeProposerIndicesCache) ProposerIndices(r [32]byte) ([]uint64, error) { | ||
return nil, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
package cache | ||
|
||
import ( | ||
"strconv" | ||
"testing" | ||
|
||
"github.com/prysmaticlabs/prysm/shared/bytesutil" | ||
"github.com/prysmaticlabs/prysm/shared/testutil/assert" | ||
"github.com/prysmaticlabs/prysm/shared/testutil/require" | ||
) | ||
|
||
func TestProposerKeyFn_OK(t *testing.T) { | ||
item := &ProposerIndices{ | ||
BlockRoot: [32]byte{'A'}, | ||
ProposerIndices: []uint64{1, 2, 3, 4, 5}, | ||
} | ||
|
||
k, err := proposerIndicesKeyFn(item) | ||
require.NoError(t, err) | ||
assert.Equal(t, key(item.BlockRoot), k) | ||
} | ||
|
||
func TestProposerKeyFn_InvalidObj(t *testing.T) { | ||
_, err := proposerIndicesKeyFn("bad") | ||
assert.Equal(t, ErrNotProposerIndices, err) | ||
} | ||
|
||
func TestProposerCache_AddProposerIndicesList(t *testing.T) { | ||
cache := NewProposerIndicesCache() | ||
bRoot := [32]byte{'A'} | ||
indices, err := cache.ProposerIndices(bRoot) | ||
require.NoError(t, err) | ||
if indices != nil { | ||
t.Error("Expected committee count not to exist in empty cache") | ||
} | ||
require.NoError(t, cache.AddProposerIndices(&ProposerIndices{ | ||
ProposerIndices: indices, | ||
BlockRoot: bRoot, | ||
})) | ||
|
||
received, err := cache.ProposerIndices(bRoot) | ||
require.NoError(t, err) | ||
assert.DeepEqual(t, received, indices) | ||
|
||
item := &ProposerIndices{BlockRoot: [32]byte{'B'}, ProposerIndices: []uint64{1, 2, 3, 4, 5, 6}} | ||
require.NoError(t, cache.AddProposerIndices(item)) | ||
|
||
received, err = cache.ProposerIndices(item.BlockRoot) | ||
require.NoError(t, err) | ||
assert.DeepEqual(t, item.ProposerIndices, received) | ||
} | ||
|
||
func TestProposerCache_CanRotate(t *testing.T) { | ||
cache := NewProposerIndicesCache() | ||
for i := 0; i < int(maxProposerIndicesCacheSize)+1; i++ { | ||
s := []byte(strconv.Itoa(i)) | ||
item := &ProposerIndices{BlockRoot: bytesutil.ToBytes32(s)} | ||
require.NoError(t, cache.AddProposerIndices(item)) | ||
} | ||
|
||
k := cache.ProposerIndicesCache.ListKeys() | ||
assert.Equal(t, maxProposerIndicesCacheSize, uint64(len(k))) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package cache | ||
|
||
import "errors" | ||
|
||
// ErrNotProposerIndices will be returned when a cache object is not a pointer to | ||
// a ProposerIndices struct. | ||
var ErrNotProposerIndices = errors.New("object is not a proposer indices struct") | ||
|
||
// ProposerIndices defines the cached struct for proposer indices. | ||
type ProposerIndices struct { | ||
BlockRoot [32]byte | ||
ProposerIndices []uint64 | ||
} |
Oops, something went wrong.