mirror of
				https://github.com/0glabs/0g-chain.git
				synced 2025-11-04 09:57:27 +00:00 
			
		
		
		
	add initial E2E testing setup (#1475)
* setup e2e test that starts kava chain * refactor into a testify suite * setup ethClient * add example test checking chain id * cleanup * refactor & support funded accounts with txs * ignore e2e tests in CI & consolidate makefiles * remove circular go.mod dependency vendors `signing` and `grpc` packages from `kava-labs/go-tools` to refrain from a circular dep and fix pulled in dep versions * add min fee for evm side * prune nothing in e2e node
This commit is contained in:
		
							parent
							
								
									d3930fff91
								
							
						
					
					
						commit
						ff5b0e814e
					
				
							
								
								
									
										11
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								Makefile
									
									
									
									
									
								
							@ -238,6 +238,10 @@ format:
 | 
			
		||||
###                                Localnet                                 ###
 | 
			
		||||
###############################################################################
 | 
			
		||||
 | 
			
		||||
# Build docker image and tag as kava/kava:local
 | 
			
		||||
docker-build:
 | 
			
		||||
	$(DOCKER) build -t kava/kava:local .
 | 
			
		||||
 | 
			
		||||
build-docker-local-kava:
 | 
			
		||||
	@$(MAKE) -C networks/local
 | 
			
		||||
 | 
			
		||||
@ -285,8 +289,13 @@ test-basic: test
 | 
			
		||||
	@# AppStateDeterminism does not use Seed flag
 | 
			
		||||
	@go test ./app -run TestAppStateDeterminism      -Enabled -Commit -NumBlocks=5 -BlockSize=200 -Seed 4 -v -timeout 2m
 | 
			
		||||
 | 
			
		||||
# run end-to-end tests (local docker container must be built, see docker-build)
 | 
			
		||||
test-e2e:
 | 
			
		||||
	export E2E_KAVA_FUNDED_ACCOUNT_MNEMONIC='season bone lucky dog depth pond royal decide unknown device fruit inch clock trap relief horse morning taxi bird session throw skull avocado private'; \
 | 
			
		||||
	go test -failfast -count=1 -v ./tests/e2e/...
 | 
			
		||||
 | 
			
		||||
test:
 | 
			
		||||
	@go test $$(go list ./... | grep -v 'contrib')
 | 
			
		||||
	@go test $$(go list ./... | grep -v 'contrib' | grep -v 'tests/e2e')
 | 
			
		||||
 | 
			
		||||
# Run cli integration tests
 | 
			
		||||
# `-p 4` to use 4 cores, `-tags cli_test` to tell go not to ignore the cli package
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										25
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										25
									
								
								go.mod
									
									
									
									
									
								
							@ -5,6 +5,7 @@ go 1.18
 | 
			
		||||
require (
 | 
			
		||||
	github.com/cosmos/cosmos-proto v1.0.0-alpha6
 | 
			
		||||
	github.com/cosmos/cosmos-sdk v0.45.10
 | 
			
		||||
	github.com/cosmos/go-bip39 v1.0.0
 | 
			
		||||
	github.com/cosmos/ibc-go/v3 v3.4.0
 | 
			
		||||
	github.com/ethereum/go-ethereum v1.10.16
 | 
			
		||||
	github.com/gogo/protobuf v1.3.3
 | 
			
		||||
@ -12,6 +13,7 @@ require (
 | 
			
		||||
	github.com/golang/protobuf v1.5.2
 | 
			
		||||
	github.com/gorilla/mux v1.8.0
 | 
			
		||||
	github.com/grpc-ecosystem/grpc-gateway v1.16.0
 | 
			
		||||
	github.com/ory/dockertest/v3 v3.9.1
 | 
			
		||||
	github.com/spf13/cast v1.5.0
 | 
			
		||||
	github.com/spf13/cobra v1.6.0
 | 
			
		||||
	github.com/stretchr/testify v1.8.0
 | 
			
		||||
@ -27,7 +29,10 @@ require (
 | 
			
		||||
require (
 | 
			
		||||
	filippo.io/edwards25519 v1.0.0-beta.2 // indirect
 | 
			
		||||
	github.com/99designs/keyring v1.1.6 // indirect
 | 
			
		||||
	github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
 | 
			
		||||
	github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d // indirect
 | 
			
		||||
	github.com/Microsoft/go-winio v0.6.0 // indirect
 | 
			
		||||
	github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect
 | 
			
		||||
	github.com/StackExchange/wmi v1.2.1 // indirect
 | 
			
		||||
	github.com/VictoriaMetrics/fastcache v1.6.0 // indirect
 | 
			
		||||
	github.com/Workiva/go-datastructures v1.0.53 // indirect
 | 
			
		||||
@ -38,13 +43,13 @@ require (
 | 
			
		||||
	github.com/btcsuite/btcd v0.22.1 // indirect
 | 
			
		||||
	github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 // indirect
 | 
			
		||||
	github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce // indirect
 | 
			
		||||
	github.com/cenkalti/backoff/v4 v4.1.1 // indirect
 | 
			
		||||
	github.com/cenkalti/backoff/v4 v4.1.3 // indirect
 | 
			
		||||
	github.com/cespare/xxhash v1.1.0 // indirect
 | 
			
		||||
	github.com/cespare/xxhash/v2 v2.1.2 // indirect
 | 
			
		||||
	github.com/coinbase/rosetta-sdk-go v0.7.0 // indirect
 | 
			
		||||
	github.com/confio/ics23/go v0.7.0 // indirect
 | 
			
		||||
	github.com/containerd/continuity v0.3.0 // indirect
 | 
			
		||||
	github.com/cosmos/btcutil v1.0.4 // indirect
 | 
			
		||||
	github.com/cosmos/go-bip39 v1.0.0 // indirect
 | 
			
		||||
	github.com/cosmos/iavl v0.19.4 // indirect
 | 
			
		||||
	github.com/cosmos/ledger-cosmos-go v0.11.1 // indirect
 | 
			
		||||
	github.com/cosmos/ledger-go v0.9.2 // indirect
 | 
			
		||||
@ -55,6 +60,10 @@ require (
 | 
			
		||||
	github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect
 | 
			
		||||
	github.com/dgraph-io/badger/v3 v3.2103.2 // indirect
 | 
			
		||||
	github.com/dgraph-io/ristretto v0.1.0 // indirect
 | 
			
		||||
	github.com/docker/cli v20.10.14+incompatible // indirect
 | 
			
		||||
	github.com/docker/docker v20.10.19+incompatible // indirect
 | 
			
		||||
	github.com/docker/go-connections v0.4.0 // indirect
 | 
			
		||||
	github.com/docker/go-units v0.5.0 // indirect
 | 
			
		||||
	github.com/dustin/go-humanize v1.0.0 // indirect
 | 
			
		||||
	github.com/dvsekhvalnov/jose2go v0.0.0-20200901110807-248326c1351b // indirect
 | 
			
		||||
	github.com/edsrzf/mmap-go v1.0.0 // indirect
 | 
			
		||||
@ -74,6 +83,7 @@ require (
 | 
			
		||||
	github.com/google/btree v1.0.1 // indirect
 | 
			
		||||
	github.com/google/flatbuffers v1.12.1 // indirect
 | 
			
		||||
	github.com/google/orderedcode v0.0.1 // indirect
 | 
			
		||||
	github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
 | 
			
		||||
	github.com/google/uuid v1.3.0 // indirect
 | 
			
		||||
	github.com/gorilla/handlers v1.5.1 // indirect
 | 
			
		||||
	github.com/gorilla/websocket v1.5.0 // indirect
 | 
			
		||||
@ -88,6 +98,7 @@ require (
 | 
			
		||||
	github.com/holiman/bloomfilter/v2 v2.0.3 // indirect
 | 
			
		||||
	github.com/holiman/uint256 v1.2.0 // indirect
 | 
			
		||||
	github.com/huin/goupnp v1.0.2 // indirect
 | 
			
		||||
	github.com/imdario/mergo v0.3.12 // indirect
 | 
			
		||||
	github.com/improbable-eng/grpc-web v0.15.0 // indirect
 | 
			
		||||
	github.com/inconshreveable/mousetrap v1.0.1 // indirect
 | 
			
		||||
	github.com/jackpal/go-nat-pmp v1.0.2 // indirect
 | 
			
		||||
@ -105,8 +116,12 @@ require (
 | 
			
		||||
	github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 // indirect
 | 
			
		||||
	github.com/minio/highwayhash v1.0.2 // indirect
 | 
			
		||||
	github.com/mitchellh/mapstructure v1.5.0 // indirect
 | 
			
		||||
	github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae // indirect
 | 
			
		||||
	github.com/mtibben/percent v0.2.1 // indirect
 | 
			
		||||
	github.com/olekukonko/tablewriter v0.0.5 // indirect
 | 
			
		||||
	github.com/opencontainers/go-digest v1.0.0 // indirect
 | 
			
		||||
	github.com/opencontainers/image-spec v1.1.0-rc2 // indirect
 | 
			
		||||
	github.com/opencontainers/runc v1.1.3 // indirect
 | 
			
		||||
	github.com/pelletier/go-toml v1.9.5 // indirect
 | 
			
		||||
	github.com/pelletier/go-toml/v2 v2.0.5 // indirect
 | 
			
		||||
	github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect
 | 
			
		||||
@ -125,6 +140,7 @@ require (
 | 
			
		||||
	github.com/rs/zerolog v1.27.0 // indirect
 | 
			
		||||
	github.com/sasha-s/go-deadlock v0.3.1 // indirect
 | 
			
		||||
	github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect
 | 
			
		||||
	github.com/sirupsen/logrus v1.9.0 // indirect
 | 
			
		||||
	github.com/spf13/afero v1.8.2 // indirect
 | 
			
		||||
	github.com/spf13/jwalterweatherman v1.1.0 // indirect
 | 
			
		||||
	github.com/spf13/pflag v1.0.5 // indirect
 | 
			
		||||
@ -139,16 +155,21 @@ require (
 | 
			
		||||
	github.com/tklauser/go-sysconf v0.3.7 // indirect
 | 
			
		||||
	github.com/tklauser/numcpus v0.2.3 // indirect
 | 
			
		||||
	github.com/tyler-smith/go-bip39 v1.1.0 // indirect
 | 
			
		||||
	github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect
 | 
			
		||||
	github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
 | 
			
		||||
	github.com/xeipuuv/gojsonschema v1.2.0 // indirect
 | 
			
		||||
	github.com/zondax/hid v0.9.0 // indirect
 | 
			
		||||
	go.etcd.io/bbolt v1.3.6 // indirect
 | 
			
		||||
	go.opencensus.io v0.23.0 // indirect
 | 
			
		||||
	golang.org/x/crypto v0.1.0 // indirect
 | 
			
		||||
	golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect
 | 
			
		||||
	golang.org/x/mod v0.6.0 // indirect
 | 
			
		||||
	golang.org/x/net v0.1.0 // indirect
 | 
			
		||||
	golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0 // indirect
 | 
			
		||||
	golang.org/x/sys v0.1.0 // indirect
 | 
			
		||||
	golang.org/x/term v0.1.0 // indirect
 | 
			
		||||
	golang.org/x/text v0.4.0 // indirect
 | 
			
		||||
	golang.org/x/tools v0.2.0 // indirect
 | 
			
		||||
	gopkg.in/ini.v1 v1.67.0 // indirect
 | 
			
		||||
	gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect
 | 
			
		||||
	gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6 // indirect
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										65
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										65
									
								
								go.sum
									
									
									
									
									
								
							@ -45,6 +45,7 @@ github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiU
 | 
			
		||||
github.com/Azure/azure-pipeline-go v0.2.2/go.mod h1:4rQ/NZncSvGqNkkOsNpOU1tgoNuIlp9AfUH5G1tvCHc=
 | 
			
		||||
github.com/Azure/azure-storage-blob-go v0.7.0/go.mod h1:f9YQKtsG1nMisotuTPpO0tjNuEjKRYAcJU8/ydDI++4=
 | 
			
		||||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
 | 
			
		||||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
 | 
			
		||||
github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
 | 
			
		||||
github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0=
 | 
			
		||||
github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc=
 | 
			
		||||
@ -65,7 +66,9 @@ github.com/DataDog/zstd v1.4.1/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t
 | 
			
		||||
github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
 | 
			
		||||
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
 | 
			
		||||
github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg=
 | 
			
		||||
github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE=
 | 
			
		||||
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw=
 | 
			
		||||
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk=
 | 
			
		||||
github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=
 | 
			
		||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
 | 
			
		||||
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
 | 
			
		||||
@ -154,8 +157,9 @@ github.com/c-bata/go-prompt v0.2.2/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOC
 | 
			
		||||
github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
 | 
			
		||||
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
 | 
			
		||||
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
 | 
			
		||||
github.com/cenkalti/backoff/v4 v4.1.1 h1:G2HAfAmvm/GcKan2oOQpBXOd2tT2G57ZnZGWa1PxPBQ=
 | 
			
		||||
github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
 | 
			
		||||
github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4=
 | 
			
		||||
github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
 | 
			
		||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
 | 
			
		||||
github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk=
 | 
			
		||||
github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s=
 | 
			
		||||
@ -164,9 +168,11 @@ github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghf
 | 
			
		||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
 | 
			
		||||
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
 | 
			
		||||
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
 | 
			
		||||
github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E=
 | 
			
		||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
 | 
			
		||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
 | 
			
		||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
 | 
			
		||||
github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA=
 | 
			
		||||
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
 | 
			
		||||
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
 | 
			
		||||
github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE=
 | 
			
		||||
@ -179,11 +185,14 @@ github.com/coinbase/rosetta-sdk-go v0.7.0 h1:lmTO/JEpCvZgpbkOITL95rA80CPKb5CtMzL
 | 
			
		||||
github.com/coinbase/rosetta-sdk-go v0.7.0/go.mod h1:7nD3oBPIiHqhRprqvMgPoGxe/nyq3yftRmpsy29coWE=
 | 
			
		||||
github.com/consensys/bavard v0.1.8-0.20210406032232-f3452dc9b572/go.mod h1:Bpd0/3mZuaj6Sj+PqrmIquiOKy397AKGThQPaGzNXAQ=
 | 
			
		||||
github.com/consensys/gnark-crypto v0.4.1-0.20210426202927-39ac3d4b3f1f/go.mod h1:815PAHg3wvysy0SyIqanF8gZ0Y1wjk/hrDHD/iT88+Q=
 | 
			
		||||
github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U=
 | 
			
		||||
github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg=
 | 
			
		||||
github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM=
 | 
			
		||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
 | 
			
		||||
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
 | 
			
		||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
 | 
			
		||||
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
 | 
			
		||||
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
 | 
			
		||||
github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
 | 
			
		||||
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
 | 
			
		||||
github.com/cosmos/btcutil v1.0.4 h1:n7C2ngKXo7UC9gNyMNLbzqz7Asuf+7Qv4gnX/rOdQ44=
 | 
			
		||||
@ -212,7 +221,10 @@ github.com/creachadair/taskgroup v0.3.2 h1:zlfutDS+5XG40AOxcHDSThxKzns8Tnr9jnr6V
 | 
			
		||||
github.com/creachadair/taskgroup v0.3.2/go.mod h1:wieWwecHVzsidg2CsUnFinW1faVN4+kq+TDlRJQ0Wbk=
 | 
			
		||||
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
 | 
			
		||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
 | 
			
		||||
github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw=
 | 
			
		||||
github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
 | 
			
		||||
github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4=
 | 
			
		||||
github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
 | 
			
		||||
github.com/danieljoos/wincred v1.0.2 h1:zf4bhty2iLuwgjgpraD2E9UbvO+fe54XXGJbOwe23fU=
 | 
			
		||||
github.com/danieljoos/wincred v1.0.2/go.mod h1:SnuYRW9lp1oJrZX/dXJqr0cPK5gYXqx3EJbmjhLdK9U=
 | 
			
		||||
github.com/dave/jennifer v1.2.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg=
 | 
			
		||||
@ -243,9 +255,16 @@ github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUn
 | 
			
		||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
 | 
			
		||||
github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
 | 
			
		||||
github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
 | 
			
		||||
github.com/docker/cli v20.10.14+incompatible h1:dSBKJOVesDgHo7rbxlYjYsXe7gPzrTT+/cKQgpDAazg=
 | 
			
		||||
github.com/docker/cli v20.10.14+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
 | 
			
		||||
github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
 | 
			
		||||
github.com/docker/docker v20.10.19+incompatible h1:lzEmjivyNHFHMNAFLXORMBXyGIhw/UP4DvJwvyKYq64=
 | 
			
		||||
github.com/docker/docker v20.10.19+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
 | 
			
		||||
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
 | 
			
		||||
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
 | 
			
		||||
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
 | 
			
		||||
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
 | 
			
		||||
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
 | 
			
		||||
github.com/dop251/goja v0.0.0-20200721192441-a695b0cdd498/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA=
 | 
			
		||||
github.com/dop251/goja v0.0.0-20211011172007-d99e4b8cbf48/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk=
 | 
			
		||||
github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y=
 | 
			
		||||
@ -279,6 +298,7 @@ github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/
 | 
			
		||||
github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
 | 
			
		||||
github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=
 | 
			
		||||
github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=
 | 
			
		||||
github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
 | 
			
		||||
github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
 | 
			
		||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
 | 
			
		||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
 | 
			
		||||
@ -329,6 +349,7 @@ github.com/go-sourcemap/sourcemap v2.1.2+incompatible/go.mod h1:F8jJfvm2KbVjc5Nq
 | 
			
		||||
github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg=
 | 
			
		||||
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
 | 
			
		||||
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
 | 
			
		||||
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
 | 
			
		||||
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
 | 
			
		||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
 | 
			
		||||
github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0=
 | 
			
		||||
@ -340,6 +361,7 @@ github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/E
 | 
			
		||||
github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 h1:ZpnhV/YsD2/4cESfV5+Hoeu/iUR3ruzNvZ+yQfO03a0=
 | 
			
		||||
github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4=
 | 
			
		||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
 | 
			
		||||
github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
 | 
			
		||||
github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
 | 
			
		||||
github.com/gogo/gateway v1.1.0 h1:u0SuhL9+Il+UbjM9VIE3ntfRujKbvVpFvNB4HbjeVQ0=
 | 
			
		||||
github.com/gogo/gateway v1.1.0/go.mod h1:S7rR8FRQyG3QFESeSv4l2WnsyzlCLG0CzBbUUo/mbic=
 | 
			
		||||
@ -425,6 +447,8 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe
 | 
			
		||||
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
 | 
			
		||||
github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
 | 
			
		||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
 | 
			
		||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
 | 
			
		||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
 | 
			
		||||
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 | 
			
		||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 | 
			
		||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 | 
			
		||||
@ -513,6 +537,8 @@ github.com/huin/goupnp v1.0.2/go.mod h1:0dxJBVBHqTMjIUMkESDTNgOOx/Mw5wYIfyFmdzSa
 | 
			
		||||
github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o=
 | 
			
		||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
 | 
			
		||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
 | 
			
		||||
github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
 | 
			
		||||
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
 | 
			
		||||
github.com/improbable-eng/grpc-web v0.15.0 h1:BN+7z6uNXZ1tQGcNAuaU1YjsLTApzkjt2tzCixLaUPQ=
 | 
			
		||||
github.com/improbable-eng/grpc-web v0.15.0/go.mod h1:1sy9HKV4Jt9aEs9JSnkWlRJPuPtwNr0l57L4f878wP8=
 | 
			
		||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
 | 
			
		||||
@ -669,6 +695,9 @@ github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyua
 | 
			
		||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
 | 
			
		||||
github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A=
 | 
			
		||||
github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4=
 | 
			
		||||
github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU=
 | 
			
		||||
github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae h1:O4SWKdcHVCvYqyDV+9CJA1fcDN2L11Bule0iFy3YlAI=
 | 
			
		||||
github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw=
 | 
			
		||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
 | 
			
		||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
 | 
			
		||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
 | 
			
		||||
@ -676,6 +705,7 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN
 | 
			
		||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
 | 
			
		||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
 | 
			
		||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
 | 
			
		||||
github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ=
 | 
			
		||||
github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg=
 | 
			
		||||
github.com/mtibben/percent v0.2.1 h1:5gssi8Nqo8QU/r2pynCm+hBQHpkB/uNK7BJCFogWdzs=
 | 
			
		||||
github.com/mtibben/percent v0.2.1/go.mod h1:KG9uO+SZkUp+VkRHsCdYQV3XSZrrSpR3O9ibNBTZrns=
 | 
			
		||||
@ -715,8 +745,13 @@ github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE=
 | 
			
		||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
 | 
			
		||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
 | 
			
		||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
 | 
			
		||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
 | 
			
		||||
github.com/opencontainers/image-spec v1.1.0-rc2 h1:2zx/Stx4Wc5pIPDvIxHXvXtQFW/7XWJGmnM7r3wg034=
 | 
			
		||||
github.com/opencontainers/image-spec v1.1.0-rc2/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ=
 | 
			
		||||
github.com/opencontainers/runc v1.1.3 h1:vIXrkId+0/J2Ymu2m7VjGvbSlAId9XNRPhn2p4b+d8w=
 | 
			
		||||
github.com/opencontainers/runc v1.1.3/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg=
 | 
			
		||||
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
 | 
			
		||||
github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI=
 | 
			
		||||
github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis=
 | 
			
		||||
github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=
 | 
			
		||||
github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
 | 
			
		||||
@ -727,6 +762,8 @@ github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJ
 | 
			
		||||
github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
 | 
			
		||||
github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
 | 
			
		||||
github.com/ory/dockertest v3.3.5+incompatible h1:iLLK6SQwIhcbrG783Dghaaa3WPzGc+4Emza6EbVUUGA=
 | 
			
		||||
github.com/ory/dockertest/v3 v3.9.1 h1:v4dkG+dlu76goxMiTT2j8zV7s4oPPEppKT8K8p2f1kY=
 | 
			
		||||
github.com/ory/dockertest/v3 v3.9.1/go.mod h1:42Ir9hmvaAPm0Mgibk6mBPi7SFvTXxEcnztDYOJ//uM=
 | 
			
		||||
github.com/otiai10/copy v1.6.0 h1:IinKAryFFuPONZ7cm6T6E2QX/vcJwSnlaA5lfoaXIiQ=
 | 
			
		||||
github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM=
 | 
			
		||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
 | 
			
		||||
@ -833,6 +870,7 @@ github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0
 | 
			
		||||
github.com/sasha-s/go-deadlock v0.3.1 h1:sqv7fDNShgjcaxkO0JNcOAlr8B9+cV5Ey/OB71efZx0=
 | 
			
		||||
github.com/sasha-s/go-deadlock v0.3.1/go.mod h1:F73l+cr82YSh10GxyRI6qZiCgK64VaZjwesgfQ1/iLM=
 | 
			
		||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
 | 
			
		||||
github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg=
 | 
			
		||||
github.com/segmentio/fasthash v1.0.3/go.mod h1:waKX8l2N8yckOgmSsXJi7x1ZfdKZ4x7KRMzBtS3oedY=
 | 
			
		||||
github.com/segmentio/kafka-go v0.1.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo=
 | 
			
		||||
github.com/segmentio/kafka-go v0.2.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo=
 | 
			
		||||
@ -845,7 +883,9 @@ github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx
 | 
			
		||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
 | 
			
		||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
 | 
			
		||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
 | 
			
		||||
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
 | 
			
		||||
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
 | 
			
		||||
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
 | 
			
		||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
 | 
			
		||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
 | 
			
		||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
 | 
			
		||||
@ -898,6 +938,7 @@ github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PK
 | 
			
		||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
 | 
			
		||||
github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs=
 | 
			
		||||
github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
 | 
			
		||||
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
 | 
			
		||||
github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca/go.mod h1:u2MKkTVTVJWe5D1rCvame8WqhBd88EuIwODJZ1VHCPM=
 | 
			
		||||
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY=
 | 
			
		||||
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc=
 | 
			
		||||
@ -939,10 +980,18 @@ github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/X
 | 
			
		||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
 | 
			
		||||
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
 | 
			
		||||
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
 | 
			
		||||
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
 | 
			
		||||
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
 | 
			
		||||
github.com/vmihailenco/msgpack/v5 v5.1.4/go.mod h1:C5gboKD0TJPqWDTVTtrQNfRbiBwHZGo8UTqP/9/XvLI=
 | 
			
		||||
github.com/vmihailenco/tagparser v0.1.2/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI=
 | 
			
		||||
github.com/willf/bitset v1.1.3/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
 | 
			
		||||
github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208/go.mod h1:IotVbo4F+mw0EzQ08zFqg7pK3FebNXpaMsRy2RT+Ees=
 | 
			
		||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c=
 | 
			
		||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
 | 
			
		||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
 | 
			
		||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
 | 
			
		||||
github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74=
 | 
			
		||||
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
 | 
			
		||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
 | 
			
		||||
github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg=
 | 
			
		||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
 | 
			
		||||
@ -1044,6 +1093,7 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 | 
			
		||||
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 | 
			
		||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 | 
			
		||||
golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
 | 
			
		||||
golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
 | 
			
		||||
golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 | 
			
		||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 | 
			
		||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 | 
			
		||||
@ -1139,6 +1189,7 @@ golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7w
 | 
			
		||||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20190712062909-fae7ac547cb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
@ -1150,6 +1201,7 @@ golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7w
 | 
			
		||||
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
@ -1196,13 +1248,18 @@ golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7w
 | 
			
		||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U=
 | 
			
		||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
@ -1242,6 +1299,7 @@ golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBn
 | 
			
		||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
 | 
			
		||||
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
 | 
			
		||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
 | 
			
		||||
golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
 | 
			
		||||
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
 | 
			
		||||
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
 | 
			
		||||
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
 | 
			
		||||
@ -1288,6 +1346,7 @@ golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4f
 | 
			
		||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
 | 
			
		||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
 | 
			
		||||
golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
 | 
			
		||||
golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
 | 
			
		||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 | 
			
		||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 | 
			
		||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 | 
			
		||||
@ -1387,6 +1446,7 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba
 | 
			
		||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
 | 
			
		||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
 | 
			
		||||
google.golang.org/protobuf v1.27.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
 | 
			
		||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
 | 
			
		||||
google.golang.org/protobuf v1.28.2-0.20220831092852-f930b1dc76e8 h1:KR8+MyP7/qOlV+8Af01LtjL04bu7on42eVsxT4EyBQk=
 | 
			
		||||
google.golang.org/protobuf v1.28.2-0.20220831092852-f930b1dc76e8/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
 | 
			
		||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
 | 
			
		||||
@ -1425,7 +1485,10 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
 | 
			
		||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 | 
			
		||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 | 
			
		||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 | 
			
		||||
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
 | 
			
		||||
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
 | 
			
		||||
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
 | 
			
		||||
gotest.tools/v3 v3.2.0 h1:I0DwBVMGAx26dttAj1BtJLAkVGncrkkUXfJLC4Flt/I=
 | 
			
		||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 | 
			
		||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 | 
			
		||||
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										51
									
								
								tests/e2e/e2e_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								tests/e2e/e2e_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,51 @@
 | 
			
		||||
package e2e_test
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"math/big"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/stretchr/testify/suite"
 | 
			
		||||
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/client/grpc/tmservice"
 | 
			
		||||
	banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
 | 
			
		||||
 | 
			
		||||
	sdk "github.com/cosmos/cosmos-sdk/types"
 | 
			
		||||
	"github.com/kava-labs/kava/tests/e2e/testutil"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func ukava(amt int64) sdk.Coin {
 | 
			
		||||
	return sdk.NewCoin("ukava", sdk.NewInt(amt))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type IntegrationTestSuite struct {
 | 
			
		||||
	testutil.E2eTestSuite
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestIntegrationTestSuite(t *testing.T) {
 | 
			
		||||
	suite.Run(t, new(IntegrationTestSuite))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// example test that queries kava chain & kava's EVM
 | 
			
		||||
func (suite *IntegrationTestSuite) TestChainID() {
 | 
			
		||||
	// TODO: make chain agnostic, don't hardcode expected chain ids
 | 
			
		||||
 | 
			
		||||
	evmNetworkId, err := suite.EvmClient.NetworkID(context.Background())
 | 
			
		||||
	suite.NoError(err)
 | 
			
		||||
	suite.Equal(big.NewInt(8888), evmNetworkId)
 | 
			
		||||
 | 
			
		||||
	nodeInfo, err := suite.Tm.GetNodeInfo(context.Background(), &tmservice.GetNodeInfoRequest{})
 | 
			
		||||
	suite.NoError(err)
 | 
			
		||||
	suite.Equal(testutil.ChainId, nodeInfo.DefaultNodeInfo.Network)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// example test that funds a new account & queries its balance
 | 
			
		||||
func (suite *IntegrationTestSuite) TestFundedAccount() {
 | 
			
		||||
	funds := ukava(1e7)
 | 
			
		||||
	acc := suite.NewFundedAccount("example-acc", sdk.NewCoins(funds))
 | 
			
		||||
	res, err := suite.Bank.Balance(context.Background(), banktypes.NewQueryBalanceRequest(
 | 
			
		||||
		acc.Address, "ukava",
 | 
			
		||||
	))
 | 
			
		||||
	suite.NoError(err)
 | 
			
		||||
	suite.Equal(funds, *res.Balance)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										4
									
								
								tests/e2e/generated/kava-1/config/addrbook.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								tests/e2e/generated/kava-1/config/addrbook.json
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,4 @@
 | 
			
		||||
{
 | 
			
		||||
	"key": "a8235b98e65b6890091537ac",
 | 
			
		||||
	"addrs": []
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										272
									
								
								tests/e2e/generated/kava-1/config/app.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										272
									
								
								tests/e2e/generated/kava-1/config/app.toml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,272 @@
 | 
			
		||||
# This is a TOML config file.
 | 
			
		||||
# For more information, see https://github.com/toml-lang/toml
 | 
			
		||||
 | 
			
		||||
###############################################################################
 | 
			
		||||
###                           Base Configuration                            ###
 | 
			
		||||
###############################################################################
 | 
			
		||||
 | 
			
		||||
# The minimum gas prices a validator is willing to accept for processing a
 | 
			
		||||
# transaction. A transaction's fees must meet the minimum of any denomination
 | 
			
		||||
# specified in this config (e.g. 0.25token1;0.0001token2).
 | 
			
		||||
minimum-gas-prices = "0.001ukava;1000000000akava"
 | 
			
		||||
 | 
			
		||||
# default: the last 100 states are kept in addition to every 500th state; pruning at 10 block intervals
 | 
			
		||||
# nothing: all historic states will be saved, nothing will be deleted (i.e. archiving node)
 | 
			
		||||
# everything: all saved states will be deleted, storing only the current and previous state; pruning at 10 block intervals
 | 
			
		||||
# custom: allow pruning options to be manually specified through 'pruning-keep-recent', 'pruning-keep-every', and 'pruning-interval'
 | 
			
		||||
pruning = "nothing"
 | 
			
		||||
 | 
			
		||||
# These are applied if and only if the pruning strategy is custom.
 | 
			
		||||
pruning-keep-recent = "0"
 | 
			
		||||
pruning-keep-every = "0"
 | 
			
		||||
pruning-interval = "0"
 | 
			
		||||
 | 
			
		||||
# HaltHeight contains a non-zero block height at which a node will gracefully
 | 
			
		||||
# halt and shutdown that can be used to assist upgrades and testing.
 | 
			
		||||
#
 | 
			
		||||
# Note: Commitment of state will be attempted on the corresponding block.
 | 
			
		||||
halt-height = 0
 | 
			
		||||
 | 
			
		||||
# HaltTime contains a non-zero minimum block time (in Unix seconds) at which
 | 
			
		||||
# a node will gracefully halt and shutdown that can be used to assist upgrades
 | 
			
		||||
# and testing.
 | 
			
		||||
#
 | 
			
		||||
# Note: Commitment of state will be attempted on the corresponding block.
 | 
			
		||||
halt-time = 0
 | 
			
		||||
 | 
			
		||||
# MinRetainBlocks defines the minimum block height offset from the current
 | 
			
		||||
# block being committed, such that all blocks past this offset are pruned
 | 
			
		||||
# from Tendermint. It is used as part of the process of determining the
 | 
			
		||||
# ResponseCommit.RetainHeight value during ABCI Commit. A value of 0 indicates
 | 
			
		||||
# that no blocks should be pruned.
 | 
			
		||||
#
 | 
			
		||||
# This configuration value is only responsible for pruning Tendermint blocks.
 | 
			
		||||
# It has no bearing on application state pruning which is determined by the
 | 
			
		||||
# "pruning-*" configurations.
 | 
			
		||||
#
 | 
			
		||||
# Note: Tendermint block pruning is dependant on this parameter in conunction
 | 
			
		||||
# with the unbonding (safety threshold) period, state pruning and state sync
 | 
			
		||||
# snapshot parameters to determine the correct minimum value of
 | 
			
		||||
# ResponseCommit.RetainHeight.
 | 
			
		||||
min-retain-blocks = 0
 | 
			
		||||
 | 
			
		||||
# InterBlockCache enables inter-block caching.
 | 
			
		||||
inter-block-cache = true
 | 
			
		||||
 | 
			
		||||
# IndexEvents defines the set of events in the form {eventType}.{attributeKey},
 | 
			
		||||
# which informs Tendermint what to index. If empty, all events will be indexed.
 | 
			
		||||
#
 | 
			
		||||
# Example:
 | 
			
		||||
# ["message.sender", "message.recipient"]
 | 
			
		||||
index-events = []
 | 
			
		||||
 | 
			
		||||
# IavlCacheSize set the size of the iavl tree cache.
 | 
			
		||||
# Default cache size is 50mb.
 | 
			
		||||
iavl-cache-size = 781250
 | 
			
		||||
trace = true
 | 
			
		||||
# IAVLDisableFastNode enables or disables the fast node feature of IAVL.
 | 
			
		||||
# Default is true.
 | 
			
		||||
iavl-disable-fastnode = true
 | 
			
		||||
 | 
			
		||||
###############################################################################
 | 
			
		||||
###                         Telemetry Configuration                         ###
 | 
			
		||||
###############################################################################
 | 
			
		||||
 | 
			
		||||
[telemetry]
 | 
			
		||||
 | 
			
		||||
# Prefixed with keys to separate services.
 | 
			
		||||
service-name = ""
 | 
			
		||||
 | 
			
		||||
# Enabled enables the application telemetry functionality. When enabled,
 | 
			
		||||
# an in-memory sink is also enabled by default. Operators may also enabled
 | 
			
		||||
# other sinks such as Prometheus.
 | 
			
		||||
enabled = false
 | 
			
		||||
 | 
			
		||||
# Enable prefixing gauge values with hostname.
 | 
			
		||||
enable-hostname = false
 | 
			
		||||
 | 
			
		||||
# Enable adding hostname to labels.
 | 
			
		||||
enable-hostname-label = false
 | 
			
		||||
 | 
			
		||||
# Enable adding service to labels.
 | 
			
		||||
enable-service-label = false
 | 
			
		||||
 | 
			
		||||
# PrometheusRetentionTime, when positive, enables a Prometheus metrics sink.
 | 
			
		||||
prometheus-retention-time = 0
 | 
			
		||||
 | 
			
		||||
# GlobalLabels defines a global set of name/value label tuples applied to all
 | 
			
		||||
# metrics emitted using the wrapper functions defined in telemetry package.
 | 
			
		||||
#
 | 
			
		||||
# Example:
 | 
			
		||||
# [["chain_id", "cosmoshub-1"]]
 | 
			
		||||
global-labels = [
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
###############################################################################
 | 
			
		||||
###                           API Configuration                             ###
 | 
			
		||||
###############################################################################
 | 
			
		||||
 | 
			
		||||
[api]
 | 
			
		||||
 | 
			
		||||
# Enable defines if the API server should be enabled.
 | 
			
		||||
enable = true
 | 
			
		||||
 | 
			
		||||
# Swagger defines if swagger documentation should automatically be registered.
 | 
			
		||||
swagger = false
 | 
			
		||||
 | 
			
		||||
# Address defines the API server to listen on.
 | 
			
		||||
address = "tcp://0.0.0.0:1317"
 | 
			
		||||
 | 
			
		||||
# MaxOpenConnections defines the number of maximum open connections.
 | 
			
		||||
max-open-connections = 1000
 | 
			
		||||
 | 
			
		||||
# RPCReadTimeout defines the Tendermint RPC read timeout (in seconds).
 | 
			
		||||
rpc-read-timeout = 10
 | 
			
		||||
 | 
			
		||||
# RPCWriteTimeout defines the Tendermint RPC write timeout (in seconds).
 | 
			
		||||
rpc-write-timeout = 0
 | 
			
		||||
 | 
			
		||||
# RPCMaxBodyBytes defines the Tendermint maximum response body (in bytes).
 | 
			
		||||
rpc-max-body-bytes = 1000000
 | 
			
		||||
 | 
			
		||||
# EnableUnsafeCORS defines if CORS should be enabled (unsafe - use it at your own risk).
 | 
			
		||||
enabled-unsafe-cors = true
 | 
			
		||||
 | 
			
		||||
###############################################################################
 | 
			
		||||
###                           Rosetta Configuration                         ###
 | 
			
		||||
###############################################################################
 | 
			
		||||
 | 
			
		||||
[rosetta]
 | 
			
		||||
 | 
			
		||||
# Enable defines if the Rosetta API server should be enabled.
 | 
			
		||||
enable = true
 | 
			
		||||
 | 
			
		||||
# Address defines the Rosetta API server to listen on.
 | 
			
		||||
address = ":8080"
 | 
			
		||||
 | 
			
		||||
# Network defines the name of the blockchain that will be returned by Rosetta.
 | 
			
		||||
blockchain = "app"
 | 
			
		||||
 | 
			
		||||
# Network defines the name of the network that will be returned by Rosetta.
 | 
			
		||||
network = "network"
 | 
			
		||||
 | 
			
		||||
# Retries defines the number of retries when connecting to the node before failing.
 | 
			
		||||
retries = 3
 | 
			
		||||
 | 
			
		||||
# Offline defines if Rosetta server should run in offline mode.
 | 
			
		||||
offline = false
 | 
			
		||||
 | 
			
		||||
###############################################################################
 | 
			
		||||
###                           gRPC Configuration                            ###
 | 
			
		||||
###############################################################################
 | 
			
		||||
 | 
			
		||||
[grpc]
 | 
			
		||||
 | 
			
		||||
# Enable defines if the gRPC server should be enabled.
 | 
			
		||||
enable = true
 | 
			
		||||
 | 
			
		||||
# Address defines the gRPC server address to bind to.
 | 
			
		||||
address = "0.0.0.0:9090"
 | 
			
		||||
 | 
			
		||||
###############################################################################
 | 
			
		||||
###                        gRPC Web Configuration                           ###
 | 
			
		||||
###############################################################################
 | 
			
		||||
 | 
			
		||||
[grpc-web]
 | 
			
		||||
 | 
			
		||||
# GRPCWebEnable defines if the gRPC-web should be enabled.
 | 
			
		||||
# NOTE: gRPC must also be enabled, otherwise, this configuration is a no-op.
 | 
			
		||||
enable = true
 | 
			
		||||
 | 
			
		||||
# Address defines the gRPC-web server address to bind to.
 | 
			
		||||
address = "0.0.0.0:9091"
 | 
			
		||||
 | 
			
		||||
# EnableUnsafeCORS defines if CORS should be enabled (unsafe - use it at your own risk).
 | 
			
		||||
enable-unsafe-cors = false
 | 
			
		||||
 | 
			
		||||
###############################################################################
 | 
			
		||||
###                        State Sync Configuration                         ###
 | 
			
		||||
###############################################################################
 | 
			
		||||
 | 
			
		||||
# State sync snapshots allow other nodes to rapidly join the network without replaying historical
 | 
			
		||||
# blocks, instead downloading and applying a snapshot of the application state at a given height.
 | 
			
		||||
[state-sync]
 | 
			
		||||
 | 
			
		||||
# snapshot-interval specifies the block interval at which local state sync snapshots are
 | 
			
		||||
# taken (0 to disable). Must be a multiple of pruning-keep-every.
 | 
			
		||||
snapshot-interval = 0
 | 
			
		||||
 | 
			
		||||
# snapshot-keep-recent specifies the number of recent snapshots to keep and serve (0 to keep all).
 | 
			
		||||
snapshot-keep-recent = 2
 | 
			
		||||
 | 
			
		||||
###############################################################################
 | 
			
		||||
###                             EVM Configuration                           ###
 | 
			
		||||
###############################################################################
 | 
			
		||||
 | 
			
		||||
[evm]
 | 
			
		||||
 | 
			
		||||
# Tracer defines the 'vm.Tracer' type that the EVM will use when the node is run in
 | 
			
		||||
# debug mode. To enable tracing use the '--evm.tracer' flag when starting your node.
 | 
			
		||||
# Valid types are: json|struct|access_list|markdown
 | 
			
		||||
tracer = "json"
 | 
			
		||||
 | 
			
		||||
# MaxTxGasWanted defines the gas wanted for each eth tx returned in ante handler in check tx mode.
 | 
			
		||||
max-tx-gas-wanted = 500000
 | 
			
		||||
 | 
			
		||||
###############################################################################
 | 
			
		||||
###                           JSON RPC Configuration                        ###
 | 
			
		||||
###############################################################################
 | 
			
		||||
 | 
			
		||||
[json-rpc]
 | 
			
		||||
 | 
			
		||||
# Enable defines if the gRPC server should be enabled.
 | 
			
		||||
enable = true
 | 
			
		||||
 | 
			
		||||
# Address defines the EVM RPC HTTP server address to bind to.
 | 
			
		||||
address = "0.0.0.0:8545"
 | 
			
		||||
 | 
			
		||||
# Address defines the EVM WebSocket server address to bind to.
 | 
			
		||||
ws-address = "0.0.0.0:8546"
 | 
			
		||||
 | 
			
		||||
# API defines a list of JSON-RPC namespaces that should be enabled
 | 
			
		||||
# Example: "eth,txpool,personal,net,debug,web3"
 | 
			
		||||
api = "eth,net,web3"
 | 
			
		||||
 | 
			
		||||
# GasCap sets a cap on gas that can be used in eth_call/estimateGas (0=infinite). Default: 25,000,000.
 | 
			
		||||
gas-cap = 25000000
 | 
			
		||||
 | 
			
		||||
# EVMTimeout is the global timeout for eth_call. Default: 5s.
 | 
			
		||||
evm-timeout = "5s"
 | 
			
		||||
 | 
			
		||||
# TxFeeCap is the global tx-fee cap for send transaction. Default: 1eth.
 | 
			
		||||
txfee-cap = 1
 | 
			
		||||
 | 
			
		||||
# FilterCap sets the global cap for total number of filters that can be created
 | 
			
		||||
filter-cap = 200
 | 
			
		||||
 | 
			
		||||
# FeeHistoryCap sets the global cap for total number of blocks that can be fetched
 | 
			
		||||
feehistory-cap = 100
 | 
			
		||||
 | 
			
		||||
# LogsCap defines the max number of results can be returned from single 'eth_getLogs' query.
 | 
			
		||||
logs-cap = 10000
 | 
			
		||||
 | 
			
		||||
# BlockRangeCap defines the max block range allowed for 'eth_getLogs' query.
 | 
			
		||||
block-range-cap = 10000
 | 
			
		||||
 | 
			
		||||
# HTTPTimeout is the read/write timeout of http json-rpc server.
 | 
			
		||||
http-timeout = "30s"
 | 
			
		||||
 | 
			
		||||
# HTTPIdleTimeout is the idle timeout of http json-rpc server.
 | 
			
		||||
http-idle-timeout = "2m0s"
 | 
			
		||||
 | 
			
		||||
###############################################################################
 | 
			
		||||
###                             TLS Configuration                           ###
 | 
			
		||||
###############################################################################
 | 
			
		||||
 | 
			
		||||
[tls]
 | 
			
		||||
 | 
			
		||||
# Certificate path defines the cert.pem file path for the TLS configuration.
 | 
			
		||||
certificate-path = ""
 | 
			
		||||
 | 
			
		||||
# Key path defines the key.pem file path for the TLS configuration.
 | 
			
		||||
key-path = ""
 | 
			
		||||
							
								
								
									
										17
									
								
								tests/e2e/generated/kava-1/config/client.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								tests/e2e/generated/kava-1/config/client.toml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,17 @@
 | 
			
		||||
# This is a TOML config file.
 | 
			
		||||
# For more information, see https://github.com/toml-lang/toml
 | 
			
		||||
 | 
			
		||||
###############################################################################
 | 
			
		||||
###                           Client Configuration                            ###
 | 
			
		||||
###############################################################################
 | 
			
		||||
 | 
			
		||||
# The network chain ID
 | 
			
		||||
chain-id = "kavalocalnet_8888-1"
 | 
			
		||||
# The keyring's backend, where the keys are stored (os|file|kwallet|pass|test|memory)
 | 
			
		||||
keyring-backend = "test"
 | 
			
		||||
# CLI output format (text|json)
 | 
			
		||||
output = "text"
 | 
			
		||||
# <host>:<port> to Tendermint RPC interface for this chain
 | 
			
		||||
node = "tcp://localhost:26657"
 | 
			
		||||
# Transaction broadcasting mode (sync|async|block)
 | 
			
		||||
broadcast-mode = "block"
 | 
			
		||||
							
								
								
									
										466
									
								
								tests/e2e/generated/kava-1/config/config.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										466
									
								
								tests/e2e/generated/kava-1/config/config.toml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,466 @@
 | 
			
		||||
# This is a TOML config file.
 | 
			
		||||
# For more information, see https://github.com/toml-lang/toml
 | 
			
		||||
 | 
			
		||||
# NOTE: Any path below can be absolute (e.g. "/var/myawesomeapp/data") or
 | 
			
		||||
# relative to the home directory (e.g. "data"). The home directory is
 | 
			
		||||
# "$HOME/.tendermint" by default, but could be changed via $TMHOME env variable
 | 
			
		||||
# or --home cmd flag.
 | 
			
		||||
 | 
			
		||||
#######################################################################
 | 
			
		||||
###                   Main Base Config Options                      ###
 | 
			
		||||
#######################################################################
 | 
			
		||||
 | 
			
		||||
# TCP or UNIX socket address of the ABCI application,
 | 
			
		||||
# or the name of an ABCI application compiled in with the Tendermint binary
 | 
			
		||||
proxy_app = "tcp://127.0.0.1:26658"
 | 
			
		||||
 | 
			
		||||
# A custom human readable name for this node
 | 
			
		||||
moniker = "validator"
 | 
			
		||||
 | 
			
		||||
# If this node is many blocks behind the tip of the chain, FastSync
 | 
			
		||||
# allows them to catchup quickly by downloading blocks in parallel
 | 
			
		||||
# and verifying their commits
 | 
			
		||||
fast_sync = true
 | 
			
		||||
 | 
			
		||||
# Database backend: goleveldb | cleveldb | boltdb | rocksdb | badgerdb
 | 
			
		||||
# * goleveldb (github.com/syndtr/goleveldb - most popular implementation)
 | 
			
		||||
#   - pure go
 | 
			
		||||
#   - stable
 | 
			
		||||
# * cleveldb (uses levigo wrapper)
 | 
			
		||||
#   - fast
 | 
			
		||||
#   - requires gcc
 | 
			
		||||
#   - use cleveldb build tag (go build -tags cleveldb)
 | 
			
		||||
# * boltdb (uses etcd's fork of bolt - github.com/etcd-io/bbolt)
 | 
			
		||||
#   - EXPERIMENTAL
 | 
			
		||||
#   - may be faster is some use-cases (random reads - indexer)
 | 
			
		||||
#   - use boltdb build tag (go build -tags boltdb)
 | 
			
		||||
# * rocksdb (uses github.com/tecbot/gorocksdb)
 | 
			
		||||
#   - EXPERIMENTAL
 | 
			
		||||
#   - requires gcc
 | 
			
		||||
#   - use rocksdb build tag (go build -tags rocksdb)
 | 
			
		||||
# * badgerdb (uses github.com/dgraph-io/badger)
 | 
			
		||||
#   - EXPERIMENTAL
 | 
			
		||||
#   - use badgerdb build tag (go build -tags badgerdb)
 | 
			
		||||
db_backend = "goleveldb"
 | 
			
		||||
 | 
			
		||||
# Database directory
 | 
			
		||||
db_dir = "data"
 | 
			
		||||
 | 
			
		||||
# Output level for logging, including package level options
 | 
			
		||||
log_level = "info"
 | 
			
		||||
 | 
			
		||||
# Output format: 'plain' (colored text) or 'json'
 | 
			
		||||
log_format = "plain"
 | 
			
		||||
 | 
			
		||||
##### additional base config options #####
 | 
			
		||||
 | 
			
		||||
# Path to the JSON file containing the initial validator set and other meta data
 | 
			
		||||
genesis_file = "config/genesis.json"
 | 
			
		||||
 | 
			
		||||
# Path to the JSON file containing the private key to use as a validator in the consensus protocol
 | 
			
		||||
priv_validator_key_file = "config/priv_validator_key.json"
 | 
			
		||||
 | 
			
		||||
# Path to the JSON file containing the last sign state of a validator
 | 
			
		||||
priv_validator_state_file = "data/priv_validator_state.json"
 | 
			
		||||
 | 
			
		||||
# TCP or UNIX socket address for Tendermint to listen on for
 | 
			
		||||
# connections from an external PrivValidator process
 | 
			
		||||
priv_validator_laddr = ""
 | 
			
		||||
 | 
			
		||||
# Path to the JSON file containing the private key to use for node authentication in the p2p protocol
 | 
			
		||||
node_key_file = "config/node_key.json"
 | 
			
		||||
 | 
			
		||||
# Mechanism to connect to the ABCI application: socket | grpc
 | 
			
		||||
abci = "socket"
 | 
			
		||||
 | 
			
		||||
# If true, query the ABCI app on connecting to a new peer
 | 
			
		||||
# so the app can decide if we should keep the connection or not
 | 
			
		||||
filter_peers = false
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#######################################################################
 | 
			
		||||
###                 Advanced Configuration Options                  ###
 | 
			
		||||
#######################################################################
 | 
			
		||||
 | 
			
		||||
#######################################################
 | 
			
		||||
###       RPC Server Configuration Options          ###
 | 
			
		||||
#######################################################
 | 
			
		||||
[rpc]
 | 
			
		||||
 | 
			
		||||
# TCP or UNIX socket address for the RPC server to listen on
 | 
			
		||||
laddr = "tcp://127.0.0.1:26657"
 | 
			
		||||
 | 
			
		||||
# A list of origins a cross-domain request can be executed from
 | 
			
		||||
# Default value '[]' disables cors support
 | 
			
		||||
# Use '["*"]' to allow any origin
 | 
			
		||||
cors_allowed_origins = []
 | 
			
		||||
 | 
			
		||||
# A list of methods the client is allowed to use with cross-domain requests
 | 
			
		||||
cors_allowed_methods = ["HEAD", "GET", "POST", ]
 | 
			
		||||
 | 
			
		||||
# A list of non simple headers the client is allowed to use with cross-domain requests
 | 
			
		||||
cors_allowed_headers = ["Origin", "Accept", "Content-Type", "X-Requested-With", "X-Server-Time", ]
 | 
			
		||||
 | 
			
		||||
# TCP or UNIX socket address for the gRPC server to listen on
 | 
			
		||||
# NOTE: This server only supports /broadcast_tx_commit
 | 
			
		||||
grpc_laddr = ""
 | 
			
		||||
 | 
			
		||||
# Maximum number of simultaneous connections.
 | 
			
		||||
# Does not include RPC (HTTP&WebSocket) connections. See max_open_connections
 | 
			
		||||
# If you want to accept a larger number than the default, make sure
 | 
			
		||||
# you increase your OS limits.
 | 
			
		||||
# 0 - unlimited.
 | 
			
		||||
# Should be < {ulimit -Sn} - {MaxNumInboundPeers} - {MaxNumOutboundPeers} - {N of wal, db and other open files}
 | 
			
		||||
# 1024 - 40 - 10 - 50 = 924 = ~900
 | 
			
		||||
grpc_max_open_connections = 900
 | 
			
		||||
 | 
			
		||||
# Activate unsafe RPC commands like /dial_seeds and /unsafe_flush_mempool
 | 
			
		||||
unsafe = false
 | 
			
		||||
 | 
			
		||||
# Maximum number of simultaneous connections (including WebSocket).
 | 
			
		||||
# Does not include gRPC connections. See grpc_max_open_connections
 | 
			
		||||
# If you want to accept a larger number than the default, make sure
 | 
			
		||||
# you increase your OS limits.
 | 
			
		||||
# 0 - unlimited.
 | 
			
		||||
# Should be < {ulimit -Sn} - {MaxNumInboundPeers} - {MaxNumOutboundPeers} - {N of wal, db and other open files}
 | 
			
		||||
# 1024 - 40 - 10 - 50 = 924 = ~900
 | 
			
		||||
max_open_connections = 900
 | 
			
		||||
 | 
			
		||||
# Maximum number of unique clientIDs that can /subscribe
 | 
			
		||||
# If you're using /broadcast_tx_commit, set to the estimated maximum number
 | 
			
		||||
# of broadcast_tx_commit calls per block.
 | 
			
		||||
max_subscription_clients = 100
 | 
			
		||||
 | 
			
		||||
# Maximum number of unique queries a given client can /subscribe to
 | 
			
		||||
# If you're using GRPC (or Local RPC client) and /broadcast_tx_commit, set to
 | 
			
		||||
# the estimated # maximum number of broadcast_tx_commit calls per block.
 | 
			
		||||
max_subscriptions_per_client = 5
 | 
			
		||||
 | 
			
		||||
# Experimental parameter to specify the maximum number of events a node will
 | 
			
		||||
# buffer, per subscription, before returning an error and closing the
 | 
			
		||||
# subscription. Must be set to at least 100, but higher values will accommodate
 | 
			
		||||
# higher event throughput rates (and will use more memory).
 | 
			
		||||
experimental_subscription_buffer_size = 200
 | 
			
		||||
 | 
			
		||||
# Experimental parameter to specify the maximum number of RPC responses that
 | 
			
		||||
# can be buffered per WebSocket client. If clients cannot read from the
 | 
			
		||||
# WebSocket endpoint fast enough, they will be disconnected, so increasing this
 | 
			
		||||
# parameter may reduce the chances of them being disconnected (but will cause
 | 
			
		||||
# the node to use more memory).
 | 
			
		||||
#
 | 
			
		||||
# Must be at least the same as "experimental_subscription_buffer_size",
 | 
			
		||||
# otherwise connections could be dropped unnecessarily. This value should
 | 
			
		||||
# ideally be somewhat higher than "experimental_subscription_buffer_size" to
 | 
			
		||||
# accommodate non-subscription-related RPC responses.
 | 
			
		||||
experimental_websocket_write_buffer_size = 200
 | 
			
		||||
 | 
			
		||||
# If a WebSocket client cannot read fast enough, at present we may
 | 
			
		||||
# silently drop events instead of generating an error or disconnecting the
 | 
			
		||||
# client.
 | 
			
		||||
#
 | 
			
		||||
# Enabling this experimental parameter will cause the WebSocket connection to
 | 
			
		||||
# be closed instead if it cannot read fast enough, allowing for greater
 | 
			
		||||
# predictability in subscription behaviour.
 | 
			
		||||
experimental_close_on_slow_client = false
 | 
			
		||||
 | 
			
		||||
# How long to wait for a tx to be committed during /broadcast_tx_commit.
 | 
			
		||||
# WARNING: Using a value larger than 10s will result in increasing the
 | 
			
		||||
# global HTTP write timeout, which applies to all connections and endpoints.
 | 
			
		||||
# See https://github.com/tendermint/tendermint/issues/3435
 | 
			
		||||
timeout_broadcast_tx_commit = "10s"
 | 
			
		||||
 | 
			
		||||
# Maximum size of request body, in bytes
 | 
			
		||||
max_body_bytes = 1000000
 | 
			
		||||
 | 
			
		||||
# Maximum size of request header, in bytes
 | 
			
		||||
max_header_bytes = 1048576
 | 
			
		||||
 | 
			
		||||
# The path to a file containing certificate that is used to create the HTTPS server.
 | 
			
		||||
# Might be either absolute path or path related to Tendermint's config directory.
 | 
			
		||||
# If the certificate is signed by a certificate authority,
 | 
			
		||||
# the certFile should be the concatenation of the server's certificate, any intermediates,
 | 
			
		||||
# and the CA's certificate.
 | 
			
		||||
# NOTE: both tls_cert_file and tls_key_file must be present for Tendermint to create HTTPS server.
 | 
			
		||||
# Otherwise, HTTP server is run.
 | 
			
		||||
tls_cert_file = ""
 | 
			
		||||
 | 
			
		||||
# The path to a file containing matching private key that is used to create the HTTPS server.
 | 
			
		||||
# Might be either absolute path or path related to Tendermint's config directory.
 | 
			
		||||
# NOTE: both tls-cert-file and tls-key-file must be present for Tendermint to create HTTPS server.
 | 
			
		||||
# Otherwise, HTTP server is run.
 | 
			
		||||
tls_key_file = ""
 | 
			
		||||
 | 
			
		||||
# pprof listen address (https://golang.org/pkg/net/http/pprof)
 | 
			
		||||
pprof_laddr = "localhost:6060"
 | 
			
		||||
 | 
			
		||||
#######################################################
 | 
			
		||||
###           P2P Configuration Options             ###
 | 
			
		||||
#######################################################
 | 
			
		||||
[p2p]
 | 
			
		||||
 | 
			
		||||
# Address to listen for incoming connections
 | 
			
		||||
laddr = "tcp://0.0.0.0:26656"
 | 
			
		||||
 | 
			
		||||
# Address to advertise to peers for them to dial
 | 
			
		||||
# If empty, will use the same port as the laddr,
 | 
			
		||||
# and will introspect on the listener or use UPnP
 | 
			
		||||
# to figure out the address. ip and port are required
 | 
			
		||||
# example: 159.89.10.97:26656
 | 
			
		||||
external_address = ""
 | 
			
		||||
 | 
			
		||||
# Comma separated list of seed nodes to connect to
 | 
			
		||||
seeds = ""
 | 
			
		||||
 | 
			
		||||
# Comma separated list of nodes to keep persistent connections to
 | 
			
		||||
persistent_peers = ""
 | 
			
		||||
 | 
			
		||||
# UPNP port forwarding
 | 
			
		||||
upnp = false
 | 
			
		||||
 | 
			
		||||
# Path to address book
 | 
			
		||||
addr_book_file = "config/addrbook.json"
 | 
			
		||||
 | 
			
		||||
# Set true for strict address routability rules
 | 
			
		||||
# Set false for private or local networks
 | 
			
		||||
addr_book_strict = true
 | 
			
		||||
 | 
			
		||||
# Maximum number of inbound peers
 | 
			
		||||
max_num_inbound_peers = 40
 | 
			
		||||
 | 
			
		||||
# Maximum number of outbound peers to connect to, excluding persistent peers
 | 
			
		||||
max_num_outbound_peers = 10
 | 
			
		||||
 | 
			
		||||
# List of node IDs, to which a connection will be (re)established ignoring any existing limits
 | 
			
		||||
unconditional_peer_ids = ""
 | 
			
		||||
 | 
			
		||||
# Maximum pause when redialing a persistent peer (if zero, exponential backoff is used)
 | 
			
		||||
persistent_peers_max_dial_period = "0s"
 | 
			
		||||
 | 
			
		||||
# Time to wait before flushing messages out on the connection
 | 
			
		||||
flush_throttle_timeout = "100ms"
 | 
			
		||||
 | 
			
		||||
# Maximum size of a message packet payload, in bytes
 | 
			
		||||
max_packet_msg_payload_size = 1024
 | 
			
		||||
 | 
			
		||||
# Rate at which packets can be sent, in bytes/second
 | 
			
		||||
send_rate = 5120000
 | 
			
		||||
 | 
			
		||||
# Rate at which packets can be received, in bytes/second
 | 
			
		||||
recv_rate = 5120000
 | 
			
		||||
 | 
			
		||||
# Set true to enable the peer-exchange reactor
 | 
			
		||||
pex = true
 | 
			
		||||
 | 
			
		||||
# Seed mode, in which node constantly crawls the network and looks for
 | 
			
		||||
# peers. If another node asks it for addresses, it responds and disconnects.
 | 
			
		||||
#
 | 
			
		||||
# Does not work if the peer-exchange reactor is disabled.
 | 
			
		||||
seed_mode = false
 | 
			
		||||
 | 
			
		||||
# Comma separated list of peer IDs to keep private (will not be gossiped to other peers)
 | 
			
		||||
private_peer_ids = ""
 | 
			
		||||
 | 
			
		||||
# Toggle to disable guard against peers connecting from the same ip.
 | 
			
		||||
allow_duplicate_ip = false
 | 
			
		||||
 | 
			
		||||
# Peer connection configuration.
 | 
			
		||||
handshake_timeout = "20s"
 | 
			
		||||
dial_timeout = "3s"
 | 
			
		||||
 | 
			
		||||
#######################################################
 | 
			
		||||
###          Mempool Configuration Option          ###
 | 
			
		||||
#######################################################
 | 
			
		||||
[mempool]
 | 
			
		||||
 | 
			
		||||
# Mempool version to use:
 | 
			
		||||
#   1) "v0" - (default) FIFO mempool.
 | 
			
		||||
#   2) "v1" - prioritized mempool.
 | 
			
		||||
version = "v0"
 | 
			
		||||
 | 
			
		||||
recheck = true
 | 
			
		||||
broadcast = true
 | 
			
		||||
wal_dir = ""
 | 
			
		||||
 | 
			
		||||
# Maximum number of transactions in the mempool
 | 
			
		||||
size = 5000
 | 
			
		||||
 | 
			
		||||
# Limit the total size of all txs in the mempool.
 | 
			
		||||
# This only accounts for raw transactions (e.g. given 1MB transactions and
 | 
			
		||||
# max_txs_bytes=5MB, mempool will only accept 5 transactions).
 | 
			
		||||
max_txs_bytes = 1073741824
 | 
			
		||||
 | 
			
		||||
# Size of the cache (used to filter transactions we saw earlier) in transactions
 | 
			
		||||
cache_size = 10000
 | 
			
		||||
 | 
			
		||||
# Do not remove invalid transactions from the cache (default: false)
 | 
			
		||||
# Set to true if it's not possible for any invalid transaction to become valid
 | 
			
		||||
# again in the future.
 | 
			
		||||
keep-invalid-txs-in-cache = false
 | 
			
		||||
 | 
			
		||||
# Maximum size of a single transaction.
 | 
			
		||||
# NOTE: the max size of a tx transmitted over the network is {max_tx_bytes}.
 | 
			
		||||
max_tx_bytes = 1048576
 | 
			
		||||
 | 
			
		||||
# Maximum size of a batch of transactions to send to a peer
 | 
			
		||||
# Including space needed by encoding (one varint per transaction).
 | 
			
		||||
# XXX: Unused due to https://github.com/tendermint/tendermint/issues/5796
 | 
			
		||||
max_batch_bytes = 0
 | 
			
		||||
 | 
			
		||||
# ttl-duration, if non-zero, defines the maximum amount of time a transaction
 | 
			
		||||
# can exist for in the mempool.
 | 
			
		||||
#
 | 
			
		||||
# Note, if ttl-num-blocks is also defined, a transaction will be removed if it
 | 
			
		||||
# has existed in the mempool at least ttl-num-blocks number of blocks or if it's
 | 
			
		||||
# insertion time into the mempool is beyond ttl-duration.
 | 
			
		||||
ttl-duration = "0s"
 | 
			
		||||
 | 
			
		||||
# ttl-num-blocks, if non-zero, defines the maximum number of blocks a transaction
 | 
			
		||||
# can exist for in the mempool.
 | 
			
		||||
#
 | 
			
		||||
# Note, if ttl-duration is also defined, a transaction will be removed if it
 | 
			
		||||
# has existed in the mempool at least ttl-num-blocks number of blocks or if
 | 
			
		||||
# it's insertion time into the mempool is beyond ttl-duration.
 | 
			
		||||
ttl-num-blocks = 0
 | 
			
		||||
 | 
			
		||||
#######################################################
 | 
			
		||||
###         State Sync Configuration Options        ###
 | 
			
		||||
#######################################################
 | 
			
		||||
[statesync]
 | 
			
		||||
# State sync rapidly bootstraps a new node by discovering, fetching, and restoring a state machine
 | 
			
		||||
# snapshot from peers instead of fetching and replaying historical blocks. Requires some peers in
 | 
			
		||||
# the network to take and serve state machine snapshots. State sync is not attempted if the node
 | 
			
		||||
# has any local state (LastBlockHeight > 0). The node will have a truncated block history,
 | 
			
		||||
# starting from the height of the snapshot.
 | 
			
		||||
enable = false
 | 
			
		||||
 | 
			
		||||
# RPC servers (comma-separated) for light client verification of the synced state machine and
 | 
			
		||||
# retrieval of state data for node bootstrapping. Also needs a trusted height and corresponding
 | 
			
		||||
# header hash obtained from a trusted source, and a period during which validators can be trusted.
 | 
			
		||||
#
 | 
			
		||||
# For Cosmos SDK-based chains, trust_period should usually be about 2/3 of the unbonding time (~2
 | 
			
		||||
# weeks) during which they can be financially punished (slashed) for misbehavior.
 | 
			
		||||
rpc_servers = ""
 | 
			
		||||
trust_height = 0
 | 
			
		||||
trust_hash = ""
 | 
			
		||||
trust_period = "168h0m0s"
 | 
			
		||||
 | 
			
		||||
# Time to spend discovering snapshots before initiating a restore.
 | 
			
		||||
discovery_time = "15s"
 | 
			
		||||
 | 
			
		||||
# Temporary directory for state sync snapshot chunks, defaults to the OS tempdir (typically /tmp).
 | 
			
		||||
# Will create a new, randomly named directory within, and remove it when done.
 | 
			
		||||
temp_dir = ""
 | 
			
		||||
 | 
			
		||||
# The timeout duration before re-requesting a chunk, possibly from a different
 | 
			
		||||
# peer (default: 1 minute).
 | 
			
		||||
chunk_request_timeout = "10s"
 | 
			
		||||
 | 
			
		||||
# The number of concurrent chunk fetchers to run (default: 1).
 | 
			
		||||
chunk_fetchers = "4"
 | 
			
		||||
 | 
			
		||||
#######################################################
 | 
			
		||||
###       Fast Sync Configuration Connections       ###
 | 
			
		||||
#######################################################
 | 
			
		||||
[fastsync]
 | 
			
		||||
 | 
			
		||||
# Fast Sync version to use:
 | 
			
		||||
#   1) "v0" (default) - the legacy fast sync implementation
 | 
			
		||||
#   2) "v1" - refactor of v0 version for better testability
 | 
			
		||||
#   2) "v2" - complete redesign of v0, optimized for testability & readability
 | 
			
		||||
version = "v0"
 | 
			
		||||
 | 
			
		||||
#######################################################
 | 
			
		||||
###         Consensus Configuration Options         ###
 | 
			
		||||
#######################################################
 | 
			
		||||
[consensus]
 | 
			
		||||
 | 
			
		||||
wal_file = "data/cs.wal/wal"
 | 
			
		||||
 | 
			
		||||
# How long we wait for a proposal block before prevoting nil
 | 
			
		||||
timeout_propose = "3s"
 | 
			
		||||
# How much timeout_propose increases with each round
 | 
			
		||||
timeout_propose_delta = "500ms"
 | 
			
		||||
# How long we wait after receiving +2/3 prevotes for “anything” (ie. not a single block or nil)
 | 
			
		||||
timeout_prevote = "1s"
 | 
			
		||||
# How much the timeout_prevote increases with each round
 | 
			
		||||
timeout_prevote_delta = "500ms"
 | 
			
		||||
# How long we wait after receiving +2/3 precommits for “anything” (ie. not a single block or nil)
 | 
			
		||||
timeout_precommit = "1s"
 | 
			
		||||
# How much the timeout_precommit increases with each round
 | 
			
		||||
timeout_precommit_delta = "500ms"
 | 
			
		||||
# How long we wait after committing a block, before starting on the new
 | 
			
		||||
# height (this gives us a chance to receive some more precommits, even
 | 
			
		||||
# though we already have +2/3).
 | 
			
		||||
timeout_commit = "1s"
 | 
			
		||||
 | 
			
		||||
# How many blocks to look back to check existence of the node's consensus votes before joining consensus
 | 
			
		||||
# When non-zero, the node will panic upon restart
 | 
			
		||||
# if the same consensus key was used to sign {double_sign_check_height} last blocks.
 | 
			
		||||
# So, validators should stop the state machine, wait for some blocks, and then restart the state machine to avoid panic.
 | 
			
		||||
double_sign_check_height = 0
 | 
			
		||||
 | 
			
		||||
# Make progress as soon as we have all the precommits (as if TimeoutCommit = 0)
 | 
			
		||||
skip_timeout_commit = false
 | 
			
		||||
 | 
			
		||||
# EmptyBlocks mode and possible interval between empty blocks
 | 
			
		||||
create_empty_blocks = true
 | 
			
		||||
create_empty_blocks_interval = "0s"
 | 
			
		||||
 | 
			
		||||
# Reactor sleep duration parameters
 | 
			
		||||
peer_gossip_sleep_duration = "100ms"
 | 
			
		||||
peer_query_maj23_sleep_duration = "2s"
 | 
			
		||||
 | 
			
		||||
#######################################################
 | 
			
		||||
###         Storage Configuration Options           ###
 | 
			
		||||
#######################################################
 | 
			
		||||
[storage]
 | 
			
		||||
 | 
			
		||||
# Set to true to discard ABCI responses from the state store, which can save a
 | 
			
		||||
# considerable amount of disk space. Set to false to ensure ABCI responses are
 | 
			
		||||
# persisted. ABCI responses are required for /block_results RPC queries, and to
 | 
			
		||||
# reindex events in the command-line tool.
 | 
			
		||||
discard_abci_responses = false
 | 
			
		||||
 | 
			
		||||
#######################################################
 | 
			
		||||
###   Transaction Indexer Configuration Options     ###
 | 
			
		||||
#######################################################
 | 
			
		||||
[tx_index]
 | 
			
		||||
 | 
			
		||||
# What indexer to use for transactions
 | 
			
		||||
#
 | 
			
		||||
# The application will set which txs to index. In some cases a node operator will be able
 | 
			
		||||
# to decide which txs to index based on configuration set in the application.
 | 
			
		||||
#
 | 
			
		||||
# Options:
 | 
			
		||||
#   1) "null"
 | 
			
		||||
#   2) "kv" (default) - the simplest possible indexer, backed by key-value storage (defaults to levelDB; see DBBackend).
 | 
			
		||||
# 		- When "kv" is chosen "tx.height" and "tx.hash" will always be indexed.
 | 
			
		||||
#   3) "psql" - the indexer services backed by PostgreSQL.
 | 
			
		||||
# When "kv" or "psql" is chosen "tx.height" and "tx.hash" will always be indexed.
 | 
			
		||||
indexer = "kv"
 | 
			
		||||
 | 
			
		||||
# The PostgreSQL connection configuration, the connection format:
 | 
			
		||||
#   postgresql://<user>:<password>@<host>:<port>/<db>?<opts>
 | 
			
		||||
psql-conn = ""
 | 
			
		||||
 | 
			
		||||
#######################################################
 | 
			
		||||
###       Instrumentation Configuration Options     ###
 | 
			
		||||
#######################################################
 | 
			
		||||
[instrumentation]
 | 
			
		||||
 | 
			
		||||
# When true, Prometheus metrics are served under /metrics on
 | 
			
		||||
# PrometheusListenAddr.
 | 
			
		||||
# Check out the documentation for the list of available metrics.
 | 
			
		||||
prometheus = false
 | 
			
		||||
 | 
			
		||||
# Address to listen for Prometheus collector(s) connections
 | 
			
		||||
prometheus_listen_addr = ":26660"
 | 
			
		||||
 | 
			
		||||
# Maximum number of simultaneous connections.
 | 
			
		||||
# If you want to accept a larger number than the default, make sure
 | 
			
		||||
# you increase your OS limits.
 | 
			
		||||
# 0 - unlimited.
 | 
			
		||||
max_open_connections = 3
 | 
			
		||||
 | 
			
		||||
# Instrumentation namespace
 | 
			
		||||
namespace = "tendermint"
 | 
			
		||||
							
								
								
									
										2976
									
								
								tests/e2e/generated/kava-1/config/genesis.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2976
									
								
								tests/e2e/generated/kava-1/config/genesis.json
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							@ -0,0 +1 @@
 | 
			
		||||
{"body":{"messages":[{"@type":"/cosmos.staking.v1beta1.MsgCreateValidator","description":{"moniker":"validator","identity":"","website":"","security_contact":"","details":""},"commission":{"rate":"0.100000000000000000","max_rate":"0.200000000000000000","max_change_rate":"0.010000000000000000"},"min_self_delegation":"1","delegator_address":"kava1ypjp0m04pyp73hwgtc0dgkx0e9rrydecm054da","validator_address":"kavavaloper1ypjp0m04pyp73hwgtc0dgkx0e9rrydeckewa42","pubkey":{"@type":"/cosmos.crypto.ed25519.PubKey","key":"/iEtt5/G+7hUT4FJ4p29yi2DCRut5Bm1Zx6doestjUA="},"value":{"denom":"ukava","amount":"1000000000"}}],"memo":"461d9761df5db0a112407ca8a82f1774ef2dbaa3@192.168.0.7:26656","timeout_height":"0","extension_options":[],"non_critical_extension_options":[]},"auth_info":{"signer_infos":[{"public_key":{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"AgIWiZpdEVb69gfaqyNjbA0b3oe+nRS9BZ9gH/I6oGz+"},"mode_info":{"single":{"mode":"SIGN_MODE_DIRECT"}},"sequence":"0"}],"fee":{"amount":[],"gas_limit":"200000","payer":"","granter":""}},"signatures":["HE2tfqs81EJLOSmbJQyGv/TLFY5p6Yj028UBRnGMJcdROiNa6QLRnq4VWgpUOViHAgMvqWyZUbMfMc2rrGMUVQ=="]}
 | 
			
		||||
							
								
								
									
										16
									
								
								tests/e2e/generated/kava-1/config/init-data-directory.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										16
									
								
								tests/e2e/generated/kava-1/config/init-data-directory.sh
									
									
									
									
									
										Executable file
									
								
							@ -0,0 +1,16 @@
 | 
			
		||||
#! /bin/sh
 | 
			
		||||
set -e
 | 
			
		||||
 | 
			
		||||
# This script creates a data directory if one doesn't exist.
 | 
			
		||||
# It's designed to run before the chain starts to properly initialize the data directory in case `kvd init` was not run.
 | 
			
		||||
# This behaviour should probably live in tendermint.
 | 
			
		||||
 | 
			
		||||
configDir=$HOME/.kava/config
 | 
			
		||||
dataDir=$HOME/.kava/data
 | 
			
		||||
valStateFile=$dataDir/priv_validator_state.json
 | 
			
		||||
 | 
			
		||||
if ! test -f "$valStateFile"; then
 | 
			
		||||
    echo "$valStateFile doesn't exist, creating it"
 | 
			
		||||
    mkdir -p $dataDir
 | 
			
		||||
    cp $configDir/priv_validator_state.json.example "$valStateFile"
 | 
			
		||||
fi
 | 
			
		||||
							
								
								
									
										1
									
								
								tests/e2e/generated/kava-1/config/node_key.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								tests/e2e/generated/kava-1/config/node_key.json
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
			
		||||
{"priv_key":{"type":"tendermint/PrivKeyEd25519","value":"CD7Hkk7hzHx/nn2DasmELmhord4rn0SDLpHrXtATuiM6anFSdulMLfZLZFrKpHtl/kvESy+B0NH4Hf2GI+BkEg=="}}
 | 
			
		||||
							
								
								
									
										11
									
								
								tests/e2e/generated/kava-1/config/priv_validator_key.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								tests/e2e/generated/kava-1/config/priv_validator_key.json
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,11 @@
 | 
			
		||||
{
 | 
			
		||||
  "address": "8A635482445A7726F17DEB53014D8E8E3E6DA6B6",
 | 
			
		||||
  "pub_key": {
 | 
			
		||||
    "type": "tendermint/PubKeyEd25519",
 | 
			
		||||
    "value": "/iEtt5/G+7hUT4FJ4p29yi2DCRut5Bm1Zx6doestjUA="
 | 
			
		||||
  },
 | 
			
		||||
  "priv_key": {
 | 
			
		||||
    "type": "tendermint/PrivKeyEd25519",
 | 
			
		||||
    "value": "w+2nJVmnZb0NEaf6mDWy85/EOvELbPtXjeioUGfBUqn+IS23n8b7uFRPgUninb3KLYMJG63kGbVnHp2h6y2NQA=="
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,5 @@
 | 
			
		||||
{
 | 
			
		||||
  "height": "0",
 | 
			
		||||
  "round": 0,
 | 
			
		||||
  "step": 0
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										151
									
								
								tests/e2e/runner/main.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										151
									
								
								tests/e2e/runner/main.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,151 @@
 | 
			
		||||
package runner
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"log"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/ory/dockertest/v3"
 | 
			
		||||
	"github.com/ory/dockertest/v3/docker"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Config struct {
 | 
			
		||||
	ConfigDir string
 | 
			
		||||
	ImageTag  string
 | 
			
		||||
 | 
			
		||||
	KavaRpcPort  string
 | 
			
		||||
	KavaGrpcPort string
 | 
			
		||||
	KavaRestPort string
 | 
			
		||||
	KavaEvmPort  string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NodeRunner is responsible for starting and managing docker containers to run a node.
 | 
			
		||||
type NodeRunner interface {
 | 
			
		||||
	StartChains()
 | 
			
		||||
	Shutdown()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SingleKavaNodeRunner manages and runs a single Kava node.
 | 
			
		||||
type SingleKavaNodeRunner struct {
 | 
			
		||||
	config Config
 | 
			
		||||
 | 
			
		||||
	pool     *dockertest.Pool
 | 
			
		||||
	resource *dockertest.Resource
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var _ NodeRunner = &SingleKavaNodeRunner{}
 | 
			
		||||
 | 
			
		||||
func NewSingleKavaNode(config Config) *SingleKavaNodeRunner {
 | 
			
		||||
	return &SingleKavaNodeRunner{
 | 
			
		||||
		config: config,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (k *SingleKavaNodeRunner) StartChains() {
 | 
			
		||||
	log.Println("starting kava node")
 | 
			
		||||
	k.setupDockerPool()
 | 
			
		||||
	err := k.waitForChainStart()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		k.Shutdown()
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (k *SingleKavaNodeRunner) Shutdown() {
 | 
			
		||||
	log.Println("shutting down kava node")
 | 
			
		||||
	k.pool.Purge(k.resource)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (k *SingleKavaNodeRunner) setupDockerPool() {
 | 
			
		||||
	pool, err := dockertest.NewPool("")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Fatalf("Failed to make docker pool: %s", err)
 | 
			
		||||
	}
 | 
			
		||||
	k.pool = pool
 | 
			
		||||
 | 
			
		||||
	err = pool.Client.Ping()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Fatalf("Failed to connect to docker: %s", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	resource, err := k.pool.RunWithOptions(&dockertest.RunOptions{
 | 
			
		||||
		Name:       "kavanode",
 | 
			
		||||
		Repository: "kava/kava",
 | 
			
		||||
		Tag:        k.config.ImageTag,
 | 
			
		||||
		Cmd: []string{
 | 
			
		||||
			"sh",
 | 
			
		||||
			"-c",
 | 
			
		||||
			"/root/.kava/config/init-data-directory.sh && kava start --rpc.laddr=tcp://0.0.0.0:26657",
 | 
			
		||||
		},
 | 
			
		||||
		Mounts: []string{
 | 
			
		||||
			fmt.Sprintf("%s:/root/.kava/config", k.config.ConfigDir),
 | 
			
		||||
		},
 | 
			
		||||
		ExposedPorts: []string{
 | 
			
		||||
			"26657", // port inside container for Kava RPC
 | 
			
		||||
			"1317",  // port inside container for Kava REST API
 | 
			
		||||
			"9090",  // port inside container for Kava GRPC
 | 
			
		||||
			"8545",  // port inside container for EVM JSON-RPC
 | 
			
		||||
		},
 | 
			
		||||
		// expose the internal ports on the configured ports
 | 
			
		||||
		PortBindings: map[docker.Port][]docker.PortBinding{
 | 
			
		||||
			"26657": {{HostIP: "", HostPort: k.config.KavaRpcPort}},
 | 
			
		||||
			"1327":  {{HostIP: "", HostPort: k.config.KavaRestPort}},
 | 
			
		||||
			"9090":  {{HostIP: "", HostPort: k.config.KavaGrpcPort}},
 | 
			
		||||
			"8545":  {{HostIP: "", HostPort: k.config.KavaEvmPort}},
 | 
			
		||||
		},
 | 
			
		||||
	}, func(config *docker.HostConfig) {
 | 
			
		||||
		// set AutoRemove to true so that stopped container goes away by itself
 | 
			
		||||
		config.AutoRemove = true
 | 
			
		||||
		config.RestartPolicy = docker.RestartPolicy{Name: "no"}
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Fatalf("Failed to start kava node: %s", err)
 | 
			
		||||
	}
 | 
			
		||||
	k.resource = resource
 | 
			
		||||
	log.Println(resource.GetHostPort("26657"))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (k *SingleKavaNodeRunner) waitForChainStart() error {
 | 
			
		||||
	// exponential backoff on trying to ping the node, timeout after 30 seconds
 | 
			
		||||
	k.pool.MaxWait = 30 * time.Second
 | 
			
		||||
	if err := k.pool.Retry(k.pingKava); err != nil {
 | 
			
		||||
		return fmt.Errorf("failed to start & connect to chain: %s", err)
 | 
			
		||||
	}
 | 
			
		||||
	// the evm takes a bit longer to start up. wait for it to start as well.
 | 
			
		||||
	if err := k.pool.Retry(k.pingEvm); err != nil {
 | 
			
		||||
		return fmt.Errorf("failed to start & connect to chain: %s", err)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (k *SingleKavaNodeRunner) pingKava() error {
 | 
			
		||||
	log.Println("pinging kava chain...")
 | 
			
		||||
	url := fmt.Sprintf("http://localhost:%s/status", k.config.KavaRpcPort)
 | 
			
		||||
	res, err := http.Get(url)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	defer res.Body.Close()
 | 
			
		||||
	if res.StatusCode >= 400 {
 | 
			
		||||
		return fmt.Errorf("ping to status failed: %d", res.StatusCode)
 | 
			
		||||
	}
 | 
			
		||||
	log.Println("successfully started Kava!")
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (k *SingleKavaNodeRunner) pingEvm() error {
 | 
			
		||||
	log.Println("pinging evm...")
 | 
			
		||||
	url := fmt.Sprintf("http://localhost:%s", k.config.KavaEvmPort)
 | 
			
		||||
	res, err := http.Get(url)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	defer res.Body.Close()
 | 
			
		||||
	// when running, it should respond 405 to a GET request
 | 
			
		||||
	if res.StatusCode != 405 {
 | 
			
		||||
		return fmt.Errorf("ping to evm failed: %d", res.StatusCode)
 | 
			
		||||
	}
 | 
			
		||||
	log.Println("successfully pinged EVM!")
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										127
									
								
								tests/e2e/testutil/account.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										127
									
								
								tests/e2e/testutil/account.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,127 @@
 | 
			
		||||
package testutil
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"log"
 | 
			
		||||
	"os"
 | 
			
		||||
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/crypto/hd"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
 | 
			
		||||
	sdk "github.com/cosmos/cosmos-sdk/types"
 | 
			
		||||
	banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
 | 
			
		||||
	"github.com/cosmos/go-bip39"
 | 
			
		||||
 | 
			
		||||
	"github.com/kava-labs/kava/app"
 | 
			
		||||
	"github.com/kava-labs/kava/tests/util"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type SigningAccount struct {
 | 
			
		||||
	name      string
 | 
			
		||||
	mnemonic  string
 | 
			
		||||
	signer    *util.Signer
 | 
			
		||||
	requests  chan<- util.MsgRequest
 | 
			
		||||
	responses <-chan util.MsgResponse
 | 
			
		||||
 | 
			
		||||
	Address sdk.AccAddress
 | 
			
		||||
 | 
			
		||||
	l *log.Logger
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetAccount returns the account with the given name or fails
 | 
			
		||||
func (suite *E2eTestSuite) GetAccount(name string) *SigningAccount {
 | 
			
		||||
	acc, found := suite.accounts[name]
 | 
			
		||||
	if !found {
 | 
			
		||||
		suite.Failf("account does not exist", "failed to find account with name %s", name)
 | 
			
		||||
	}
 | 
			
		||||
	return acc
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// AddNewSigningAccount sets up a new account with a signer.
 | 
			
		||||
func (suite *E2eTestSuite) AddNewSigningAccount(name string, hdPath *hd.BIP44Params, chainId, mnemonic string) *SigningAccount {
 | 
			
		||||
	if _, found := suite.accounts[name]; found {
 | 
			
		||||
		suite.Failf("can't create signing account", "account with name %s already exists", name)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	privKeyBytes, err := hd.Secp256k1.Derive()(mnemonic, "", hdPath.String())
 | 
			
		||||
	suite.NoErrorf(err, "failed to derive private key from mnemonic for %s: %s", name, err)
 | 
			
		||||
	privKey := &secp256k1.PrivKey{Key: privKeyBytes}
 | 
			
		||||
 | 
			
		||||
	signer := util.NewSigner(
 | 
			
		||||
		chainId,
 | 
			
		||||
		suite.encodingConfig,
 | 
			
		||||
		suite.Auth,
 | 
			
		||||
		suite.Tx,
 | 
			
		||||
		privKey,
 | 
			
		||||
		100,
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	requests := make(chan util.MsgRequest)
 | 
			
		||||
	responses, err := signer.Run(requests)
 | 
			
		||||
	suite.NoErrorf(err, "failed to start signer for account %s: %s", name, err)
 | 
			
		||||
 | 
			
		||||
	logger := log.New(os.Stdout, fmt.Sprintf("[%s] ", name), log.LstdFlags)
 | 
			
		||||
 | 
			
		||||
	// TODO: authenticated eth client.
 | 
			
		||||
	suite.accounts[name] = &SigningAccount{
 | 
			
		||||
		name:      name,
 | 
			
		||||
		mnemonic:  mnemonic,
 | 
			
		||||
		signer:    signer,
 | 
			
		||||
		requests:  requests,
 | 
			
		||||
		responses: responses,
 | 
			
		||||
		l:         logger,
 | 
			
		||||
 | 
			
		||||
		Address: signer.Address(),
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return suite.accounts[name]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SignAndBroadcastKavaTx sends a request to the signer and awaits its response.
 | 
			
		||||
func (a *SigningAccount) SignAndBroadcastKavaTx(req util.MsgRequest) util.MsgResponse {
 | 
			
		||||
	a.l.Printf("broadcasting tx %+v\n", req.Data)
 | 
			
		||||
	// send the request to signer
 | 
			
		||||
	a.requests <- req
 | 
			
		||||
 | 
			
		||||
	// block and await response
 | 
			
		||||
	// response is not returned until the msg is committed to a block
 | 
			
		||||
	res := <-a.responses
 | 
			
		||||
 | 
			
		||||
	// error will be set if response is not Code 0 (success) or Code 19 (already in mempool)
 | 
			
		||||
	if res.Err != nil {
 | 
			
		||||
		a.l.Printf("response code: %d error: %s\n", res.Result.Code, res.Result.RawLog)
 | 
			
		||||
	} else {
 | 
			
		||||
		a.l.Printf("response code: %d, hash %s\n", res.Result.Code, res.Result.TxHash)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (suite *E2eTestSuite) NewFundedAccount(name string, funds sdk.Coins) *SigningAccount {
 | 
			
		||||
	entropy, err := bip39.NewEntropy(128)
 | 
			
		||||
	suite.NoErrorf(err, "failed to generate entropy for account %s: %s", name, err)
 | 
			
		||||
	mnemonic, err := bip39.NewMnemonic(entropy)
 | 
			
		||||
	suite.NoErrorf(err, "failed to create new mnemonic for account %s: %s", name, err)
 | 
			
		||||
 | 
			
		||||
	acc := suite.AddNewSigningAccount(
 | 
			
		||||
		name,
 | 
			
		||||
		hd.CreateHDPath(app.Bip44CoinType, 0, 0),
 | 
			
		||||
		ChainId,
 | 
			
		||||
		mnemonic,
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	whale := suite.GetAccount(FundedAccountName)
 | 
			
		||||
	res := whale.SignAndBroadcastKavaTx(
 | 
			
		||||
		util.MsgRequest{
 | 
			
		||||
			Msgs: []sdk.Msg{
 | 
			
		||||
				banktypes.NewMsgSend(whale.Address, acc.Address, funds),
 | 
			
		||||
			},
 | 
			
		||||
			GasLimit:  1e5,
 | 
			
		||||
			FeeAmount: sdk.NewCoins(sdk.NewCoin(StakingDenom, sdk.NewInt(75000))),
 | 
			
		||||
			Data:      fmt.Sprintf("initial funding of account %s", name),
 | 
			
		||||
		},
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	suite.NoErrorf(res.Err, "failed to fund new account %s: %s", name, res.Err)
 | 
			
		||||
 | 
			
		||||
	return acc
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										114
									
								
								tests/e2e/testutil/suite.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								tests/e2e/testutil/suite.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,114 @@
 | 
			
		||||
package testutil
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"os"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
 | 
			
		||||
	"github.com/stretchr/testify/suite"
 | 
			
		||||
	"google.golang.org/grpc"
 | 
			
		||||
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/client/grpc/tmservice"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/crypto/hd"
 | 
			
		||||
	txtypes "github.com/cosmos/cosmos-sdk/types/tx"
 | 
			
		||||
	authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
 | 
			
		||||
	banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
 | 
			
		||||
	"github.com/ethereum/go-ethereum/ethclient"
 | 
			
		||||
 | 
			
		||||
	"github.com/kava-labs/kava/app"
 | 
			
		||||
	kavaparams "github.com/kava-labs/kava/app/params"
 | 
			
		||||
	"github.com/kava-labs/kava/tests/e2e/runner"
 | 
			
		||||
	"github.com/kava-labs/kava/tests/util"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	ChainId           = "kavalocalnet_8888-1"
 | 
			
		||||
	FundedAccountName = "whale"
 | 
			
		||||
	StakingDenom      = "ukava"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type E2eTestSuite struct {
 | 
			
		||||
	suite.Suite
 | 
			
		||||
 | 
			
		||||
	runner         runner.NodeRunner
 | 
			
		||||
	grpcConn       *grpc.ClientConn
 | 
			
		||||
	encodingConfig kavaparams.EncodingConfig
 | 
			
		||||
 | 
			
		||||
	EvmClient *ethclient.Client
 | 
			
		||||
	Auth      authtypes.QueryClient
 | 
			
		||||
	Bank      banktypes.QueryClient
 | 
			
		||||
	Tm        tmservice.ServiceClient
 | 
			
		||||
	Tx        txtypes.ServiceClient
 | 
			
		||||
 | 
			
		||||
	accounts map[string]*SigningAccount
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (suite *E2eTestSuite) SetupSuite() {
 | 
			
		||||
	app.SetSDKConfig()
 | 
			
		||||
	suite.encodingConfig = app.MakeEncodingConfig()
 | 
			
		||||
 | 
			
		||||
	// this mnemonic is expected to be a funded account that can seed the funds for all
 | 
			
		||||
	// new accounts created during tests. it will be available under Accounts["whale"]
 | 
			
		||||
	fundedAccountMnemonic := os.Getenv("E2E_KAVA_FUNDED_ACCOUNT_MNEMONIC")
 | 
			
		||||
	if fundedAccountMnemonic == "" {
 | 
			
		||||
		suite.Fail("no E2E_KAVA_FUNDED_ACCOUNT_MNEMONIC provided")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	configDir, err := filepath.Abs("./generated/kava-1/config")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		suite.Fail("failed to get config dir: %s", err)
 | 
			
		||||
	}
 | 
			
		||||
	config := runner.Config{
 | 
			
		||||
		ConfigDir: configDir,
 | 
			
		||||
 | 
			
		||||
		KavaRpcPort:  "26657",
 | 
			
		||||
		KavaRestPort: "1317",
 | 
			
		||||
		KavaGrpcPort: "9090",
 | 
			
		||||
		KavaEvmPort:  "8545",
 | 
			
		||||
 | 
			
		||||
		ImageTag: "local",
 | 
			
		||||
	}
 | 
			
		||||
	suite.runner = runner.NewSingleKavaNode(config)
 | 
			
		||||
	suite.runner.StartChains()
 | 
			
		||||
 | 
			
		||||
	// setup an unauthenticated evm client
 | 
			
		||||
	evmRpcUrl := fmt.Sprintf("http://localhost:%s", config.KavaEvmPort)
 | 
			
		||||
	suite.EvmClient, err = ethclient.Dial(evmRpcUrl)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		suite.runner.Shutdown()
 | 
			
		||||
		suite.Fail("failed to connect to evm: %s", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// create grpc connection
 | 
			
		||||
	grpcUrl := fmt.Sprintf("http://localhost:%s", config.KavaGrpcPort)
 | 
			
		||||
	suite.grpcConn, err = util.NewGrpcConnection(grpcUrl)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		suite.runner.Shutdown()
 | 
			
		||||
		suite.Fail("failed to create grpc connection: %s", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// setup unauthenticated query clients for kava / cosmos
 | 
			
		||||
	suite.Auth = authtypes.NewQueryClient(suite.grpcConn)
 | 
			
		||||
	suite.Bank = banktypes.NewQueryClient(suite.grpcConn)
 | 
			
		||||
	suite.Tm = tmservice.NewServiceClient(suite.grpcConn)
 | 
			
		||||
	suite.Tx = txtypes.NewServiceClient(suite.grpcConn)
 | 
			
		||||
 | 
			
		||||
	// initialize accounts map
 | 
			
		||||
	suite.accounts = make(map[string]*SigningAccount)
 | 
			
		||||
	// setup the signing account for the initially funded account (used to fund all other accounts)
 | 
			
		||||
	suite.AddNewSigningAccount(
 | 
			
		||||
		FundedAccountName,
 | 
			
		||||
		hd.CreateHDPath(app.Bip44CoinType, 0, 0),
 | 
			
		||||
		ChainId,
 | 
			
		||||
		fundedAccountMnemonic,
 | 
			
		||||
	)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (suite *E2eTestSuite) TearDownSuite() {
 | 
			
		||||
	// close all account request channels
 | 
			
		||||
	for _, a := range suite.accounts {
 | 
			
		||||
		close(a.requests)
 | 
			
		||||
	}
 | 
			
		||||
	// gracefully shutdown docker container(s)
 | 
			
		||||
	suite.runner.Shutdown()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										36
									
								
								tests/util/grpc.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								tests/util/grpc.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,36 @@
 | 
			
		||||
package util
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"crypto/tls"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"net/url"
 | 
			
		||||
 | 
			
		||||
	"google.golang.org/grpc"
 | 
			
		||||
	"google.golang.org/grpc/credentials"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// NewGrpcConnection parses a GRPC endpoint and creates a connection to it
 | 
			
		||||
func NewGrpcConnection(endpoint string) (*grpc.ClientConn, error) {
 | 
			
		||||
	grpcUrl, err := url.Parse(endpoint)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var secureOpt grpc.DialOption
 | 
			
		||||
	switch grpcUrl.Scheme {
 | 
			
		||||
	case "http":
 | 
			
		||||
		secureOpt = grpc.WithInsecure()
 | 
			
		||||
	case "https":
 | 
			
		||||
		creds := credentials.NewTLS(&tls.Config{})
 | 
			
		||||
		secureOpt = grpc.WithTransportCredentials(creds)
 | 
			
		||||
	default:
 | 
			
		||||
		return nil, fmt.Errorf("unknown grpc url scheme: %s", grpcUrl.Scheme)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	grpcConn, err := grpc.Dial(grpcUrl.Host, secureOpt)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return grpcConn, nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										421
									
								
								tests/util/signing.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										421
									
								
								tests/util/signing.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,421 @@
 | 
			
		||||
package util
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/kava-labs/kava/app/params"
 | 
			
		||||
 | 
			
		||||
	sdkclient "github.com/cosmos/cosmos-sdk/client"
 | 
			
		||||
	cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
 | 
			
		||||
	sdk "github.com/cosmos/cosmos-sdk/types"
 | 
			
		||||
	sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
 | 
			
		||||
	txtypes "github.com/cosmos/cosmos-sdk/types/tx"
 | 
			
		||||
	"github.com/cosmos/cosmos-sdk/types/tx/signing"
 | 
			
		||||
	authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
 | 
			
		||||
	authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
 | 
			
		||||
	tmmempool "github.com/tendermint/tendermint/mempool"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type MsgRequest struct {
 | 
			
		||||
	Msgs      []sdk.Msg
 | 
			
		||||
	GasLimit  uint64
 | 
			
		||||
	FeeAmount sdk.Coins
 | 
			
		||||
	Memo      string
 | 
			
		||||
	// Arbitrary data to be referenced in the corresponding MsgResponse, unused
 | 
			
		||||
	// in signing. This is mostly useful to match MsgResponses with MsgRequests.
 | 
			
		||||
	Data interface{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type MsgResponse struct {
 | 
			
		||||
	Request MsgRequest
 | 
			
		||||
	Tx      authsigning.Tx
 | 
			
		||||
	TxBytes []byte
 | 
			
		||||
	Result  sdk.TxResponse
 | 
			
		||||
	Err     error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// internal result for inner loop logic
 | 
			
		||||
type broadcastTxResult int
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	txOK broadcastTxResult = iota
 | 
			
		||||
	txFailed
 | 
			
		||||
	txRetry
 | 
			
		||||
	txResetSequence
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Signer broadcasts msgs to a single kava node
 | 
			
		||||
type Signer struct {
 | 
			
		||||
	chainID         string
 | 
			
		||||
	encodingConfig  params.EncodingConfig
 | 
			
		||||
	authClient      authtypes.QueryClient
 | 
			
		||||
	txClient        txtypes.ServiceClient
 | 
			
		||||
	privKey         cryptotypes.PrivKey
 | 
			
		||||
	inflightTxLimit uint64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewSigner(
 | 
			
		||||
	chainID string,
 | 
			
		||||
	encodingConfig params.EncodingConfig,
 | 
			
		||||
	authClient authtypes.QueryClient,
 | 
			
		||||
	txClient txtypes.ServiceClient,
 | 
			
		||||
	privKey cryptotypes.PrivKey,
 | 
			
		||||
	inflightTxLimit uint64) *Signer {
 | 
			
		||||
 | 
			
		||||
	return &Signer{
 | 
			
		||||
		chainID:         chainID,
 | 
			
		||||
		encodingConfig:  encodingConfig,
 | 
			
		||||
		authClient:      authClient,
 | 
			
		||||
		txClient:        txClient,
 | 
			
		||||
		privKey:         privKey,
 | 
			
		||||
		inflightTxLimit: inflightTxLimit,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *Signer) pollAccountState() <-chan authtypes.AccountI {
 | 
			
		||||
	accountState := make(chan authtypes.AccountI)
 | 
			
		||||
 | 
			
		||||
	go func() {
 | 
			
		||||
		for {
 | 
			
		||||
			request := authtypes.QueryAccountRequest{
 | 
			
		||||
				Address: GetAccAddress(s.privKey).String(),
 | 
			
		||||
			}
 | 
			
		||||
			response, err := s.authClient.Account(context.Background(), &request)
 | 
			
		||||
 | 
			
		||||
			if err == nil {
 | 
			
		||||
				var account authtypes.AccountI
 | 
			
		||||
 | 
			
		||||
				err = s.encodingConfig.InterfaceRegistry.UnpackAny(response.Account, &account)
 | 
			
		||||
				if err == nil {
 | 
			
		||||
					accountState <- account
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			time.Sleep(1 * time.Second)
 | 
			
		||||
		}
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	return accountState
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *Signer) Run(requests <-chan MsgRequest) (<-chan MsgResponse, error) {
 | 
			
		||||
	// poll account state in it's own goroutine
 | 
			
		||||
	// and send status updates to the signing goroutine
 | 
			
		||||
	//
 | 
			
		||||
	// TODO: instead of polling, we can wait for block
 | 
			
		||||
	// websocket events with a fallback to polling
 | 
			
		||||
	accountState := s.pollAccountState()
 | 
			
		||||
 | 
			
		||||
	responses := make(chan MsgResponse)
 | 
			
		||||
	go func() {
 | 
			
		||||
		// wait until account is loaded to start signing
 | 
			
		||||
		account := <-accountState
 | 
			
		||||
		// store current request waiting to be broadcasted
 | 
			
		||||
		var currentRequest *MsgRequest
 | 
			
		||||
		// keep track of all successfully broadcasted txs
 | 
			
		||||
		// index is sequence % inflightTxLimit
 | 
			
		||||
		inflight := make([]*MsgResponse, s.inflightTxLimit)
 | 
			
		||||
		// used for confirming sent txs only
 | 
			
		||||
		prevDeliverTxSeq := account.GetSequence()
 | 
			
		||||
		// tx sequence of already signed messages
 | 
			
		||||
		checkTxSeq := account.GetSequence()
 | 
			
		||||
		// tx sequence of broadcast queue, is reset upon
 | 
			
		||||
		// unauthorized errors to recheck/refill mempool
 | 
			
		||||
		broadcastTxSeq := account.GetSequence()
 | 
			
		||||
 | 
			
		||||
		for {
 | 
			
		||||
			// the inflight limit includes the current request
 | 
			
		||||
			//
 | 
			
		||||
			// account.GetSequence() represents the first tx in the mempool (at the last known state)
 | 
			
		||||
			// or the next sequence to sign with if checkTxSeq == account.GetSequence() (zero msgs in flight)
 | 
			
		||||
			//
 | 
			
		||||
			// checkTxSeq always represents the next available mempool sequence to sign with
 | 
			
		||||
			//
 | 
			
		||||
			// if currentRequest is nil, then it will be used for the next request received
 | 
			
		||||
			// if currentRequest is not nil, then checkTxSeq will be used to sign that request
 | 
			
		||||
			//
 | 
			
		||||
			// therefore, assuming no errors, broadcastTxSeq will be checkTxSeq-1 or checkTxSeq, dependent on
 | 
			
		||||
			// if the currentRequest has been been successfully broadcast
 | 
			
		||||
			//
 | 
			
		||||
			// if an unauthorized error occurs, a tx in the mempool was dropped (or mempool flushed, node restart, etc)
 | 
			
		||||
			// and broadcastTxSeq is reset to account.GetSequence() in order to refil the mempool and ensure
 | 
			
		||||
			// checkTxSeq is valid
 | 
			
		||||
			//
 | 
			
		||||
			// if an authorized error occurs due to another process signing messages on behalf of the same
 | 
			
		||||
			// address, then broadcastTxSeq will continually be reset until that sequence is delivered to a block
 | 
			
		||||
			//
 | 
			
		||||
			// this results in the message we signed with the same sequence being skipped as well as
 | 
			
		||||
			// draining our inflight messages to 0.
 | 
			
		||||
			//
 | 
			
		||||
			// On deployments, a similar event will occur. we will continually broadcast until
 | 
			
		||||
			// all of the previous transactions are processed and out of the mempool.
 | 
			
		||||
			//
 | 
			
		||||
			// it's possible to increase the checkTx (up to the inflight limit) until met with a successful broadcast,
 | 
			
		||||
			// to fill the mempool faster, but this feature is umimplemented and would be best enabled only once
 | 
			
		||||
			// on startup.  An authorized error during normal operation would be difficult or impossible to tell apart
 | 
			
		||||
			// from a dropped mempool tx (without further improving mempool queries).  Options such as persisting inflight
 | 
			
		||||
			// state out of process may be better.
 | 
			
		||||
			inflightLimitReached := checkTxSeq-account.GetSequence() >= s.inflightTxLimit
 | 
			
		||||
 | 
			
		||||
			// if we are still processing a request or the inflight limit is reached
 | 
			
		||||
			// then block until the next account update without accepting new requests
 | 
			
		||||
			if currentRequest != nil || inflightLimitReached {
 | 
			
		||||
				account = <-accountState
 | 
			
		||||
			} else {
 | 
			
		||||
				// block on state update or new requests
 | 
			
		||||
				select {
 | 
			
		||||
				case account = <-accountState:
 | 
			
		||||
				case request := <-requests:
 | 
			
		||||
					currentRequest = &request
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// send delivered (included in block) responses to caller
 | 
			
		||||
			if account.GetSequence() > prevDeliverTxSeq {
 | 
			
		||||
				for i := prevDeliverTxSeq; i < account.GetSequence(); i++ {
 | 
			
		||||
					response := inflight[i%s.inflightTxLimit]
 | 
			
		||||
					// sequences may be skipped due to errors
 | 
			
		||||
					if response != nil {
 | 
			
		||||
						responses <- *response
 | 
			
		||||
					}
 | 
			
		||||
					// clear to prevent duplicate confirmations on errors
 | 
			
		||||
					inflight[i%s.inflightTxLimit] = nil
 | 
			
		||||
				}
 | 
			
		||||
				prevDeliverTxSeq = account.GetSequence()
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// recover from errors due to untracked messages in mempool
 | 
			
		||||
			// this will happen on deploys, or if another process
 | 
			
		||||
			// signs a tx using the same address
 | 
			
		||||
			if checkTxSeq < account.GetSequence() {
 | 
			
		||||
				checkTxSeq = account.GetSequence()
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// if currentRequest then lastRequestTxSeq == checkTxSeq
 | 
			
		||||
			// if not currentRequest then lastRequestTxSeq == checkTxSeq - 1
 | 
			
		||||
			lastRequestTxSeq := checkTxSeq
 | 
			
		||||
			if currentRequest == nil && lastRequestTxSeq > 0 {
 | 
			
		||||
				lastRequestTxSeq--
 | 
			
		||||
			}
 | 
			
		||||
			// reset broadcast seq if iterated over last request seq
 | 
			
		||||
			// we always want to broadcast the current or last request
 | 
			
		||||
			// to heartbeat the mempool
 | 
			
		||||
			if broadcastTxSeq > lastRequestTxSeq {
 | 
			
		||||
				broadcastTxSeq = lastRequestTxSeq
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// loop serves three purposes
 | 
			
		||||
			//   - recover from dropped txs (broadcastTxSeq < lastRequestTxSeq)
 | 
			
		||||
			//   - send new requests (currentRequest is set)
 | 
			
		||||
			//   - send mempool heartbeat (currentRequest is nil)
 | 
			
		||||
		BROADCAST_LOOP:
 | 
			
		||||
			for broadcastTxSeq <= lastRequestTxSeq {
 | 
			
		||||
 | 
			
		||||
				// we have a new request that has not been successfully broadcasted
 | 
			
		||||
				// and are at the last broadcastTxSeq (broadcastTxSeq == checkTxSeq in this case)
 | 
			
		||||
				sendingCurrentRequest := broadcastTxSeq == lastRequestTxSeq && currentRequest != nil
 | 
			
		||||
 | 
			
		||||
				// check if we have a previous response to check/retry/send for the broadcastTxSeq
 | 
			
		||||
				response := inflight[broadcastTxSeq%s.inflightTxLimit]
 | 
			
		||||
 | 
			
		||||
				// no response -- either checkTxSeq was skipped (untracked mempool tx), or
 | 
			
		||||
				// we are signing a new transactions (currentRequest is not nil)
 | 
			
		||||
				if response == nil {
 | 
			
		||||
					// nothing to do if no response to retry and not sending a current request
 | 
			
		||||
					if !sendingCurrentRequest {
 | 
			
		||||
						// move onto next broadcastTxSeq or exit loop
 | 
			
		||||
						broadcastTxSeq++
 | 
			
		||||
						continue
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					txBuilder := s.encodingConfig.TxConfig.NewTxBuilder()
 | 
			
		||||
					txBuilder.SetMsgs(currentRequest.Msgs...)
 | 
			
		||||
					txBuilder.SetGasLimit(currentRequest.GasLimit)
 | 
			
		||||
					txBuilder.SetFeeAmount(currentRequest.FeeAmount)
 | 
			
		||||
 | 
			
		||||
					signerData := authsigning.SignerData{
 | 
			
		||||
						ChainID:       s.chainID,
 | 
			
		||||
						AccountNumber: account.GetAccountNumber(),
 | 
			
		||||
						Sequence:      broadcastTxSeq,
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					tx, txBytes, err := Sign(s.encodingConfig.TxConfig, s.privKey, txBuilder, signerData)
 | 
			
		||||
 | 
			
		||||
					response = &MsgResponse{
 | 
			
		||||
						Request: *currentRequest,
 | 
			
		||||
						Tx:      tx,
 | 
			
		||||
						TxBytes: txBytes,
 | 
			
		||||
						Err:     err,
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					// could not sign and encode the currentRequest
 | 
			
		||||
					if response.Err != nil {
 | 
			
		||||
						// clear invalid request, since this is non-recoverable
 | 
			
		||||
						currentRequest = nil
 | 
			
		||||
 | 
			
		||||
						// response immediately with error
 | 
			
		||||
						responses <- *response
 | 
			
		||||
 | 
			
		||||
						// exit loop
 | 
			
		||||
						broadcastTxSeq++
 | 
			
		||||
						continue
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				// broadcast tx and get result
 | 
			
		||||
				//
 | 
			
		||||
				// there are four main types of results
 | 
			
		||||
				//
 | 
			
		||||
				// OK (tx in mempool, store response - add to inflight txs)
 | 
			
		||||
				// Retry (tx not in mempool, but retry - do not change inflight status)
 | 
			
		||||
				// Failed (tx not in mempool, not recoverable - clear inflight status, reply to channel)
 | 
			
		||||
				// Unauthorized (tx not in mempool - sequence not valid)
 | 
			
		||||
				broadcastRequest := txtypes.BroadcastTxRequest{
 | 
			
		||||
					TxBytes: response.TxBytes,
 | 
			
		||||
					Mode:    txtypes.BroadcastMode_BROADCAST_MODE_SYNC,
 | 
			
		||||
				}
 | 
			
		||||
				broadcastResponse, err := s.txClient.BroadcastTx(context.Background(), &broadcastRequest)
 | 
			
		||||
 | 
			
		||||
				// set to determine action at the end of loop
 | 
			
		||||
				// default is OK
 | 
			
		||||
				txResult := txOK
 | 
			
		||||
 | 
			
		||||
				// determine action to take when err (and no response)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					if tmmempool.IsPreCheckError(err) {
 | 
			
		||||
						// ErrPreCheck - not recoverable
 | 
			
		||||
						response.Err = err
 | 
			
		||||
						txResult = txFailed
 | 
			
		||||
					} else {
 | 
			
		||||
						// could not contact node (POST failed, dns errors, etc)
 | 
			
		||||
						// exit loop, wait for another account state update
 | 
			
		||||
						// TODO: are there cases here that we will never recover from?
 | 
			
		||||
						// should we implement retry limit?
 | 
			
		||||
						response.Err = err
 | 
			
		||||
						txResult = txRetry
 | 
			
		||||
					}
 | 
			
		||||
				} else {
 | 
			
		||||
					// store rpc result in response
 | 
			
		||||
					response.Result = *broadcastResponse.TxResponse
 | 
			
		||||
 | 
			
		||||
					// determine action to take based on rpc result
 | 
			
		||||
					switch response.Result.Code {
 | 
			
		||||
					// 0: success, in mempool
 | 
			
		||||
					case sdkerrors.SuccessABCICode:
 | 
			
		||||
						txResult = txOK
 | 
			
		||||
					// 4: unauthorized
 | 
			
		||||
					case sdkerrors.ErrUnauthorized.ABCICode():
 | 
			
		||||
						txResult = txResetSequence
 | 
			
		||||
					// 19: success, tx already in mempool
 | 
			
		||||
					case sdkerrors.ErrTxInMempoolCache.ABCICode():
 | 
			
		||||
						txResult = txOK
 | 
			
		||||
					// 20: mempool full
 | 
			
		||||
					case sdkerrors.ErrMempoolIsFull.ABCICode():
 | 
			
		||||
						txResult = txRetry
 | 
			
		||||
					// 32: wrong sequence
 | 
			
		||||
					case sdkerrors.ErrWrongSequence.ABCICode():
 | 
			
		||||
						txResult = txResetSequence
 | 
			
		||||
					default:
 | 
			
		||||
						response.Err = fmt.Errorf("message failed to broadcast, unrecoverable error code %d", response.Result.Code)
 | 
			
		||||
						txResult = txFailed
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				switch txResult {
 | 
			
		||||
				case txOK:
 | 
			
		||||
					// clear any errors from previous attempts
 | 
			
		||||
					response.Err = nil
 | 
			
		||||
 | 
			
		||||
					// store for delivery later
 | 
			
		||||
					inflight[broadcastTxSeq%s.inflightTxLimit] = response
 | 
			
		||||
 | 
			
		||||
					// if this is the current/last request, then clear
 | 
			
		||||
					// the request and increment the checkTxSeq
 | 
			
		||||
					if sendingCurrentRequest {
 | 
			
		||||
						currentRequest = nil
 | 
			
		||||
						checkTxSeq++
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					// go to next request
 | 
			
		||||
					broadcastTxSeq++
 | 
			
		||||
				case txFailed:
 | 
			
		||||
					// do not store the request as inflight (it's not in the mempool)
 | 
			
		||||
					inflight[broadcastTxSeq%s.inflightTxLimit] = nil
 | 
			
		||||
 | 
			
		||||
					// clear current request if it failed
 | 
			
		||||
					if sendingCurrentRequest {
 | 
			
		||||
						currentRequest = nil
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					// immediatley response to channel
 | 
			
		||||
					responses <- *response
 | 
			
		||||
					// go to next request
 | 
			
		||||
					broadcastTxSeq++
 | 
			
		||||
				case txRetry:
 | 
			
		||||
					break BROADCAST_LOOP
 | 
			
		||||
				case txResetSequence:
 | 
			
		||||
					broadcastTxSeq = account.GetSequence()
 | 
			
		||||
					break BROADCAST_LOOP
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	return responses, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Address returns the address of the Signer
 | 
			
		||||
func (s *Signer) Address() sdk.AccAddress {
 | 
			
		||||
	return GetAccAddress(s.privKey)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Sign signs a populated TxBuilder and returns a signed Tx and raw transaction bytes
 | 
			
		||||
func Sign(
 | 
			
		||||
	txConfig sdkclient.TxConfig,
 | 
			
		||||
	privKey cryptotypes.PrivKey,
 | 
			
		||||
	txBuilder sdkclient.TxBuilder,
 | 
			
		||||
	signerData authsigning.SignerData,
 | 
			
		||||
) (authsigning.Tx, []byte, error) {
 | 
			
		||||
	signatureData := signing.SingleSignatureData{
 | 
			
		||||
		SignMode:  signing.SignMode_SIGN_MODE_DIRECT,
 | 
			
		||||
		Signature: nil,
 | 
			
		||||
	}
 | 
			
		||||
	sigV2 := signing.SignatureV2{
 | 
			
		||||
		PubKey:   privKey.PubKey(),
 | 
			
		||||
		Data:     &signatureData,
 | 
			
		||||
		Sequence: signerData.Sequence,
 | 
			
		||||
	}
 | 
			
		||||
	if err := txBuilder.SetSignatures(sigV2); err != nil {
 | 
			
		||||
		return txBuilder.GetTx(), nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	signBytes, err := txConfig.SignModeHandler().GetSignBytes(signing.SignMode_SIGN_MODE_DIRECT, signerData, txBuilder.GetTx())
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return txBuilder.GetTx(), nil, err
 | 
			
		||||
	}
 | 
			
		||||
	signature, err := privKey.Sign(signBytes)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return txBuilder.GetTx(), nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	sigV2.Data = &signing.SingleSignatureData{
 | 
			
		||||
		SignMode:  signing.SignMode_SIGN_MODE_DIRECT,
 | 
			
		||||
		Signature: signature,
 | 
			
		||||
	}
 | 
			
		||||
	if err := txBuilder.SetSignatures(sigV2); err != nil {
 | 
			
		||||
		return txBuilder.GetTx(), nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	txBytes, err := txConfig.TxEncoder()(txBuilder.GetTx())
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return txBuilder.GetTx(), nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return txBuilder.GetTx(), txBytes, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func GetAccAddress(privKey cryptotypes.PrivKey) sdk.AccAddress {
 | 
			
		||||
	return privKey.PubKey().Address().Bytes()
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user