2022-04-06 23:36:52 +00:00
|
|
|
package cache
|
|
|
|
|
|
|
|
import (
|
2022-08-10 22:49:35 +00:00
|
|
|
"bytes"
|
2022-04-06 23:36:52 +00:00
|
|
|
"sync"
|
|
|
|
|
2023-01-26 14:40:12 +00:00
|
|
|
"github.com/prysmaticlabs/prysm/v3/consensus-types/primitives"
|
2022-08-16 12:20:13 +00:00
|
|
|
"github.com/prysmaticlabs/prysm/v3/encoding/bytesutil"
|
2022-04-06 23:36:52 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
const vIdLength = 8
|
|
|
|
const pIdLength = 8
|
|
|
|
const vpIdsLength = vIdLength + pIdLength
|
|
|
|
|
|
|
|
// ProposerPayloadIDsCache is a cache of proposer payload IDs.
|
|
|
|
// The key is the slot. The value is the concatenation of the proposer and payload IDs. 8 bytes each.
|
|
|
|
type ProposerPayloadIDsCache struct {
|
2022-08-11 14:55:26 +00:00
|
|
|
slotToProposerAndPayloadIDs map[[40]byte][vpIdsLength]byte
|
2022-04-06 23:36:52 +00:00
|
|
|
sync.RWMutex
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewProposerPayloadIDsCache creates a new proposer payload IDs cache.
|
|
|
|
func NewProposerPayloadIDsCache() *ProposerPayloadIDsCache {
|
|
|
|
return &ProposerPayloadIDsCache{
|
2022-08-11 14:55:26 +00:00
|
|
|
slotToProposerAndPayloadIDs: make(map[[40]byte][vpIdsLength]byte),
|
2022-04-06 23:36:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetProposerPayloadIDs returns the proposer and payload IDs for the given slot.
|
2023-01-26 14:40:12 +00:00
|
|
|
func (f *ProposerPayloadIDsCache) GetProposerPayloadIDs(slot primitives.Slot, r [32]byte) (primitives.ValidatorIndex, [8]byte, bool) {
|
2022-04-06 23:36:52 +00:00
|
|
|
f.RLock()
|
|
|
|
defer f.RUnlock()
|
2022-08-11 14:55:26 +00:00
|
|
|
ids, ok := f.slotToProposerAndPayloadIDs[idKey(slot, r)]
|
2022-04-06 23:36:52 +00:00
|
|
|
if !ok {
|
|
|
|
return 0, [8]byte{}, false
|
|
|
|
}
|
|
|
|
vId := ids[:vIdLength]
|
|
|
|
|
|
|
|
b := ids[vIdLength:]
|
|
|
|
var pId [pIdLength]byte
|
|
|
|
copy(pId[:], b)
|
|
|
|
|
2023-01-26 14:40:12 +00:00
|
|
|
return primitives.ValidatorIndex(bytesutil.BytesToUint64BigEndian(vId)), pId, true
|
2022-04-06 23:36:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// SetProposerAndPayloadIDs sets the proposer and payload IDs for the given slot.
|
2023-01-26 14:40:12 +00:00
|
|
|
func (f *ProposerPayloadIDsCache) SetProposerAndPayloadIDs(slot primitives.Slot, vId primitives.ValidatorIndex, pId [8]byte, r [32]byte) {
|
2022-04-06 23:36:52 +00:00
|
|
|
f.Lock()
|
|
|
|
defer f.Unlock()
|
|
|
|
var vIdBytes [vIdLength]byte
|
|
|
|
copy(vIdBytes[:], bytesutil.Uint64ToBytesBigEndian(uint64(vId)))
|
|
|
|
|
2022-08-10 22:49:35 +00:00
|
|
|
var bs [vpIdsLength]byte
|
|
|
|
copy(bs[:], append(vIdBytes[:], pId[:]...))
|
2022-04-06 23:36:52 +00:00
|
|
|
|
2022-08-11 14:55:26 +00:00
|
|
|
k := idKey(slot, r)
|
|
|
|
ids, ok := f.slotToProposerAndPayloadIDs[k]
|
2022-08-10 22:49:35 +00:00
|
|
|
// Ok to overwrite if the slot is already set but the cached payload ID is not set.
|
|
|
|
// This combats the re-org case where payload assignment could change at the start of the epoch.
|
2022-12-22 09:20:10 +00:00
|
|
|
var byte8 [vIdLength]byte
|
2022-08-10 22:49:35 +00:00
|
|
|
if !ok || (ok && bytes.Equal(ids[vIdLength:], byte8[:])) {
|
2022-08-11 14:55:26 +00:00
|
|
|
f.slotToProposerAndPayloadIDs[k] = bs
|
2022-04-06 23:36:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// PrunePayloadIDs removes the payload id entries that's current than input slot.
|
2023-01-26 14:40:12 +00:00
|
|
|
func (f *ProposerPayloadIDsCache) PrunePayloadIDs(slot primitives.Slot) {
|
2022-04-06 23:36:52 +00:00
|
|
|
f.Lock()
|
|
|
|
defer f.Unlock()
|
|
|
|
|
2022-08-11 14:55:26 +00:00
|
|
|
for k := range f.slotToProposerAndPayloadIDs {
|
2023-01-26 14:40:12 +00:00
|
|
|
s := primitives.Slot(bytesutil.BytesToUint64BigEndian(k[:8]))
|
2022-04-06 23:36:52 +00:00
|
|
|
if slot > s {
|
2022-08-11 14:55:26 +00:00
|
|
|
delete(f.slotToProposerAndPayloadIDs, k)
|
2022-04-06 23:36:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-08-11 14:55:26 +00:00
|
|
|
|
2023-01-26 14:40:12 +00:00
|
|
|
func idKey(slot primitives.Slot, r [32]byte) [40]byte {
|
2022-08-11 14:55:26 +00:00
|
|
|
var k [40]byte
|
|
|
|
copy(k[:], append(bytesutil.Uint64ToBytesBigEndian(uint64(slot)), r[:]...))
|
|
|
|
return k
|
|
|
|
}
|