light: expand on errors and docs (#5443)

This commit is contained in:
Callum Waters
2020-10-02 20:05:15 +02:00
committed by GitHub
parent bf9e36d02d
commit a4b7018732
4 changed files with 48 additions and 16 deletions
+14 -8
View File
@@ -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],
+2 -2
View File
@@ -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.
+7
View File
@@ -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.