misbehaviour.gno
2.36 Kb · 73 lines
1package tendermint
2
3import (
4 "gno.land/p/aib/ibc/lightclient"
5 "gno.land/p/nt/ufmt/v0"
6)
7
8// Misbehaviour is a wrapper over two conflicting Headers
9// that implements Misbehaviour interface expected by ICS-02
10type Misbehaviour struct {
11 Header1 *MsgHeader
12 Header2 *MsgHeader
13}
14
15// Implements lightclient.ClientMessage
16func (Misbehaviour) ClientType() string {
17 return lightclient.Tendermint
18}
19
20// Implements lightclient.ClientMessage
21func (m Misbehaviour) ValidateBasic() error {
22 if m.Header1 == nil {
23 return ufmt.Errorf("misbehaviour Header1 cannot be nil")
24 }
25 if m.Header2 == nil {
26 return ufmt.Errorf("misbehaviour Header2 cannot be nil")
27 }
28 if m.Header1.TrustedHeight.RevisionHeight == 0 {
29 return ufmt.Errorf("misbehaviour Header1 cannot have zero revision height")
30 }
31 if m.Header2.TrustedHeight.RevisionHeight == 0 {
32 return ufmt.Errorf("misbehaviour Header2 cannot have zero revision height")
33 }
34 if m.Header1.TrustedValidators == nil {
35 return ufmt.Errorf("trusted validator set in Header1 cannot be empty")
36 }
37 if m.Header2.TrustedValidators == nil {
38 return ufmt.Errorf("trusted validator set in Header2 cannot be empty")
39 }
40 if m.Header1.Header.ChainID != m.Header2.Header.ChainID {
41 return ufmt.Errorf("headers must have identical chainIDs")
42 }
43
44 // ValidateBasic on both validators
45 if err := m.Header1.ValidateBasic(); err != nil {
46 return ufmt.Errorf("header 1 failed validation: %v", err)
47 }
48 if err := m.Header2.ValidateBasic(); err != nil {
49 return ufmt.Errorf("header 2 failed validation: %v", err)
50 }
51 // Ensure that Height1 is greater than or equal to Height2
52 if m.Header1.GetHeight().LT(m.Header2.GetHeight()) {
53 return ufmt.Errorf("Header1 height is less than Header2 height (%s < %s)", m.Header1.GetHeight(), m.Header2.GetHeight())
54 }
55
56 if err := validateCommit(m.Header1); err != nil {
57 return ufmt.Errorf("invalid header1 commit: %v", err)
58 }
59 if err := validateCommit(m.Header2); err != nil {
60 return ufmt.Errorf("invalid header2 commit: %v", err)
61 }
62 return nil
63}
64
65// validateCommit checks if the given commit is a valid commit from the
66// passed-in MsgHeader.
67func validateCommit(msg *MsgHeader) error {
68 votingPowerNeeded := msg.ValidatorSet.TotalVotingPower * 2 / 3
69 if err := verifyCommit(msg.Header.ChainID, msg.ValidatorSet, msg.Commit, votingPowerNeeded, true); err != nil {
70 return ufmt.Errorf("validator set did not commit to header: %v", err)
71 }
72 return nil
73}