Search Apps Documentation Source Content File Folder Download Copy Actions Download

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}