beacon/light: more renames and cleanups

This commit is contained in:
zsfelfoldi 2023-11-10 13:56:06 +01:00
parent 623d195b70
commit 4d71502ab0
5 changed files with 73 additions and 77 deletions

View file

@ -53,11 +53,11 @@ func (c *CheckpointData) InitChain(chain *CommitteeChain) {
} }
} }
period := c.Header.SyncPeriod() period := c.Header.SyncPeriod()
must(chain.DeleteFixedRootsFrom(period + 2)) must(chain.DeleteFixedCommitteeRootsFrom(period + 2))
if chain.AddFixedRoot(period, c.CommitteeRoot) != nil { if chain.AddFixedCommitteeRoot(period, c.CommitteeRoot) != nil {
chain.Reset() chain.Reset()
must(chain.AddFixedRoot(period, c.CommitteeRoot)) must(chain.AddFixedCommitteeRoot(period, c.CommitteeRoot))
} }
must(chain.AddFixedRoot(period+1, common.Hash(c.CommitteeBranch[0]))) must(chain.AddFixedCommitteeRoot(period+1, common.Hash(c.CommitteeBranch[0])))
must(chain.AddCommittee(period, c.Committee)) must(chain.AddCommittee(period, c.Committee))
} }

View file

@ -63,14 +63,14 @@ var (
// signed beacon headers. // signed beacon headers.
type CommitteeChain struct { type CommitteeChain struct {
// chainmu guards against concurrent access to the canonicalStore structures // chainmu guards against concurrent access to the canonicalStore structures
// (updates, committees, fixedRoots) and ensures that they stay consistent // (updates, committees, fixedCommitteeRoots) and ensures that they stay consistent
// with each other and with committeeCache. // with each other and with committeeCache.
chainmu sync.RWMutex chainmu sync.RWMutex
db ethdb.KeyValueStore db ethdb.KeyValueStore
updates *canonicalStore[*types.LightClientUpdate] updates *canonicalStore[*types.LightClientUpdate]
committees *canonicalStore[*types.SerializedSyncCommittee] committees *canonicalStore[*types.SerializedSyncCommittee]
fixedRoots *canonicalStore[common.Hash] fixedCommitteeRoots *canonicalStore[common.Hash]
committeeCache *lru.Cache[uint64, syncCommittee] // cache deserialized committees committeeCache *lru.Cache[uint64, syncCommittee] // cache deserialized committees
clock mclock.Clock // monotonic clock (simulated clock in tests) clock mclock.Clock // monotonic clock (simulated clock in tests)
unixNano func() int64 // system clock (simulated clock in tests) unixNano func() int64 // system clock (simulated clock in tests)
@ -91,10 +91,10 @@ func NewCommitteeChain(db ethdb.KeyValueStore, config *types.ChainConfig, signer
// clock source and signature verification for testing purposes. // clock source and signature verification for testing purposes.
func newCommitteeChain(db ethdb.KeyValueStore, config *types.ChainConfig, signerThreshold int, enforceTime bool, sigVerifier committeeSigVerifier, clock mclock.Clock, unixNano func() int64) *CommitteeChain { func newCommitteeChain(db ethdb.KeyValueStore, config *types.ChainConfig, signerThreshold int, enforceTime bool, sigVerifier committeeSigVerifier, clock mclock.Clock, unixNano func() int64) *CommitteeChain {
var ( var (
fixedRootEncoder = func(root common.Hash) ([]byte, error) { fixedCommitteeRootEncoder = func(root common.Hash) ([]byte, error) {
return root[:], nil return root[:], nil
} }
fixedRootDecoder = func(enc []byte) (root common.Hash, err error) { fixedCommitteeRootDecoder = func(enc []byte) (root common.Hash, err error) {
if len(enc) != common.HashLength { if len(enc) != common.HashLength {
return common.Hash{}, errors.New("incorrect length for committee root entry in the database") return common.Hash{}, errors.New("incorrect length for committee root entry in the database")
} }
@ -123,17 +123,17 @@ func newCommitteeChain(db ethdb.KeyValueStore, config *types.ChainConfig, signer
} }
) )
s := &CommitteeChain{ s := &CommitteeChain{
fixedRoots: newCanonicalStore[common.Hash](db, rawdb.FixedRootKey, fixedRootEncoder, fixedRootDecoder), fixedCommitteeRoots: newCanonicalStore[common.Hash](db, rawdb.FixedCommitteeRootKey, fixedCommitteeRootEncoder, fixedCommitteeRootDecoder),
committees: newCanonicalStore[*types.SerializedSyncCommittee](db, rawdb.SyncCommitteeKey, committeeEncoder, committeeDecoder), committees: newCanonicalStore[*types.SerializedSyncCommittee](db, rawdb.SyncCommitteeKey, committeeEncoder, committeeDecoder),
updates: newCanonicalStore[*types.LightClientUpdate](db, rawdb.BestUpdateKey, updateEncoder, updateDecoder), updates: newCanonicalStore[*types.LightClientUpdate](db, rawdb.BestUpdateKey, updateEncoder, updateDecoder),
committeeCache: lru.NewCache[uint64, syncCommittee](10), committeeCache: lru.NewCache[uint64, syncCommittee](10),
db: db, db: db,
sigVerifier: sigVerifier, sigVerifier: sigVerifier,
clock: clock, clock: clock,
unixNano: unixNano, unixNano: unixNano,
config: config, config: config,
signerThreshold: signerThreshold, signerThreshold: signerThreshold,
enforceTime: enforceTime, enforceTime: enforceTime,
minimumUpdateScore: types.UpdateScore{ minimumUpdateScore: types.UpdateScore{
SignerCount: uint32(signerThreshold), SignerCount: uint32(signerThreshold),
SubPeriodIndex: params.SyncPeriodLength / 16, SubPeriodIndex: params.SyncPeriodLength / 16,
@ -169,15 +169,15 @@ func newCommitteeChain(db ethdb.KeyValueStore, config *types.ChainConfig, signer
// checkConstraints checks committee chain validity constraints // checkConstraints checks committee chain validity constraints
func (s *CommitteeChain) checkConstraints() bool { func (s *CommitteeChain) checkConstraints() bool {
isNotInFixedRootRange := func(r Range) bool { isNotInFixedCommitteeRootRange := func(r Range) bool {
return s.fixedRoots.periods.IsEmpty() || return s.fixedCommitteeRoots.periods.IsEmpty() ||
r.Start < s.fixedRoots.periods.Start || r.Start < s.fixedCommitteeRoots.periods.Start ||
r.Start >= s.fixedRoots.periods.End r.Start >= s.fixedCommitteeRoots.periods.End
} }
valid := true valid := true
if !s.updates.periods.IsEmpty() { if !s.updates.periods.IsEmpty() {
if isNotInFixedRootRange(s.updates.periods) { if isNotInFixedCommitteeRootRange(s.updates.periods) {
log.Error("Start update is not in the fixed roots range") log.Error("Start update is not in the fixed roots range")
valid = false valid = false
} }
@ -187,11 +187,11 @@ func (s *CommitteeChain) checkConstraints() bool {
} }
} }
if !s.committees.periods.IsEmpty() { if !s.committees.periods.IsEmpty() {
if isNotInFixedRootRange(s.committees.periods) { if isNotInFixedCommitteeRootRange(s.committees.periods) {
log.Error("Start committee is not in the fixed roots range") log.Error("Start committee is not in the fixed roots range")
valid = false valid = false
} }
if s.committees.periods.End > s.fixedRoots.periods.End && s.committees.periods.End > s.updates.periods.End+1 { if s.committees.periods.End > s.fixedCommitteeRoots.periods.End && s.committees.periods.End > s.updates.periods.End+1 {
log.Error("Last committee is neither in the fixed roots range nor proven by updates") log.Error("Last committee is neither in the fixed roots range nor proven by updates")
valid = false valid = false
} }
@ -209,10 +209,10 @@ func (s *CommitteeChain) Reset() {
} }
} }
// AddFixedRoot sets a fixed committee root at the given period. // AddFixedCommitteeRoot sets a fixed committee root at the given period.
// Note that the period where the first committee is added has to have a fixed // Note that the period where the first committee is added has to have a fixed
// root which can either come from a CheckpointData or a trusted source. // root which can either come from a CheckpointData or a trusted source.
func (s *CommitteeChain) AddFixedRoot(period uint64, root common.Hash) error { func (s *CommitteeChain) AddFixedCommitteeRoot(period uint64, root common.Hash) error {
s.chainmu.Lock() s.chainmu.Lock()
defer s.chainmu.Unlock() defer s.chainmu.Unlock()
@ -222,7 +222,7 @@ func (s *CommitteeChain) AddFixedRoot(period uint64, root common.Hash) error {
batch := s.db.NewBatch() batch := s.db.NewBatch()
oldRoot := s.getCommitteeRoot(period) oldRoot := s.getCommitteeRoot(period)
if !s.fixedRoots.periods.CanExpand(period) { if !s.fixedCommitteeRoots.periods.CanExpand(period) {
// Note: the fixed committee root range should always be continuous and // Note: the fixed committee root range should always be continuous and
// therefore the expected syncing method is to forward sync and optionally // therefore the expected syncing method is to forward sync and optionally
// backward sync periods one by one, starting from a checkpoint. The only // backward sync periods one by one, starting from a checkpoint. The only
@ -238,8 +238,8 @@ func (s *CommitteeChain) AddFixedRoot(period uint64, root common.Hash) error {
// if the old root exists and matches the new one then it is guaranteed // if the old root exists and matches the new one then it is guaranteed
// that the given period is after the existing fixed range and the roots // that the given period is after the existing fixed range and the roots
// in between can also be fixed. // in between can also be fixed.
for p := s.fixedRoots.periods.End; p < period; p++ { for p := s.fixedCommitteeRoots.periods.End; p < period; p++ {
if err := s.fixedRoots.add(batch, p, s.getCommitteeRoot(p)); err != nil { if err := s.fixedCommitteeRoots.add(batch, p, s.getCommitteeRoot(p)); err != nil {
return err return err
} }
} }
@ -250,7 +250,7 @@ func (s *CommitteeChain) AddFixedRoot(period uint64, root common.Hash) error {
return err return err
} }
} }
if err := s.fixedRoots.add(batch, period, root); err != nil { if err := s.fixedCommitteeRoots.add(batch, period, root); err != nil {
return err return err
} }
if err := batch.Write(); err != nil { if err := batch.Write(); err != nil {
@ -260,18 +260,18 @@ func (s *CommitteeChain) AddFixedRoot(period uint64, root common.Hash) error {
return nil return nil
} }
// DeleteFixedRootsFrom deletes fixed roots starting from the given period. // DeleteFixedCommitteeRootsFrom deletes fixed roots starting from the given period.
// It also maintains chain consistency, meaning that it also deletes updates and // It also maintains chain consistency, meaning that it also deletes updates and
// committees if they are no longer supported by a valid update chain. // committees if they are no longer supported by a valid update chain.
func (s *CommitteeChain) DeleteFixedRootsFrom(period uint64) error { func (s *CommitteeChain) DeleteFixedCommitteeRootsFrom(period uint64) error {
s.chainmu.Lock() s.chainmu.Lock()
defer s.chainmu.Unlock() defer s.chainmu.Unlock()
if period >= s.fixedRoots.periods.End { if period >= s.fixedCommitteeRoots.periods.End {
return nil return nil
} }
batch := s.db.NewBatch() batch := s.db.NewBatch()
s.fixedRoots.deleteFrom(batch, period) s.fixedCommitteeRoots.deleteFrom(batch, period)
if s.updates.periods.IsEmpty() || period <= s.updates.periods.Start { if s.updates.periods.IsEmpty() || period <= s.updates.periods.Start {
// Note: the first period of the update chain should always be fixed so if // Note: the first period of the update chain should always be fixed so if
// the fixed root at the first update is removed then the entire update chain // the fixed root at the first update is removed then the entire update chain
@ -327,7 +327,7 @@ func (s *CommitteeChain) AddCommittee(period uint64, committee *types.Serialized
if root != committee.Root() { if root != committee.Root() {
return ErrWrongCommitteeRoot return ErrWrongCommitteeRoot
} }
if !s.committees.periods.Includes(period) { if !s.committees.periods.Contains(period) {
if err := s.committees.add(s.db, period, committee); err != nil { if err := s.committees.add(s.db, period, committee); err != nil {
return err return err
} }
@ -349,7 +349,7 @@ func (s *CommitteeChain) InsertUpdate(update *types.LightClientUpdate, nextCommi
defer s.chainmu.Unlock() defer s.chainmu.Unlock()
period := update.AttestedHeader.Header.SyncPeriod() period := update.AttestedHeader.Header.SyncPeriod()
if !s.updates.periods.CanExpand(period) || !s.committees.periods.Includes(period) { if !s.updates.periods.CanExpand(period) || !s.committees.periods.Contains(period) {
return ErrInvalidPeriod return ErrInvalidPeriod
} }
if s.minimumUpdateScore.BetterThan(update.Score()) { if s.minimumUpdateScore.BetterThan(update.Score()) {
@ -364,7 +364,7 @@ func (s *CommitteeChain) InsertUpdate(update *types.LightClientUpdate, nextCommi
} }
return nil return nil
} }
if s.fixedRoots.periods.Includes(period+1) && reorg { if s.fixedCommitteeRoots.periods.Contains(period+1) && reorg {
return ErrCannotReorg return ErrCannotReorg
} }
if ok, err := s.verifyUpdate(update); err != nil { if ok, err := s.verifyUpdate(update); err != nil {
@ -372,7 +372,7 @@ func (s *CommitteeChain) InsertUpdate(update *types.LightClientUpdate, nextCommi
} else if !ok { } else if !ok {
return ErrInvalidUpdate return ErrInvalidUpdate
} }
addCommittee := !s.committees.periods.Includes(period+1) || reorg addCommittee := !s.committees.periods.Contains(period+1) || reorg
if addCommittee { if addCommittee {
if nextCommittee == nil { if nextCommittee == nil {
return ErrNeedCommittee return ErrNeedCommittee
@ -426,14 +426,14 @@ func (s *CommitteeChain) rollback(period uint64) error {
if s.committees.periods.End > max { if s.committees.periods.End > max {
max = s.committees.periods.End max = s.committees.periods.End
} }
if s.fixedRoots.periods.End > max { if s.fixedCommitteeRoots.periods.End > max {
max = s.fixedRoots.periods.End max = s.fixedCommitteeRoots.periods.End
} }
for max > period { for max > period {
max-- max--
batch := s.db.NewBatch() batch := s.db.NewBatch()
s.deleteCommitteesFrom(batch, max) s.deleteCommitteesFrom(batch, max)
s.fixedRoots.deleteFrom(batch, max) s.fixedCommitteeRoots.deleteFrom(batch, max)
if max > 0 { if max > 0 {
s.updates.deleteFrom(batch, max-1) s.updates.deleteFrom(batch, max-1)
} }
@ -449,7 +449,7 @@ func (s *CommitteeChain) rollback(period uint64) error {
// proven by a previous update or both. It returns an empty hash if the committee // proven by a previous update or both. It returns an empty hash if the committee
// root is unknown. // root is unknown.
func (s *CommitteeChain) getCommitteeRoot(period uint64) common.Hash { func (s *CommitteeChain) getCommitteeRoot(period uint64) common.Hash {
if root, ok := s.fixedRoots.get(period); ok || period == 0 { if root, ok := s.fixedCommitteeRoots.get(period); ok || period == 0 {
return root return root
} }
if update, ok := s.updates.get(period - 1); ok { if update, ok := s.updates.get(period - 1); ok {

View file

@ -53,16 +53,16 @@ var (
tcAnotherGenesis = newTestCommitteeChain(nil, tfAnotherGenesis, true, 0, 10, 400, false) tcAnotherGenesis = newTestCommitteeChain(nil, tfAnotherGenesis, true, 0, 10, 400, false)
) )
func TestCommitteeChainFixedRoots(t *testing.T) { func TestCommitteeChainFixedCommitteeRoots(t *testing.T) {
for _, reload := range []bool{false, true} { for _, reload := range []bool{false, true} {
c := newCommitteeChainTest(t, tfBase, 300, true) c := newCommitteeChainTest(t, tfBase, 300, true)
c.setClockPeriod(7) c.setClockPeriod(7)
c.addFixedRoot(tcBase, 4, nil) c.addFixedCommitteeRoot(tcBase, 4, nil)
c.addFixedRoot(tcBase, 5, nil) c.addFixedCommitteeRoot(tcBase, 5, nil)
c.addFixedRoot(tcBase, 6, nil) c.addFixedCommitteeRoot(tcBase, 6, nil)
c.addFixedRoot(tcBase, 8, ErrInvalidPeriod) // range has to be continuous c.addFixedCommitteeRoot(tcBase, 8, ErrInvalidPeriod) // range has to be continuous
c.addFixedRoot(tcBase, 3, nil) c.addFixedCommitteeRoot(tcBase, 3, nil)
c.addFixedRoot(tcBase, 2, nil) c.addFixedCommitteeRoot(tcBase, 2, nil)
if reload { if reload {
c.reloadChain() c.reloadChain()
} }
@ -87,8 +87,8 @@ func TestCommitteeChainCheckpointSync(t *testing.T) {
c.setClockPeriod(6) c.setClockPeriod(6)
} }
c.insertUpdate(tcBase, 3, true, ErrInvalidPeriod) c.insertUpdate(tcBase, 3, true, ErrInvalidPeriod)
c.addFixedRoot(tcBase, 3, nil) c.addFixedCommitteeRoot(tcBase, 3, nil)
c.addFixedRoot(tcBase, 4, nil) c.addFixedCommitteeRoot(tcBase, 4, nil)
c.insertUpdate(tcBase, 4, true, ErrInvalidPeriod) // still no committee c.insertUpdate(tcBase, 4, true, ErrInvalidPeriod) // still no committee
c.addCommittee(tcBase, 3, nil) c.addCommittee(tcBase, 3, nil)
c.addCommittee(tcBase, 4, nil) c.addCommittee(tcBase, 4, nil)
@ -120,7 +120,7 @@ func TestCommitteeChainCheckpointSync(t *testing.T) {
c.verifyRange(tcBase, 3, 7) // now period 7 can also be verified c.verifyRange(tcBase, 3, 7) // now period 7 can also be verified
// try reverse syncing an update // try reverse syncing an update
c.insertUpdate(tcBase, 2, false, ErrInvalidPeriod) // fixed committee is needed first c.insertUpdate(tcBase, 2, false, ErrInvalidPeriod) // fixed committee is needed first
c.addFixedRoot(tcBase, 2, nil) c.addFixedCommitteeRoot(tcBase, 2, nil)
c.addCommittee(tcBase, 2, nil) c.addCommittee(tcBase, 2, nil)
c.insertUpdate(tcBase, 2, false, nil) c.insertUpdate(tcBase, 2, false, nil)
c.verifyRange(tcBase, 2, 7) c.verifyRange(tcBase, 2, 7)
@ -133,8 +133,8 @@ func TestCommitteeChainReorg(t *testing.T) {
for _, addBetterUpdates := range []bool{false, true} { for _, addBetterUpdates := range []bool{false, true} {
c := newCommitteeChainTest(t, tfBase, 300, true) c := newCommitteeChainTest(t, tfBase, 300, true)
c.setClockPeriod(11) c.setClockPeriod(11)
c.addFixedRoot(tcBase, 3, nil) c.addFixedCommitteeRoot(tcBase, 3, nil)
c.addFixedRoot(tcBase, 4, nil) c.addFixedCommitteeRoot(tcBase, 4, nil)
c.addCommittee(tcBase, 3, nil) c.addCommittee(tcBase, 3, nil)
for period := uint64(3); period < 10; period++ { for period := uint64(3); period < 10; period++ {
c.insertUpdate(tcBase, period, true, nil) c.insertUpdate(tcBase, period, true, nil)
@ -193,8 +193,8 @@ func TestCommitteeChainFork(t *testing.T) {
c := newCommitteeChainTest(t, tfAlternative, 300, true) c := newCommitteeChainTest(t, tfAlternative, 300, true)
c.setClockPeriod(11) c.setClockPeriod(11)
// trying to sync a chain on an alternative fork with the base chain data // trying to sync a chain on an alternative fork with the base chain data
c.addFixedRoot(tcBase, 0, nil) c.addFixedCommitteeRoot(tcBase, 0, nil)
c.addFixedRoot(tcBase, 1, nil) c.addFixedCommitteeRoot(tcBase, 1, nil)
c.addCommittee(tcBase, 0, nil) c.addCommittee(tcBase, 0, nil)
// shared section should sync without errors // shared section should sync without errors
for period := uint64(0); period < 7; period++ { for period := uint64(0); period < 7; period++ {
@ -258,9 +258,9 @@ func (c *committeeChainTest) setClockPeriod(period float64) {
c.clock.Run(wait) c.clock.Run(wait)
} }
func (c *committeeChainTest) addFixedRoot(tc *testCommitteeChain, period uint64, expErr error) { func (c *committeeChainTest) addFixedCommitteeRoot(tc *testCommitteeChain, period uint64, expErr error) {
if err := c.chain.AddFixedRoot(period, tc.periods[period].committee.Root()); err != expErr { if err := c.chain.AddFixedCommitteeRoot(period, tc.periods[period].committee.Root()); err != expErr {
c.t.Errorf("Incorrect error output from AddFixedRoot at period %d (expected %v, got %v)", period, expErr, err) c.t.Errorf("Incorrect error output from AddFixedCommitteeRoot at period %d (expected %v, got %v)", period, expErr, err)
} }
} }

View file

@ -26,8 +26,8 @@ func (a Range) IsEmpty() bool {
return a.End == a.Start return a.End == a.Start
} }
// Includes returns true if the range includes the given period. // Contains returns true if the range includes the given period.
func (a Range) Includes(period uint64) bool { func (a Range) Contains(period uint64) bool {
return period >= a.Start && period < a.End return period >= a.Start && period < a.End
} }
@ -38,21 +38,17 @@ func (a Range) CanExpand(period uint64) bool {
return a.IsEmpty() || (period+1 >= a.Start && period <= a.End) return a.IsEmpty() || (period+1 >= a.Start && period <= a.End)
} }
// Expand expands the range with the given period (assumes that CanExpand returned true). // Expand expands the range with the given period.
// This method assumes that CanExpand returned true: otherwise this is a no-op.
func (a *Range) Expand(period uint64) { func (a *Range) Expand(period uint64) {
if a.IsEmpty() { if a.IsEmpty() {
a.Start, a.End = period, period+1 a.Start, a.End = period, period+1
return return
} }
if a.Includes(period) {
return
}
if a.Start == period+1 { if a.Start == period+1 {
a.Start-- a.Start--
return
} }
if a.End == period { if a.End == period {
a.End++ a.End++
return
} }
} }

View file

@ -132,9 +132,9 @@ var (
CliqueSnapshotPrefix = []byte("clique-") CliqueSnapshotPrefix = []byte("clique-")
BestUpdateKey = []byte("update-") // bigEndian64(syncPeriod) -> RLP(types.LightClientUpdate) (nextCommittee only referenced by root hash) BestUpdateKey = []byte("update-") // bigEndian64(syncPeriod) -> RLP(types.LightClientUpdate) (nextCommittee only referenced by root hash)
FixedRootKey = []byte("fixedRoot-") // bigEndian64(syncPeriod) -> committee root hash FixedCommitteeRootKey = []byte("fixedRoot-") // bigEndian64(syncPeriod) -> committee root hash
SyncCommitteeKey = []byte("committee-") // bigEndian64(syncPeriod) -> serialized committee SyncCommitteeKey = []byte("committee-") // bigEndian64(syncPeriod) -> serialized committee
preimageCounter = metrics.NewRegisteredCounter("db/preimage/total", nil) preimageCounter = metrics.NewRegisteredCounter("db/preimage/total", nil)
preimageHitCounter = metrics.NewRegisteredCounter("db/preimage/hits", nil) preimageHitCounter = metrics.NewRegisteredCounter("db/preimage/hits", nil)