-
Notifications
You must be signed in to change notification settings - Fork 921
/
verify.go
84 lines (68 loc) · 2.42 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
package header
import (
"bytes"
"fmt"
"time"
"github.com/tendermint/tendermint/light"
libhead "github.com/celestiaorg/go-header"
)
// Verify validates given untrusted Header against trusted ExtendedHeader.
func (eh *ExtendedHeader) Verify(untrusted libhead.Header) error {
untrst, ok := untrusted.(*ExtendedHeader)
if !ok {
// if the header of the type was given, something very wrong happens
panic(fmt.Sprintf("invalid header type: expected %T, got %T", eh, untrusted))
}
if err := eh.verify(untrst); err != nil {
return &libhead.VerifyError{Reason: err}
}
isAdjacent := eh.Height()+1 == untrst.Height()
if isAdjacent {
// Optimized verification for adjacent headers
// Check the validator hashes are the same
if !bytes.Equal(untrst.ValidatorsHash, eh.NextValidatorsHash) {
return &libhead.VerifyError{
Reason: fmt.Errorf("expected old header next validators (%X) to match those from new header (%X)",
eh.NextValidatorsHash,
untrst.ValidatorsHash,
),
}
}
if !bytes.Equal(untrst.LastHeader(), eh.Hash()) {
return &libhead.VerifyError{
Reason: fmt.Errorf("expected new header to point to last header hash (%X), but got %X)",
eh.Hash(),
untrst.LastHeader(),
),
}
}
return nil
}
// Ensure that untrusted commit has enough of trusted commit's power.
err := eh.ValidatorSet.VerifyCommitLightTrusting(eh.ChainID(), untrst.Commit, light.DefaultTrustLevel)
if err != nil {
return &libhead.VerifyError{Reason: err}
}
return nil
}
// clockDrift defines how much new header's time can drift into
// the future relative to the now time during verification.
var clockDrift = 10 * time.Second
// verify performs basic verification of untrusted header.
func (eh *ExtendedHeader) verify(untrst libhead.Header) error {
if untrst.Height() <= eh.Height() {
return fmt.Errorf("untrusted header height(%d) <= current trusted header(%d)", untrst.Height(), eh.Height())
}
if untrst.ChainID() != eh.ChainID() {
return fmt.Errorf("untrusted header has different chain %s, not %s", untrst.ChainID(), eh.ChainID())
}
if !untrst.Time().After(eh.Time()) {
return fmt.Errorf("untrusted header time(%v) must be after current trusted header(%v)", untrst.Time(), eh.Time())
}
now := time.Now()
if !untrst.Time().Before(now.Add(clockDrift)) {
return fmt.Errorf(
"new untrusted header has a time from the future %v (now: %v, clockDrift: %v)", untrst.Time(), now, clockDrift)
}
return nil
}