Skip to content

Commit d1e1313

Browse files
committed
dbft: optimize the API for obtaining the list of validators
1 parent 6d13893 commit d1e1313

File tree

4 files changed

+40
-34
lines changed

4 files changed

+40
-34
lines changed

consensus/dbft/dbft.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -426,16 +426,16 @@ func (c *DBFT) getValidatorsCb(txs ...dbft.Transaction[common.Hash]) []dbft.Publ
426426
err error
427427
)
428428
if txs == nil {
429-
// GetValidatorsSorted with empty args is used by dbft to fill the list of
429+
// GetValidatorsSortedByBlockNumber is used by dbft to fill the list of
430430
// block's validators, thus should return validators from the current
431431
// epoch without recalculation.
432432
if c.backend != nil {
433-
pKeys, err = c.backend.GetValidatorsSorted(&c.lastIndex, nil, nil)
433+
pKeys, err = c.backend.GetValidatorsSortedByBlockNumber(c.lastIndex)
434434
} else {
435435
err = errNotInitializedBackend
436436
}
437437
}
438-
// GetValidatorsSorted with non-empty args is used by dbft to fill block's
438+
// GetValidatorsSortedByState is used by dbft to fill block's
439439
// NextConsensus field, but DBFT doesn't provide WithGetConsensusAddress
440440
// callback and fills NextConsensus by itself via WithNewBlockFromContext
441441
// callback. Thus, leave pKeys empty if txes != nil.
@@ -2405,7 +2405,7 @@ func (c *DBFT) validatePayload(p *Payload) error {
24052405
if c.backend == nil {
24062406
return errNotInitializedBackend
24072407
}
2408-
validators, err := c.backend.GetValidatorsSorted(&h, nil, nil)
2408+
validators, err := c.backend.GetValidatorsSortedByBlockNumber(h)
24092409
if err != nil {
24102410
return fmt.Errorf("failed to get next block validators: %w", err)
24112411
}
@@ -2491,7 +2491,7 @@ func (c *DBFT) calcDifficulty(signer common.Address, parent *types.Header) *big.
24912491
if c.backend == nil {
24922492
return nil
24932493
}
2494-
vals, err := c.backend.GetValidatorsSorted(&h, nil, nil)
2494+
vals, err := c.backend.GetValidatorsSortedByBlockNumber(h)
24952495
if err != nil {
24962496
return nil
24972497
}
@@ -2712,7 +2712,7 @@ func (c *DBFT) getNextConsensus(h *types.Header, s *state.StateDB) (common.Hash,
27122712
if c.backend == nil {
27132713
log.Crit("Can't calculate next consensus", "err", errNotInitializedBackend)
27142714
}
2715-
nextVals, err := c.backend.GetValidatorsSorted(nil, s.Copy(), h)
2715+
nextVals, err := c.backend.GetValidatorsSortedByState(s.Copy(), h)
27162716
if err != nil {
27172717
log.Crit("Failed to compute next block validators",
27182718
"err", err)

eth/api_backend.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -470,8 +470,12 @@ func (b *EthAPIBackend) IsExtensibleAllowed(blockNum uint64, addr common.Address
470470
return b.eth.extensibleVerifier.IsExtensibleAllowed(blockNum, addr)
471471
}
472472

473-
func (b *EthAPIBackend) GetValidatorsSorted(blockNum *uint64, state *state.StateDB, header *types.Header) ([]common.Address, error) {
474-
return b.eth.extensibleVerifier.GetValidatorsSorted(blockNum, state, header)
473+
func (b *EthAPIBackend) GetValidatorsSortedByBlockNumber(blockNum uint64) ([]common.Address, error) {
474+
return b.eth.extensibleVerifier.GetValidatorsSortedByBlockNumber(blockNum)
475+
}
476+
477+
func (b *EthAPIBackend) GetValidatorsSortedByState(state *state.StateDB, header *types.Header) ([]common.Address, error) {
478+
return b.eth.extensibleVerifier.GetValidatorsSortedByState(state, header)
475479
}
476480

477481
func (b *EthAPIBackend) GetDKGIndex(blockNum uint64, validatorIndex int) (int, error) {

eth/verifier/extensible_verifier.go

Lines changed: 26 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -115,48 +115,47 @@ func (v *ExtensibleVerifier) Close() {
115115

116116
// IsExtensibleAllowed determines if address is allowed to send extensible payloads
117117
// (only consensus payloads for now) at the specified height.
118-
func (v *ExtensibleVerifier) IsExtensibleAllowed(h uint64, u common.Address) error {
118+
func (v *ExtensibleVerifier) IsExtensibleAllowed(blockNum uint64, addr common.Address) error {
119119
// Can't verify extensible sender if the node has an outdated state.
120120
if v.syncing.Load() {
121121
return dbftproto.ErrSyncing
122122
}
123123
// Only validators are included into extensible whitelist for now.
124-
validators, err := v.GetValidatorsSorted(&h, nil, nil)
124+
validators, err := v.GetValidatorsSortedByBlockNumber(blockNum)
125125
if err != nil {
126126
return fmt.Errorf("failed to get validators: %w", err)
127127
}
128-
_, found := slices.BinarySearchFunc(validators, u, common.Address.Cmp)
128+
_, found := slices.BinarySearchFunc(validators, addr, common.Address.Cmp)
129129
if !found {
130130
return fmt.Errorf("address is not a validator")
131131
}
132132
return nil
133133
}
134134

135-
// GetValidatorsSorted returns validators chosen in the result of the latest
136-
// finalized voting epoch. It calls Governance contract under the hood. The call
137-
// is based on the provided state or (if not provided) on the state of the block
138-
// with the specified height. Validators returned from this method are always
139-
// sorted by bytes order (even if the list returned from governance contract is
140-
// sorted in another way). This method uses cached values in case of validators
141-
// requested by block height.
142-
func (v *ExtensibleVerifier) GetValidatorsSorted(blockNum *uint64, state *state.StateDB, header *types.Header) ([]common.Address, error) {
143-
res, err := v.getValidators(blockNum, state, header)
144-
if err != nil {
145-
return nil, err
146-
}
135+
// GetValidatorsSortedByBlockNumber returns validators chosen in the result of the
136+
// latest finalized voting epoch. It calls Governance contract under the hood. The
137+
// call is based on the state of the block with the specified height. Validators
138+
// returned from this method are sorted in the original order used by Governance
139+
// contract. This method will use the cached values.
140+
func (v *ExtensibleVerifier) GetValidatorsSortedByBlockNumber(blockNum uint64) ([]common.Address, error) {
141+
return v.getValidatorsSorted(&blockNum, nil, nil)
142+
}
147143

148-
sortedList := slices.Clone(res)
149-
slices.SortFunc(sortedList, common.Address.Cmp)
150-
return sortedList, err
144+
// GetValidatorsSortedByState returns validators chosen in the result of the latest
145+
// finalized voting epoch. It calls Governance contract under the hood. The call is
146+
// based on the provided state. Validators returned from this method are sorted in
147+
// the original order used by Governance contract.
148+
func (v *ExtensibleVerifier) GetValidatorsSortedByState(state *state.StateDB, header *types.Header) ([]common.Address, error) {
149+
return v.getValidatorsSorted(nil, state, header)
151150
}
152151

153-
// getValidators returns validators chosen in the result of the latest finalized
152+
// getValidatorsSorted returns validators chosen in the result of the latest finalized
154153
// voting epoch. It calls Governance contract under the hood. The call is based
155154
// on the provided state or (if not provided) on the state of the block with the
156155
// specified height. Validators returned from this method are sorted in the original
157156
// order used by Governance contract. This method uses cached values in case of
158157
// validators requested by block height.
159-
func (v *ExtensibleVerifier) getValidators(blockNum *uint64, state *state.StateDB, header *types.Header) ([]common.Address, error) {
158+
func (v *ExtensibleVerifier) getValidatorsSorted(blockNum *uint64, state *state.StateDB, header *types.Header) ([]common.Address, error) {
160159
if state == nil && blockNum != nil {
161160
vals, ok := v.validatorsCache.Get(*blockNum)
162161
if ok {
@@ -193,18 +192,20 @@ func (v *ExtensibleVerifier) getValidators(blockNum *uint64, state *state.StateD
193192
if err != nil {
194193
return nil, fmt.Errorf("failed to perform '%s' call: %w", method, err)
195194
}
196-
var res []common.Address
197-
err = unpackContractExecutionResult(&res, result, systemcontracts.GovernanceABI, method)
195+
var validators []common.Address
196+
err = unpackContractExecutionResult(&validators, result, systemcontracts.GovernanceABI, method)
198197
if err != nil {
199198
return nil, err
200199
}
201200

201+
slices.SortFunc(validators, common.Address.Cmp)
202+
202203
// Update cache in case if existing state was used for validators retrieval.
203204
if state == nil && blockNum != nil {
204-
_ = v.validatorsCache.Add(*blockNum, res)
205+
_ = v.validatorsCache.Add(*blockNum, validators)
205206
}
206207

207-
return res, err
208+
return validators, err
208209
}
209210

210211
func unpackContractExecutionResult(res interface{}, result *core.ExecutionResult, contractAbi abi.ABI, method string) error {
@@ -223,7 +224,7 @@ func unpackContractExecutionResult(res interface{}, result *core.ExecutionResult
223224
func (v *ExtensibleVerifier) GetDKGIndex(blockNum uint64, validatorIndex int) (int, error) {
224225
indices, ok := v.dkgIndexCache.Get(blockNum)
225226
if !ok {
226-
originValidators, err := v.getValidators(&blockNum, nil, nil)
227+
originValidators, err := v.getValidatorsSorted(&blockNum, nil, nil)
227228
if err != nil {
228229
return -1, err
229230
}

internal/ethapi/backend.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,8 @@ type Backend interface {
106106
IsExtensibleAllowed(blockNum uint64, addr common.Address) error
107107

108108
// Validators API
109-
GetValidatorsSorted(blockNum *uint64, state *state.StateDB, header *types.Header) ([]common.Address, error)
109+
GetValidatorsSortedByBlockNumber(blockNum uint64) ([]common.Address, error)
110+
GetValidatorsSortedByState(state *state.StateDB, header *types.Header) ([]common.Address, error)
110111
GetDKGIndex(blockNum uint64, validatorIndex int) (int, error)
111112
}
112113

0 commit comments

Comments
 (0)