misbehaviour_test.gno
10.71 Kb · 257 lines
1package tendermint_test
2
3import (
4 "strings"
5 "testing"
6 "time"
7
8 "gno.land/p/aib/ibc/lightclient/tendermint"
9 "gno.land/p/aib/ibc/types"
10)
11
12func TestMisbehaviourValidateBasic(t *testing.T) {
13 var misbehaviour *tendermint.Misbehaviour
14 tests := []struct {
15 name string
16 malleate func()
17 expErr string
18 }{
19 {
20 name: "valid misbehaviour, two headers of different height same time",
21 malleate: func() {},
22 expErr: "",
23 },
24 {
25 name: "invalid misbehaviour, header1 is nil",
26 malleate: func() {
27 misbehaviour.Header1 = nil
28 },
29 expErr: "misbehaviour Header1 cannot be nil",
30 },
31 {
32 name: "invalid misbehaviour, header2 is nil",
33 malleate: func() {
34 misbehaviour.Header2 = nil
35 },
36 expErr: "misbehaviour Header2 cannot be nil",
37 },
38 {
39 name: "invalid misbehaviour, header1 trusted height is 0",
40 malleate: func() {
41 misbehaviour.Header1.TrustedHeight = types.NewHeight(0, 0)
42 },
43 expErr: "misbehaviour Header1 cannot have zero revision height",
44 },
45 {
46 name: "invalid misbehaviour, header2 tusted height is 0",
47 malleate: func() {
48 misbehaviour.Header2.TrustedHeight = types.NewHeight(0, 0)
49 },
50 expErr: "misbehaviour Header2 cannot have zero revision height",
51 },
52 {
53 name: "invalid misbehaviour, header1 trusted val is nil",
54 malleate: func() {
55 misbehaviour.Header1.TrustedValidators = nil
56 },
57 expErr: "trusted validator set in Header1 cannot be empty",
58 },
59 {
60 name: "invalid misbehaviour, header2 trusted val is nil",
61 malleate: func() {
62 misbehaviour.Header2.TrustedValidators = nil
63 },
64 expErr: "trusted validator set in Header2 cannot be empty",
65 },
66 {
67 name: "invalid misbehaviour, chainID mismatch",
68 malleate: func() {
69 misbehaviour.Header2.Header.ChainID = "xxx"
70 },
71 expErr: "headers must have identical chainIDs",
72 },
73 {
74 name: "valid misbehaviour, same headers",
75 malleate: func() {
76 misbehaviour.Header2 = misbehaviour.Header1
77 },
78 expErr: "",
79 },
80 {
81 name: "invalid misbehaviour, header2 height is greater",
82 malleate: func() {
83 // Update header2 so it has a height greater than header1 (3)
84 // NOTE code generated by:
85 // go run -C ./cmd/gen-block-signatures . -chainid=gno.land -header-time-shift=0 -height=4 -new-validators=0 -privkeys=JR6fAmf/x02hJxbgPlOUlEw82K1g5L6t7T0ochto3n/IQH0mFRpgSOtSqy3rxrjQmFKzT36uAKK7mHczlEvg0w==,uUowEMik5bYqOuxT8xXS6+vhmeJ1ogEoG7lUuKColILehBmNNm2bNvn7IQmuyrnkIhRFVI2XQ6tO4HWVxCFoOA==
86 var (
87 apphash = hash("apphash-4")
88 // priv=JR6fAmf/x02hJxbgPlOUlEw82K1g5L6t7T0ochto3n/IQH0mFRpgSOtSqy3rxrjQmFKzT36uAKK7mHczlEvg0w==
89 val1 = tendermint.NewValidator("ZekR7Mi3r4Uewt3lPS3YmWPr81o=", "yEB9JhUaYEjrUqst68a40JhSs09+rgCiu5h3M5RL4NM=", 10)
90 // priv=uUowEMik5bYqOuxT8xXS6+vhmeJ1ogEoG7lUuKColILehBmNNm2bNvn7IQmuyrnkIhRFVI2XQ6tO4HWVxCFoOA==
91 val2 = tendermint.NewValidator("mdEIzF8KCHUrBT16vM7dhc/nZ4Q=", "3oQZjTZtmzb5+yEJrsq55CIURVSNl0OrTuB1lcQhaDg=", 10)
92 valset = tendermint.NewValset(val1, val2)
93 commitTimestamp = toTime("2025-09-25T07:55:57.306746166Z")
94 newHeight = uint64(4)
95 newTimestamp = time.Now()
96 nextValset = tendermint.NewValset(val1, val2)
97 trustedValset = tendermint.NewValset(val1, val2)
98 trustedHeight = types.NewHeight(0, 2)
99
100 signatures = []tendermint.CommitSig{
101 {
102 BlockIDFlag: tendermint.BlockIDFlagCommit,
103 ValidatorAddress: valset.Validators[0].Address,
104 Timestamp: commitTimestamp,
105 Signature: []byte("\xcb\x8f\x2f\x54\x34\xe9\xc7\xa5\x3e\xd4\x4b\x1d\x37\xbd\x69\xeb\x75\x01\x12\xbd\x11\x3b\x5d\xb1\x7f\xe1\xce\xd6\x8f\xd6\xf2\x79\x49\xd8\x20\xb3\x8c\x74\x35\xc5\x36\x37\x03\x21\x8c\x38\x2e\xf3\x1c\xd1\xfb\xee\xd1\xee\x8c\x0e\x16\x0e\x06\x0f\xdb\x4f\xbe\x03"),
106 },
107 {
108 BlockIDFlag: tendermint.BlockIDFlagCommit,
109 ValidatorAddress: valset.Validators[1].Address,
110 Timestamp: commitTimestamp,
111 Signature: []byte("\xde\x94\xa7\x23\x40\x3d\xa4\xb6\x92\xb0\x39\xdc\x88\xb7\x22\x0d\x5d\x1f\x3e\xb0\xab\x09\xb8\x48\x4e\x5b\xcc\x68\xe1\xcf\x06\xff\xc5\x67\xe9\x5d\x6a\xd6\xd1\x5f\xf7\xf0\x28\x3f\x18\xd9\xf4\xc7\xd4\xd2\x30\x73\xbb\xe4\xde\x4b\xfe\x71\xd3\x05\x75\xe2\xf8\x0f"),
112 },
113 }
114 )
115
116 misbehaviour.Header2 = newMsgHeader(
117 chainID, newTimestamp, apphash, newHeight, trustedHeight, valset,
118 nextValset, trustedValset, signatures,
119 )
120 },
121 expErr: "Header1 height is less than Header2 height (0/3 < 0/4)",
122 },
123 {
124 name: "invalid misbehabiour: header1 doesnt have 2/3 majority",
125 malleate: func() {
126 misbehaviour.Header1.Commit.Signatures[0] = tendermint.CommitSig{
127 BlockIDFlag: tendermint.BlockIDFlagAbsent,
128 }
129 },
130 expErr: "invalid header1 commit: validator set did not commit to header: not enough voting power, got 10, needed >13",
131 },
132 {
133 name: "invalid misbehabiour: header2 doesnt have 2/3 majority",
134 malleate: func() {
135 misbehaviour.Header2.Commit.Signatures[0] = tendermint.CommitSig{
136 BlockIDFlag: tendermint.BlockIDFlagAbsent,
137 }
138 },
139 expErr: "invalid header2 commit: validator set did not commit to header: not enough voting power, got 10, needed >13",
140 },
141 {
142 name: "invalid misbehabiour: header1 wrong signature",
143 malleate: func() {
144 misbehaviour.Header1.Commit.Signatures[0].Timestamp = time.Now()
145 },
146 expErr: "invalid header1 commit: validator set did not commit to header: verify signature fail (#0)",
147 },
148 {
149 name: "invalid misbehabiour: header2 wrong signature",
150 malleate: func() {
151 misbehaviour.Header2.Commit.Signatures[0].Timestamp = time.Now()
152 },
153 expErr: "invalid header2 commit: validator set did not commit to header: verify signature fail (#0)",
154 },
155 }
156
157 for _, tt := range tests {
158 t.Run(tt.name, func(t *testing.T) {
159 var header1, header2 *tendermint.MsgHeader
160 // NOTE code generated by:
161 // go run -C ./cmd/gen-block-signatures . -chainid=gno.land -header-time-shift=0 -height=3 -new-validators=0 -privkeys=JR6fAmf/x02hJxbgPlOUlEw82K1g5L6t7T0ochto3n/IQH0mFRpgSOtSqy3rxrjQmFKzT36uAKK7mHczlEvg0w==,uUowEMik5bYqOuxT8xXS6+vhmeJ1ogEoG7lUuKColILehBmNNm2bNvn7IQmuyrnkIhRFVI2XQ6tO4HWVxCFoOA==
162 {
163 var (
164 apphash = hash("apphash-3")
165 // priv=JR6fAmf/x02hJxbgPlOUlEw82K1g5L6t7T0ochto3n/IQH0mFRpgSOtSqy3rxrjQmFKzT36uAKK7mHczlEvg0w==
166 val1 = tendermint.NewValidator("ZekR7Mi3r4Uewt3lPS3YmWPr81o=", "yEB9JhUaYEjrUqst68a40JhSs09+rgCiu5h3M5RL4NM=", 10)
167 // priv=uUowEMik5bYqOuxT8xXS6+vhmeJ1ogEoG7lUuKColILehBmNNm2bNvn7IQmuyrnkIhRFVI2XQ6tO4HWVxCFoOA==
168 val2 = tendermint.NewValidator("mdEIzF8KCHUrBT16vM7dhc/nZ4Q=", "3oQZjTZtmzb5+yEJrsq55CIURVSNl0OrTuB1lcQhaDg=", 10)
169 valset = tendermint.NewValset(val1, val2)
170 commitTimestamp = toTime("2025-09-25T07:55:57.306746166Z")
171 newHeight = uint64(3)
172 newTimestamp = time.Now()
173 nextValset = tendermint.NewValset(val1, val2)
174 trustedValset = tendermint.NewValset(val1, val2)
175 trustedHeight = types.NewHeight(0, 2)
176
177 signatures = []tendermint.CommitSig{
178 {
179 BlockIDFlag: tendermint.BlockIDFlagCommit,
180 ValidatorAddress: valset.Validators[0].Address,
181 Timestamp: commitTimestamp,
182 Signature: []byte("\x70\x47\xa3\x9d\x70\xe7\x8b\x61\x51\xb8\x76\xfb\x0a\xf1\xd8\xb9\x98\x54\x57\x68\xe5\x5a\x93\x9d\x6a\x4e\x1e\x0f\x1e\xa7\xce\x8c\x58\x93\xfc\xe7\x58\x85\xb2\x7a\x8d\xe1\x1f\xde\xda\x10\x0f\x85\xcd\x42\x0a\xa1\xff\x20\xb3\x8b\x7c\x20\xc6\x56\x83\xf9\xf5\x09"),
183 },
184 {
185 BlockIDFlag: tendermint.BlockIDFlagCommit,
186 ValidatorAddress: valset.Validators[1].Address,
187 Timestamp: commitTimestamp,
188 Signature: []byte("\x80\x31\x76\x91\x4f\x71\x3e\xe5\x4f\xcf\xd1\x9e\xff\x49\x90\xbb\x09\x81\x22\x6d\xb0\x23\x85\xc3\x07\x49\x3a\x20\x75\x7e\x10\x4f\x98\x97\xb0\x0b\xa2\xdb\x49\x8c\x4c\x6d\xc6\x40\xd6\x6f\x16\xad\x0f\xf6\xff\xa6\x9f\x8e\x51\x95\xc1\x39\x78\x74\x24\x0e\x80\x02"),
189 },
190 }
191 )
192
193 header1 = newMsgHeader(
194 chainID, newTimestamp, apphash, newHeight, trustedHeight, valset,
195 nextValset, trustedValset, signatures,
196 )
197 }
198 // NOTE code generated by:
199 // go run -C ./cmd/gen-block-signatures . -chainid=gno.land -header-time-shift=0 -height=2 -new-validators=0 -privkeys=JR6fAmf/x02hJxbgPlOUlEw82K1g5L6t7T0ochto3n/IQH0mFRpgSOtSqy3rxrjQmFKzT36uAKK7mHczlEvg0w==,uUowEMik5bYqOuxT8xXS6+vhmeJ1ogEoG7lUuKColILehBmNNm2bNvn7IQmuyrnkIhRFVI2XQ6tO4HWVxCFoOA==
200 {
201 var (
202 apphash = hash("apphash-2")
203 // priv=JR6fAmf/x02hJxbgPlOUlEw82K1g5L6t7T0ochto3n/IQH0mFRpgSOtSqy3rxrjQmFKzT36uAKK7mHczlEvg0w==
204 val1 = tendermint.NewValidator("ZekR7Mi3r4Uewt3lPS3YmWPr81o=", "yEB9JhUaYEjrUqst68a40JhSs09+rgCiu5h3M5RL4NM=", 10)
205 // priv=uUowEMik5bYqOuxT8xXS6+vhmeJ1ogEoG7lUuKColILehBmNNm2bNvn7IQmuyrnkIhRFVI2XQ6tO4HWVxCFoOA==
206 val2 = tendermint.NewValidator("mdEIzF8KCHUrBT16vM7dhc/nZ4Q=", "3oQZjTZtmzb5+yEJrsq55CIURVSNl0OrTuB1lcQhaDg=", 10)
207 valset = tendermint.NewValset(val1, val2)
208 commitTimestamp = toTime("2025-09-25T07:55:57.306746166Z")
209 newHeight = uint64(2)
210 newTimestamp = time.Now()
211 nextValset = tendermint.NewValset(val1, val2)
212 trustedValset = tendermint.NewValset(val1, val2)
213 trustedHeight = types.NewHeight(0, 1)
214
215 signatures = []tendermint.CommitSig{
216 {
217 BlockIDFlag: tendermint.BlockIDFlagCommit,
218 ValidatorAddress: valset.Validators[0].Address,
219 Timestamp: commitTimestamp,
220 Signature: []byte("\x05\x93\x46\x01\x51\x5e\x42\xd2\xdc\xef\xd4\x07\xc2\x13\x92\x03\xb2\x5c\x1a\xae\xf8\x45\x98\x5d\xea\xc1\x7a\xb8\xec\x8b\x48\x82\xf6\x76\xfe\xf6\xbd\x26\xc9\xb2\x59\x8c\xf3\xa1\xdc\x6e\xa5\xf5\xef\x3b\x7a\x5d\xa0\xa9\xb9\xcc\x8f\x62\xc7\xa6\x95\xae\xdc\x09"),
221 },
222 {
223 BlockIDFlag: tendermint.BlockIDFlagCommit,
224 ValidatorAddress: valset.Validators[1].Address,
225 Timestamp: commitTimestamp,
226 Signature: []byte("\x8d\xe9\x5c\x39\xdf\x3f\x15\xe8\xa8\x20\x90\x6f\xa1\x2f\xf1\x04\xb6\x1e\xd1\xbf\x9b\xd3\xc9\x3f\x0b\xcc\x81\x76\xdc\x0f\xf7\x75\x0a\x5a\xed\x9f\x7d\xb9\x9e\x37\x3c\xcc\x5b\x38\x6d\x5d\x34\x32\x45\x85\x9d\xb0\x6c\x09\x49\x89\x39\x8f\xe8\x00\x82\x0f\x2f\x04"),
227 },
228 }
229 )
230
231 header2 = newMsgHeader(
232 chainID, newTimestamp, apphash, newHeight, trustedHeight, valset,
233 nextValset, trustedValset, signatures,
234 )
235 }
236 misbehaviour = &tendermint.Misbehaviour{
237 Header1: header1,
238 Header2: header2,
239 }
240 if tt.malleate != nil {
241 tt.malleate()
242 }
243
244 err := misbehaviour.ValidateBasic()
245
246 if tt.expErr == "" && err != nil {
247 t.Errorf("expected no error got %v", err)
248 return
249 }
250 if tt.expErr != "" {
251 if err == nil || !strings.Contains(err.Error(), tt.expErr) {
252 t.Errorf("expected error %s, got %s", tt.expErr, err)
253 }
254 }
255 })
256 }
257}