mirror of
https://github.com/tendermint/tendermint.git
synced 2026-08-21 06:36:19 +00:00
light: expand on errors and docs (#5443)
This commit is contained in:
+14
-8
@@ -90,13 +90,19 @@ func (c *Client) detectDivergence(ctx context.Context, primaryTrace []*types.Lig
|
||||
|
||||
// We are suspecting that the primary is faulty, hence we hold the witness as the source of truth
|
||||
// and generate evidence against the primary that we can send to the witness
|
||||
ev := &types.LightClientAttackEvidence{
|
||||
primaryEv := &types.LightClientAttackEvidence{
|
||||
ConflictingBlock: primaryBlock,
|
||||
CommonHeight: commonHeight, // the first block in the bisection is common to both providers
|
||||
}
|
||||
c.logger.Error("Attack detected. Sending evidence againt primary by witness", "ev", ev,
|
||||
c.logger.Error("Attempted attack detected. Sending evidence againt primary by witness", "ev", primaryEv,
|
||||
"primary", c.primary, "witness", supportingWitness)
|
||||
c.sendEvidence(ctx, ev, supportingWitness)
|
||||
c.sendEvidence(ctx, primaryEv, supportingWitness)
|
||||
|
||||
if primaryBlock.Commit.Round != witnessTrace[len(witnessTrace)-1].Commit.Round {
|
||||
c.logger.Info("The light client has detected, and prevented, an attempted amnesia attack." +
|
||||
" We think this attack is pretty unlikely, so if you see it, that's interesting to us." +
|
||||
" Can you let us know by opening an issue through https://github.com/tendermint/tendermint/issues/new?")
|
||||
}
|
||||
|
||||
// This may not be valid because the witness itself is at fault. So now we reverse it, examining the
|
||||
// trace provided by the witness and holding the primary as the source of truth. Note: primary may not
|
||||
@@ -110,7 +116,7 @@ func (c *Client) detectDivergence(ctx context.Context, primaryTrace []*types.Lig
|
||||
)
|
||||
if err != nil {
|
||||
c.logger.Info("Error validating primary's divergent header", "primary", c.primary, "err", err)
|
||||
continue
|
||||
return ErrLightClientAttack
|
||||
}
|
||||
// if this is an equivocation or amnesia attack, i.e. the validator sets are the same, then we
|
||||
// return the height of the conflicting block else if it is a lunatic attack and the validator sets
|
||||
@@ -122,15 +128,15 @@ func (c *Client) detectDivergence(ctx context.Context, primaryTrace []*types.Lig
|
||||
}
|
||||
|
||||
// We now use the primary trace to create evidence against the witness and send it to the primary
|
||||
ev = &types.LightClientAttackEvidence{
|
||||
witnessEv := &types.LightClientAttackEvidence{
|
||||
ConflictingBlock: witnessBlock,
|
||||
CommonHeight: commonHeight, // the first block in the bisection is common to both providers
|
||||
}
|
||||
c.logger.Error("Sending evidence against witness by primary", "ev", ev,
|
||||
c.logger.Error("Sending evidence against witness by primary", "ev", witnessEv,
|
||||
"primary", c.primary, "witness", supportingWitness)
|
||||
c.sendEvidence(ctx, ev, c.primary)
|
||||
c.sendEvidence(ctx, witnessEv, c.primary)
|
||||
// We return the error and don't process anymore witnesses
|
||||
return e
|
||||
return ErrLightClientAttack
|
||||
|
||||
case errBadWitness:
|
||||
c.logger.Info("Witness returned an error during header comparison", "witness", c.witnesses[e.WitnessIndex],
|
||||
|
||||
@@ -63,7 +63,7 @@ func TestLightClientAttackEvidence_Lunatic(t *testing.T) {
|
||||
// Check verification returns an error.
|
||||
_, err = c.VerifyLightBlockAtHeight(ctx, 10, bTime.Add(1*time.Hour))
|
||||
if assert.Error(t, err) {
|
||||
assert.Contains(t, err.Error(), "does not match primary")
|
||||
assert.Equal(t, err, light.ErrLightClientAttack)
|
||||
}
|
||||
|
||||
// Check evidence was sent to both full nodes.
|
||||
@@ -137,7 +137,7 @@ func TestLightClientAttackEvidence_Equivocation(t *testing.T) {
|
||||
// Check verification returns an error.
|
||||
_, err = c.VerifyLightBlockAtHeight(ctx, 10, bTime.Add(1*time.Hour))
|
||||
if assert.Error(t, err) {
|
||||
assert.Contains(t, err.Error(), "does not match primary")
|
||||
assert.Equal(t, err, light.ErrLightClientAttack)
|
||||
}
|
||||
|
||||
// Check evidence was sent to both full nodes.
|
||||
|
||||
@@ -65,6 +65,13 @@ func (e ErrVerificationFailed) Error() string {
|
||||
e.From, e.To, e.Reason)
|
||||
}
|
||||
|
||||
// ErrLightClientAttack is returned when the light client has detected an attempt
|
||||
// to verify a false header and has sent the evidence to either a witness or primary.
|
||||
var ErrLightClientAttack = errors.New("attempted attack detected." +
|
||||
" Light client received valid conflicting header from witness." +
|
||||
" Unable to verify header. Evidence has been sent to both providers." +
|
||||
" Check logs for full evidence and trace")
|
||||
|
||||
// ----------------------------- INTERNAL ERRORS ---------------------------------
|
||||
|
||||
// ErrConflictingHeaders is thrown when two conflicting headers are discovered.
|
||||
|
||||
Reference in New Issue
Block a user