mirror of
https://github.com/tendermint/tendermint.git
synced 2026-01-05 13:05:09 +00:00
Don't allow duplicates for light client providers (#7781)
* Allow for zero witness providers * Verify provider duplicates, fix tests * Add duplicate provider ID to the error * Return error on attempt to remove last witness * Verify duplicates when restoring from store
This commit is contained in:
@@ -142,14 +142,29 @@ type Client struct {
|
||||
logger log.Logger
|
||||
}
|
||||
|
||||
func validatePrimaryAndWitnesses(primary provider.Provider, witnesses []provider.Provider) error {
|
||||
witnessMap := make(map[string]struct{})
|
||||
for _, w := range witnesses {
|
||||
if w.ID() == primary.ID() {
|
||||
return fmt.Errorf("primary (%s) cannot be also configured as witness", primary.ID())
|
||||
}
|
||||
if _, duplicate := witnessMap[w.ID()]; duplicate {
|
||||
return fmt.Errorf("witness list must not contain duplicates; duplicate found: %s", w.ID())
|
||||
}
|
||||
witnessMap[w.ID()] = struct{}{}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewClient returns a new light client. It returns an error if it fails to
|
||||
// obtain the light block from the primary or they are invalid (e.g. trust
|
||||
// obtain the light block from the primary, or they are invalid (e.g. trust
|
||||
// hash does not match with the one from the headers).
|
||||
//
|
||||
// Witnesses are providers, which will be used for cross-checking the primary
|
||||
// provider. At least one witness must be given when skipping verification is
|
||||
// used (default). A witness can become a primary iff the current primary is
|
||||
// unavailable.
|
||||
// provider. At least one witness should be given when skipping verification is
|
||||
// used (default). A verified header is compared with the headers at same height
|
||||
// obtained from the specified witnesses. A witness can become a primary iff the
|
||||
// current primary is unavailable.
|
||||
//
|
||||
// See all Option(s) for the additional configuration.
|
||||
func NewClient(
|
||||
@@ -174,16 +189,16 @@ func NewClient(
|
||||
)
|
||||
}
|
||||
|
||||
// Check that the witness list does not include duplicates or the primary
|
||||
if err := validatePrimaryAndWitnesses(primary, witnesses); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Validate trust options
|
||||
if err := trustOptions.ValidateBasic(); err != nil {
|
||||
return nil, fmt.Errorf("invalid TrustOptions: %w", err)
|
||||
}
|
||||
|
||||
// Validate the number of witnesses.
|
||||
if len(witnesses) < 1 {
|
||||
return nil, ErrNoWitnesses
|
||||
}
|
||||
|
||||
c := &Client{
|
||||
chainID: chainID,
|
||||
trustingPeriod: trustOptions.Period,
|
||||
@@ -226,6 +241,11 @@ func NewClientFromTrustedStore(
|
||||
trustedStore store.Store,
|
||||
options ...Option) (*Client, error) {
|
||||
|
||||
// Check that the witness list does not include duplicates or the primary
|
||||
if err := validatePrimaryAndWitnesses(primary, witnesses); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c := &Client{
|
||||
chainID: chainID,
|
||||
trustingPeriod: trustingPeriod,
|
||||
@@ -244,11 +264,6 @@ func NewClientFromTrustedStore(
|
||||
o(c)
|
||||
}
|
||||
|
||||
// Validate the number of witnesses.
|
||||
if len(c.witnesses) < 1 {
|
||||
return nil, ErrNoWitnesses
|
||||
}
|
||||
|
||||
// Validate trust level.
|
||||
if err := ValidateTrustLevel(c.trustLevel); err != nil {
|
||||
return nil, err
|
||||
@@ -960,7 +975,6 @@ func (c *Client) getLightBlock(ctx context.Context, p provider.Provider, height
|
||||
|
||||
// NOTE: requires a providerMutex lock
|
||||
func (c *Client) removeWitnesses(indexes []int) error {
|
||||
// check that we will still have witnesses remaining
|
||||
if len(c.witnesses) <= len(indexes) {
|
||||
return ErrNoWitnesses
|
||||
}
|
||||
@@ -1082,7 +1096,7 @@ func (c *Client) compareFirstHeaderWithWitnesses(ctx context.Context, h *types.S
|
||||
defer c.providerMutex.Unlock()
|
||||
|
||||
if len(c.witnesses) < 1 {
|
||||
return ErrNoWitnesses
|
||||
return nil
|
||||
}
|
||||
|
||||
errc := make(chan error, len(c.witnesses))
|
||||
|
||||
Reference in New Issue
Block a user