Skip to content

Commit d1a4667

Browse files
committed
Add fuzz test on identifers
1 parent b00af8b commit d1a4667

3 files changed

Lines changed: 78 additions & 76 deletions

File tree

ibc/host/identifiers.go

Lines changed: 44 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -40,35 +40,6 @@ func init() {
4040
}
4141
}
4242

43-
// basicValidation performs basic validation on the given identifier
44-
func basicValidation(id string, minLength, maxLength int) error {
45-
if strings.TrimSpace(id) == "" {
46-
return coreTypes.ErrIBCInvalidID(id, "cannot be blank")
47-
}
48-
49-
if len(id) < minLength || len(id) > maxLength {
50-
return coreTypes.ErrIBCInvalidID(id, fmt.Sprintf("length must be between %d and %d", minLength, maxLength))
51-
}
52-
53-
if !strings.HasPrefix(id, identifierPrefix) {
54-
return coreTypes.ErrIBCInvalidID(id, fmt.Sprintf("must start with '%s'", identifierPrefix))
55-
}
56-
57-
for _, c := range invalidIdChars {
58-
if _, ok := invalidIdMap[c]; ok {
59-
return coreTypes.ErrIBCInvalidID(id, fmt.Sprintf("cannot contain '%s'", string(c)))
60-
}
61-
}
62-
63-
for _, c := range id {
64-
if _, ok := validIdMap[c]; !ok {
65-
return coreTypes.ErrIBCInvalidID(id, fmt.Sprintf("contains invalid character '%c'", c))
66-
}
67-
}
68-
69-
return nil
70-
}
71-
7243
// ValidateClientID validates the client identifier string
7344
func ValidateClientID(id string) error {
7445
return basicValidation(id, minClientIdLength, defaultMaxIdLength)
@@ -89,6 +60,26 @@ func ValidatePortID(id string) error {
8960
return basicValidation(id, minPortIdLength, maxPortIdLength)
9061
}
9162

63+
// GenerateClientIdentifier generates a new client identifier
64+
func GenerateClientIdentifier() string {
65+
return generateNewIdentifier(minClientIdLength, defaultMaxIdLength)
66+
}
67+
68+
// GenerateConnectionIdentifier generates a new connection identifier
69+
func GenerateConnectionIdentifier() string {
70+
return generateNewIdentifier(minConnectionIdLength, defaultMaxIdLength)
71+
}
72+
73+
// GenerateChannelIdentifier generates a new channel identifier
74+
func GenerateChannelIdentifier() string {
75+
return generateNewIdentifier(minChannelIdLength, defaultMaxIdLength)
76+
}
77+
78+
// GeneratePortIdentifier generates a new port identifier
79+
func GeneratePortIdentifier() string {
80+
return generateNewIdentifier(minPortIdLength, maxPortIdLength)
81+
}
82+
9283
// generateNewIdentifier generates a new identifier in the given range
9384
func generateNewIdentifier(min, max int) string {
9485
return generateNewIdentifierWithSeed(min, max, time.Now().UnixNano())
@@ -111,22 +102,31 @@ func generateNewIdentifierWithSeed(min, max int, seed int64) string {
111102
return identifierPrefix + string(b)
112103
}
113104

114-
// GenerateClientIdentifier generates a new client identifier
115-
func GenerateClientIdentifier() string {
116-
return generateNewIdentifier(minClientIdLength, defaultMaxIdLength)
117-
}
105+
// basicValidation performs basic validation on the given identifier
106+
func basicValidation(id string, minLength, maxLength int) error {
107+
if strings.TrimSpace(id) == "" {
108+
return coreTypes.ErrIBCInvalidID(id, "cannot be blank")
109+
}
118110

119-
// GenerateConnectionIdentifier generates a new connection identifier
120-
func GenerateConnectionIdentifier() string {
121-
return generateNewIdentifier(minConnectionIdLength, defaultMaxIdLength)
122-
}
111+
if len(id) < minLength || len(id) > maxLength {
112+
return coreTypes.ErrIBCInvalidID(id, fmt.Sprintf("length must be between %d and %d", minLength, maxLength))
113+
}
123114

124-
// GenerateChannelIdentifier generates a new channel identifier
125-
func GenerateChannelIdentifier() string {
126-
return generateNewIdentifier(minChannelIdLength, defaultMaxIdLength)
127-
}
115+
if !strings.HasPrefix(id, identifierPrefix) {
116+
return coreTypes.ErrIBCInvalidID(id, fmt.Sprintf("must start with '%s'", identifierPrefix))
117+
}
128118

129-
// GeneratePortIdentifier generates a new port identifier
130-
func GeneratePortIdentifier() string {
131-
return generateNewIdentifier(minPortIdLength, maxPortIdLength)
119+
for _, c := range id {
120+
if _, ok := invalidIdMap[c]; ok {
121+
return coreTypes.ErrIBCInvalidID(id, fmt.Sprintf("cannot contain '%s'", string(c)))
122+
}
123+
}
124+
125+
for _, c := range id {
126+
if _, ok := validIdMap[c]; !ok {
127+
return coreTypes.ErrIBCInvalidID(id, fmt.Sprintf("contains invalid character '%c'", c))
128+
}
129+
}
130+
131+
return nil
132132
}

ibc/host/keys.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ import (
55
"strings"
66
)
77

8-
// Store key prefixes for IBC
8+
// Store key prefixes for IBC as defined in ICS-24
9+
// https://github.com/cosmos/ibc/blob/main/spec/core/ics-024-host-requirements/README.md
910
const (
1011
KeyClientStorePrefix = "clients"
1112
KeyClientState = "clientState"

ibc/host/path_test.go

Lines changed: 32 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -7,50 +7,51 @@ import (
77
"github.com/stretchr/testify/require"
88
)
99

10-
func TestPaths_GenerateValidIdentifiers(t *testing.T) {
11-
ids := make(map[string]string, 100)
10+
func FuzzIdentifiers_GenerateValidIdentifiers(f *testing.F) {
1211
for i := 0; i < 100; i++ {
1312
switch i % 4 {
1413
case 0:
15-
cl := GenerateClientIdentifier()
16-
require.NotNil(t, cl)
17-
_, ok := ids[cl]
18-
require.False(t, ok)
19-
ids[cl] = "client"
14+
f.Add("client")
2015
case 1:
21-
co := GenerateConnectionIdentifier()
22-
require.NotNil(t, co)
23-
_, ok := ids[co]
24-
require.False(t, ok)
25-
ids[co] = "connection"
16+
f.Add("connection")
2617
case 2:
27-
ch := GenerateChannelIdentifier()
28-
require.NotNil(t, ch)
29-
_, ok := ids[ch]
30-
require.False(t, ok)
31-
ids[ch] = "channel"
18+
f.Add("channel")
3219
case 3:
33-
po := GeneratePortIdentifier()
34-
require.NotNil(t, po)
35-
_, ok := ids[po]
36-
require.False(t, ok)
37-
ids[po] = "port"
20+
f.Add("port")
3821
}
3922
}
40-
for k, v := range ids {
41-
var err error
42-
switch v {
23+
f.Fuzz(func(t *testing.T, idType string) {
24+
switch idType {
4325
case "client":
44-
err = ValidateClientID(k)
26+
id := GenerateClientIdentifier()
27+
require.NotEmpty(t, id)
28+
require.GreaterOrEqual(t, len(id), 9)
29+
require.LessOrEqual(t, len(id), 64)
30+
err := ValidateClientID(id)
31+
require.NoError(t, err)
4532
case "connection":
46-
err = ValidateConnectionID(k)
33+
id := GenerateConnectionIdentifier()
34+
require.NotEmpty(t, id)
35+
require.GreaterOrEqual(t, len(id), 10)
36+
require.LessOrEqual(t, len(id), 64)
37+
err := ValidateConnectionID(id)
38+
require.NoError(t, err)
4739
case "channel":
48-
err = ValidateChannelID(k)
40+
id := GenerateChannelIdentifier()
41+
require.NotEmpty(t, id)
42+
require.GreaterOrEqual(t, len(id), 8)
43+
require.LessOrEqual(t, len(id), 64)
44+
err := ValidateChannelID(id)
45+
require.NoError(t, err)
4946
case "port":
50-
err = ValidatePortID(k)
47+
id := GeneratePortIdentifier()
48+
require.NotEmpty(t, id)
49+
require.GreaterOrEqual(t, len(id), 2)
50+
require.LessOrEqual(t, len(id), 128)
51+
err := ValidatePortID(id)
52+
require.NoError(t, err)
5153
}
52-
require.NoError(t, err)
53-
}
54+
})
5455
}
5556

5657
func TestPaths_CommitmentPrefix(t *testing.T) {

0 commit comments

Comments
 (0)