Skip to content

Commit 41288bd

Browse files
authored
chore: lint and add go linting action (#114)
* lint and add go linting * Update go/Makefile * fix Co-authored-by: Marko Baricevic <[email protected]>
1 parent 4d119ac commit 41288bd

9 files changed

+126
-55
lines changed

.github/workflows/lint.yml

+16
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,20 @@ jobs:
3535
- name: Clippy linting on workspace (host functions only)
3636
working-directory: ./rust
3737
run: cargo clippy --tests --no-default-features --features host-functions -- -D warnings
38+
39+
golangci:
40+
name: golangci-lint
41+
runs-on: ubuntu-latest
42+
steps:
43+
- uses: actions/setup-go@v3
44+
with:
45+
# ci is set to go1.19 to match developer setups
46+
go-version: 1.19.2
47+
- uses: actions/checkout@v3
48+
- name: golangci-lint
49+
uses: golangci/golangci-lint-action@v3
50+
with:
51+
# Optional: version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` to use the latest version
52+
version: v1.50.0
53+
working-directory: go
3854

go/.golangci.yml

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
run:
2+
tests: false
3+
# timeout for analysis, e.g. 30s, 5m, default is 1m
4+
timeout: 5m
5+
6+
linters:
7+
disable-all: true
8+
enable:
9+
- depguard
10+
- dogsled
11+
- exportloopref
12+
- goconst
13+
- gocritic
14+
- gofumpt
15+
- gosec
16+
- gosimple
17+
- govet
18+
- ineffassign
19+
- misspell
20+
- nakedret
21+
- nolintlint
22+
- staticcheck
23+
- stylecheck
24+
- typecheck
25+
- unconvert
26+
- unused

go/Makefile

+21
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,24 @@ install-proto-dep:
1818
@go install github.com/regen-network/cosmos-proto/protoc-gen-gocosmos
1919

2020

21+
golangci_lint_cmd=golangci-lint
22+
golangci_version=v1.50.0
23+
24+
lint:
25+
@echo "--> Running linter"
26+
@go install github.com/golangci/golangci-lint/cmd/golangci-lint@$(golangci_version)
27+
@$(golangci_lint_cmd) run --timeout=10m
28+
29+
lint-fix:
30+
@echo "--> Running linter"
31+
@go install github.com/golangci/golangci-lint/cmd/golangci-lint@$(golangci_version)
32+
@$(golangci_lint_cmd) run --fix --out-format=tab --issues-exit-code=0
33+
34+
.PHONY: lint lint-fix
35+
36+
format:
37+
@go install mvdan.cc/gofumpt@latest
38+
@go install github.com/golangci/golangci-lint/cmd/golangci-lint@$(golangci_version)
39+
find . -name '*.go' -type f -not -name "*.pb.go" | xargs gofumpt -w -l
40+
$(golangci_lint_cmd) run --fix
41+
.PHONY: format

go/ics23.go

+10-9
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,21 @@
1-
/**
1+
/*
2+
*
23
This implements the client side functions as specified in
34
https://github.com/cosmos/ibc/tree/main/spec/core/ics-023-vector-commitments
45
56
In particular:
67
7-
// Assumes ExistenceProof
8-
type verifyMembership = (root: CommitmentRoot, proof: CommitmentProof, key: Key, value: Value) => boolean
8+
// Assumes ExistenceProof
9+
type verifyMembership = (root: CommitmentRoot, proof: CommitmentProof, key: Key, value: Value) => boolean
910
10-
// Assumes NonExistenceProof
11-
type verifyNonMembership = (root: CommitmentRoot, proof: CommitmentProof, key: Key) => boolean
11+
// Assumes NonExistenceProof
12+
type verifyNonMembership = (root: CommitmentRoot, proof: CommitmentProof, key: Key) => boolean
1213
13-
// Assumes BatchProof - required ExistenceProofs may be a subset of all items proven
14-
type batchVerifyMembership = (root: CommitmentRoot, proof: CommitmentProof, items: Map<Key, Value>) => boolean
14+
// Assumes BatchProof - required ExistenceProofs may be a subset of all items proven
15+
type batchVerifyMembership = (root: CommitmentRoot, proof: CommitmentProof, items: Map<Key, Value>) => boolean
1516
16-
// Assumes BatchProof - required NonExistenceProofs may be a subset of all items proven
17-
type batchVerifyNonMembership = (root: CommitmentRoot, proof: CommitmentProof, keys: Set<Key>) => boolean
17+
// Assumes BatchProof - required NonExistenceProofs may be a subset of all items proven
18+
type batchVerifyNonMembership = (root: CommitmentRoot, proof: CommitmentProof, keys: Set<Key>) => boolean
1819
1920
We make an adjustment to accept a Spec to ensure the provided proof is in the format of the expected merkle store.
2021
This can avoid an range of attacks on fake preimages, as we need to be careful on how to map key, value -> leaf

go/ops.go

+25-19
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,16 @@ import (
1313
_ "crypto/sha512"
1414

1515
// adds ripemd160 capability to crypto.RIPEMD160
16-
_ "golang.org/x/crypto/ripemd160"
16+
_ "golang.org/x/crypto/ripemd160" //nolint:staticcheck
1717
)
1818

1919
// Apply will calculate the leaf hash given the key and value being proven
2020
func (op *LeafOp) Apply(key []byte, value []byte) ([]byte, error) {
2121
if len(key) == 0 {
22-
return nil, errors.New("Leaf op needs key")
22+
return nil, errors.New("leaf op needs key")
2323
}
2424
if len(value) == 0 {
25-
return nil, errors.New("Leaf op needs value")
25+
return nil, errors.New("leaf op needs value")
2626
}
2727
pkey, err := prepareLeafData(op.PrehashKey, op.Length, key)
2828
if err != nil {
@@ -32,8 +32,11 @@ func (op *LeafOp) Apply(key []byte, value []byte) ([]byte, error) {
3232
if err != nil {
3333
return nil, fmt.Errorf("prehash value, %w", err)
3434
}
35-
data := append(op.Prefix, pkey...)
35+
36+
data := op.Prefix
37+
data = append(data, pkey...)
3638
data = append(data, pvalue...)
39+
3740
return doHash(op.Hash, data)
3841
}
3942

@@ -42,49 +45,52 @@ func (op *LeafOp) CheckAgainstSpec(spec *ProofSpec) error {
4245
lspec := spec.LeafSpec
4346

4447
if op.Hash != lspec.Hash {
45-
return fmt.Errorf("Unexpected HashOp: %d", op.Hash)
48+
return fmt.Errorf("unexpected HashOp: %d", op.Hash)
4649
}
4750
if op.PrehashKey != lspec.PrehashKey {
48-
return fmt.Errorf("Unexpected PrehashKey: %d", op.PrehashKey)
51+
return fmt.Errorf("unexpected PrehashKey: %d", op.PrehashKey)
4952
}
5053
if op.PrehashValue != lspec.PrehashValue {
51-
return fmt.Errorf("Unexpected PrehashValue: %d", op.PrehashValue)
54+
return fmt.Errorf("unexpected PrehashValue: %d", op.PrehashValue)
5255
}
5356
if op.Length != lspec.Length {
54-
return fmt.Errorf("Unexpected LengthOp: %d", op.Length)
57+
return fmt.Errorf("unexpected LengthOp: %d", op.Length)
5558
}
5659
if !bytes.HasPrefix(op.Prefix, lspec.Prefix) {
57-
return fmt.Errorf("Leaf Prefix doesn't start with %X", lspec.Prefix)
60+
return fmt.Errorf("leaf Prefix doesn't start with %X", lspec.Prefix)
5861
}
5962
return nil
6063
}
6164

6265
// Apply will calculate the hash of the next step, given the hash of the previous step
6366
func (op *InnerOp) Apply(child []byte) ([]byte, error) {
6467
if len(child) == 0 {
65-
return nil, errors.New("Inner op needs child value")
68+
return nil, errors.New("inner op needs child value")
6669
}
67-
preimage := append(op.Prefix, child...)
70+
71+
preimage := op.Prefix
72+
preimage = append(preimage, child...)
6873
preimage = append(preimage, op.Suffix...)
74+
6975
return doHash(op.Hash, preimage)
7076
}
7177

7278
// CheckAgainstSpec will verify the InnerOp is in the format defined in spec
7379
func (op *InnerOp) CheckAgainstSpec(spec *ProofSpec) error {
7480
if op.Hash != spec.InnerSpec.Hash {
75-
return fmt.Errorf("Unexpected HashOp: %d", op.Hash)
81+
return fmt.Errorf("unexpected HashOp: %d", op.Hash)
7682
}
7783

7884
leafPrefix := spec.LeafSpec.Prefix
7985
if bytes.HasPrefix(op.Prefix, leafPrefix) {
80-
return fmt.Errorf("Inner Prefix starts with %X", leafPrefix)
86+
return fmt.Errorf("inner Prefix starts with %X", leafPrefix)
8187
}
8288
if len(op.Prefix) < int(spec.InnerSpec.MinPrefixLength) {
83-
return fmt.Errorf("InnerOp prefix too short (%d)", len(op.Prefix))
89+
return fmt.Errorf("innerOp prefix too short (%d)", len(op.Prefix))
8490
}
8591
maxLeftChildBytes := (len(spec.InnerSpec.ChildOrder) - 1) * int(spec.InnerSpec.ChildSize)
8692
if len(op.Prefix) > int(spec.InnerSpec.MaxPrefixLength)+maxLeftChildBytes {
87-
return fmt.Errorf("InnerOp prefix too long (%d)", len(op.Prefix))
93+
return fmt.Errorf("innerOp prefix too long (%d)", len(op.Prefix))
8894
}
8995
return nil
9096
}
@@ -137,7 +143,7 @@ func doHash(hashOp HashOp, preimage []byte) ([]byte, error) {
137143
hash.Write(preimage)
138144
return hash.Sum(nil), nil
139145
}
140-
return nil, fmt.Errorf("Unsupported hashop: %d", hashOp)
146+
return nil, fmt.Errorf("unsupported hashop: %d", hashOp)
141147
}
142148

143149
// doLengthOp will calculate the proper prefix and return it prepended
@@ -152,12 +158,12 @@ func doLengthOp(lengthOp LengthOp, data []byte) ([]byte, error) {
152158
return res, nil
153159
case LengthOp_REQUIRE_32_BYTES:
154160
if len(data) != 32 {
155-
return nil, fmt.Errorf("Data was %d bytes, not 32", len(data))
161+
return nil, fmt.Errorf("data was %d bytes, not 32", len(data))
156162
}
157163
return data, nil
158164
case LengthOp_REQUIRE_64_BYTES:
159165
if len(data) != 64 {
160-
return nil, fmt.Errorf("Data was %d bytes, not 64", len(data))
166+
return nil, fmt.Errorf("data was %d bytes, not 64", len(data))
161167
}
162168
return data, nil
163169
case LengthOp_FIXED32_LITTLE:
@@ -171,7 +177,7 @@ func doLengthOp(lengthOp LengthOp, data []byte) ([]byte, error) {
171177
// case LengthOp_FIXED64_BIG:
172178
// case LengthOp_FIXED64_LITTLE:
173179
}
174-
return nil, fmt.Errorf("Unsupported lengthop: %d", lengthOp)
180+
return nil, fmt.Errorf("unsupported lengthop: %d", lengthOp)
175181
}
176182

177183
func encodeVarintProto(l int) []byte {

go/proof.go

+18-16
Original file line numberDiff line numberDiff line change
@@ -98,30 +98,29 @@ func (p *ExistenceProof) Verify(spec *ProofSpec, root CommitmentRoot, key []byte
9898
}
9999

100100
if !bytes.Equal(key, p.Key) {
101-
return fmt.Errorf("Provided key doesn't match proof")
101+
return fmt.Errorf("provided key doesn't match proof")
102102
}
103103
if !bytes.Equal(value, p.Value) {
104-
return fmt.Errorf("Provided value doesn't match proof")
104+
return fmt.Errorf("provided value doesn't match proof")
105105
}
106106

107107
calc, err := p.Calculate()
108108
if err != nil {
109-
return fmt.Errorf("Error calculating root, %w", err)
109+
return fmt.Errorf("error calculating root, %w", err)
110110
}
111111
if !bytes.Equal(root, calc) {
112-
return fmt.Errorf("Calculcated root doesn't match provided root")
112+
return fmt.Errorf("calculcated root doesn't match provided root")
113113
}
114114

115115
return nil
116-
117116
}
118117

119118
// Calculate determines the root hash that matches the given proof.
120119
// You must validate the result is what you have in a header.
121120
// Returns error if the calculations cannot be performed.
122121
func (p *ExistenceProof) Calculate() (CommitmentRoot, error) {
123122
if p.GetLeaf() == nil {
124-
return nil, errors.New("Existence Proof needs defined LeafOp")
123+
return nil, errors.New("existence Proof needs defined LeafOp")
125124
}
126125

127126
// leaf step takes the key and value as input
@@ -151,24 +150,24 @@ func (p *NonExistenceProof) Calculate() (CommitmentRoot, error) {
151150
case p.Right != nil:
152151
return p.Right.Calculate()
153152
default:
154-
return nil, errors.New("Nonexistence proof has empty Left and Right proof")
153+
return nil, errors.New("nonexistence proof has empty Left and Right proof")
155154
}
156155
}
157156

158157
// CheckAgainstSpec will verify the leaf and all path steps are in the format defined in spec
159158
func (p *ExistenceProof) CheckAgainstSpec(spec *ProofSpec) error {
160159
if p.GetLeaf() == nil {
161-
return errors.New("Existence Proof needs defined LeafOp")
160+
return errors.New("existence Proof needs defined LeafOp")
162161
}
163162
err := p.Leaf.CheckAgainstSpec(spec)
164163
if err != nil {
165164
return fmt.Errorf("leaf, %w", err)
166165
}
167166
if spec.MinDepth > 0 && len(p.Path) < int(spec.MinDepth) {
168-
return fmt.Errorf("InnerOps depth too short: %d", len(p.Path))
167+
return fmt.Errorf("innerOps depth too short: %d", len(p.Path))
169168
}
170169
if spec.MaxDepth > 0 && len(p.Path) > int(spec.MaxDepth) {
171-
return fmt.Errorf("InnerOps depth too long: %d", len(p.Path))
170+
return fmt.Errorf("innerOps depth too long: %d", len(p.Path))
172171
}
173172

174173
for _, inner := range p.Path {
@@ -208,25 +207,28 @@ func (p *NonExistenceProof) Verify(spec *ProofSpec, root CommitmentRoot, key []b
208207
return errors.New("key is not left of right proof")
209208
}
210209
}
210+
211211
if leftKey != nil {
212212
if bytes.Compare(key, leftKey) <= 0 {
213213
return errors.New("key is not right of left proof")
214214
}
215215
}
216216

217-
if leftKey == nil {
217+
switch {
218+
case leftKey == nil:
218219
if !IsLeftMost(spec.InnerSpec, p.Right.Path) {
219220
return errors.New("left proof missing, right proof must be left-most")
220221
}
221-
} else if rightKey == nil {
222+
case rightKey == nil:
222223
if !IsRightMost(spec.InnerSpec, p.Left.Path) {
223224
return errors.New("right proof missing, left proof must be right-most")
224225
}
225-
} else { // in the middle
226+
default:
226227
if !IsLeftNeighbor(spec.InnerSpec, p.Left.Path, p.Right.Path) {
227228
return errors.New("right proof missing, left proof must be right-most")
228229
}
229230
}
231+
230232
return nil
231233
}
232234

@@ -387,14 +389,14 @@ func rightBranchesAreEmpty(spec *InnerSpec, op *InnerOp) bool {
387389
// the index of this branch
388390
func getPosition(order []int32, branch int32) int {
389391
if branch < 0 || int(branch) >= len(order) {
390-
panic(fmt.Errorf("Invalid branch: %d", branch))
392+
panic(fmt.Errorf("invalid branch: %d", branch))
391393
}
392394
for i, item := range order {
393395
if branch == item {
394396
return i
395397
}
396398
}
397-
panic(fmt.Errorf("Branch %d not found in order %v", branch, order))
399+
panic(fmt.Errorf("branch %d not found in order %v", branch, order))
398400
}
399401

400402
// This will look at the proof and determine which order it is...
@@ -407,5 +409,5 @@ func orderFromPadding(spec *InnerSpec, inner *InnerOp) (int32, error) {
407409
return branch, nil
408410
}
409411
}
410-
return 0, errors.New("Cannot find any valid spacing for this node")
412+
return 0, errors.New("cannot find any valid spacing for this node")
411413
}

0 commit comments

Comments
 (0)