Co-authored-by: Matt Kocubinski <mkocubinski@gmail.com> Co-authored-by: Julien Robert <julien@rbrt.fr>
This commit is contained in:
parent
a0458127fc
commit
1250d2a6da
@ -16,6 +16,13 @@ import (
|
||||
"github.com/cosmos/cosmos-sdk/codec/types"
|
||||
)
|
||||
|
||||
var DefaultProviders = depinject.Provide(
|
||||
ProvideInterfaceRegistry,
|
||||
ProvideLegacyAmino,
|
||||
ProvideProtoCodec,
|
||||
ProvideAddressCodec,
|
||||
)
|
||||
|
||||
func ProvideInterfaceRegistry(
|
||||
addressCodec address.Codec,
|
||||
validatorAddressCodec address.ValidatorAddressCodec,
|
||||
|
||||
@ -8,8 +8,10 @@ import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
var _ Mempool[sdk.Tx] = (*NoOpMempool[sdk.Tx])(nil) // verify interface at compile time
|
||||
var _ Mempool[transaction.Tx] = (*NoOpMempool[transaction.Tx])(nil)
|
||||
var (
|
||||
_ Mempool[sdk.Tx] = (*NoOpMempool[sdk.Tx])(nil) // verify interface at compile time
|
||||
_ Mempool[transaction.Tx] = (*NoOpMempool[transaction.Tx])(nil)
|
||||
)
|
||||
|
||||
// NoOpMempool defines a no-op mempool. Transactions are completely discarded and
|
||||
// ignored when BaseApp interacts with the mempool.
|
||||
|
||||
@ -48,11 +48,8 @@ func AppConfig() depinject.Config {
|
||||
return depinject.Configs(
|
||||
ModuleConfig, // Alternatively use appconfig.LoadYAML(AppConfigYAML)
|
||||
runtime.DefaultServiceBindings(),
|
||||
codec.DefaultProviders,
|
||||
depinject.Provide(
|
||||
codec.ProvideInterfaceRegistry,
|
||||
codec.ProvideAddressCodec,
|
||||
codec.ProvideProtoCodec,
|
||||
codec.ProvideLegacyAmino,
|
||||
ProvideRootStoreConfig,
|
||||
// inject desired account types:
|
||||
multisigdepinject.ProvideAccount,
|
||||
|
||||
26
tests/go.mod
26
tests/go.mod
@ -6,12 +6,15 @@ require (
|
||||
cosmossdk.io/api v0.8.0 // main
|
||||
cosmossdk.io/collections v0.4.1-0.20241107084833-00f3065e70ee // main
|
||||
cosmossdk.io/core v1.0.0-alpha.5 // main
|
||||
cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 // main
|
||||
cosmossdk.io/core/testing v0.0.0 // main
|
||||
cosmossdk.io/depinject v1.1.0
|
||||
cosmossdk.io/log v1.4.1
|
||||
cosmossdk.io/math v1.3.0
|
||||
cosmossdk.io/runtime/v2 v2.0.0-20241107153845-4e240908dd60
|
||||
cosmossdk.io/server/v2/stf v0.0.0-20241107153845-4e240908dd60
|
||||
cosmossdk.io/simapp v0.0.0-20230309163709-87da587416ba
|
||||
cosmossdk.io/store v1.1.1-0.20240909133312-50288938d1b6 // main
|
||||
cosmossdk.io/store v1.1.1
|
||||
cosmossdk.io/store/v2 v2.0.0-00010101000000-000000000000
|
||||
cosmossdk.io/x/accounts v0.0.0-20240913065641-0064ccbce64e
|
||||
cosmossdk.io/x/accounts/defaults/base v0.0.0-00010101000000-000000000000
|
||||
cosmossdk.io/x/accounts/defaults/lockup v0.0.0-20240417181816-5e7aae0db1f5
|
||||
@ -29,7 +32,7 @@ require (
|
||||
cosmossdk.io/x/protocolpool v0.0.0-20230925135524-a1bc045b3190
|
||||
cosmossdk.io/x/slashing v0.0.0-00010101000000-000000000000
|
||||
cosmossdk.io/x/staking v0.0.0-20240226161501-23359a0b6d91
|
||||
cosmossdk.io/x/tx v1.0.0-alpha.2 // main
|
||||
cosmossdk.io/x/tx v1.0.0-alpha.2
|
||||
cosmossdk.io/x/upgrade v0.0.0-20230613133644-0a778132a60f
|
||||
github.com/cometbft/cometbft v1.0.0-rc1.0.20240908111210-ab0be101882f
|
||||
github.com/cometbft/cometbft/api v1.0.0-rc.1
|
||||
@ -46,6 +49,7 @@ require (
|
||||
github.com/spf13/cobra v1.8.1 // indirect
|
||||
github.com/spf13/viper v1.19.0
|
||||
github.com/stretchr/testify v1.9.0
|
||||
gitlab.com/yawning/secp256k1-voi v0.0.0-20230925100816-f2616030848b
|
||||
google.golang.org/grpc v1.67.1
|
||||
google.golang.org/protobuf v1.35.1
|
||||
gotest.tools/v3 v3.5.1
|
||||
@ -63,8 +67,10 @@ require (
|
||||
cloud.google.com/go/storage v1.42.0 // indirect
|
||||
cosmossdk.io/client/v2 v2.0.0-20230630094428-02b760776860 // indirect
|
||||
cosmossdk.io/errors v1.0.1 // indirect
|
||||
cosmossdk.io/errors/v2 v2.0.0-20240731132947-df72853b3ca5 // indirect
|
||||
cosmossdk.io/indexer/postgres v0.0.0-20241107084833-00f3065e70ee // indirect
|
||||
cosmossdk.io/schema v0.3.1-0.20241010135032-192601639cac // indirect
|
||||
cosmossdk.io/server/v2/appmanager v0.0.0-20241107153845-4e240908dd60 // indirect
|
||||
cosmossdk.io/x/circuit v0.0.0-20230613133644-0a778132a60f // indirect
|
||||
cosmossdk.io/x/epochs v0.0.0-20240522060652-a1ae4c3e0337 // indirect
|
||||
filippo.io/edwards25519 v1.1.0 // indirect
|
||||
@ -107,7 +113,7 @@ require (
|
||||
github.com/emicklei/dot v1.6.2 // indirect
|
||||
github.com/fatih/color v1.18.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||
github.com/fsnotify/fsnotify v1.8.0 // indirect
|
||||
github.com/getsentry/sentry-go v0.29.0 // indirect
|
||||
github.com/go-kit/kit v0.13.0 // indirect
|
||||
github.com/go-kit/log v0.2.1 // indirect
|
||||
@ -164,6 +170,7 @@ require (
|
||||
github.com/manifoldco/promptui v0.9.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-sqlite3 v1.14.22 // indirect
|
||||
github.com/minio/highwayhash v1.0.3 // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
|
||||
@ -176,9 +183,9 @@ require (
|
||||
github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/prometheus/client_golang v1.20.4 // indirect
|
||||
github.com/prometheus/client_golang v1.20.5 // indirect
|
||||
github.com/prometheus/client_model v0.6.1 // indirect
|
||||
github.com/prometheus/common v0.59.1 // indirect
|
||||
github.com/prometheus/common v0.60.1 // indirect
|
||||
github.com/prometheus/procfs v0.15.1 // indirect
|
||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
|
||||
github.com/rogpeppe/go-internal v1.13.1 // indirect
|
||||
@ -198,7 +205,6 @@ require (
|
||||
github.com/ulikunitz/xz v0.5.12 // indirect
|
||||
github.com/zondax/hid v0.9.2 // indirect
|
||||
github.com/zondax/ledger-go v0.14.3 // indirect
|
||||
gitlab.com/yawning/secp256k1-voi v0.0.0-20230925100816-f2616030848b // indirect
|
||||
gitlab.com/yawning/tuplehash v0.0.0-20230713102510-df83abbf9a02 // indirect
|
||||
go.etcd.io/bbolt v1.4.0-alpha.1 // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
@ -212,7 +218,7 @@ require (
|
||||
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 // indirect
|
||||
golang.org/x/mod v0.21.0 // indirect
|
||||
golang.org/x/net v0.30.0 // indirect
|
||||
golang.org/x/oauth2 v0.22.0 // indirect
|
||||
golang.org/x/oauth2 v0.23.0 // indirect
|
||||
golang.org/x/sync v0.8.0 // indirect
|
||||
golang.org/x/sys v0.26.0 // indirect
|
||||
golang.org/x/term v0.25.0 // indirect
|
||||
@ -239,8 +245,10 @@ replace (
|
||||
// pseudo version lower than the latest tag
|
||||
cosmossdk.io/api => cosmossdk.io/api v0.7.3-0.20240924065902-eb7653cfecdf // main
|
||||
cosmossdk.io/client/v2 => ../client/v2
|
||||
// pseudo version lower than the latest tag
|
||||
cosmossdk.io/core/testing => cosmossdk.io/core/testing v0.0.0-20241107153845-4e240908dd60
|
||||
cosmossdk.io/store => cosmossdk.io/store v1.0.0-rc.0.0.20241106093505-9611c5a0e6e3 // main
|
||||
// pseudo version lower than the latest tag
|
||||
cosmossdk.io/store/v2 => cosmossdk.io/store/v2 v2.0.0-20241107153845-4e240908dd60
|
||||
cosmossdk.io/x/accounts => ../x/accounts
|
||||
cosmossdk.io/x/accounts/defaults/base => ../x/accounts/defaults/base
|
||||
cosmossdk.io/x/accounts/defaults/lockup => ../x/accounts/defaults/lockup
|
||||
|
||||
32
tests/go.sum
32
tests/go.sum
@ -198,23 +198,33 @@ cosmossdk.io/collections v0.4.1-0.20241107084833-00f3065e70ee h1:OLqvi9ekfShobmd
|
||||
cosmossdk.io/collections v0.4.1-0.20241107084833-00f3065e70ee/go.mod h1:DcD++Yfcq0OFtM3CJNYLIBjfZ+4DEyeJ/AUk6gkwlOE=
|
||||
cosmossdk.io/core v1.0.0-alpha.5 h1:McjYXAQ6XcT20v2uHyH7PhoWH8V+mebzfVFqT3GinsI=
|
||||
cosmossdk.io/core v1.0.0-alpha.5/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY=
|
||||
cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 h1:NxxUo0GMJUbIuVg0R70e3cbn9eFTEuMr7ev1AFvypdY=
|
||||
cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29/go.mod h1:8s2tPeJtSiQuoyPmr2Ag7meikonISO4Fv4MoO8+ORrs=
|
||||
cosmossdk.io/core/testing v0.0.0-20241107153845-4e240908dd60 h1:owHSnQ2LZ4Kqgb1qhl8HeOTgebR04FwKHrZk4Q2d50Y=
|
||||
cosmossdk.io/core/testing v0.0.0-20241107153845-4e240908dd60/go.mod h1:3YvVv9aJayjPhdX0DY1IMrGse4sR63hNBWx2VtDWjGQ=
|
||||
cosmossdk.io/depinject v1.1.0 h1:wLan7LG35VM7Yo6ov0jId3RHWCGRhe8E8bsuARorl5E=
|
||||
cosmossdk.io/depinject v1.1.0/go.mod h1:kkI5H9jCGHeKeYWXTqYdruogYrEeWvBQCw1Pj4/eCFI=
|
||||
cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0=
|
||||
cosmossdk.io/errors v1.0.1/go.mod h1:MeelVSZThMi4bEakzhhhE/CKqVv3nOJDA25bIqRDu/U=
|
||||
cosmossdk.io/errors/v2 v2.0.0-20240731132947-df72853b3ca5 h1:IQNdY2kB+k+1OM2DvqFG1+UgeU1JzZrWtwuWzI3ZfwA=
|
||||
cosmossdk.io/errors/v2 v2.0.0-20240731132947-df72853b3ca5/go.mod h1:0CuYKkFHxc1vw2JC+t21THBCALJVROrWVR/3PQ1urpc=
|
||||
cosmossdk.io/indexer/postgres v0.0.0-20241107084833-00f3065e70ee h1:BfzybkpW7xSpRSQPSvv4T6MbEYtcezJMFZ16hZcftDE=
|
||||
cosmossdk.io/indexer/postgres v0.0.0-20241107084833-00f3065e70ee/go.mod h1:vb5uiIC3rDjz+V7UaSLNA3g5TpbRygWi652qtMugWHA=
|
||||
cosmossdk.io/log v1.4.1 h1:wKdjfDRbDyZRuWa8M+9nuvpVYxrEOwbD/CA8hvhU8QM=
|
||||
cosmossdk.io/log v1.4.1/go.mod h1:k08v0Pyq+gCP6phvdI6RCGhLf/r425UT6Rk/m+o74rU=
|
||||
cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE=
|
||||
cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k=
|
||||
cosmossdk.io/runtime/v2 v2.0.0-20241107153845-4e240908dd60 h1:305IbyP2jaJeKNRglxBtEAY/JKz8rD3l+081zrAThGY=
|
||||
cosmossdk.io/runtime/v2 v2.0.0-20241107153845-4e240908dd60/go.mod h1:zXxA8bHeShGxzTLR9m3OdF+aJ/IEmWSnrz343Ri6Me8=
|
||||
cosmossdk.io/schema v0.3.0/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ=
|
||||
cosmossdk.io/schema v0.3.1-0.20241010135032-192601639cac h1:3joNZZWZ3k7fMsrBDL1ktuQ2xQwYLZOaDhkruadDFmc=
|
||||
cosmossdk.io/schema v0.3.1-0.20241010135032-192601639cac/go.mod h1:RDAhxIeNB4bYqAlF4NBJwRrgtnciMcyyg0DOKnhNZQQ=
|
||||
cosmossdk.io/server/v2/appmanager v0.0.0-20241107153845-4e240908dd60 h1:M26/YrNRru59kzRkW/Mm7bnpEEsnR9rIFdNFGTXicGQ=
|
||||
cosmossdk.io/server/v2/appmanager v0.0.0-20241107153845-4e240908dd60/go.mod h1:mONOF8GRbxs5R04zMscuQQI1gx/XHTY7imKjcwLI5uo=
|
||||
cosmossdk.io/server/v2/stf v0.0.0-20241107153845-4e240908dd60 h1:+PYG1Wjsu8ZX5vvINPu7UjRxzT9m9sJ9SlS8MVApmOU=
|
||||
cosmossdk.io/server/v2/stf v0.0.0-20241107153845-4e240908dd60/go.mod h1:njNsfl5hKTylxDgSiBTLuOM1tic04aPk0k5Af6ybPN0=
|
||||
cosmossdk.io/store v1.0.0-rc.0.0.20241106093505-9611c5a0e6e3 h1:p69ThBO2dqCHKA3GcVoGr18Q4oH04asl1TsDPloxtSI=
|
||||
cosmossdk.io/store v1.0.0-rc.0.0.20241106093505-9611c5a0e6e3/go.mod h1:uaysXSQHWUykekFPvS1JqQ7HM58Zuqcby1DNlLQPWSg=
|
||||
cosmossdk.io/store/v2 v2.0.0-20241107153845-4e240908dd60 h1:2DnhJcJEoVDqz1aoqmy4RXiAnpqy9GNW1gzgnkesJmI=
|
||||
cosmossdk.io/store/v2 v2.0.0-20241107153845-4e240908dd60/go.mod h1:calxpXVRO0AZRYdV+Kup74XP7rhDWAzVHKwHWm2TQZc=
|
||||
cosmossdk.io/x/tx v1.0.0-alpha.2 h1:UW80FMm7B0fiAMsrfe5+HabSJ3XBg+tQa6/GK9prqWk=
|
||||
cosmossdk.io/x/tx v1.0.0-alpha.2/go.mod h1:r4yTKSJ7ZCCR95YbBfY3nfvbgNw6m9F6f25efWYYQWo=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
@ -395,8 +405,8 @@ github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7z
|
||||
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=
|
||||
github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
|
||||
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
||||
github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M=
|
||||
github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||
github.com/getsentry/sentry-go v0.29.0 h1:YtWluuCFg9OfcqnaujpY918N/AhCCwarIDWOYSBAjCA=
|
||||
github.com/getsentry/sentry-go v0.29.0/go.mod h1:jhPesDAL0Q0W2+2YEuVOvdWmVtdsr1+jtBrlDEVWwLY=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
@ -665,6 +675,8 @@ github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
|
||||
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/minio/highwayhash v1.0.3 h1:kbnuUMoHYyVl7szWjSxJnxw11k2U709jqFPPmIUyD6Q=
|
||||
github.com/minio/highwayhash v1.0.3/go.mod h1:GGYsuwP/fPD6Y9hMiXuapVvlIUEhFhMTh0rxU3ik1LQ=
|
||||
@ -732,8 +744,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||
github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU=
|
||||
github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI=
|
||||
github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
|
||||
github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y=
|
||||
github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
@ -742,8 +754,8 @@ github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p
|
||||
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
|
||||
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4=
|
||||
github.com/prometheus/common v0.59.1 h1:LXb1quJHWm1P6wq/U824uxYi4Sg0oGvNeUm1z5dJoX0=
|
||||
github.com/prometheus/common v0.59.1/go.mod h1:GpWM7dewqmVYcd7SmRaiWVe9SSqjf0UrwnYnpEZNuT0=
|
||||
github.com/prometheus/common v0.60.1 h1:FUas6GcOw66yB/73KC+BOZoFJmbo/1pojoILArPAaSc=
|
||||
github.com/prometheus/common v0.60.1/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
|
||||
@ -992,8 +1004,8 @@ golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri
|
||||
golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg=
|
||||
golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg=
|
||||
golang.org/x/oauth2 v0.1.0/go.mod h1:G9FE4dLTsbXUu90h/Pf85g4w1D+SSAgR+q46nJZ8M4A=
|
||||
golang.org/x/oauth2 v0.22.0 h1:BzDx2FehcG7jJwgWLELCdmLuxk2i+x9UDpSiss2u0ZA=
|
||||
golang.org/x/oauth2 v0.22.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
|
||||
golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs=
|
||||
golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
||||
411
tests/integration/v2/app.go
Normal file
411
tests/integration/v2/app.go
Normal file
@ -0,0 +1,411 @@
|
||||
package integration
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1"
|
||||
cmtjson "github.com/cometbft/cometbft/libs/json"
|
||||
cmttypes "github.com/cometbft/cometbft/types"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"cosmossdk.io/core/comet"
|
||||
corecontext "cosmossdk.io/core/context"
|
||||
"cosmossdk.io/core/server"
|
||||
corestore "cosmossdk.io/core/store"
|
||||
"cosmossdk.io/core/transaction"
|
||||
"cosmossdk.io/depinject"
|
||||
sdkmath "cosmossdk.io/math"
|
||||
"cosmossdk.io/runtime/v2"
|
||||
"cosmossdk.io/runtime/v2/services"
|
||||
"cosmossdk.io/server/v2/stf"
|
||||
"cosmossdk.io/server/v2/stf/branch"
|
||||
"cosmossdk.io/store/v2"
|
||||
"cosmossdk.io/store/v2/root"
|
||||
bankkeeper "cosmossdk.io/x/bank/keeper"
|
||||
banktypes "cosmossdk.io/x/bank/types"
|
||||
consensustypes "cosmossdk.io/x/consensus/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
|
||||
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||
"github.com/cosmos/cosmos-sdk/std"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/types/simulation"
|
||||
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||
authsign "github.com/cosmos/cosmos-sdk/x/auth/signing"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/tx"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
)
|
||||
|
||||
const DefaultGenTxGas = 10000000
|
||||
const (
|
||||
Genesis_COMMIT = iota
|
||||
Genesis_NOCOMMIT
|
||||
Genesis_SKIP
|
||||
)
|
||||
|
||||
type stateMachineTx = transaction.Tx
|
||||
|
||||
// DefaultConsensusParams defines the default CometBFT consensus params used in
|
||||
// SimApp testing.
|
||||
var DefaultConsensusParams = &cmtproto.ConsensusParams{
|
||||
Version: &cmtproto.VersionParams{
|
||||
App: 1,
|
||||
},
|
||||
Block: &cmtproto.BlockParams{
|
||||
MaxBytes: 200000,
|
||||
MaxGas: 100_000_000,
|
||||
},
|
||||
Evidence: &cmtproto.EvidenceParams{
|
||||
MaxAgeNumBlocks: 302400,
|
||||
MaxAgeDuration: 504 * time.Hour, // 3 weeks is the max duration
|
||||
MaxBytes: 10000,
|
||||
},
|
||||
Validator: &cmtproto.ValidatorParams{
|
||||
PubKeyTypes: []string{
|
||||
cmttypes.ABCIPubKeyTypeEd25519,
|
||||
cmttypes.ABCIPubKeyTypeSecp256k1,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// StartupConfig defines the startup configuration of a new test app.
|
||||
type StartupConfig struct {
|
||||
// ValidatorSet defines a custom validator set to be validating the app.
|
||||
ValidatorSet func() (*cmttypes.ValidatorSet, error)
|
||||
// AppOption defines the additional operations that will be run in the app builder phase.
|
||||
AppOption runtime.AppBuilderOption[stateMachineTx]
|
||||
// GenesisBehavior defines the behavior of the app at genesis.
|
||||
GenesisBehavior int
|
||||
// GenesisAccounts defines the genesis accounts to be used in the app.
|
||||
GenesisAccounts []GenesisAccount
|
||||
// HomeDir defines the home directory of the app where config and data will be stored.
|
||||
HomeDir string
|
||||
}
|
||||
|
||||
func DefaultStartUpConfig(t *testing.T) StartupConfig {
|
||||
t.Helper()
|
||||
|
||||
priv := secp256k1.GenPrivKey()
|
||||
ba := authtypes.NewBaseAccount(
|
||||
priv.PubKey().Address().Bytes(),
|
||||
priv.PubKey(),
|
||||
0,
|
||||
0,
|
||||
)
|
||||
ga := GenesisAccount{
|
||||
ba,
|
||||
sdk.NewCoins(
|
||||
sdk.NewCoin(sdk.DefaultBondDenom, sdkmath.NewInt(100000000000000)),
|
||||
),
|
||||
}
|
||||
homedir := t.TempDir()
|
||||
t.Logf("generated integration test app config; HomeDir=%s", homedir)
|
||||
return StartupConfig{
|
||||
ValidatorSet: CreateRandomValidatorSet,
|
||||
GenesisBehavior: Genesis_COMMIT,
|
||||
GenesisAccounts: []GenesisAccount{ga},
|
||||
HomeDir: homedir,
|
||||
}
|
||||
}
|
||||
|
||||
// NewApp initializes a new runtime.App. A Nop logger is set in runtime.App.
|
||||
// appConfig defines the application configuration (f.e. app_config.go).
|
||||
// extraOutputs defines the extra outputs to be assigned by the dependency injector (depinject).
|
||||
func NewApp(
|
||||
appConfig depinject.Config,
|
||||
startupConfig StartupConfig,
|
||||
extraOutputs ...interface{},
|
||||
) (*App, error) {
|
||||
// create the app with depinject
|
||||
var (
|
||||
storeBuilder = root.NewBuilder()
|
||||
app *runtime.App[stateMachineTx]
|
||||
appBuilder *runtime.AppBuilder[stateMachineTx]
|
||||
txConfig client.TxConfig
|
||||
txConfigOptions tx.ConfigOptions
|
||||
cometService comet.Service = &cometServiceImpl{}
|
||||
kvFactory corestore.KVStoreServiceFactory = func(actor []byte) corestore.KVStoreService {
|
||||
return services.NewGenesisKVService(actor, &storeService{actor, stf.NewKVStoreService(actor)})
|
||||
}
|
||||
cdc codec.Codec
|
||||
err error
|
||||
)
|
||||
|
||||
if err := depinject.Inject(
|
||||
depinject.Configs(
|
||||
appConfig,
|
||||
codec.DefaultProviders,
|
||||
depinject.Supply(
|
||||
&root.Config{
|
||||
Home: startupConfig.HomeDir,
|
||||
AppDBBackend: "goleveldb",
|
||||
Options: root.DefaultStoreOptions(),
|
||||
},
|
||||
runtime.GlobalConfig{
|
||||
"server": server.ConfigMap{
|
||||
"minimum-gas-prices": "0stake",
|
||||
},
|
||||
},
|
||||
services.NewGenesisHeaderService(stf.HeaderService{}),
|
||||
cometService,
|
||||
kvFactory,
|
||||
&eventService{},
|
||||
storeBuilder,
|
||||
),
|
||||
depinject.Invoke(
|
||||
std.RegisterInterfaces,
|
||||
),
|
||||
),
|
||||
append(extraOutputs, &appBuilder, &cdc, &txConfigOptions, &txConfig, &storeBuilder)...); err != nil {
|
||||
return nil, fmt.Errorf("failed to inject dependencies: %w", err)
|
||||
}
|
||||
|
||||
app, err = appBuilder.Build()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to build app: %w", err)
|
||||
}
|
||||
if err := app.LoadLatest(); err != nil {
|
||||
return nil, fmt.Errorf("failed to load app: %w", err)
|
||||
}
|
||||
|
||||
store := storeBuilder.Get()
|
||||
if store == nil {
|
||||
return nil, fmt.Errorf("failed to build store: %w", err)
|
||||
}
|
||||
err = store.SetInitialVersion(1)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to set initial version: %w", err)
|
||||
}
|
||||
|
||||
integrationApp := &App{App: app, Store: store, txConfig: txConfig, lastHeight: 1}
|
||||
if startupConfig.GenesisBehavior == Genesis_SKIP {
|
||||
return integrationApp, nil
|
||||
}
|
||||
|
||||
// create validator set
|
||||
valSet, err := startupConfig.ValidatorSet()
|
||||
if err != nil {
|
||||
return nil, errors.New("failed to create validator set")
|
||||
}
|
||||
|
||||
var (
|
||||
balances []banktypes.Balance
|
||||
genAccounts []authtypes.GenesisAccount
|
||||
)
|
||||
for _, ga := range startupConfig.GenesisAccounts {
|
||||
genAccounts = append(genAccounts, ga.GenesisAccount)
|
||||
balances = append(
|
||||
balances,
|
||||
banktypes.Balance{
|
||||
Address: ga.GenesisAccount.GetAddress().String(),
|
||||
Coins: ga.Coins,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
genesisJSON, err := genesisStateWithValSet(
|
||||
cdc,
|
||||
app.DefaultGenesis(),
|
||||
valSet,
|
||||
genAccounts,
|
||||
balances...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create genesis state: %w", err)
|
||||
}
|
||||
|
||||
// init chain must be called to stop deliverState from being nil
|
||||
genesisJSONBytes, err := cmtjson.MarshalIndent(genesisJSON, "", " ")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf(
|
||||
"failed to marshal default genesis state: %w",
|
||||
err,
|
||||
)
|
||||
}
|
||||
|
||||
ctx := context.WithValue(
|
||||
context.Background(),
|
||||
corecontext.CometParamsInitInfoKey,
|
||||
&consensustypes.MsgUpdateParams{
|
||||
Authority: "consensus",
|
||||
Block: DefaultConsensusParams.Block,
|
||||
Evidence: DefaultConsensusParams.Evidence,
|
||||
Validator: DefaultConsensusParams.Validator,
|
||||
Abci: DefaultConsensusParams.Abci,
|
||||
Synchrony: DefaultConsensusParams.Synchrony,
|
||||
Feature: DefaultConsensusParams.Feature,
|
||||
},
|
||||
)
|
||||
|
||||
emptyHash := sha256.Sum256(nil)
|
||||
_, genesisState, err := app.InitGenesis(
|
||||
ctx,
|
||||
&server.BlockRequest[stateMachineTx]{
|
||||
Height: 1,
|
||||
Time: time.Now(),
|
||||
Hash: emptyHash[:],
|
||||
ChainId: "test-chain",
|
||||
AppHash: emptyHash[:],
|
||||
IsGenesis: true,
|
||||
},
|
||||
genesisJSONBytes,
|
||||
&genesisTxCodec{txConfigOptions},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed init genesis: %w", err)
|
||||
}
|
||||
|
||||
if startupConfig.GenesisBehavior == Genesis_NOCOMMIT {
|
||||
integrationApp.lastHeight = 0
|
||||
return integrationApp, nil
|
||||
}
|
||||
|
||||
_, err = integrationApp.Commit(genesisState)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to commit initial version: %w", err)
|
||||
}
|
||||
|
||||
return integrationApp, nil
|
||||
}
|
||||
|
||||
// App is a wrapper around runtime.App that provides additional testing utilities.
|
||||
type App struct {
|
||||
*runtime.App[stateMachineTx]
|
||||
lastHeight uint64
|
||||
Store store.RootStore
|
||||
txConfig client.TxConfig
|
||||
}
|
||||
|
||||
// Deliver delivers a block with the given transactions and returns the resulting state.
|
||||
func (a *App) Deliver(
|
||||
t *testing.T, ctx context.Context, txs []stateMachineTx,
|
||||
) (*server.BlockResponse, corestore.WriterMap) {
|
||||
t.Helper()
|
||||
req := &server.BlockRequest[stateMachineTx]{
|
||||
Height: a.lastHeight + 1,
|
||||
Txs: txs,
|
||||
Hash: make([]byte, 32),
|
||||
AppHash: make([]byte, 32),
|
||||
}
|
||||
resp, state, err := a.DeliverBlock(ctx, req)
|
||||
require.NoError(t, err)
|
||||
a.lastHeight++
|
||||
return resp, state
|
||||
}
|
||||
|
||||
// StateLatestContext creates returns a new context from context.Background() with the latest state.
|
||||
func (a *App) StateLatestContext(t *testing.T) context.Context {
|
||||
t.Helper()
|
||||
_, state, err := a.Store.StateLatest()
|
||||
require.NoError(t, err)
|
||||
writeableState := branch.DefaultNewWriterMap(state)
|
||||
iCtx := &integrationContext{state: writeableState}
|
||||
return context.WithValue(context.Background(), contextKey, iCtx)
|
||||
}
|
||||
|
||||
// Commit commits the given state and returns the new state hash.
|
||||
func (a *App) Commit(state corestore.WriterMap) ([]byte, error) {
|
||||
changes, err := state.GetStateChanges()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get state changes: %w", err)
|
||||
}
|
||||
cs := &corestore.Changeset{Changes: changes}
|
||||
return a.Store.Commit(cs)
|
||||
}
|
||||
|
||||
// SignCheckDeliver signs and checks the given messages and delivers them.
|
||||
func (a *App) SignCheckDeliver(
|
||||
t *testing.T, ctx context.Context, msgs []sdk.Msg,
|
||||
chainID string, accNums, accSeqs []uint64, privateKeys []cryptotypes.PrivKey,
|
||||
txErrString string,
|
||||
) server.TxResult {
|
||||
t.Helper()
|
||||
|
||||
r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
sigs := make([]signing.SignatureV2, len(privateKeys))
|
||||
|
||||
// create a random length memo
|
||||
memo := simulation.RandStringOfLength(r, simulation.RandIntBetween(r, 0, 100))
|
||||
|
||||
signMode, err := authsign.APISignModeToInternal(a.txConfig.SignModeHandler().DefaultMode())
|
||||
require.NoError(t, err)
|
||||
|
||||
// 1st round: set SignatureV2 with empty signatures, to set correct
|
||||
// signer infos.
|
||||
for i, p := range privateKeys {
|
||||
sigs[i] = signing.SignatureV2{
|
||||
PubKey: p.PubKey(),
|
||||
Data: &signing.SingleSignatureData{
|
||||
SignMode: signMode,
|
||||
},
|
||||
Sequence: accSeqs[i],
|
||||
}
|
||||
}
|
||||
|
||||
txBuilder := a.txConfig.NewTxBuilder()
|
||||
err = txBuilder.SetMsgs(msgs...)
|
||||
require.NoError(t, err)
|
||||
err = txBuilder.SetSignatures(sigs...)
|
||||
require.NoError(t, err)
|
||||
txBuilder.SetMemo(memo)
|
||||
txBuilder.SetFeeAmount(sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 0)})
|
||||
txBuilder.SetGasLimit(DefaultGenTxGas)
|
||||
|
||||
// 2nd round: once all signer infos are set, every signer can sign.
|
||||
for i, p := range privateKeys {
|
||||
signerData := authsign.SignerData{
|
||||
Address: sdk.AccAddress(p.PubKey().Address()).String(),
|
||||
ChainID: chainID,
|
||||
AccountNumber: accNums[i],
|
||||
Sequence: accSeqs[i],
|
||||
PubKey: p.PubKey(),
|
||||
}
|
||||
|
||||
signBytes, err := authsign.GetSignBytesAdapter(
|
||||
ctx, a.txConfig.SignModeHandler(), signMode, signerData,
|
||||
// todo why fetch twice?
|
||||
txBuilder.GetTx())
|
||||
require.NoError(t, err)
|
||||
sig, err := p.Sign(signBytes)
|
||||
require.NoError(t, err)
|
||||
sigs[i].Data.(*signing.SingleSignatureData).Signature = sig
|
||||
}
|
||||
err = txBuilder.SetSignatures(sigs...)
|
||||
require.NoError(t, err)
|
||||
|
||||
builtTx := txBuilder.GetTx()
|
||||
blockResponse, blockState := a.Deliver(t, ctx, []stateMachineTx{builtTx})
|
||||
|
||||
require.Equal(t, 1, len(blockResponse.TxResults))
|
||||
txResult := blockResponse.TxResults[0]
|
||||
if txErrString != "" {
|
||||
require.ErrorContains(t, txResult.Error, txErrString)
|
||||
} else {
|
||||
require.NoError(t, txResult.Error)
|
||||
}
|
||||
|
||||
_, err = a.Commit(blockState)
|
||||
require.NoError(t, err)
|
||||
|
||||
return txResult
|
||||
}
|
||||
|
||||
// CheckBalance checks the balance of the given address.
|
||||
func (a *App) CheckBalance(
|
||||
t *testing.T, ctx context.Context, addr sdk.AccAddress, expected sdk.Coins, keeper bankkeeper.Keeper,
|
||||
) {
|
||||
t.Helper()
|
||||
balances := keeper.GetAllBalances(ctx, addr)
|
||||
require.Equal(t, expected, balances)
|
||||
}
|
||||
|
||||
func (a *App) Close() error {
|
||||
return a.Store.Close()
|
||||
}
|
||||
469
tests/integration/v2/bank/app_test.go
Normal file
469
tests/integration/v2/bank/app_test.go
Normal file
@ -0,0 +1,469 @@
|
||||
package bank
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
secp256k1_internal "gitlab.com/yawning/secp256k1-voi"
|
||||
"gitlab.com/yawning/secp256k1-voi/secec"
|
||||
|
||||
"cosmossdk.io/depinject"
|
||||
"cosmossdk.io/log"
|
||||
sdkmath "cosmossdk.io/math"
|
||||
_ "cosmossdk.io/x/accounts"
|
||||
_ "cosmossdk.io/x/bank"
|
||||
bankkeeper "cosmossdk.io/x/bank/keeper"
|
||||
"cosmossdk.io/x/bank/testutil"
|
||||
"cosmossdk.io/x/bank/types"
|
||||
_ "cosmossdk.io/x/consensus"
|
||||
_ "cosmossdk.io/x/distribution"
|
||||
distrkeeper "cosmossdk.io/x/distribution/keeper"
|
||||
_ "cosmossdk.io/x/gov"
|
||||
govv1 "cosmossdk.io/x/gov/types/v1"
|
||||
_ "cosmossdk.io/x/protocolpool"
|
||||
_ "cosmossdk.io/x/staking"
|
||||
stakingtypes "cosmossdk.io/x/staking/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
cdctestutil "github.com/cosmos/cosmos-sdk/codec/testutil"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
|
||||
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||
"github.com/cosmos/cosmos-sdk/tests/integration/v2"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/configurator"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
_ "github.com/cosmos/cosmos-sdk/x/auth"
|
||||
_ "github.com/cosmos/cosmos-sdk/x/auth/tx/config"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
)
|
||||
|
||||
var (
|
||||
stablePrivateKey, _ = secec.NewPrivateKeyFromScalar(secp256k1_internal.NewScalarFromUint64(100))
|
||||
priv1 = &secp256k1.PrivKey{Key: stablePrivateKey.Bytes()}
|
||||
addr1 = sdk.AccAddress(priv1.PubKey().Address())
|
||||
priv2 = secp256k1.GenPrivKey()
|
||||
addr2 = sdk.AccAddress(priv2.PubKey().Address())
|
||||
addr3 = sdk.AccAddress(secp256k1.GenPrivKey().PubKey().Address())
|
||||
coins = sdk.Coins{sdk.NewInt64Coin("foocoin", 10)}
|
||||
halfCoins = sdk.Coins{sdk.NewInt64Coin("foocoin", 5)}
|
||||
moduleAccAddr = authtypes.NewModuleAddress(stakingtypes.BondedPoolName)
|
||||
)
|
||||
|
||||
type suite struct {
|
||||
BankKeeper bankkeeper.Keeper
|
||||
AccountKeeper types.AccountKeeper
|
||||
DistributionKeeper distrkeeper.Keeper
|
||||
App *integration.App
|
||||
TxConfig client.TxConfig
|
||||
}
|
||||
|
||||
type expectedBalance struct {
|
||||
addr sdk.AccAddress
|
||||
coins sdk.Coins
|
||||
}
|
||||
|
||||
type appTestCase struct {
|
||||
desc string
|
||||
msgs []sdk.Msg
|
||||
accNums []uint64
|
||||
accSeqs []uint64
|
||||
privKeys []cryptotypes.PrivKey
|
||||
expectedBalances []expectedBalance
|
||||
expInError []string
|
||||
}
|
||||
|
||||
func createTestSuite(t *testing.T, genesisAccounts []authtypes.GenesisAccount) suite {
|
||||
t.Helper()
|
||||
res := suite{}
|
||||
|
||||
moduleConfigs := []configurator.ModuleOption{
|
||||
configurator.AccountsModule(),
|
||||
configurator.AuthModule(),
|
||||
configurator.StakingModule(),
|
||||
configurator.TxModule(),
|
||||
configurator.ValidateModule(),
|
||||
configurator.ConsensusModule(),
|
||||
configurator.BankModule(),
|
||||
configurator.GovModule(),
|
||||
configurator.DistributionModule(),
|
||||
configurator.ProtocolPoolModule(),
|
||||
}
|
||||
var err error
|
||||
startupCfg := integration.DefaultStartUpConfig(t)
|
||||
var genAccounts []integration.GenesisAccount
|
||||
for _, acc := range genesisAccounts {
|
||||
genAccounts = append(genAccounts, integration.GenesisAccount{GenesisAccount: acc})
|
||||
}
|
||||
startupCfg.GenesisAccounts = genAccounts
|
||||
res.App, err = integration.NewApp(
|
||||
depinject.Configs(configurator.NewAppV2Config(moduleConfigs...), depinject.Supply(log.NewNopLogger())),
|
||||
startupCfg,
|
||||
&res.BankKeeper, &res.AccountKeeper, &res.DistributionKeeper, &res.TxConfig)
|
||||
require.NoError(t, err)
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
func TestSendNotEnoughBalance(t *testing.T) {
|
||||
acc := &authtypes.BaseAccount{
|
||||
Address: addr1.String(),
|
||||
}
|
||||
|
||||
genAccs := []authtypes.GenesisAccount{acc}
|
||||
s := createTestSuite(t, genAccs)
|
||||
ctx := s.App.StateLatestContext(t)
|
||||
|
||||
err := testutil.FundAccount(
|
||||
ctx, s.BankKeeper, addr1,
|
||||
sdk.NewCoins(sdk.NewInt64Coin("foocoin", 67)))
|
||||
require.NoError(t, err)
|
||||
res1 := s.AccountKeeper.GetAccount(ctx, addr1)
|
||||
require.NotNil(t, res1)
|
||||
require.Equal(t, acc, res1.(*authtypes.BaseAccount))
|
||||
|
||||
origAccNum := res1.GetAccountNumber()
|
||||
origSeq := res1.GetSequence()
|
||||
addr1Str, err := s.AccountKeeper.AddressCodec().BytesToString(addr1)
|
||||
require.NoError(t, err)
|
||||
addr2Str, err := s.AccountKeeper.AddressCodec().BytesToString(addr2)
|
||||
require.NoError(t, err)
|
||||
sendMsg := types.NewMsgSend(addr1Str, addr2Str, sdk.Coins{sdk.NewInt64Coin("foocoin", 100)})
|
||||
|
||||
// TODO how to auto-advance height with app v2 interface?
|
||||
s.App.SignCheckDeliver(
|
||||
t, ctx, []sdk.Msg{sendMsg}, "", []uint64{origAccNum}, []uint64{origSeq},
|
||||
[]cryptotypes.PrivKey{priv1},
|
||||
"spendable balance 67foocoin is smaller than 100foocoin",
|
||||
)
|
||||
s.App.CheckBalance(t, ctx, addr1, sdk.Coins{sdk.NewInt64Coin("foocoin", 67)}, s.BankKeeper)
|
||||
res2 := s.AccountKeeper.GetAccount(ctx, addr1)
|
||||
require.NotNil(t, res2)
|
||||
|
||||
require.Equal(t, origAccNum, res2.GetAccountNumber())
|
||||
require.Equal(t, origSeq+1, res2.GetSequence())
|
||||
}
|
||||
|
||||
func TestMsgMultiSendWithAccounts(t *testing.T) {
|
||||
addr1Str, err := cdctestutil.CodecOptions{}.GetAddressCodec().BytesToString(addr1)
|
||||
require.NoError(t, err)
|
||||
acc := &authtypes.BaseAccount{
|
||||
Address: addr1Str,
|
||||
}
|
||||
|
||||
addr2Str, err := cdctestutil.CodecOptions{}.GetAddressCodec().BytesToString(addr2)
|
||||
require.NoError(t, err)
|
||||
|
||||
moduleStrAddr, err := cdctestutil.CodecOptions{}.GetAddressCodec().BytesToString(moduleAccAddr)
|
||||
require.NoError(t, err)
|
||||
|
||||
genAccs := []authtypes.GenesisAccount{acc}
|
||||
s := createTestSuite(t, genAccs)
|
||||
ctx := s.App.StateLatestContext(t)
|
||||
|
||||
require.NoError(t, testutil.FundAccount(ctx, s.BankKeeper, addr1, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 67))))
|
||||
|
||||
_, state := s.App.Deliver(t, ctx, nil)
|
||||
_, err = s.App.Commit(state)
|
||||
require.NoError(t, err)
|
||||
|
||||
res1 := s.AccountKeeper.GetAccount(ctx, addr1)
|
||||
require.NotNil(t, res1)
|
||||
require.Equal(t, acc, res1.(*authtypes.BaseAccount))
|
||||
|
||||
testCases := []appTestCase{
|
||||
{
|
||||
desc: "make a valid tx",
|
||||
msgs: []sdk.Msg{&types.MsgMultiSend{
|
||||
Inputs: []types.Input{types.NewInput(addr1Str, coins)},
|
||||
Outputs: []types.Output{types.NewOutput(addr2Str, coins)},
|
||||
}},
|
||||
accNums: []uint64{0},
|
||||
accSeqs: []uint64{0},
|
||||
privKeys: []cryptotypes.PrivKey{priv1},
|
||||
expectedBalances: []expectedBalance{
|
||||
{addr1, sdk.Coins{sdk.NewInt64Coin("foocoin", 57)}},
|
||||
{addr2, sdk.Coins{sdk.NewInt64Coin("foocoin", 10)}},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "wrong accNum should pass Simulate, but not Deliver",
|
||||
msgs: []sdk.Msg{&types.MsgMultiSend{
|
||||
Inputs: []types.Input{types.NewInput(addr1Str, coins)},
|
||||
Outputs: []types.Output{types.NewOutput(addr2Str, coins)},
|
||||
}},
|
||||
accNums: []uint64{1}, // wrong account number
|
||||
accSeqs: []uint64{1},
|
||||
expInError: []string{"signature verification failed; please verify account number"},
|
||||
privKeys: []cryptotypes.PrivKey{priv1},
|
||||
},
|
||||
{
|
||||
desc: "wrong accSeq should not pass Simulate",
|
||||
msgs: []sdk.Msg{&types.MsgMultiSend{
|
||||
Inputs: []types.Input{types.NewInput(addr1Str, coins)},
|
||||
Outputs: []types.Output{
|
||||
types.NewOutput(moduleStrAddr, coins),
|
||||
},
|
||||
}},
|
||||
accNums: []uint64{0},
|
||||
accSeqs: []uint64{0}, // wrong account sequence
|
||||
expInError: []string{"account sequence mismatch"},
|
||||
privKeys: []cryptotypes.PrivKey{priv1},
|
||||
},
|
||||
{
|
||||
desc: "multiple inputs not allowed",
|
||||
msgs: []sdk.Msg{&types.MsgMultiSend{
|
||||
Inputs: []types.Input{types.NewInput(addr1Str, coins), types.NewInput(addr2Str, coins)},
|
||||
Outputs: []types.Output{},
|
||||
}},
|
||||
accNums: []uint64{0},
|
||||
accSeqs: []uint64{0},
|
||||
expInError: []string{"invalid number of signatures"},
|
||||
privKeys: []cryptotypes.PrivKey{priv1},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
var errString string
|
||||
if len(tc.expInError) > 0 {
|
||||
errString = tc.expInError[0]
|
||||
}
|
||||
s.App.SignCheckDeliver(t, ctx, tc.msgs, "", tc.accNums, tc.accSeqs, tc.privKeys, errString)
|
||||
|
||||
for _, eb := range tc.expectedBalances {
|
||||
s.App.CheckBalance(t, ctx, eb.addr, eb.coins, s.BankKeeper)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestMsgMultiSendMultipleOut(t *testing.T) {
|
||||
ac := cdctestutil.CodecOptions{}.GetAddressCodec()
|
||||
addr1Str, err := ac.BytesToString(addr1)
|
||||
require.NoError(t, err)
|
||||
acc1 := &authtypes.BaseAccount{
|
||||
Address: addr1Str,
|
||||
}
|
||||
addr2Str, err := ac.BytesToString(addr2)
|
||||
require.NoError(t, err)
|
||||
acc2 := &authtypes.BaseAccount{
|
||||
Address: addr2Str,
|
||||
}
|
||||
addr3Str, err := ac.BytesToString(addr3)
|
||||
require.NoError(t, err)
|
||||
|
||||
genAccs := []authtypes.GenesisAccount{acc1, acc2}
|
||||
s := createTestSuite(t, genAccs)
|
||||
ctx := s.App.StateLatestContext(t)
|
||||
|
||||
require.NoError(t, testutil.FundAccount(ctx, s.BankKeeper, addr1, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 42))))
|
||||
require.NoError(t, testutil.FundAccount(ctx, s.BankKeeper, addr2, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 42))))
|
||||
_, state := s.App.Deliver(t, ctx, nil)
|
||||
_, err = s.App.Commit(state)
|
||||
require.NoError(t, err)
|
||||
|
||||
testCases := []appTestCase{
|
||||
{
|
||||
msgs: []sdk.Msg{&types.MsgMultiSend{
|
||||
Inputs: []types.Input{types.NewInput(addr1Str, coins)},
|
||||
Outputs: []types.Output{
|
||||
types.NewOutput(addr2Str, halfCoins),
|
||||
types.NewOutput(addr3Str, halfCoins),
|
||||
},
|
||||
}},
|
||||
accNums: []uint64{0},
|
||||
accSeqs: []uint64{0},
|
||||
privKeys: []cryptotypes.PrivKey{priv1},
|
||||
expectedBalances: []expectedBalance{
|
||||
{addr1, sdk.Coins{sdk.NewInt64Coin("foocoin", 32)}},
|
||||
{addr2, sdk.Coins{sdk.NewInt64Coin("foocoin", 47)}},
|
||||
{addr3, sdk.Coins{sdk.NewInt64Coin("foocoin", 5)}},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
s.App.SignCheckDeliver(t, ctx, tc.msgs, "", tc.accNums, tc.accSeqs, tc.privKeys, "")
|
||||
|
||||
for _, eb := range tc.expectedBalances {
|
||||
s.App.CheckBalance(t, ctx, eb.addr, eb.coins, s.BankKeeper)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMsgMultiSendDependent(t *testing.T) {
|
||||
ac := cdctestutil.CodecOptions{}.GetAddressCodec()
|
||||
addr1Str, err := ac.BytesToString(addr1)
|
||||
require.NoError(t, err)
|
||||
addr2Str, err := ac.BytesToString(addr2)
|
||||
require.NoError(t, err)
|
||||
|
||||
acc1 := authtypes.NewBaseAccountWithAddress(addr1)
|
||||
acc2 := authtypes.NewBaseAccountWithAddress(addr2)
|
||||
err = acc2.SetAccountNumber(1)
|
||||
require.NoError(t, err)
|
||||
|
||||
genAccs := []authtypes.GenesisAccount{acc1, acc2}
|
||||
s := createTestSuite(t, genAccs)
|
||||
ctx := s.App.StateLatestContext(t)
|
||||
|
||||
require.NoError(t, testutil.FundAccount(ctx, s.BankKeeper, addr1, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 42))))
|
||||
_, state := s.App.Deliver(t, ctx, nil)
|
||||
_, err = s.App.Commit(state)
|
||||
require.NoError(t, err)
|
||||
|
||||
testCases := []appTestCase{
|
||||
{
|
||||
msgs: []sdk.Msg{&types.MsgMultiSend{
|
||||
Inputs: []types.Input{types.NewInput(addr1Str, coins)},
|
||||
Outputs: []types.Output{types.NewOutput(addr2Str, coins)},
|
||||
}},
|
||||
accNums: []uint64{0},
|
||||
accSeqs: []uint64{0},
|
||||
privKeys: []cryptotypes.PrivKey{priv1},
|
||||
expectedBalances: []expectedBalance{
|
||||
{addr1, sdk.Coins{sdk.NewInt64Coin("foocoin", 32)}},
|
||||
{addr2, sdk.Coins{sdk.NewInt64Coin("foocoin", 10)}},
|
||||
},
|
||||
},
|
||||
{
|
||||
msgs: []sdk.Msg{&types.MsgMultiSend{
|
||||
Inputs: []types.Input{types.NewInput(addr2Str, coins)},
|
||||
Outputs: []types.Output{
|
||||
types.NewOutput(addr1Str, coins),
|
||||
},
|
||||
}},
|
||||
accNums: []uint64{1},
|
||||
accSeqs: []uint64{0},
|
||||
privKeys: []cryptotypes.PrivKey{priv2},
|
||||
expectedBalances: []expectedBalance{
|
||||
{addr1, sdk.Coins{sdk.NewInt64Coin("foocoin", 42)}},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
s.App.SignCheckDeliver(t, ctx, tc.msgs, "", tc.accNums, tc.accSeqs, tc.privKeys, "")
|
||||
|
||||
for _, eb := range tc.expectedBalances {
|
||||
s.App.CheckBalance(t, ctx, eb.addr, eb.coins, s.BankKeeper)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMsgSetSendEnabled(t *testing.T) {
|
||||
acc1 := authtypes.NewBaseAccountWithAddress(addr1)
|
||||
|
||||
genAccs := []authtypes.GenesisAccount{acc1}
|
||||
s := createTestSuite(t, genAccs)
|
||||
|
||||
ctx := s.App.StateLatestContext(t)
|
||||
require.NoError(t, testutil.FundAccount(ctx, s.BankKeeper, addr1, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 101))))
|
||||
require.NoError(t, testutil.FundAccount(ctx, s.BankKeeper, addr1, sdk.NewCoins(sdk.NewInt64Coin("stake", 100000))))
|
||||
addr1Str := addr1.String()
|
||||
govAddr := s.BankKeeper.GetAuthority()
|
||||
goodGovProp, err := govv1.NewMsgSubmitProposal(
|
||||
[]sdk.Msg{
|
||||
types.NewMsgSetSendEnabled(govAddr, nil, nil),
|
||||
},
|
||||
sdk.Coins{{Denom: "stake", Amount: sdkmath.NewInt(100000)}},
|
||||
addr1Str,
|
||||
"set default send enabled to true",
|
||||
"Change send enabled",
|
||||
"Modify send enabled and set to true",
|
||||
govv1.ProposalType_PROPOSAL_TYPE_STANDARD,
|
||||
)
|
||||
require.NoError(t, err, "making goodGovProp")
|
||||
|
||||
testCases := []appTestCase{
|
||||
{
|
||||
desc: "wrong authority",
|
||||
msgs: []sdk.Msg{
|
||||
types.NewMsgSetSendEnabled(addr1Str, nil, nil),
|
||||
},
|
||||
accSeqs: []uint64{0},
|
||||
expInError: []string{
|
||||
"invalid authority",
|
||||
"cosmos10d07y265gmmuvt4z0w9aw880jnsr700j6zn9kn",
|
||||
addr1Str,
|
||||
"expected authority account as only signer for proposal message",
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "right authority wrong signer",
|
||||
msgs: []sdk.Msg{
|
||||
types.NewMsgSetSendEnabled(govAddr, nil, nil),
|
||||
},
|
||||
accSeqs: []uint64{1}, // wrong signer, so this sequence doesn't actually get used.
|
||||
expInError: []string{
|
||||
"cannot be claimed by public key with address",
|
||||
govAddr,
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "submitted good as gov prop",
|
||||
msgs: []sdk.Msg{
|
||||
goodGovProp,
|
||||
},
|
||||
accSeqs: []uint64{1},
|
||||
expInError: nil,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.desc, func(tt *testing.T) {
|
||||
var errString string
|
||||
if len(tc.expInError) > 0 {
|
||||
errString = tc.expInError[0]
|
||||
}
|
||||
txResult := s.App.SignCheckDeliver(
|
||||
tt, ctx, tc.msgs, "", []uint64{0}, tc.accSeqs, []cryptotypes.PrivKey{priv1}, errString)
|
||||
if len(tc.expInError) > 0 {
|
||||
require.Error(tt, txResult.Error)
|
||||
for _, exp := range tc.expInError {
|
||||
require.ErrorContains(tt, txResult.Error, exp)
|
||||
}
|
||||
} else {
|
||||
require.NoError(tt, txResult.Error)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestSendToNonExistingAccount tests sending coins to an account that does not exist, and this account
|
||||
// must not be created.
|
||||
func TestSendToNonExistingAccount(t *testing.T) {
|
||||
acc1 := authtypes.NewBaseAccountWithAddress(addr1)
|
||||
genAccs := []authtypes.GenesisAccount{acc1}
|
||||
s := createTestSuite(t, genAccs)
|
||||
ctx := s.App.StateLatestContext(t)
|
||||
|
||||
require.NoError(t, testutil.FundAccount(ctx, s.BankKeeper, addr1, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 42))))
|
||||
_, state := s.App.Deliver(t, ctx, nil)
|
||||
_, err := s.App.Commit(state)
|
||||
require.NoError(t, err)
|
||||
|
||||
addr2Str, err := s.AccountKeeper.AddressCodec().BytesToString(addr2)
|
||||
require.NoError(t, err)
|
||||
sendMsg := types.NewMsgSend(addr1.String(), addr2Str, coins)
|
||||
res := s.App.SignCheckDeliver(t, ctx, []sdk.Msg{sendMsg}, "", []uint64{0}, []uint64{0}, []cryptotypes.PrivKey{priv1}, "")
|
||||
require.NoError(t, res.Error)
|
||||
|
||||
// Check that the account was not created
|
||||
acc2 := s.AccountKeeper.GetAccount(ctx, addr2)
|
||||
require.Nil(t, acc2)
|
||||
|
||||
// But it does have a balance
|
||||
s.App.CheckBalance(t, ctx, addr2, coins, s.BankKeeper)
|
||||
|
||||
// Now we send coins back and the account should be created
|
||||
sendMsg = types.NewMsgSend(addr2Str, addr1.String(), coins)
|
||||
res = s.App.SignCheckDeliver(t, ctx, []sdk.Msg{sendMsg}, "", []uint64{0}, []uint64{0}, []cryptotypes.PrivKey{priv2}, "")
|
||||
require.NoError(t, res.Error)
|
||||
|
||||
// Balance has been reduced
|
||||
s.App.CheckBalance(t, ctx, addr2, sdk.NewCoins(), s.BankKeeper)
|
||||
|
||||
// Check that the account was created
|
||||
acc2 = s.AccountKeeper.GetAccount(ctx, addr2)
|
||||
require.NotNil(t, acc2, "account should have been created %s", addr2.String())
|
||||
}
|
||||
570
tests/integration/v2/bank/determinisitic_test.go
Normal file
570
tests/integration/v2/bank/determinisitic_test.go
Normal file
@ -0,0 +1,570 @@
|
||||
package bank
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/cosmos/gogoproto/proto"
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/stretchr/testify/require"
|
||||
"pgregory.net/rapid"
|
||||
|
||||
"cosmossdk.io/core/gas"
|
||||
"cosmossdk.io/depinject"
|
||||
"cosmossdk.io/log"
|
||||
"cosmossdk.io/math"
|
||||
bankkeeper "cosmossdk.io/x/bank/keeper"
|
||||
banktestutil "cosmossdk.io/x/bank/testutil"
|
||||
banktypes "cosmossdk.io/x/bank/types"
|
||||
minttypes "cosmossdk.io/x/mint/types"
|
||||
|
||||
codectestutil "github.com/cosmos/cosmos-sdk/codec/testutil"
|
||||
"github.com/cosmos/cosmos-sdk/tests/integration/v2"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/configurator"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/testdata"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
authtestutil "github.com/cosmos/cosmos-sdk/x/auth/testutil"
|
||||
)
|
||||
|
||||
var (
|
||||
denomRegex = `[a-zA-Z][a-zA-Z0-9/:._-]{2,127}`
|
||||
coin1 = sdk.NewCoin("denom", math.NewInt(10))
|
||||
metadataAtom = banktypes.Metadata{
|
||||
Description: "The native staking token of the Cosmos Hub.",
|
||||
DenomUnits: []*banktypes.DenomUnit{
|
||||
{
|
||||
Denom: "uatom",
|
||||
Exponent: 0,
|
||||
Aliases: []string{"microatom"},
|
||||
},
|
||||
{
|
||||
Denom: "atom",
|
||||
Exponent: 6,
|
||||
Aliases: []string{"ATOM"},
|
||||
},
|
||||
},
|
||||
Base: "uatom",
|
||||
Display: "atom",
|
||||
}
|
||||
)
|
||||
|
||||
type deterministicFixture struct {
|
||||
*testing.T
|
||||
ctx context.Context
|
||||
app *integration.App
|
||||
bankKeeper bankkeeper.Keeper
|
||||
}
|
||||
|
||||
func queryFnFactory[RequestT, ResponseT proto.Message](
|
||||
f *deterministicFixture,
|
||||
) func(RequestT) (ResponseT, error) {
|
||||
return func(req RequestT) (ResponseT, error) {
|
||||
var emptyResponse ResponseT
|
||||
res, err := f.app.Query(f.ctx, 0, req)
|
||||
if err != nil {
|
||||
return emptyResponse, err
|
||||
}
|
||||
castedRes, ok := res.(ResponseT)
|
||||
if !ok {
|
||||
return emptyResponse, fmt.Errorf("unexpected response type: %T", res)
|
||||
}
|
||||
return castedRes, nil
|
||||
}
|
||||
}
|
||||
|
||||
func fundAccount(f *deterministicFixture, addr sdk.AccAddress, coin ...sdk.Coin) {
|
||||
err := banktestutil.FundAccount(f.ctx, f.bankKeeper, addr, sdk.NewCoins(coin...))
|
||||
require.NoError(f.T, err)
|
||||
}
|
||||
|
||||
func getCoin(rt *rapid.T) sdk.Coin {
|
||||
return sdk.NewCoin(
|
||||
rapid.StringMatching(denomRegex).Draw(rt, "denom"),
|
||||
math.NewInt(rapid.Int64Min(1).Draw(rt, "amount")),
|
||||
)
|
||||
}
|
||||
|
||||
func initDeterministicFixture(t *testing.T) *deterministicFixture {
|
||||
t.Helper()
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
acctsModKeeper := authtestutil.NewMockAccountsModKeeper(ctrl)
|
||||
accNum := uint64(0)
|
||||
acctsModKeeper.EXPECT().NextAccountNumber(gomock.Any()).AnyTimes().DoAndReturn(func(ctx context.Context) (
|
||||
uint64, error,
|
||||
) {
|
||||
currentNum := accNum
|
||||
accNum++
|
||||
return currentNum, nil
|
||||
})
|
||||
|
||||
startupConfig := integration.DefaultStartUpConfig(t)
|
||||
startupConfig.GenesisBehavior = integration.Genesis_SKIP
|
||||
diConfig := configurator.NewAppV2Config(
|
||||
configurator.TxModule(),
|
||||
configurator.AuthModule(),
|
||||
configurator.BankModule(),
|
||||
)
|
||||
|
||||
var bankKeeper bankkeeper.Keeper
|
||||
diConfig = depinject.Configs(diConfig, depinject.Supply(acctsModKeeper, log.NewNopLogger()))
|
||||
app, err := integration.NewApp(diConfig, startupConfig, &bankKeeper)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, app)
|
||||
return &deterministicFixture{app: app, bankKeeper: bankKeeper, T: t}
|
||||
}
|
||||
|
||||
func assertNonZeroGas(t *testing.T, gasUsed gas.Gas) {
|
||||
t.Helper()
|
||||
require.NotZero(t, gasUsed)
|
||||
}
|
||||
|
||||
func TestQueryBalance(t *testing.T) {
|
||||
t.Parallel()
|
||||
f := initDeterministicFixture(t)
|
||||
f.ctx = f.app.StateLatestContext(t)
|
||||
gasMeterFactory := integration.GasMeterFactory(f.ctx)
|
||||
queryFn := queryFnFactory[*banktypes.QueryBalanceRequest, *banktypes.QueryBalanceResponse](f)
|
||||
assertBalance := func(coin sdk.Coin) func(t *testing.T, res *banktypes.QueryBalanceResponse) {
|
||||
return func(t *testing.T, res *banktypes.QueryBalanceResponse) {
|
||||
t.Helper()
|
||||
require.Equal(t, coin.Denom, res.Balance.Denom)
|
||||
require.Truef(t, coin.Amount.Equal(res.Balance.Amount),
|
||||
"expected %s, got %s", coin.Amount, res.Balance.Amount)
|
||||
}
|
||||
}
|
||||
|
||||
rapid.Check(t, func(rt *rapid.T) {
|
||||
addr := testdata.AddressGenerator(rt).Draw(rt, "address")
|
||||
coin := getCoin(rt)
|
||||
fundAccount(f, addr, coin)
|
||||
|
||||
addrStr, err := codectestutil.CodecOptions{}.GetAddressCodec().BytesToString(addr)
|
||||
require.NoError(t, err)
|
||||
|
||||
req := banktypes.NewQueryBalanceRequest(addrStr, coin.GetDenom())
|
||||
|
||||
testdata.DeterministicIterationsV2(t, req, gasMeterFactory, queryFn, assertNonZeroGas, assertBalance(coin))
|
||||
})
|
||||
|
||||
fundAccount(f, addr1, coin1)
|
||||
addr1Str, err := codectestutil.CodecOptions{}.GetAddressCodec().BytesToString(addr1)
|
||||
require.NoError(t, err)
|
||||
req := banktypes.NewQueryBalanceRequest(addr1Str, coin1.GetDenom())
|
||||
testdata.DeterministicIterationsV2(t, req, gasMeterFactory, queryFn, assertNonZeroGas, assertBalance(coin1))
|
||||
}
|
||||
|
||||
func TestQueryAllBalances(t *testing.T) {
|
||||
t.Parallel()
|
||||
f := initDeterministicFixture(t)
|
||||
f.ctx = f.app.StateLatestContext(t)
|
||||
gasMeterFactory := integration.GasMeterFactory(f.ctx)
|
||||
addressCodec := codectestutil.CodecOptions{}.GetAddressCodec()
|
||||
queryFn := queryFnFactory[*banktypes.QueryAllBalancesRequest, *banktypes.QueryAllBalancesResponse](f)
|
||||
|
||||
rapid.Check(t, func(rt *rapid.T) {
|
||||
addr := testdata.AddressGenerator(rt).Draw(rt, "address")
|
||||
numCoins := rapid.IntRange(1, 10).Draw(rt, "num-count")
|
||||
coins := make(sdk.Coins, 0, numCoins)
|
||||
|
||||
addrStr, err := addressCodec.BytesToString(addr)
|
||||
require.NoError(t, err)
|
||||
|
||||
for i := 0; i < numCoins; i++ {
|
||||
coin := getCoin(rt)
|
||||
if exists, _ := coins.Find(coin.Denom); exists {
|
||||
t.Skip("duplicate denom")
|
||||
}
|
||||
// NewCoins sorts the denoms
|
||||
coins = sdk.NewCoins(append(coins, coin)...)
|
||||
}
|
||||
|
||||
fundAccount(f, addr, coins...)
|
||||
|
||||
req := banktypes.NewQueryAllBalancesRequest(
|
||||
addrStr, testdata.PaginationGenerator(rt, uint64(numCoins)).Draw(rt, "pagination"), false)
|
||||
testdata.DeterministicIterationsV2(t, req, gasMeterFactory, queryFn, assertNonZeroGas, nil)
|
||||
})
|
||||
|
||||
coins := sdk.NewCoins(
|
||||
sdk.NewCoin("stake", math.NewInt(10)),
|
||||
sdk.NewCoin("denom", math.NewInt(100)),
|
||||
)
|
||||
|
||||
fundAccount(f, addr1, coins...)
|
||||
addr1Str, err := addressCodec.BytesToString(addr1)
|
||||
require.NoError(t, err)
|
||||
|
||||
req := banktypes.NewQueryAllBalancesRequest(addr1Str, nil, false)
|
||||
testdata.DeterministicIterationsV2(t, req, gasMeterFactory, queryFn, assertNonZeroGas, nil)
|
||||
}
|
||||
|
||||
func TestQuerySpendableBalances(t *testing.T) {
|
||||
t.Parallel()
|
||||
f := initDeterministicFixture(t)
|
||||
f.ctx = f.app.StateLatestContext(t)
|
||||
gasMeterFactory := integration.GasMeterFactory(f.ctx)
|
||||
queryFn := queryFnFactory[*banktypes.QuerySpendableBalancesRequest, *banktypes.QuerySpendableBalancesResponse](f)
|
||||
|
||||
rapid.Check(t, func(rt *rapid.T) {
|
||||
addr := testdata.AddressGenerator(rt).Draw(rt, "address")
|
||||
addrStr, err := codectestutil.CodecOptions{}.GetAddressCodec().BytesToString(addr)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Denoms must be unique, otherwise sdk.NewCoins will panic.
|
||||
denoms := rapid.SliceOfNDistinct(rapid.StringMatching(denomRegex), 1, 10, rapid.ID[string]).Draw(rt, "denoms")
|
||||
coins := make(sdk.Coins, 0, len(denoms))
|
||||
for _, denom := range denoms {
|
||||
coin := sdk.NewCoin(
|
||||
denom,
|
||||
math.NewInt(rapid.Int64Min(1).Draw(rt, "amount")),
|
||||
)
|
||||
|
||||
// NewCoins sorts the denoms
|
||||
coins = sdk.NewCoins(append(coins, coin)...)
|
||||
}
|
||||
|
||||
err = banktestutil.FundAccount(f.ctx, f.bankKeeper, addr, coins)
|
||||
require.NoError(t, err)
|
||||
|
||||
req := banktypes.NewQuerySpendableBalancesRequest(addrStr, testdata.PaginationGenerator(rt, uint64(len(denoms))).Draw(rt, "pagination"))
|
||||
testdata.DeterministicIterationsV2(t, req, gasMeterFactory, queryFn, assertNonZeroGas, nil)
|
||||
})
|
||||
|
||||
coins := sdk.NewCoins(
|
||||
sdk.NewCoin("stake", math.NewInt(10)),
|
||||
sdk.NewCoin("denom", math.NewInt(100)),
|
||||
)
|
||||
|
||||
err := banktestutil.FundAccount(f.ctx, f.bankKeeper, addr1, coins)
|
||||
require.NoError(t, err)
|
||||
|
||||
addr1Str, err := codectestutil.CodecOptions{}.GetAddressCodec().BytesToString(addr1)
|
||||
require.NoError(t, err)
|
||||
|
||||
req := banktypes.NewQuerySpendableBalancesRequest(addr1Str, nil)
|
||||
testdata.DeterministicIterationsV2(t, req, gasMeterFactory, queryFn, assertNonZeroGas, nil)
|
||||
}
|
||||
|
||||
func TestQueryTotalSupply(t *testing.T) {
|
||||
t.Parallel()
|
||||
f := initDeterministicFixture(t)
|
||||
f.ctx = f.app.StateLatestContext(t)
|
||||
gasMeterFactory := integration.GasMeterFactory(f.ctx)
|
||||
queryFn := queryFnFactory[*banktypes.QueryTotalSupplyRequest, *banktypes.QueryTotalSupplyResponse](f)
|
||||
|
||||
res, err := queryFn(&banktypes.QueryTotalSupplyRequest{})
|
||||
require.NoError(t, err)
|
||||
initialSupply := res.GetSupply()
|
||||
|
||||
rapid.Check(t, func(rt *rapid.T) {
|
||||
numCoins := rapid.IntRange(1, 3).Draw(rt, "num-count")
|
||||
coins := make(sdk.Coins, 0, numCoins)
|
||||
|
||||
for i := 0; i < numCoins; i++ {
|
||||
coin := sdk.NewCoin(
|
||||
rapid.StringMatching(denomRegex).Draw(rt, "denom"),
|
||||
math.NewInt(rapid.Int64Min(1).Draw(rt, "amount")),
|
||||
)
|
||||
|
||||
coins = coins.Add(coin)
|
||||
}
|
||||
|
||||
require.NoError(t, f.bankKeeper.MintCoins(f.ctx, minttypes.ModuleName, coins))
|
||||
|
||||
initialSupply = initialSupply.Add(coins...)
|
||||
|
||||
req := &banktypes.QueryTotalSupplyRequest{
|
||||
Pagination: testdata.PaginationGenerator(rt, uint64(len(initialSupply))).Draw(rt, "pagination"),
|
||||
}
|
||||
|
||||
testdata.DeterministicIterationsV2(t, req, gasMeterFactory, queryFn, assertNonZeroGas, nil)
|
||||
})
|
||||
|
||||
f = initDeterministicFixture(t) // reset
|
||||
f.ctx = f.app.StateLatestContext(t)
|
||||
gasMeterFactory = integration.GasMeterFactory(f.ctx)
|
||||
queryFn = queryFnFactory[*banktypes.QueryTotalSupplyRequest, *banktypes.QueryTotalSupplyResponse](f)
|
||||
|
||||
coins := sdk.NewCoins(
|
||||
sdk.NewCoin("foo", math.NewInt(10)),
|
||||
sdk.NewCoin("bar", math.NewInt(100)),
|
||||
)
|
||||
|
||||
require.NoError(t, f.bankKeeper.MintCoins(f.ctx, minttypes.ModuleName, coins))
|
||||
|
||||
req := &banktypes.QueryTotalSupplyRequest{}
|
||||
testdata.DeterministicIterationsV2(t, req, gasMeterFactory, queryFn, assertNonZeroGas, nil)
|
||||
}
|
||||
|
||||
func TestQueryTotalSupplyOf(t *testing.T) {
|
||||
t.Parallel()
|
||||
f := initDeterministicFixture(t)
|
||||
f.ctx = f.app.StateLatestContext(t)
|
||||
gasMeterFactory := integration.GasMeterFactory(f.ctx)
|
||||
queryFn := queryFnFactory[*banktypes.QuerySupplyOfRequest, *banktypes.QuerySupplyOfResponse](f)
|
||||
|
||||
rapid.Check(t, func(rt *rapid.T) {
|
||||
coin := sdk.NewCoin(
|
||||
rapid.StringMatching(denomRegex).Draw(rt, "denom"),
|
||||
math.NewInt(rapid.Int64Min(1).Draw(rt, "amount")),
|
||||
)
|
||||
|
||||
require.NoError(t, f.bankKeeper.MintCoins(f.ctx, minttypes.ModuleName, sdk.NewCoins(coin)))
|
||||
|
||||
req := &banktypes.QuerySupplyOfRequest{Denom: coin.GetDenom()}
|
||||
testdata.DeterministicIterationsV2(t, req, gasMeterFactory, queryFn, assertNonZeroGas, nil)
|
||||
})
|
||||
|
||||
coin := sdk.NewCoin("bar", math.NewInt(100))
|
||||
|
||||
require.NoError(t, f.bankKeeper.MintCoins(f.ctx, minttypes.ModuleName, sdk.NewCoins(coin)))
|
||||
req := &banktypes.QuerySupplyOfRequest{Denom: coin.GetDenom()}
|
||||
testdata.DeterministicIterationsV2(t, req, gasMeterFactory, queryFn, assertNonZeroGas, nil)
|
||||
}
|
||||
|
||||
func TestQueryParams(t *testing.T) {
|
||||
t.Parallel()
|
||||
f := initDeterministicFixture(t)
|
||||
f.ctx = f.app.StateLatestContext(t)
|
||||
gasMeterFactory := integration.GasMeterFactory(f.ctx)
|
||||
queryFn := queryFnFactory[*banktypes.QueryParamsRequest, *banktypes.QueryParamsResponse](f)
|
||||
|
||||
rapid.Check(t, func(rt *rapid.T) {
|
||||
enabledStatus := banktypes.SendEnabled{
|
||||
Denom: rapid.StringMatching(denomRegex).Draw(rt, "denom"),
|
||||
Enabled: rapid.Bool().Draw(rt, "status"),
|
||||
}
|
||||
|
||||
params := banktypes.Params{
|
||||
SendEnabled: []*banktypes.SendEnabled{&enabledStatus},
|
||||
DefaultSendEnabled: rapid.Bool().Draw(rt, "send"),
|
||||
}
|
||||
|
||||
err := f.bankKeeper.SetParams(f.ctx, params)
|
||||
require.NoError(t, err)
|
||||
|
||||
req := &banktypes.QueryParamsRequest{}
|
||||
testdata.DeterministicIterationsV2(t, req, gasMeterFactory, queryFn, assertNonZeroGas, nil)
|
||||
})
|
||||
|
||||
enabledStatus := banktypes.SendEnabled{
|
||||
Denom: "denom",
|
||||
Enabled: true,
|
||||
}
|
||||
|
||||
params := banktypes.Params{
|
||||
SendEnabled: []*banktypes.SendEnabled{&enabledStatus},
|
||||
DefaultSendEnabled: false,
|
||||
}
|
||||
|
||||
err := f.bankKeeper.SetParams(f.ctx, params)
|
||||
require.NoError(t, err)
|
||||
req := &banktypes.QueryParamsRequest{}
|
||||
testdata.DeterministicIterationsV2(t, req, gasMeterFactory, queryFn, assertNonZeroGas, nil)
|
||||
}
|
||||
|
||||
func createAndReturnMetadatas(t *rapid.T, count int) []banktypes.Metadata {
|
||||
denomsMetadata := make([]banktypes.Metadata, 0, count)
|
||||
for i := 0; i < count; i++ {
|
||||
|
||||
denom := rapid.StringMatching(denomRegex).Draw(t, "denom")
|
||||
|
||||
aliases := rapid.SliceOf(rapid.String()).Draw(t, "aliases")
|
||||
// In the GRPC server code, empty arrays are returned as nil
|
||||
if len(aliases) == 0 {
|
||||
aliases = nil
|
||||
}
|
||||
|
||||
metadata := banktypes.Metadata{
|
||||
Description: rapid.StringN(1, 100, 100).Draw(t, "desc"),
|
||||
DenomUnits: []*banktypes.DenomUnit{
|
||||
{
|
||||
Denom: denom,
|
||||
Exponent: rapid.Uint32().Draw(t, "exponent"),
|
||||
Aliases: aliases,
|
||||
},
|
||||
},
|
||||
Base: denom,
|
||||
Display: denom,
|
||||
Name: rapid.String().Draw(t, "name"),
|
||||
Symbol: rapid.String().Draw(t, "symbol"),
|
||||
URI: rapid.String().Draw(t, "uri"),
|
||||
URIHash: rapid.String().Draw(t, "uri-hash"),
|
||||
}
|
||||
|
||||
denomsMetadata = append(denomsMetadata, metadata)
|
||||
}
|
||||
|
||||
return denomsMetadata
|
||||
}
|
||||
|
||||
func TestDenomsMetadata(t *testing.T) {
|
||||
t.Parallel()
|
||||
f := initDeterministicFixture(t)
|
||||
f.ctx = f.app.StateLatestContext(t)
|
||||
gasMeterFactory := integration.GasMeterFactory(f.ctx)
|
||||
queryFn := queryFnFactory[*banktypes.QueryDenomsMetadataRequest, *banktypes.QueryDenomsMetadataResponse](f)
|
||||
|
||||
rapid.Check(t, func(rt *rapid.T) {
|
||||
count := rapid.IntRange(1, 3).Draw(rt, "count")
|
||||
denomsMetadata := createAndReturnMetadatas(rt, count)
|
||||
require.True(t, len(denomsMetadata) == count)
|
||||
|
||||
for i := 0; i < count; i++ {
|
||||
f.bankKeeper.SetDenomMetaData(f.ctx, denomsMetadata[i])
|
||||
}
|
||||
|
||||
req := &banktypes.QueryDenomsMetadataRequest{
|
||||
Pagination: testdata.PaginationGenerator(rt, uint64(count)).Draw(rt, "pagination"),
|
||||
}
|
||||
|
||||
testdata.DeterministicIterationsV2(t, req, gasMeterFactory, queryFn, assertNonZeroGas, nil)
|
||||
})
|
||||
|
||||
require.NoError(t, f.app.Close())
|
||||
|
||||
f = initDeterministicFixture(t) // reset
|
||||
f.ctx = f.app.StateLatestContext(t)
|
||||
gasMeterFactory = integration.GasMeterFactory(f.ctx)
|
||||
queryFn = queryFnFactory[*banktypes.QueryDenomsMetadataRequest, *banktypes.QueryDenomsMetadataResponse](f)
|
||||
|
||||
f.bankKeeper.SetDenomMetaData(f.ctx, metadataAtom)
|
||||
|
||||
req := &banktypes.QueryDenomsMetadataRequest{}
|
||||
testdata.DeterministicIterationsV2(t, req, gasMeterFactory, queryFn, assertNonZeroGas, nil)
|
||||
}
|
||||
|
||||
func TestDenomMetadata(t *testing.T) {
|
||||
t.Parallel()
|
||||
f := initDeterministicFixture(t)
|
||||
f.ctx = f.app.StateLatestContext(t)
|
||||
gasMeterFactory := integration.GasMeterFactory(f.ctx)
|
||||
queryFn := queryFnFactory[*banktypes.QueryDenomMetadataRequest, *banktypes.QueryDenomMetadataResponse](f)
|
||||
|
||||
rapid.Check(t, func(rt *rapid.T) {
|
||||
denomMetadata := createAndReturnMetadatas(rt, 1)
|
||||
require.True(t, len(denomMetadata) == 1)
|
||||
f.bankKeeper.SetDenomMetaData(f.ctx, denomMetadata[0])
|
||||
|
||||
req := &banktypes.QueryDenomMetadataRequest{
|
||||
Denom: denomMetadata[0].Base,
|
||||
}
|
||||
|
||||
testdata.DeterministicIterationsV2(t, req, gasMeterFactory, queryFn, assertNonZeroGas, nil)
|
||||
})
|
||||
|
||||
f.bankKeeper.SetDenomMetaData(f.ctx, metadataAtom)
|
||||
|
||||
req := &banktypes.QueryDenomMetadataRequest{
|
||||
Denom: metadataAtom.Base,
|
||||
}
|
||||
|
||||
testdata.DeterministicIterationsV2(t, req, gasMeterFactory, queryFn, assertNonZeroGas, nil)
|
||||
}
|
||||
|
||||
func TestSendEnabled(t *testing.T) {
|
||||
t.Parallel()
|
||||
f := initDeterministicFixture(t)
|
||||
f.ctx = f.app.StateLatestContext(t)
|
||||
gasMeterFactory := integration.GasMeterFactory(f.ctx)
|
||||
queryFn := queryFnFactory[*banktypes.QuerySendEnabledRequest, *banktypes.QuerySendEnabledResponse](f)
|
||||
allDenoms := []string{}
|
||||
|
||||
rapid.Check(t, func(rt *rapid.T) {
|
||||
count := rapid.IntRange(0, 10).Draw(rt, "count")
|
||||
denoms := make([]string, 0, count)
|
||||
|
||||
for i := 0; i < count; i++ {
|
||||
coin := banktypes.SendEnabled{
|
||||
Denom: rapid.StringMatching(denomRegex).Draw(rt, "denom"),
|
||||
Enabled: rapid.Bool().Draw(rt, "enabled-status"),
|
||||
}
|
||||
|
||||
f.bankKeeper.SetSendEnabled(f.ctx, coin.Denom, coin.Enabled)
|
||||
denoms = append(denoms, coin.Denom)
|
||||
}
|
||||
|
||||
allDenoms = append(allDenoms, denoms...)
|
||||
|
||||
req := &banktypes.QuerySendEnabledRequest{
|
||||
Denoms: denoms,
|
||||
// Pagination is only taken into account when `denoms` is an empty array
|
||||
Pagination: testdata.PaginationGenerator(rt, uint64(len(allDenoms))).Draw(rt, "pagination"),
|
||||
}
|
||||
testdata.DeterministicIterationsV2(t, req, gasMeterFactory, queryFn, assertNonZeroGas, nil)
|
||||
})
|
||||
|
||||
coin1 := banktypes.SendEnabled{
|
||||
Denom: "falsecoin",
|
||||
Enabled: false,
|
||||
}
|
||||
coin2 := banktypes.SendEnabled{
|
||||
Denom: "truecoin",
|
||||
Enabled: true,
|
||||
}
|
||||
|
||||
f.bankKeeper.SetSendEnabled(f.ctx, coin1.Denom, false)
|
||||
f.bankKeeper.SetSendEnabled(f.ctx, coin2.Denom, true)
|
||||
|
||||
req := &banktypes.QuerySendEnabledRequest{
|
||||
Denoms: []string{coin1.GetDenom(), coin2.GetDenom()},
|
||||
}
|
||||
|
||||
testdata.DeterministicIterationsV2(t, req, gasMeterFactory, queryFn, assertNonZeroGas, nil)
|
||||
}
|
||||
|
||||
func TestDenomOwners(t *testing.T) {
|
||||
t.Parallel()
|
||||
f := initDeterministicFixture(t)
|
||||
f.ctx = f.app.StateLatestContext(t)
|
||||
gasMeterFactory := integration.GasMeterFactory(f.ctx)
|
||||
queryFn := queryFnFactory[*banktypes.QueryDenomOwnersRequest, *banktypes.QueryDenomOwnersResponse](f)
|
||||
|
||||
rapid.Check(t, func(rt *rapid.T) {
|
||||
denom := rapid.StringMatching(denomRegex).Draw(rt, "denom")
|
||||
numAddr := rapid.IntRange(1, 10).Draw(rt, "number-address")
|
||||
for i := 0; i < numAddr; i++ {
|
||||
addr := testdata.AddressGenerator(rt).Draw(rt, "address")
|
||||
|
||||
coin := sdk.NewCoin(
|
||||
denom,
|
||||
math.NewInt(rapid.Int64Min(1).Draw(rt, "amount")),
|
||||
)
|
||||
|
||||
err := banktestutil.FundAccount(f.ctx, f.bankKeeper, addr, sdk.NewCoins(coin))
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
req := &banktypes.QueryDenomOwnersRequest{
|
||||
Denom: denom,
|
||||
Pagination: testdata.PaginationGenerator(rt, uint64(numAddr)).Draw(rt, "pagination"),
|
||||
}
|
||||
testdata.DeterministicIterationsV2(t, req, gasMeterFactory, queryFn, assertNonZeroGas, nil)
|
||||
})
|
||||
|
||||
denomOwners := []*banktypes.DenomOwner{
|
||||
{
|
||||
Address: "cosmos1qg65a9q6k2sqq7l3ycp428sqqpmqcucgzze299",
|
||||
Balance: coin1,
|
||||
},
|
||||
{
|
||||
Address: "cosmos1qglnsqgpq48l7qqzgs8qdshr6fh3gqq9ej3qut",
|
||||
Balance: coin1,
|
||||
},
|
||||
}
|
||||
|
||||
for i := 0; i < len(denomOwners); i++ {
|
||||
addr, err := sdk.AccAddressFromBech32(denomOwners[i].Address)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = banktestutil.FundAccount(f.ctx, f.bankKeeper, addr, sdk.NewCoins(coin1))
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
req := &banktypes.QueryDenomOwnersRequest{
|
||||
Denom: coin1.GetDenom(),
|
||||
}
|
||||
testdata.DeterministicIterationsV2(t, req, gasMeterFactory, queryFn, assertNonZeroGas, nil)
|
||||
}
|
||||
182
tests/integration/v2/genesis.go
Normal file
182
tests/integration/v2/genesis.go
Normal file
@ -0,0 +1,182 @@
|
||||
package integration
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
cmttypes "github.com/cometbft/cometbft/types"
|
||||
|
||||
sdkmath "cosmossdk.io/math"
|
||||
banktypes "cosmossdk.io/x/bank/types"
|
||||
stakingtypes "cosmossdk.io/x/staking/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/mock"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/tx"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
)
|
||||
|
||||
// genesisStateWithValSet returns a new genesis state with the validator set
|
||||
func genesisStateWithValSet(
|
||||
codec codec.Codec,
|
||||
genesisState map[string]json.RawMessage,
|
||||
valSet *cmttypes.ValidatorSet,
|
||||
genAccs []authtypes.GenesisAccount,
|
||||
balances ...banktypes.Balance,
|
||||
) (map[string]json.RawMessage, error) {
|
||||
if len(genAccs) == 0 {
|
||||
return nil, errors.New("no genesis accounts provided")
|
||||
}
|
||||
// set genesis accounts
|
||||
authGenesis := authtypes.NewGenesisState(authtypes.DefaultParams(), genAccs)
|
||||
genesisState[authtypes.ModuleName] = codec.MustMarshalJSON(authGenesis)
|
||||
|
||||
validators := make([]stakingtypes.Validator, 0, len(valSet.Validators))
|
||||
delegations := make([]stakingtypes.Delegation, 0, len(valSet.Validators))
|
||||
|
||||
bondAmt := sdk.DefaultPowerReduction
|
||||
|
||||
for _, val := range valSet.Validators {
|
||||
pk, err := cryptocodec.FromCmtPubKeyInterface(val.PubKey)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to convert pubkey: %w", err)
|
||||
}
|
||||
|
||||
pkAny, err := codectypes.NewAnyWithValue(pk)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create new any: %w", err)
|
||||
}
|
||||
|
||||
validator := stakingtypes.Validator{
|
||||
OperatorAddress: sdk.ValAddress(val.Address).String(),
|
||||
ConsensusPubkey: pkAny,
|
||||
Jailed: false,
|
||||
Status: stakingtypes.Bonded,
|
||||
Tokens: bondAmt,
|
||||
DelegatorShares: sdkmath.LegacyOneDec(),
|
||||
Description: stakingtypes.Description{},
|
||||
UnbondingHeight: int64(0),
|
||||
UnbondingTime: time.Unix(0, 0).UTC(),
|
||||
Commission: stakingtypes.NewCommission(
|
||||
sdkmath.LegacyZeroDec(),
|
||||
sdkmath.LegacyZeroDec(),
|
||||
sdkmath.LegacyZeroDec(),
|
||||
),
|
||||
MinSelfDelegation: sdkmath.ZeroInt(),
|
||||
}
|
||||
validators = append(validators, validator)
|
||||
delegations = append(
|
||||
delegations,
|
||||
stakingtypes.NewDelegation(
|
||||
genAccs[0].GetAddress().String(),
|
||||
sdk.ValAddress(val.Address).String(),
|
||||
sdkmath.LegacyOneDec(),
|
||||
),
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
// set validators and delegations
|
||||
stakingGenesis := stakingtypes.NewGenesisState(
|
||||
stakingtypes.DefaultParams(),
|
||||
validators,
|
||||
delegations,
|
||||
)
|
||||
genesisState[stakingtypes.ModuleName] = codec.MustMarshalJSON(
|
||||
stakingGenesis,
|
||||
)
|
||||
|
||||
totalSupply := sdk.NewCoins()
|
||||
for _, b := range balances {
|
||||
// add genesis acc tokens to total supply
|
||||
totalSupply = totalSupply.Add(b.Coins...)
|
||||
}
|
||||
|
||||
for range delegations {
|
||||
// add delegated tokens to total supply
|
||||
totalSupply = totalSupply.Add(
|
||||
sdk.NewCoin(sdk.DefaultBondDenom, bondAmt),
|
||||
)
|
||||
}
|
||||
|
||||
// add bonded amount to bonded pool module account
|
||||
balances = append(balances, banktypes.Balance{
|
||||
Address: authtypes.NewModuleAddress(stakingtypes.BondedPoolName).
|
||||
String(),
|
||||
Coins: sdk.Coins{sdk.NewCoin(sdk.DefaultBondDenom, bondAmt)},
|
||||
})
|
||||
|
||||
// update total supply
|
||||
bankGenesis := banktypes.NewGenesisState(
|
||||
banktypes.DefaultGenesisState().Params,
|
||||
balances,
|
||||
totalSupply,
|
||||
[]banktypes.Metadata{},
|
||||
[]banktypes.SendEnabled{},
|
||||
)
|
||||
genesisState[banktypes.ModuleName] = codec.MustMarshalJSON(bankGenesis)
|
||||
|
||||
return genesisState, nil
|
||||
}
|
||||
|
||||
// CreateRandomValidatorSet creates a validator set with one random validator
|
||||
func CreateRandomValidatorSet() (*cmttypes.ValidatorSet, error) {
|
||||
privVal := mock.NewPV()
|
||||
pubKey, err := privVal.GetPubKey()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get pub key: %w", err)
|
||||
}
|
||||
|
||||
// create validator set with single validator
|
||||
validator := cmttypes.NewValidator(pubKey, 1)
|
||||
|
||||
return cmttypes.NewValidatorSet([]*cmttypes.Validator{validator}), nil
|
||||
}
|
||||
|
||||
type GenesisAccount struct {
|
||||
authtypes.GenesisAccount
|
||||
Coins sdk.Coins
|
||||
}
|
||||
|
||||
type genesisTxCodec struct {
|
||||
tx.ConfigOptions
|
||||
}
|
||||
|
||||
// Decode implements transaction.Codec.
|
||||
func (t *genesisTxCodec) Decode(bz []byte) (stateMachineTx, error) {
|
||||
var out stateMachineTx
|
||||
tx, err := t.ProtoDecoder(bz)
|
||||
if err != nil {
|
||||
return out, err
|
||||
}
|
||||
|
||||
var ok bool
|
||||
out, ok = tx.(stateMachineTx)
|
||||
if !ok {
|
||||
return out, errors.New("unexpected Tx type")
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// DecodeJSON implements transaction.Codec.
|
||||
func (t *genesisTxCodec) DecodeJSON(bz []byte) (stateMachineTx, error) {
|
||||
var out stateMachineTx
|
||||
tx, err := t.JSONDecoder(bz)
|
||||
if err != nil {
|
||||
return out, err
|
||||
}
|
||||
|
||||
var ok bool
|
||||
out, ok = tx.(stateMachineTx)
|
||||
if !ok {
|
||||
return out, errors.New("unexpected Tx type")
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
119
tests/integration/v2/services.go
Normal file
119
tests/integration/v2/services.go
Normal file
@ -0,0 +1,119 @@
|
||||
package integration
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"cosmossdk.io/core/comet"
|
||||
"cosmossdk.io/core/event"
|
||||
"cosmossdk.io/core/gas"
|
||||
"cosmossdk.io/core/server"
|
||||
corestore "cosmossdk.io/core/store"
|
||||
"cosmossdk.io/core/transaction"
|
||||
stfgas "cosmossdk.io/server/v2/stf/gas"
|
||||
)
|
||||
|
||||
func (c cometServiceImpl) CometInfo(context.Context) comet.Info {
|
||||
return comet.Info{}
|
||||
}
|
||||
|
||||
// Services
|
||||
|
||||
var _ server.DynamicConfig = &dynamicConfigImpl{}
|
||||
|
||||
type dynamicConfigImpl struct {
|
||||
homeDir string
|
||||
}
|
||||
|
||||
func (d *dynamicConfigImpl) Get(key string) any {
|
||||
return d.GetString(key)
|
||||
}
|
||||
|
||||
func (d *dynamicConfigImpl) GetString(key string) string {
|
||||
switch key {
|
||||
case "home":
|
||||
return d.homeDir
|
||||
case "store.app-db-backend":
|
||||
return "goleveldb"
|
||||
case "server.minimum-gas-prices":
|
||||
return "0stake"
|
||||
default:
|
||||
panic(fmt.Sprintf("unknown key: %s", key))
|
||||
}
|
||||
}
|
||||
|
||||
func (d *dynamicConfigImpl) UnmarshalSub(string, any) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
var _ comet.Service = &cometServiceImpl{}
|
||||
|
||||
type cometServiceImpl struct{}
|
||||
|
||||
type storeService struct {
|
||||
actor []byte
|
||||
executionService corestore.KVStoreService
|
||||
}
|
||||
|
||||
type contextKeyType struct{}
|
||||
|
||||
var contextKey = contextKeyType{}
|
||||
|
||||
type integrationContext struct {
|
||||
state corestore.WriterMap
|
||||
gasMeter gas.Meter
|
||||
}
|
||||
|
||||
func GasMeterFromContext(ctx context.Context) gas.Meter {
|
||||
iCtx, ok := ctx.Value(contextKey).(*integrationContext)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
return iCtx.gasMeter
|
||||
}
|
||||
|
||||
func GasMeterFactory(ctx context.Context) func() gas.Meter {
|
||||
return func() gas.Meter {
|
||||
return GasMeterFromContext(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
func (s storeService) OpenKVStore(ctx context.Context) corestore.KVStore {
|
||||
const gasLimit = 100_000
|
||||
iCtx, ok := ctx.Value(contextKey).(*integrationContext)
|
||||
if !ok {
|
||||
return s.executionService.OpenKVStore(ctx)
|
||||
}
|
||||
|
||||
iCtx.gasMeter = stfgas.NewMeter(gasLimit)
|
||||
writerMap := stfgas.NewMeteredWriterMap(stfgas.DefaultConfig, iCtx.gasMeter, iCtx.state)
|
||||
state, err := writerMap.GetWriter(s.actor)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return state
|
||||
}
|
||||
|
||||
var (
|
||||
_ event.Service = &eventService{}
|
||||
_ event.Manager = &eventManager{}
|
||||
)
|
||||
|
||||
type eventService struct{}
|
||||
|
||||
// EventManager implements event.Service.
|
||||
func (e *eventService) EventManager(context.Context) event.Manager {
|
||||
return &eventManager{}
|
||||
}
|
||||
|
||||
type eventManager struct{}
|
||||
|
||||
// Emit implements event.Manager.
|
||||
func (e *eventManager) Emit(event transaction.Msg) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// EmitKV implements event.Manager.
|
||||
func (e *eventManager) EmitKV(eventType string, attrs ...event.Attribute) error {
|
||||
return nil
|
||||
}
|
||||
@ -3,6 +3,7 @@ package configurator
|
||||
import (
|
||||
accountsmodulev1 "cosmossdk.io/api/cosmos/accounts/module/v1"
|
||||
runtimev1alpha1 "cosmossdk.io/api/cosmos/app/runtime/v1alpha1"
|
||||
runtimev2 "cosmossdk.io/api/cosmos/app/runtime/v2"
|
||||
appv1alpha1 "cosmossdk.io/api/cosmos/app/v1alpha1"
|
||||
authmodulev1 "cosmossdk.io/api/cosmos/auth/module/v1"
|
||||
authzmodulev1 "cosmossdk.io/api/cosmos/authz/module/v1"
|
||||
@ -440,3 +441,71 @@ func NewAppConfig(opts ...ModuleOption) depinject.Config {
|
||||
|
||||
return appconfig.Compose(&appv1alpha1.Config{Modules: modules})
|
||||
}
|
||||
|
||||
func NewAppV2Config(opts ...ModuleOption) depinject.Config {
|
||||
cfg := defaultConfig()
|
||||
for _, opt := range opts {
|
||||
opt(cfg)
|
||||
}
|
||||
|
||||
preBlockers := make([]string, 0)
|
||||
beginBlockers := make([]string, 0)
|
||||
endBlockers := make([]string, 0)
|
||||
initGenesis := make([]string, 0)
|
||||
overrides := make([]*runtimev2.StoreKeyConfig, 0)
|
||||
|
||||
for _, s := range cfg.PreBlockersOrder {
|
||||
if _, ok := cfg.ModuleConfigs[s]; ok {
|
||||
preBlockers = append(preBlockers, s)
|
||||
}
|
||||
}
|
||||
|
||||
for _, s := range cfg.BeginBlockersOrder {
|
||||
if _, ok := cfg.ModuleConfigs[s]; ok {
|
||||
beginBlockers = append(beginBlockers, s)
|
||||
}
|
||||
}
|
||||
|
||||
for _, s := range cfg.EndBlockersOrder {
|
||||
if _, ok := cfg.ModuleConfigs[s]; ok {
|
||||
endBlockers = append(endBlockers, s)
|
||||
}
|
||||
}
|
||||
|
||||
for _, s := range cfg.InitGenesisOrder {
|
||||
if _, ok := cfg.ModuleConfigs[s]; ok {
|
||||
initGenesis = append(initGenesis, s)
|
||||
}
|
||||
}
|
||||
|
||||
if _, ok := cfg.ModuleConfigs[testutil.AuthModuleName]; ok {
|
||||
overrides = append(overrides, &runtimev2.StoreKeyConfig{ModuleName: testutil.AuthModuleName, KvStoreKey: "acc"})
|
||||
}
|
||||
|
||||
runtimeConfig := &runtimev2.Module{
|
||||
AppName: "TestApp",
|
||||
PreBlockers: preBlockers,
|
||||
BeginBlockers: beginBlockers,
|
||||
EndBlockers: endBlockers,
|
||||
OverrideStoreKeys: overrides,
|
||||
GasConfig: &runtimev2.GasConfig{
|
||||
ValidateTxGasLimit: 100_000,
|
||||
QueryGasLimit: 100_000,
|
||||
SimulationGasLimit: 100_000,
|
||||
},
|
||||
}
|
||||
if cfg.setInitGenesis {
|
||||
runtimeConfig.InitGenesis = initGenesis
|
||||
}
|
||||
|
||||
modules := []*appv1alpha1.ModuleConfig{{
|
||||
Name: "runtime",
|
||||
Config: appconfig.WrapAny(runtimeConfig),
|
||||
}}
|
||||
|
||||
for _, m := range cfg.ModuleConfigs {
|
||||
modules = append(modules, m)
|
||||
}
|
||||
|
||||
return appconfig.Compose(&appv1alpha1.Config{Modules: modules})
|
||||
}
|
||||
|
||||
34
testutil/testdata/grpc_query.go
vendored
34
testutil/testdata/grpc_query.go
vendored
@ -5,13 +5,15 @@ import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/cosmos/gogoproto/proto"
|
||||
gogoprotoany "github.com/cosmos/gogoproto/types/any"
|
||||
"github.com/cosmos/gogoproto/types/any/test"
|
||||
|
||||
"github.com/cosmos/gogoproto/proto"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/grpc"
|
||||
"gotest.tools/v3/assert"
|
||||
|
||||
"cosmossdk.io/core/gas"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
@ -84,6 +86,7 @@ func DeterministicIterations[request, response proto.Message](
|
||||
if gasOverwrite { // to handle regressions, i.e. check that gas consumption didn't change
|
||||
gasConsumed = ctx.GasMeter().GasConsumed() - before
|
||||
}
|
||||
t.Logf("gas consumed: %d", gasConsumed)
|
||||
|
||||
for i := 0; i < iterCount; i++ {
|
||||
before := ctx.GasMeter().GasConsumed()
|
||||
@ -93,3 +96,30 @@ func DeterministicIterations[request, response proto.Message](
|
||||
assert.DeepEqual(t, res, prevRes)
|
||||
}
|
||||
}
|
||||
|
||||
func DeterministicIterationsV2[request, response proto.Message](
|
||||
t *testing.T,
|
||||
req request,
|
||||
meterFn func() gas.Meter,
|
||||
queryFn func(request) (response, error),
|
||||
assertGas func(*testing.T, gas.Gas),
|
||||
assertResponse func(*testing.T, response),
|
||||
) {
|
||||
t.Helper()
|
||||
prevRes, err := queryFn(req)
|
||||
gasMeter := meterFn()
|
||||
gasConsumed := gasMeter.Consumed()
|
||||
require.NoError(t, err)
|
||||
assertGas(t, gasConsumed)
|
||||
|
||||
for i := 0; i < iterCount; i++ {
|
||||
res, err := queryFn(req)
|
||||
require.NoError(t, err)
|
||||
sameGas := gasMeter.Consumed()
|
||||
require.Equal(t, gasConsumed, sameGas)
|
||||
require.Equal(t, res, prevRes)
|
||||
if assertResponse != nil {
|
||||
assertResponse(t, res)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,8 +66,7 @@ func newMockContext(t *testing.T) (context.Context, store.KVStoreService) {
|
||||
)
|
||||
}
|
||||
|
||||
type transactionService struct {
|
||||
}
|
||||
type transactionService struct{}
|
||||
|
||||
func (t transactionService) ExecMode(ctx context.Context) transaction.ExecMode {
|
||||
return transaction.ExecModeFinalize
|
||||
|
||||
Loading…
Reference in New Issue
Block a user