diff --git a/module/Makefile b/module/Makefile index 9b46d720a..7e0125ddf 100644 --- a/module/Makefile +++ b/module/Makefile @@ -1,4 +1,4 @@ -PACKAGES=$(shell go list ./... | grep -v '/simulation') +PACKAGES=$(shell gotip list ./... | grep -v '/simulation') VERSION := $(shell git describe --abbrev=6 --dirty --always --tags) COMMIT := $(shell git log -1 --format='%H') DOCKER := $(shell which docker) @@ -50,20 +50,20 @@ BUILD_FLAGS := -ldflags '$(ldflags)' -gcflags="all=-N -l" all: install install: go.sum - go install $(BUILD_FLAGS) ./cmd/gravity + gotip install $(BUILD_FLAGS) ./cmd/gravity go.sum: go.mod @echo "--> Ensure dependencies have not been modified" - GO111MODULE=on go mod verify + GO111MODULE=on gotip mod verify test: - @go test -mod=readonly $(PACKAGES) + @gotip test -mod=readonly $(PACKAGES) # look into .golangci.yml for enabling / disabling linters lint: @echo "--> Running linter" @golangci-lint run - @go mod verify + @gotip mod verify ############################################################################### ### Protobuf ### @@ -161,7 +161,7 @@ proto-tools-stamp: rm -f ${PROTOC_ZIP}) echo "Installing protoc-gen-gocosmos..." - go install github.com/regen-network/cosmos-proto/protoc-gen-gocosmos + gotip install github.com/regen-network/cosmos-proto/protoc-gen-gocosmos # Create dummy file to satisfy dependency and avoid # rebuilding when this Makefile target is hit twice diff --git a/module/go.mod b/module/go.mod index 658d97b2c..4c4c97747 100644 --- a/module/go.mod +++ b/module/go.mod @@ -4,11 +4,14 @@ go 1.15 require ( github.com/cosmos/cosmos-sdk v0.42.1 + github.com/cosmos/iavl v0.15.3 github.com/ethereum/go-ethereum v1.10.3 github.com/gogo/protobuf v1.3.3 github.com/golang/protobuf v1.4.3 + github.com/google/gofuzz v1.2.0 // indirect github.com/gorilla/mux v1.8.0 github.com/grpc-ecosystem/grpc-gateway v1.16.0 + github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d github.com/pkg/errors v0.9.1 github.com/rakyll/statik v0.1.7 github.com/spf13/cast v1.3.1 diff --git a/module/go.sum b/module/go.sum index ed7c5d4a1..f98aa61fc 100644 --- a/module/go.sum +++ b/module/go.sum @@ -307,8 +307,9 @@ github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa h1:Q75Upo5UN4JbPFURXZ8nLKYUvF85dyFRop/vQ0Rv+64= github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= diff --git a/module/x/gravity/keeper/pool_test.go b/module/x/gravity/keeper/pool_test.go index 02d5c61b1..0a9ad52bb 100644 --- a/module/x/gravity/keeper/pool_test.go +++ b/module/x/gravity/keeper/pool_test.go @@ -1,6 +1,11 @@ +// +build gofuzzbeta + package keeper import ( + "encoding/binary" + "fmt" + "math" "math/big" "testing" @@ -79,6 +84,102 @@ func TestAddToOutgoingPool(t *testing.T) { assert.Equal(t, exp, got) } +func createSeedUint64ByteArrayWithValue(numElts int, value uint64) []byte { + numBytes := numElts * 64 + arr := make([]byte, numBytes) + for i := 0; i < numElts; i++ { + binary.PutUvarint(arr[64*i:64*(i+1)], value) + } + return arr +} + +func deserializeByteArrayToUint64Array(bytes []byte, numElts int) []uint64 { + uints := make([]uint64, numElts) + + for j := 0; j < numElts; j++ { + uints[j] = binary.BigEndian.Uint64(bytes[64*j : 64*(j+1)]) + } + return uints +} + +func FuzzAddToOutgoingPool(f *testing.F) { + numInputs := 6 + ones := createSeedUint64ByteArrayWithValue(numInputs, uint64(1)) + oneHundreds := createSeedUint64ByteArrayWithValue(numInputs, uint64(100)) + + f.Add(ones, oneHundreds, "0000000000000000000000000000000000000000") + f.Fuzz(func(t *testing.T, feez []byte, amountz []byte, contractAddr string) { + if types.ValidateEthAddress(contractAddr) != nil { + t.Skip() + } + fees := deserializeByteArrayToUint64Array(feez, numInputs) + amounts := deserializeByteArrayToUint64Array(amountz, numInputs) + for j := 0; j < numInputs; j++ { + fees[j] = binary.BigEndian.Uint64(feez[64*j : 64*(j+1)]) + amounts[j] = binary.BigEndian.Uint64(amountz[64*j : 64*(j+1)]) + } + + input := CreateTestEnv(t) + ctx := input.Context + var ( + mySender, _ = sdk.AccAddressFromBech32("cosmos1ahx7f8wyertuus9r20284ej0asrs085case3kn") + myReceiver = "0xd041c41EA1bf0F006ADBb6d2c9ef9D425dE5eaD7" + myTokenContractAddr = "0x" + contractAddr + ) + + // mint some voucher first + var balance uint64 = math.MaxUint64 + allVouchers := sdk.Coins{types.NewERC20Token(balance, myTokenContractAddr).GravityCoin()} + err := input.BankKeeper.MintCoins(ctx, types.ModuleName, allVouchers) + if err != nil { + t.Skip() + } + + // set senders balance + input.AccountKeeper.NewAccountWithAddress(ctx, mySender) + err = input.BankKeeper.SetBalances(ctx, mySender, allVouchers) + if err != nil { + t.Skip() + } + + transacts := make([]*types.OutgoingTransferTx, len(fees)) + // create transactions + for i, _ := range fees { + txAmt := amounts[i] + txFee := fees[i] + if uint64(txAmt+txFee) >= balance { + txAmt = uint64(balance / 2) + txFee = uint64(txAmt / 2) + } + amount := types.NewERC20Token(txAmt, myTokenContractAddr).GravityCoin() + fee := types.NewERC20Token(txFee, myTokenContractAddr).GravityCoin() + transacts[i] = &types.OutgoingTransferTx{ + Id: uint64(i + 1), + Sender: mySender.String(), + DestAddress: myReceiver, + Erc20Token: types.NewSDKIntERC20Token(amount.Amount, amount.Denom), + Erc20Fee: types.NewSDKIntERC20Token(fee.Amount, fee.Denom), + } + r, err := input.GravityKeeper.AddToOutgoingPool(ctx, mySender, myReceiver, amount, fee) + balance = balance - uint64(txAmt+txFee) + require.NoError(t, err) + t.Logf("___ response: %#v", r) + // Should create: + // 1: amount 100, fee 2 + // 2: amount 101, fee 3 + // 3: amount 102, fee 2 + // 4: amount 103, fee 1 + + } + + got := input.GravityKeeper.GetUnbatchedTransactionsByContract(ctx, myTokenContractAddr) + if len(got) != len(fees) { + t.Fatal(fmt.Errorf("generated transactions do not match ones received\nexpected: %v\nreceived: %v", transacts, got)) + } + }) + +} + func TestTotalBatchFeeInPool(t *testing.T) { input := CreateTestEnv(t) ctx := input.Context diff --git a/module/x/gravity/keeper/testdata/corpus/FuzzAddToOutgoingPool/797614c6a8d027755f4e24114a94fd5b546e1435616e5664d027b886d42d295f b/module/x/gravity/keeper/testdata/corpus/FuzzAddToOutgoingPool/797614c6a8d027755f4e24114a94fd5b546e1435616e5664d027b886d42d295f new file mode 100644 index 000000000..65e2c799d --- /dev/null +++ b/module/x/gravity/keeper/testdata/corpus/FuzzAddToOutgoingPool/797614c6a8d027755f4e24114a94fd5b546e1435616e5664d027b886d42d295f @@ -0,0 +1,4 @@ +go test fuzz v1 +[]byte("\x01") +[]byte("d") +string("0") \ No newline at end of file