Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion .docker/volumes/node_1/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,5 +44,13 @@
"individualMaxTxSize": 4000,
"dropPercentage": 35,
"metricsEnabled": true,
"prometheusAddress": "0.0.0.0:9090"
"prometheusAddress": "0.0.0.0:9090",
"initialTokensPerBlock": 80000000,
"blocksPerHalvening": 3150000,
"upgrades": {
"skipCommitteeStore": {
"enabled": true,
"activationHeight": 0
}
}
}
10 changes: 9 additions & 1 deletion .docker/volumes/node_2/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,13 @@
"individualMaxTxSize": 4000,
"dropPercentage": 35,
"metricsEnabled": true,
"prometheusAddress": "0.0.0.0:9091"
"prometheusAddress": "0.0.0.0:9091",
"initialTokensPerBlock": 80000000,
"blocksPerHalvening": 3150000,
"upgrades": {
"skipCommitteeStore": {
"enabled": true,
"activationHeight": 0
}
}
}
10 changes: 9 additions & 1 deletion .docker/volumes/node_3/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,13 @@
"individualMaxTxSize": 4000,
"dropPercentage": 35,
"metricsEnabled": true,
"prometheusAddress": "0.0.0.0:9090"
"prometheusAddress": "0.0.0.0:9090",
"initialTokensPerBlock": 80000000,
"blocksPerHalvening": 3150000,
"upgrades": {
"skipCommitteeStore": {
"enabled": true,
"activationHeight": 0
}
}
}
126 changes: 86 additions & 40 deletions fsm/committee.go
Original file line number Diff line number Diff line change
Expand Up @@ -251,23 +251,34 @@ func (s *StateMachine) GetCommitteeMembers(chainId uint64) (vs lib.ValidatorSet,
func (s *StateMachine) GetCommitteePaginated(p lib.PageParams, chainId uint64) (page *lib.Page, err lib.ErrorI) {
// define a page and result variables
page, res := lib.NewPage(p, ValidatorsPageName), make(ValidatorPage, 0)
// populate the page using an iterator over the 'committee prefix' ordered by stake (high to low)
err = page.Load(CommitteePrefix(chainId), true, &res, s.store, func(key, value []byte) (err lib.ErrorI) {
// get the address from the key
address, err := AddressFromKey(key)
if err != nil {
return err
// retrieve the full committee member set
vs, err := s.GetCommitteeMembers(chainId)
if err != nil {
// if there are no validators, return empty page instead of error
if err.Error() == lib.ErrNoValidators().Error() {
page.Results = &res
return page, nil
}
// get the validator from the address
validator, err := s.GetValidator(address)
if err != nil {
return err
return nil, err
}
// populate the page using the consensus validator list
err = page.LoadArray(vs.ValidatorSet.ValidatorSet, &res, func(i any) (e lib.ErrorI) {
// cast to consensus validator
v, ok := i.(*lib.ConsensusValidator)
if !ok {
return lib.ErrInvalidArgument()
}
// skip if validator is not paused and not unstaking
if validator.UnstakingHeight != 0 || validator.MaxPausedHeight != 0 {
return
// calculate the address from the public key
address, e := s.pubKeyBytesToAddress(v.PublicKey)
if e != nil {
return e
}
// append the validator to the page
// get the full validator from the address
validator, e := s.GetValidator(crypto.NewAddress(address))
if e != nil {
return e
}
// append the validator to the result
res = append(res, validator)
return
})
Expand All @@ -286,11 +297,15 @@ func (s *StateMachine) UpdateCommittees(address crypto.AddressI, oldValidator *V

// SetCommittees() sets the membership and staked supply for all an addresses' committees
func (s *StateMachine) SetCommittees(address crypto.AddressI, totalStake uint64, committees []uint64) (err lib.ErrorI) {
// check if committee store operations should be skipped
skipStore := s.ShouldSkipCommitteeStore()
// for each committee in the list
for _, committee := range committees {
// set the address as a member
if err = s.SetCommitteeMember(address, committee, totalStake); err != nil {
return
if !skipStore {
// set the address as a member
if err = s.SetCommitteeMember(address, committee, totalStake); err != nil {
return
}
}
// add to the committee staked supply
if err = s.AddToCommitteeSupplyForChain(committee, totalStake); err != nil {
Expand All @@ -302,11 +317,15 @@ func (s *StateMachine) SetCommittees(address crypto.AddressI, totalStake uint64,

// DeleteCommittees() deletes the membership and staked supply for each of an address' committees
func (s *StateMachine) DeleteCommittees(address crypto.AddressI, totalStake uint64, committees []uint64) (err lib.ErrorI) {
// check if committee store operations should be skipped
skipStore := s.ShouldSkipCommitteeStore()
// for each committee in the list
for _, committee := range committees {
// remove the address from being a member
if err = s.DeleteCommitteeMember(address, committee, totalStake); err != nil {
return
if !skipStore {
// remove the address from being a member
if err = s.DeleteCommitteeMember(address, committee, totalStake); err != nil {
return
}
}
// subtract from the committee staked supply
if err = s.SubFromCommitteeStakedSupplyForChain(committee, totalStake); err != nil {
Expand All @@ -326,6 +345,12 @@ func (s *StateMachine) DeleteCommitteeMember(address crypto.AddressI, chainId, s
return s.Delete(KeyForCommittee(chainId, address, stakeForCommittee))
}

// ShouldSkipCommitteeStore returns true if the committee store operations should be skipped
func (s *StateMachine) ShouldSkipCommitteeStore() bool {
return s.Config.Upgrades.SkipCommitteeStore.Enabled &&
s.height >= s.Config.Upgrades.SkipCommitteeStore.ActivationHeight
}

// DELEGATIONS BELOW

// GetDelegates returns the active delegates for a given chainId.
Expand All @@ -338,23 +363,34 @@ func (s *StateMachine) GetDelegates(chainId uint64) (vs lib.ValidatorSet, err li
func (s *StateMachine) GetDelegatesPaginated(p lib.PageParams, chainId uint64) (page *lib.Page, err lib.ErrorI) {
// create a page of validator objects
page, res := lib.NewPage(p, ValidatorsPageName), make(ValidatorPage, 0)
// populate the page using the 'delegates' prefix sorted by stake (high to low)
err = page.Load(DelegatePrefix(chainId), true, &res, s.store, func(key, _ []byte) (err lib.ErrorI) {
// get the address from the key
address, err := AddressFromKey(key)
if err != nil {
return err
// retrieve the full delegate set
vs, err := s.GetDelegates(chainId)
if err != nil {
// if there are no validators, return empty page instead of error
if err.Error() == lib.ErrNoValidators().Error() {
page.Results = &res
return page, nil
}
// get the validator from the address
validator, err := s.GetValidator(address)
if err != nil {
return err
return nil, err
}
// populate the page using the consensus validator list
err = page.LoadArray(vs.ValidatorSet.ValidatorSet, &res, func(i any) (e lib.ErrorI) {
// cast to consensus validator
v, ok := i.(*lib.ConsensusValidator)
if !ok {
return lib.ErrInvalidArgument()
}
// skip if validator is paused or unstaking
if validator.UnstakingHeight != 0 || validator.MaxPausedHeight != 0 {
return
// calculate the address from the public key
address, e := s.pubKeyBytesToAddress(v.PublicKey)
if e != nil {
return e
}
// append the validator to the page
// get the full validator from the address
validator, e := s.GetValidator(crypto.NewAddress(address))
if e != nil {
return e
}
// append the validator to the result
res = append(res, validator)
return
})
Expand All @@ -373,10 +409,15 @@ func (s *StateMachine) UpdateDelegations(address crypto.AddressI, oldValidator *

// SetDelegations() sets the delegate 'membership' for an address, adding to the list and updating the supply pools
func (s *StateMachine) SetDelegations(address crypto.AddressI, totalStake uint64, committees []uint64) lib.ErrorI {
// check if committee store operations should be skipped
skipStore := s.ShouldSkipCommitteeStore()
// for each committee in the list
for _, committee := range committees {
// actually set the address in the delegate list
if err := s.SetDelegate(address, committee, totalStake); err != nil {
return err
if !skipStore {
// actually set the address in the delegate list
if err := s.SetDelegate(address, committee, totalStake); err != nil {
return err
}
}
// add to the delegate supply (used for tracking amounts)
if err := s.AddToDelegateSupplyForChain(committee, totalStake); err != nil {
Expand All @@ -392,10 +433,15 @@ func (s *StateMachine) SetDelegations(address crypto.AddressI, totalStake uint64

// DeleteDelegations() removes the delegate 'membership' for an address, removing from the list and updating the supply pools
func (s *StateMachine) DeleteDelegations(address crypto.AddressI, totalStake uint64, committees []uint64) lib.ErrorI {
// check if committee store operations should be skipped
skipStore := s.ShouldSkipCommitteeStore()
// for each committee in the list
for _, committee := range committees {
// remove the address from the delegate list
if err := s.DeleteDelegate(address, committee, totalStake); err != nil {
return err
if !skipStore {
// remove the address from the delegate list
if err := s.DeleteDelegate(address, committee, totalStake); err != nil {
return err
}
}
// remove from the delegate supply (used for tracking amounts)
if err := s.SubFromDelegateStakedSupplyForChain(committee, totalStake); err != nil {
Expand Down
10 changes: 10 additions & 0 deletions fsm/committee_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1175,12 +1175,14 @@ func TestGetDelegatesPaginated(t *testing.T) {
PublicKey: newTestPublicKeyBytes(t),
StakedAmount: 1,
Committees: []uint64{lib.CanopyChainId},
Delegate: true,
},
{
Address: newTestAddressBytes(t, 1),
PublicKey: newTestPublicKeyBytes(t, 1),
StakedAmount: 2,
Committees: []uint64{lib.CanopyChainId},
Delegate: true,
},
},
pageParams: lib.PageParams{
Expand All @@ -1198,12 +1200,14 @@ func TestGetDelegatesPaginated(t *testing.T) {
PublicKey: newTestPublicKeyBytes(t),
StakedAmount: 1,
Committees: []uint64{lib.CanopyChainId},
Delegate: true,
},
{
Address: newTestAddressBytes(t, 1),
PublicKey: newTestPublicKeyBytes(t, 1),
StakedAmount: 2,
Committees: []uint64{lib.CanopyChainId},
Delegate: true,
},
},
pageParams: lib.PageParams{
Expand All @@ -1221,12 +1225,14 @@ func TestGetDelegatesPaginated(t *testing.T) {
PublicKey: newTestPublicKeyBytes(t),
StakedAmount: 1,
Committees: []uint64{lib.CanopyChainId},
Delegate: true,
},
{
Address: newTestAddressBytes(t, 1),
PublicKey: newTestPublicKeyBytes(t, 1),
StakedAmount: 2,
Committees: []uint64{lib.CanopyChainId},
Delegate: true,
},
},
pageParams: lib.PageParams{
Expand Down Expand Up @@ -1383,6 +1389,10 @@ func TestUpdateDelegates(t *testing.T) {
require.NoError(t, err)
// run the function
require.NoError(t, sm.UpdateDelegations(addr, val, v.StakedAmount, v.Committees))
// update validator object with new committees and stake
val.StakedAmount = v.StakedAmount
val.Committees = v.Committees
require.NoError(t, sm.SetValidator(val))
}
// for each expected committee
for id, publicKeys := range test.expected {
Expand Down
8 changes: 8 additions & 0 deletions fsm/message_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1067,6 +1067,7 @@ func TestHandleMessageEditStake(t *testing.T) {
detail: "the validator is updated but the balance and delegations remains the same",
presetValidator: &Validator{
Address: newTestAddressBytes(t),
PublicKey: newTestPublicKeyBytes(t),
StakedAmount: 1,
Committees: []uint64{0, 1},
Output: newTestAddressBytes(t),
Expand All @@ -1080,6 +1081,7 @@ func TestHandleMessageEditStake(t *testing.T) {
},
expectedValidator: &Validator{
Address: newTestAddressBytes(t),
PublicKey: newTestPublicKeyBytes(t),
StakedAmount: 1,
Committees: []uint64{0, 1},
Output: newTestAddressBytes(t),
Expand Down Expand Up @@ -1164,6 +1166,7 @@ func TestHandleMessageEditStake(t *testing.T) {
detail: "the validator is updated with different delegations but the balance remains the same",
presetValidator: &Validator{
Address: newTestAddressBytes(t),
PublicKey: newTestPublicKeyBytes(t),
StakedAmount: 1,
Committees: []uint64{0, 1},
Delegate: true,
Expand All @@ -1175,6 +1178,7 @@ func TestHandleMessageEditStake(t *testing.T) {
},
expectedValidator: &Validator{
Address: newTestAddressBytes(t),
PublicKey: newTestPublicKeyBytes(t),
StakedAmount: 1,
Committees: []uint64{1, 2, 3},
Delegate: true,
Expand Down Expand Up @@ -1219,6 +1223,7 @@ func TestHandleMessageEditStake(t *testing.T) {
presetSender: 2,
presetValidator: &Validator{
Address: newTestAddressBytes(t),
PublicKey: newTestPublicKeyBytes(t),
StakedAmount: 1,
NetAddress: "tcp://example.com",
Committees: []uint64{0, 1},
Expand All @@ -1232,6 +1237,7 @@ func TestHandleMessageEditStake(t *testing.T) {
},
expectedValidator: &Validator{
Address: newTestAddressBytes(t),
PublicKey: newTestPublicKeyBytes(t),
StakedAmount: 2,
NetAddress: "tcp://example.com",
Committees: []uint64{1, 2, 3},
Expand Down Expand Up @@ -1261,6 +1267,7 @@ func TestHandleMessageEditStake(t *testing.T) {
presetSender: 2,
presetValidator: &Validator{
Address: newTestAddressBytes(t),
PublicKey: newTestPublicKeyBytes(t),
StakedAmount: 1,
Committees: []uint64{0, 1},
Delegate: true,
Expand All @@ -1273,6 +1280,7 @@ func TestHandleMessageEditStake(t *testing.T) {
},
expectedValidator: &Validator{
Address: newTestAddressBytes(t),
PublicKey: newTestPublicKeyBytes(t),
StakedAmount: 2,
Committees: []uint64{1, 2, 3},
Delegate: true,
Expand Down
3 changes: 2 additions & 1 deletion fsm/state_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,7 @@ func newTestStateMachine(t *testing.T) StateMachine {
log := lib.NewDefaultLogger()
db, err := store.NewStoreInMemory(log)
require.NoError(t, err)
smConfig := lib.DefaultStateMachineConfig()
sm := StateMachine{
store: db,
ProtocolVersion: 0,
Expand All @@ -320,7 +321,7 @@ func newTestStateMachine(t *testing.T) StateMachine {
proposeVoteConfig: AcceptAllProposals,
Config: lib.Config{
MainConfig: lib.DefaultMainConfig(),
StateMachineConfig: lib.DefaultStateMachineConfig(),
StateMachineConfig: smConfig,
},
events: new(lib.EventsTracker),
log: log,
Expand Down
Loading
Loading