Skip to content

Commit

Permalink
Merge pull request #640 from iotaledger/feat/activity-window
Browse files Browse the repository at this point in the history
Activity Window from Protocol Parameters
  • Loading branch information
cyberphysic4l authored Jan 14, 2024
2 parents 52146a2 + d2653c4 commit e0e827a
Show file tree
Hide file tree
Showing 19 changed files with 82 additions and 113 deletions.
4 changes: 2 additions & 2 deletions pkg/core/account/accounts.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,8 @@ func (a *Accounts) ForEach(callback func(id iotago.AccountID, pool *Pool) bool)
a.accountPools.ForEach(callback)
}

// SelectCommittee creates a new SeatedAccounts instance, that maintains the seats of the given members.
func (a *Accounts) SelectCommittee(members ...iotago.AccountID) *SeatedAccounts {
// SeatedAccounts creates a new SeatedAccounts instance, that maintains the seats of the given members.
func (a *Accounts) SeatedAccounts(members ...iotago.AccountID) *SeatedAccounts {
return NewSeatedAccounts(a, members...)
}

Expand Down
4 changes: 2 additions & 2 deletions pkg/core/account/accounts_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,11 +108,11 @@ func TestAccounts(t *testing.T) {
// check "SelectCommittee"

// get 1 issuer
seated := accounts.SelectCommittee(accountIDs[0])
seated := accounts.SeatedAccounts(accountIDs[0])
require.Equal(t, 1, seated.SeatCount())

// get all issuers
seated = accounts.SelectCommittee(accountIDs...)
seated = accounts.SeatedAccounts(accountIDs...)
require.Equal(t, len(accountIDs), seated.SeatCount())

/*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ func NewTestFramework(test *testing.T) *TestFramework {
members = append(members, issuer.accountID)
return true
})
return accounts.SelectCommittee(members...), true
return accounts.SeatedAccounts(members...), true
}

t.testAPI = iotago.V3API(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ type AccountsTestFramework struct {
func NewAccountsTestFramework(test *testing.T, instance *account.Accounts) *AccountsTestFramework {
return &AccountsTestFramework{
Instance: instance,
Committee: instance.SelectCommittee(),
Committee: instance.SeatedAccounts(),

test: test,
identitiesByAlias: make(map[string]iotago.AccountID),
Expand Down
2 changes: 1 addition & 1 deletion pkg/protocol/engine/mempool/v1/mempool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ func newTestFramework(t *testing.T) *mempooltests.TestFramework {
workers := workerpool.NewGroup(t.Name())

ledgerState := ledgertests.New(ledgertests.NewMockedState(iotago.EmptyTransactionID, 0))
spendDAG := spenddagv1.New[iotago.TransactionID, mempool.StateID, vote.MockedRank](account.NewAccounts().SelectCommittee().SeatCount)
spendDAG := spenddagv1.New[iotago.TransactionID, mempool.StateID, vote.MockedRank](account.NewAccounts().SeatedAccounts().SeatCount)

mutationsFunc := func(index iotago.SlotIndex) (kvstore.KVStore, error) {
return mapdb.NewMapDB(), nil
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,17 @@ type ActivityTracker struct {
lastActivityTime time.Time
activityMutex syncutils.RWMutex

activityWindow time.Duration
apiProvider iotago.APIProvider
}

func NewActivityTracker(activityWindow time.Duration) *ActivityTracker {
func NewActivityTracker(apiProvider iotago.APIProvider) *ActivityTracker {
return &ActivityTracker{
Events: activitytracker.NewEvents(),
onlineCommittee: ds.NewSet[account.SeatIndex](),
inactivityQueue: timed.NewPriorityQueue[account.SeatIndex](true),
lastActivities: shrinkingmap.New[account.SeatIndex, time.Time](),

activityWindow: activityWindow,
apiProvider: apiProvider,
}
}

Expand All @@ -48,7 +48,10 @@ func (a *ActivityTracker) MarkSeatActive(seat account.SeatIndex, id iotago.Accou
a.activityMutex.Lock()
defer a.activityMutex.Unlock()

if lastActivity, exists := a.lastActivities.Get(seat); (exists && lastActivity.After(seatActivityTime)) || seatActivityTime.Before(a.lastActivityTime.Add(-a.activityWindow)) {
// activity window is given by min committable age in seconds from the protocol parameters
protocolParams := a.apiProvider.APIForTime(seatActivityTime).ProtocolParameters()
activityWindow := time.Duration(protocolParams.MinCommittableAge()*iotago.SlotIndex(protocolParams.SlotDurationInSeconds())) * time.Second
if lastActivity, exists := a.lastActivities.Get(seat); (exists && lastActivity.After(seatActivityTime)) || seatActivityTime.Before(a.lastActivityTime.Add(-activityWindow)) {
return
} else if !exists {
a.onlineCommittee.Add(seat)
Expand All @@ -65,7 +68,7 @@ func (a *ActivityTracker) MarkSeatActive(seat account.SeatIndex, id iotago.Accou

a.lastActivityTime = seatActivityTime

activityThreshold := seatActivityTime.Add(-a.activityWindow)
activityThreshold := seatActivityTime.Add(-activityWindow)
for _, inactiveSeat := range a.inactivityQueue.PopUntil(activityThreshold) {
if lastActivityForInactiveSeat, exists := a.lastActivities.Get(inactiveSeat); exists && lastActivityForInactiveSeat.After(activityThreshold) {
continue
Expand Down
14 changes: 7 additions & 7 deletions pkg/protocol/sybilprotection/seatmanager/mock/mockseatmanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func NewManualPOA(e iotago.APIProvider, committeeStore *epochstore.Store[*accoun
online: ds.NewSet[account.SeatIndex](),
aliases: shrinkingmap.New[string, iotago.AccountID](),
}
m.committee = m.accounts.SelectCommittee()
m.committee = m.accounts.SeatedAccounts()

return m
}
Expand Down Expand Up @@ -71,7 +71,7 @@ func (m *ManualPOA) AddRandomAccount(alias string) iotago.AccountID {

m.aliases.Set(alias, id)

m.committee = m.accounts.SelectCommittee(m.accounts.IDs()...)
m.committee = m.accounts.SeatedAccounts(m.accounts.IDs()...)

if err := m.committeeStore.Store(0, m.accounts); err != nil {
panic(err)
Expand All @@ -90,7 +90,7 @@ func (m *ManualPOA) AddAccount(id iotago.AccountID, alias string) iotago.Account
}
m.aliases.Set(alias, id)

m.committee = m.accounts.SelectCommittee(m.accounts.IDs()...)
m.committee = m.accounts.SeatedAccounts(m.accounts.IDs()...)

if err := m.committeeStore.Store(0, m.accounts); err != nil {
panic(err)
Expand Down Expand Up @@ -152,7 +152,7 @@ func (m *ManualPOA) committeeInEpoch(epoch iotago.EpochIndex) (*account.SeatedAc
return nil, false
}

return c.SelectCommittee(c.IDs()...), true
return c.SeatedAccounts(c.IDs()...), true
}

func (m *ManualPOA) OnlineCommittee() ds.Set[account.SeatIndex] {
Expand All @@ -179,7 +179,7 @@ func (m *ManualPOA) RotateCommittee(epoch iotago.EpochIndex, validators accounts
return nil, ierrors.Wrapf(err, "error while setting pool for epoch %d for validator %s", epoch, validatorData.ID.String())
}
}
m.committee = m.accounts.SelectCommittee(m.accounts.IDs()...)
m.committee = m.accounts.SeatedAccounts(m.accounts.IDs()...)
}

if err := m.committeeStore.Store(epoch, m.accounts); err != nil {
Expand All @@ -189,10 +189,10 @@ func (m *ManualPOA) RotateCommittee(epoch iotago.EpochIndex, validators accounts
return m.committee, nil
}

func (m *ManualPOA) SetCommittee(epoch iotago.EpochIndex, validators *account.Accounts) error {
func (m *ManualPOA) ReuseCommittee(epoch iotago.EpochIndex, validators *account.Accounts) error {
if m.committee == nil || m.accounts.Size() == 0 {
m.accounts = validators
m.committee = m.accounts.SelectCommittee(validators.IDs()...)
m.committee = m.accounts.SeatedAccounts(validators.IDs()...)
}

if err := m.committeeStore.Store(epoch, validators); err != nil {
Expand Down
9 changes: 0 additions & 9 deletions pkg/protocol/sybilprotection/seatmanager/poa/options.go
Original file line number Diff line number Diff line change
@@ -1,19 +1,10 @@
package poa

import (
"time"

"github.com/iotaledger/hive.go/runtime/options"
iotago "github.com/iotaledger/iota.go/v4"
)

// WithActivityWindow sets the duration for which a validator is recognized as active after issuing a block.
func WithActivityWindow(activityWindow time.Duration) options.Option[SeatManager] {
return func(p *SeatManager) {
p.optsActivityWindow = activityWindow
}
}

func WithOnlineCommitteeStartup(optsOnlineCommittee ...iotago.AccountID) options.Option[SeatManager] {
return func(p *SeatManager) {
p.optsOnlineCommitteeStartup = optsOnlineCommittee
Expand Down
15 changes: 6 additions & 9 deletions pkg/protocol/sybilprotection/seatmanager/poa/poa.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ type SeatManager struct {

committeeMutex syncutils.RWMutex

optsActivityWindow time.Duration
optsOnlineCommitteeStartup []iotago.AccountID

module.Module
Expand All @@ -44,10 +43,8 @@ func NewProvider(opts ...options.Option[SeatManager]) module.Provider[*engine.En
events: seatmanager.NewEvents(),
apiProvider: e,
committeeStore: e.Storage.Committee(),

optsActivityWindow: time.Second * 30,
}, opts, func(s *SeatManager) {
activityTracker := activitytrackerv1.NewActivityTracker(s.optsActivityWindow)
activityTracker := activitytrackerv1.NewActivityTracker(e)
s.activityTracker = activityTracker
s.events.OnlineCommitteeSeatAdded.LinkTo(activityTracker.Events.OnlineCommitteeSeatAdded)
s.events.OnlineCommitteeSeatRemoved.LinkTo(activityTracker.Events.OnlineCommitteeSeatRemoved)
Expand Down Expand Up @@ -97,7 +94,7 @@ func (s *SeatManager) RotateCommittee(epoch iotago.EpochIndex, validators accoun
return nil, ierrors.Wrapf(err, "error while setting committee for epoch %d for validator %s", epoch, validatorData.ID.String())
}
}
s.committee = committeeAccounts.SelectCommittee(committeeAccounts.IDs()...)
s.committee = committeeAccounts.SeatedAccounts(committeeAccounts.IDs()...)
}

accounts, err := s.committee.Accounts()
Expand Down Expand Up @@ -138,7 +135,7 @@ func (s *SeatManager) committeeInEpoch(epoch iotago.EpochIndex) (*account.Seated
return nil, false
}

return c.SelectCommittee(c.IDs()...), true
return c.SeatedAccounts(c.IDs()...), true
}

// OnlineCommittee returns the set of validators selected to be part of the committee that has been seen recently.
Expand Down Expand Up @@ -174,7 +171,7 @@ func (s *SeatManager) InitializeCommittee(epoch iotago.EpochIndex, activityTime
}

committeeAccountsIDs := committeeAccounts.IDs()
s.committee = committeeAccounts.SelectCommittee(committeeAccountsIDs...)
s.committee = committeeAccounts.SeatedAccounts(committeeAccountsIDs...)

// Set validators that are part of the committee as active.
onlineValidators := committeeAccountsIDs
Expand All @@ -195,11 +192,11 @@ func (s *SeatManager) InitializeCommittee(epoch iotago.EpochIndex, activityTime
return nil
}

func (s *SeatManager) SetCommittee(epoch iotago.EpochIndex, validators *account.Accounts) error {
func (s *SeatManager) ReuseCommittee(epoch iotago.EpochIndex, validators *account.Accounts) error {
s.committeeMutex.Lock()
defer s.committeeMutex.Unlock()

s.committee = validators.SelectCommittee(validators.IDs()...)
s.committee = validators.SeatedAccounts(validators.IDs()...)

accounts, err := s.committee.Accounts()
if err != nil {
Expand Down
5 changes: 2 additions & 3 deletions pkg/protocol/sybilprotection/seatmanager/seatmanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,8 @@ type SeatManager interface {
// RotateCommittee rotates the committee evaluating the given set of candidates to produce the new committee.
RotateCommittee(epoch iotago.EpochIndex, candidates accounts.AccountsData) (*account.SeatedAccounts, error)

// SetCommittee sets the committee for a given slot.
// This is used when re-using the same committee for consecutive epochs.
SetCommittee(epoch iotago.EpochIndex, committee *account.Accounts) error
// ReuseCommittee reuses the committee from a previous epoch.
ReuseCommittee(epoch iotago.EpochIndex, committee *account.Accounts) error

// InitializeCommittee initializes the committee for the current slot by marking whole or a subset of the committee as active.
// This is used when initializing committee after node startup (loaded from snapshot or database).
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,10 @@
package topstakers

import (
"time"

"github.com/iotaledger/hive.go/runtime/options"
iotago "github.com/iotaledger/iota.go/v4"
)

// WithActivityWindow sets the duration for which a validator is recognized as active after issuing a block.
func WithActivityWindow(activityWindow time.Duration) options.Option[SeatManager] {
return func(p *SeatManager) {
p.optsActivityWindow = activityWindow
}
}

func WithOnlineCommitteeStartup(optsOnlineCommittee ...iotago.AccountID) options.Option[SeatManager] {
return func(p *SeatManager) {
p.optsOnlineCommitteeStartup = optsOnlineCommittee
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ type SeatManager struct {
committeeMutex syncutils.RWMutex
activityTracker activitytracker.ActivityTracker

optsActivityWindow time.Duration
optsOnlineCommitteeStartup []iotago.AccountID

module.Module
Expand All @@ -45,10 +44,8 @@ func NewProvider(opts ...options.Option[SeatManager]) module.Provider[*engine.En
apiProvider: e,
events: seatmanager.NewEvents(),
committeeStore: e.Storage.Committee(),

optsActivityWindow: time.Second * 30,
}, opts, func(s *SeatManager) {
activityTracker := activitytrackerv1.NewActivityTracker(s.optsActivityWindow)
activityTracker := activitytrackerv1.NewActivityTracker(e)
s.activityTracker = activityTracker
s.events.OnlineCommitteeSeatAdded.LinkTo(activityTracker.Events.OnlineCommitteeSeatAdded)
s.events.OnlineCommitteeSeatRemoved.LinkTo(activityTracker.Events.OnlineCommitteeSeatRemoved)
Expand Down Expand Up @@ -132,7 +129,7 @@ func (s *SeatManager) committeeInEpoch(epoch iotago.EpochIndex) (*account.Seated
return nil, false
}

return c.SelectCommittee(c.IDs()...), true
return c.SeatedAccounts(c.IDs()...), true
}

// OnlineCommittee returns the set of validators selected to be part of the committee that has been seen recently.
Expand Down Expand Up @@ -171,7 +168,7 @@ func (s *SeatManager) InitializeCommittee(epoch iotago.EpochIndex, activityTime
return ierrors.Wrapf(err, "failed to load PoA committee for epoch %d", epoch)
}

committee := committeeAccounts.SelectCommittee(committeeAccounts.IDs()...)
committee := committeeAccounts.SeatedAccounts(committeeAccounts.IDs()...)

onlineValidators := committeeAccounts.IDs()
if len(s.optsOnlineCommitteeStartup) > 0 {
Expand All @@ -191,7 +188,7 @@ func (s *SeatManager) InitializeCommittee(epoch iotago.EpochIndex, activityTime
return nil
}

func (s *SeatManager) SetCommittee(epoch iotago.EpochIndex, validators *account.Accounts) error {
func (s *SeatManager) ReuseCommittee(epoch iotago.EpochIndex, validators *account.Accounts) error {
s.committeeMutex.Lock()
defer s.committeeMutex.Unlock()

Expand Down Expand Up @@ -249,7 +246,7 @@ func (s *SeatManager) selectNewCommittee(epoch iotago.EpochIndex, candidates acc
return nil, ierrors.Wrapf(err, "error while setting pool for committee candidate %s", candidateData.ID.String())
}
}
committee := newCommitteeAccounts.SelectCommittee(newCommitteeAccounts.IDs()...)
committee := newCommitteeAccounts.SeatedAccounts(newCommitteeAccounts.IDs()...)

return committee, nil
}
Loading

0 comments on commit e0e827a

Please sign in to comment.