-
Notifications
You must be signed in to change notification settings - Fork 0
/
verify.go
123 lines (107 loc) · 4.01 KB
/
verify.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package utils
import (
"bytes"
"errors"
"fmt"
"time"
tmmath "github.com/tendermint/tendermint/libs/math"
"github.com/tendermint/tendermint/light"
"github.com/tendermint/tendermint/types"
)
// VerifyNonAdjacent is identical to VerifyNonAdjacent in tendermint/tendermint/light/verifier.go, with the exception that
// it does not attempt to validate that the block is _newer_ than the current consensus state.
func VerifyNonAdjacent(
trustedHeader *types.SignedHeader, // height=X
trustedVals *types.ValidatorSet, // height=X or height=X+1
untrustedHeader *types.SignedHeader, // height=Y
untrustedVals *types.ValidatorSet, // height=Y
trustingPeriod time.Duration,
now time.Time,
maxClockDrift time.Duration,
trustLevel tmmath.Fraction,
) error {
if untrustedHeader.Height == trustedHeader.Height+1 {
return errors.New("headers must be non adjacent in height")
}
if light.HeaderExpired(trustedHeader, trustingPeriod, now) {
return light.ErrOldHeaderExpired{At: trustedHeader.Time.Add(trustingPeriod), Now: now}
}
// if err := verifyNewHeaderAndVals(
// untrustedHeader, untrustedVals,
// trustedHeader,
// now, maxClockDrift); err != nil {
// return ErrInvalidHeader{err}
// }
// Ensure that +`trustLevel` (default 1/3) or more of last trusted validators signed correctly.
err := trustedVals.VerifyCommitLightTrusting(trustedHeader.ChainID, untrustedHeader.Commit, trustLevel)
if err != nil {
switch e := err.(type) {
case types.ErrNotEnoughVotingPowerSigned:
return light.ErrNewValSetCantBeTrusted{Reason: e}
default:
return e
}
}
// Ensure that +2/3 of new validators signed correctly.
//
// NOTE: this should always be the last check because untrustedVals can be
// intentionally made very large to DOS the light client. not the case for
// VerifyAdjacent, where validator set is known in advance.
if err := untrustedVals.VerifyCommitLight(trustedHeader.ChainID, untrustedHeader.Commit.BlockID,
untrustedHeader.Height, untrustedHeader.Commit); err != nil {
return light.ErrInvalidHeader{Reason: err}
}
return nil
}
func VerifyAdjacent(
trustedHeader *types.SignedHeader, // height=X
untrustedHeader *types.SignedHeader, // height=X+1
untrustedVals *types.ValidatorSet, // height=X+1
trustingPeriod time.Duration,
now time.Time,
maxClockDrift time.Duration,
) error {
if untrustedHeader.Height != trustedHeader.Height+1 {
return errors.New("headers must be adjacent in height")
}
if light.HeaderExpired(trustedHeader, trustingPeriod, now) {
return light.ErrOldHeaderExpired{At: trustedHeader.Time.Add(trustingPeriod), Now: now}
}
// if err := verifyNewHeaderAndVals(
// untrustedHeader, untrustedVals,
// trustedHeader,
// now, maxClockDrift); err != nil {
// return ErrInvalidHeader{err}
// }
// Check the validator hashes are the same
if !bytes.Equal(untrustedHeader.ValidatorsHash, trustedHeader.NextValidatorsHash) {
err := fmt.Errorf("expected old header next validators (%X) to match those from new header (%X)",
trustedHeader.NextValidatorsHash,
untrustedHeader.ValidatorsHash,
)
return err
}
// Ensure that +2/3 of new validators signed correctly.
if err := untrustedVals.VerifyCommitLight(trustedHeader.ChainID, untrustedHeader.Commit.BlockID,
untrustedHeader.Height, untrustedHeader.Commit); err != nil {
return light.ErrInvalidHeader{Reason: err}
}
return nil
}
// Verify combines both VerifyAdjacent and VerifyNonAdjacent functions.
func Verify(
trustedHeader *types.SignedHeader, // height=X
trustedVals *types.ValidatorSet, // height=X or height=X+1
untrustedHeader *types.SignedHeader, // height=Y
untrustedVals *types.ValidatorSet, // height=Y
trustingPeriod time.Duration,
now time.Time,
maxClockDrift time.Duration,
trustLevel tmmath.Fraction,
) error {
if untrustedHeader.Height != trustedHeader.Height+1 {
return VerifyNonAdjacent(trustedHeader, trustedVals, untrustedHeader, untrustedVals,
trustingPeriod, now, maxClockDrift, trustLevel)
}
return VerifyAdjacent(trustedHeader, untrustedHeader, untrustedVals, trustingPeriod, now, maxClockDrift)
}