From d00699bcca47e669092886ddd77a44329774477d Mon Sep 17 00:00:00 2001 From: hacheigriega Date: Thu, 8 Feb 2024 16:57:08 -0500 Subject: [PATCH 01/15] feat: initial implementation of clawback continuous vesting --- app/app.go | 17 +- app/export.go | 2 +- app/keepers/keepers.go | 3 +- go.mod | 1 - go.sum | 2 - go.work.sum | 55 ++ proto/buf.lock | 8 +- x/staking/keeper/keeper.go | 278 +++++++ x/staking/keeper/msg_server.go | 9 +- x/staking/module.go | 13 +- x/vesting/client/cli/tx.go | 112 +++ x/vesting/keeper/msg_server.go | 415 ++++++++++ x/vesting/module.go | 150 ++++ x/vesting/types/codec.go | 55 ++ x/vesting/types/expected_keepers.go | 35 + x/vesting/types/msgs.go | 27 + x/vesting/types/tx.pb.go | 1187 +++++++++++++++++++++++++++ x/vesting/types/types.go | 12 + x/vesting/types/vesting.go | 21 + x/vesting/types/vesting.pb.go | 376 +++++++++ 20 files changed, 2752 insertions(+), 26 deletions(-) create mode 100644 x/staking/keeper/keeper.go create mode 100644 x/vesting/client/cli/tx.go create mode 100644 x/vesting/keeper/msg_server.go create mode 100644 x/vesting/module.go create mode 100644 x/vesting/types/codec.go create mode 100644 x/vesting/types/expected_keepers.go create mode 100644 x/vesting/types/msgs.go create mode 100644 x/vesting/types/tx.pb.go create mode 100644 x/vesting/types/types.go create mode 100644 x/vesting/types/vesting.go create mode 100644 x/vesting/types/vesting.pb.go diff --git a/app/app.go b/app/app.go index 10f24f7a..b373b9b7 100644 --- a/app/app.go +++ b/app/app.go @@ -65,8 +65,9 @@ import ( authtx "github.com/cosmos/cosmos-sdk/x/auth/tx" txmodule "github.com/cosmos/cosmos-sdk/x/auth/tx/config" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - "github.com/cosmos/cosmos-sdk/x/auth/vesting" - vestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" + + // "github.com/cosmos/cosmos-sdk/x/auth/vesting" + // vestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" "github.com/cosmos/cosmos-sdk/x/authz" authzkeeper "github.com/cosmos/cosmos-sdk/x/authz/keeper" authzmodule "github.com/cosmos/cosmos-sdk/x/authz/module" @@ -98,7 +99,7 @@ import ( slashingkeeper "github.com/cosmos/cosmos-sdk/x/slashing/keeper" slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" "github.com/cosmos/cosmos-sdk/x/staking" - stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" + sdkstakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/cosmos/gogoproto/proto" "github.com/cosmos/ibc-go/modules/capability" @@ -134,6 +135,9 @@ import ( "github.com/sedaprotocol/seda-chain/app/keepers" appparams "github.com/sedaprotocol/seda-chain/app/params" "github.com/sedaprotocol/seda-chain/docs" + stakingkeeper "github.com/sedaprotocol/seda-chain/x/staking/keeper" + "github.com/sedaprotocol/seda-chain/x/vesting" + vestingtypes "github.com/sedaprotocol/seda-chain/x/vesting/types" ) const ( @@ -375,7 +379,7 @@ func NewApp( } app.txConfig = txConfig - app.StakingKeeper = stakingkeeper.NewKeeper( + sdkStakingKeeper := sdkstakingkeeper.NewKeeper( appCodec, runtime.NewKVStoreService(keys[stakingtypes.StoreKey]), app.AccountKeeper, @@ -384,6 +388,7 @@ func NewApp( authcodec.NewBech32Codec(sdk.GetConfig().GetBech32ValidatorAddrPrefix()), authcodec.NewBech32Codec(sdk.GetConfig().GetBech32ConsensusAddrPrefix()), ) + app.StakingKeeper = stakingkeeper.NewKeeper(sdkStakingKeeper) app.FeeGrantKeeper = feegrantkeeper.NewKeeper( appCodec, @@ -688,7 +693,7 @@ func NewApp( genutil.NewAppModule(app.AccountKeeper, app.StakingKeeper, app, txConfig), auth.NewAppModule(appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts, nil), authzmodule.NewAppModule(appCodec, app.AuthzKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry), - vesting.NewAppModule(app.AccountKeeper, app.BankKeeper), + vesting.NewAppModule(app.AccountKeeper, app.BankKeeper, app.StakingKeeper), bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper, nil), feegrantmodule.NewAppModule(appCodec, app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper, app.interfaceRegistry), groupmodule.NewAppModule(appCodec, app.GroupKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry), @@ -696,7 +701,7 @@ func NewApp( mint.NewAppModule(appCodec, app.MintKeeper, app.AccountKeeper, nil, nil), slashing.NewAppModule(appCodec, app.SlashingKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper, nil, app.interfaceRegistry), distr.NewAppModule(appCodec, app.DistrKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper, nil), - staking.NewAppModule(appCodec, app.StakingKeeper, app.AccountKeeper, app.BankKeeper, nil), // customstaking.NewAppModule(appCodec, app.StakingKeeper, app.AccountKeeper, app.BankKeeper, app.RandomnessKeeper), + staking.NewAppModule(appCodec, sdkStakingKeeper, app.AccountKeeper, app.BankKeeper, nil), upgrade.NewAppModule(app.UpgradeKeeper, app.AccountKeeper.AddressCodec()), evidence.NewAppModule(app.EvidenceKeeper), consensus.NewAppModule(appCodec, app.ConsensusParamsKeeper), diff --git a/app/export.go b/app/export.go index 113f92dc..b2389b41 100644 --- a/app/export.go +++ b/app/export.go @@ -44,7 +44,7 @@ func (app *App) ExportAppStateAndValidators( return servertypes.ExportedApp{}, err } - validators, err := staking.WriteValidators(ctx, app.StakingKeeper) + validators, err := staking.WriteValidators(ctx, app.StakingKeeper.Keeper) return servertypes.ExportedApp{ AppState: appState, Validators: validators, diff --git a/app/keepers/keepers.go b/app/keepers/keepers.go index 49948a13..4e2cf93a 100644 --- a/app/keepers/keepers.go +++ b/app/keepers/keepers.go @@ -15,7 +15,6 @@ import ( groupkeeper "github.com/cosmos/cosmos-sdk/x/group/keeper" mintkeeper "github.com/cosmos/cosmos-sdk/x/mint/keeper" slashingkeeper "github.com/cosmos/cosmos-sdk/x/slashing/keeper" - stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" capabilitykeeper "github.com/cosmos/ibc-go/modules/capability/keeper" ibckeeper "github.com/cosmos/ibc-go/v8/modules/core/keeper" @@ -28,6 +27,8 @@ import ( // ica icacontrollerkeeper "github.com/cosmos/ibc-go/v8/modules/apps/27-interchain-accounts/controller/keeper" icahostkeeper "github.com/cosmos/ibc-go/v8/modules/apps/27-interchain-accounts/host/keeper" + + stakingkeeper "github.com/sedaprotocol/seda-chain/x/staking/keeper" ) type AppKeepers struct { diff --git a/go.mod b/go.mod index 3b1374fa..2acf720b 100644 --- a/go.mod +++ b/go.mod @@ -225,7 +225,6 @@ require ( gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect gotest.tools/v3 v3.5.1 // indirect - mvdan.cc/gofumpt v0.5.0 // indirect nhooyr.io/websocket v1.8.6 // indirect pgregory.net/rapid v1.1.0 // indirect sigs.k8s.io/yaml v1.4.0 // indirect diff --git a/go.sum b/go.sum index 09bc552f..de1c4921 100644 --- a/go.sum +++ b/go.sum @@ -1787,8 +1787,6 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -mvdan.cc/gofumpt v0.5.0 h1:0EQ+Z56k8tXjj/6TQD25BFNKQXpCvT0rnansIc7Ug5E= -mvdan.cc/gofumpt v0.5.0/go.mod h1:HBeVDtMKRZpXyxFciAirzdKklDlGu8aAy1wEbH5Y9js= nhooyr.io/websocket v1.8.6 h1:s+C3xAMLwGmlI31Nyn/eAehUlZPwfYZu2JXM621Q5/k= nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= pgregory.net/rapid v1.1.0 h1:CMa0sjHSru3puNx+J0MIAuiiEV4N0qj8/cMWGBBCsjw= diff --git a/go.work.sum b/go.work.sum index f426a727..489b8257 100644 --- a/go.work.sum +++ b/go.work.sum @@ -254,6 +254,7 @@ cosmossdk.io/store v1.0.0/go.mod h1:ABMprwjvx6IpMp8l06TwuMrj6694/QP5NIW+X6jaTYc= cosmossdk.io/x/upgrade v0.1.0/go.mod h1:/6jjNGbiPCNtmA1N+rBtP601sr0g4ZXuj3yC6ClPCGY= dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8= +git.sr.ht/~sbinet/gg v0.3.1/go.mod h1:KGYtlADtqsqANL9ueOFkWymvzUvLMQllU5Ixo+8v3pc= github.com/Abirdcfly/dupword v0.0.11/go.mod h1:wH8mVGuf3CP5fsBTkfWwwwKTjDnVVCxtU8d8rgeVYXA= github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= github.com/Antonboom/errname v0.1.9/go.mod h1:nLTcJzevREuAsgTbG85UsuiWpMpAqbKD1HNZ29OzE58= @@ -267,6 +268,7 @@ github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3 github.com/CloudyKit/jet v2.1.3-0.20180809161101-62edd43e4f88+incompatible/go.mod h1:HPYO+50pSWkPoj9Q/eq0aRGByCL6ScRlUmiEX5Zgm+w= github.com/CloudyKit/jet/v6 v6.2.0/go.mod h1:d3ypHeIRNo2+XyqnGA8s+aphtcVpjP5hPwP/Lzo7Ro4= github.com/CosmWasm/wasmvm v1.5.0/go.mod h1:fXB+m2gyh4v9839zlIXdMZGeLAxqUdYdFQqYsTha2hc= +github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= github.com/GaijinEntertainment/go-exhaustruct/v2 v2.3.0/go.mod h1:b3g59n2Y+T5xmcxJL+UEG2f8cQploZm1mR/v6BW0mU0= @@ -286,9 +288,11 @@ github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06/go.mod h1:7erjK github.com/VictoriaMetrics/fastcache v1.12.1/go.mod h1:tX04vaqcNoQeGLD+ra5pU5sWkuxnzWhEzLwhP9w653o= github.com/aclements/go-gg v0.0.0-20170118225347-6dbb4e4fefb0/go.mod h1:55qNq4vcpkIuHowELi5C8e+1yUHtoLoOUR9QU5j7Tes= github.com/aclements/go-moremath v0.0.0-20210112150236-f10218a38794/go.mod h1:7e+I0LQFUI9AXWxOfsQROs9xPhoJtbsyWcjJqDd4KPY= +github.com/acomagu/bufpipe v1.0.4/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= github.com/ajstarks/svgo v0.0.0-20210923152817-c3b6e2f0c527/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= +github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b/go.mod h1:1KcenG0jGWcpt8ov532z81sp/kMMUG485J2InIOyADM= github.com/alecthomas/kingpin/v2 v2.3.2/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE= github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= github.com/alexkohler/prealloc v1.0.0/go.mod h1:VetnK3dIgFBBKmg0YnD9F9x6Icjd+9cvfHR56wJVlKE= @@ -296,8 +300,10 @@ github.com/alingse/asasalint v0.0.11/go.mod h1:nCaoMhw7a9kSJObvQyVzNTPBDbNpdocqr github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/ashanbrown/forbidigo v1.5.1/go.mod h1:Y8j9jy9ZYAEHXdu723cUlraTqbzjKF1MUyfOKL+AjcU= github.com/ashanbrown/makezero v1.1.1/go.mod h1:i1bJLCRSCHOcOa9Y6MyF2FTfMZMFdHvxKHxgO5Z1axI= github.com/aws/aws-sdk-go-v2 v1.21.2/go.mod h1:ErQhvNuEMhJjweavOYhxVkn2RUx7kQXVATHrjKtxIpM= @@ -307,6 +313,7 @@ github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.13/go.mod h1:f/Ib/qYjhV2/qds github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.43/go.mod h1:auo+PiyLl0n1l8A0e8RIeR8tOzYPfZZH/JNlrJ8igTQ= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.37/go.mod h1:Qe+2KtKml+FEsQF/DHmDV+xjtche/hwoF75EG4UlHW8= github.com/aws/aws-sdk-go-v2/internal/ini v1.3.45/go.mod h1:lD5M20o09/LCuQ2mE62Mb/iSdSlCNuj6H5ci7tW7OsE= +github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.8.1/go.mod h1:CM+19rL1+4dFWnOQKwDc7H1KwXTz+h61oUSHyhV0b3o= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.37/go.mod h1:vBmDnwWXWxNPFRMmG2m/3MKOe+xEcMDo1tanpaWCcck= github.com/aws/aws-sdk-go-v2/service/route53 v1.30.2/go.mod h1:TQZBt/WaQy+zTHoW++rnl8JBrmZ0VO6EUbVua1+foCA= github.com/aws/aws-sdk-go-v2/service/sso v1.15.2/go.mod h1:gsL4keucRCgW+xA85ALBpRFfdSLH4kHOVSnLMSuBECo= @@ -336,6 +343,7 @@ github.com/bufbuild/connect-go v1.5.2/go.mod h1:GmMJYR6orFqD0Y6ZgX8pwQ8j9baizDrI github.com/bufbuild/protocompile v0.5.1/go.mod h1:G5iLmavmF4NsYtpZFvE3B/zFch2GIY8+wjsYLR/lc40= github.com/butuzov/ireturn v0.1.1/go.mod h1:Wh6Zl3IMtTpaIKbmwzqi6olnM9ptYQxxVacMsOEFPoc= github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= +github.com/casbin/casbin/v2 v2.37.0/go.mod h1:vByNa/Fchek0KZUgG5wEsl7iFsiviAYKRtgrQfcJqHg= github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -349,6 +357,7 @@ github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moA github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY= github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86cAH8qUic= github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/clbanning/mxj v1.8.4/go.mod h1:BVjHeAH+rl9rs6f+QIpeRl0tfu10SXn1pUSa5PVGJng= github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= github.com/cloudflare/cloudflare-go v0.79.0/go.mod h1:gkHQf9xEubaQPEuerBuoinR9P8bf8a05Lq0X6WKy1Oc= github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= @@ -380,6 +389,7 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsr github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233/go.mod h1:geZJZH3SzKCqnz5VT0q/DyIG/tvu/dZk+VIfXicupJs= github.com/crate-crypto/go-kzg-4844 v0.7.0/go.mod h1:1kMhvPgI0Ky3yIa+9lFySEBUBXkYxeOi8ZF1sYioxhc= +github.com/cristalhq/acmd v0.11.1/go.mod h1:LG5oa43pE/BbxtfMoImHCQN++0Su7dzipdgBjMCBVDQ= github.com/curioswitch/go-reassign v0.2.0/go.mod h1:x6OpXuWvgfQaMGks2BZybTngWjT84hqJfKoO8Tt/Roc= github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4= github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= @@ -387,12 +397,14 @@ github.com/daixiang0/gci v0.10.1/go.mod h1:xtHP9N7AHdNvtRNfcx9gwTDfw7FRJx4bZUsiE github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= github.com/deepmap/oapi-codegen v1.6.0/go.mod h1:ryDa9AgbELGeB+YEXE1dR53yAjHwFvE9iAUlWl9Al3M= github.com/denis-tingaikin/go-header v0.4.3/go.mod h1:0wOCWuN71D5qIgE2nz9KrKmuYBAC2Mra5RassOIQ2/c= +github.com/denisenkom/go-mssqldb v0.12.0/go.mod h1:iiK0YP1ZeepvmBQk/QpLEhhTNJgfzrpArPY/aFvc9yU= github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= github.com/dgraph-io/ristretto v0.0.3/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/djherbis/atime v1.1.0/go.mod h1:28OF6Y8s3NQWwacXc5eZTsEsiMzp7LF8MbXE+XJPdBE= github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= +github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker v23.0.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= @@ -439,6 +451,7 @@ github.com/getsentry/sentry-go v0.23.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w github.com/ghemawat/stream v0.0.0-20171120220530-696b145b53b9/go.mod h1:106OIgooyS7OzLDOpUGgm9fA3bQENb/cFSyyBmMoJDs= github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s= github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM= +github.com/gliderlabs/ssh v0.3.5/go.mod h1:8XB4KraRrX39qHhT6yxPsHedjA08I/uBVwj4xC+/+z4= github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= github.com/go-chi/chi/v5 v5.0.0/go.mod h1:BBug9lr0cqtdAhsu6R4AAdvufI0/XBzAQSsUqJpoZOs= github.com/go-chi/chi/v5 v5.0.8/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= @@ -464,9 +477,11 @@ github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiU github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-pdf/fpdf v0.5.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M= +github.com/go-pdf/fpdf v0.6.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M= github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos= github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= @@ -476,10 +491,12 @@ github.com/go-toolsmith/astequal v1.0.3/go.mod h1:9Ai4UglvtR+4up+bAD4+hCj7iTo4m/ github.com/go-toolsmith/astequal v1.1.0/go.mod h1:sedf7VIdCL22LD8qIvv7Nn9MuWJruQA/ysswh64lffQ= github.com/go-toolsmith/astfmt v1.1.0/go.mod h1:OrcLlRwu0CuiIBp/8b5PYF9ktGVZUjlNMV634mhwuQ4= github.com/go-toolsmith/astp v1.1.0/go.mod h1:0T1xFGz9hicKs8Z5MfAqSUitoUYS30pDMsRVIDHs8CA= +github.com/go-toolsmith/pkgload v1.2.2/go.mod h1:R2hxLNRKuAsiXCo2i5J6ZQPhnPMOVtU+f0arbFPWCus= github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8= github.com/go-toolsmith/strparse v1.1.0/go.mod h1:7ksGy58fsaQkGQlY8WVoBFNyEPMGuJin1rfoPS4lBSQ= github.com/go-toolsmith/typep v1.1.0/go.mod h1:fVIw+7zjdsMxDA3ITWnH1yOiw1rnTQKCsF/sk2H/qig= github.com/go-xmlfmt/xmlfmt v1.1.2/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= +github.com/go-zookeeper/zk v1.0.2/go.mod h1:nOB03cncLtlp4t+UAkGSV+9beXP/akpekBwL+UX1Qcw= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= @@ -490,6 +507,8 @@ github.com/gofrs/uuid/v5 v5.0.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV github.com/gogo/googleapis v0.0.0-20180223154316-0cd9801be74a/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/status v1.1.0/go.mod h1:BFv9nrluPLmrS0EmGVvLaPNmRosr9KapBYd5/hpY1WM= github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= +github.com/golang-sql/sqlexp v0.0.0-20170517235910-f1bb20e5a188/go.mod h1:vXjM/+wXQnTPR4KqTKDgJukSZ6amVRtWMPEjE6sQoK8= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -510,6 +529,7 @@ github.com/gonum/floats v0.0.0-20181209220543-c233463c7e82/go.mod h1:PxC8OnwL11+ github.com/gonum/internal v0.0.0-20181124074243-f884aa714029/go.mod h1:Pu4dmpkhSyOzRwuXkOgAvijx4o+4YMUJJo9OvPYMkks= github.com/gonum/lapack v0.0.0-20181123203213-e4cdc5a0bff9/go.mod h1:XA3DeT6rxh2EAE789SSiSJNqxPaC0aE9J8NTOI0Jo/A= github.com/gonum/matrix v0.0.0-20181209220409-c518dec07be9/go.mod h1:0EXg4mc1CNP0HCqCz+K4ts155PXIlUywf0wqN+GfPZw= +github.com/google/flatbuffers v2.0.8+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/go-containerregistry v0.13.0/go.mod h1:J9FQ+eSS4a1aC2GNZxvNpbWhgp0487v+cgiilB4FqDo= github.com/google/go-pkcs11 v0.2.1-0.20230907215043-c6f79328ddf9/go.mod h1:6eQoGcuNJpa7jnd5pMGdkSaQpNDYvPlXWMcjXXThLlY= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= @@ -536,6 +556,7 @@ github.com/gostaticanalysis/comment v1.4.2/go.mod h1:KLUTGDv6HOCotCH8h2erHKmpci2 github.com/gostaticanalysis/forcetypeassert v0.1.0/go.mod h1:qZEedyP/sY1lTGV1uJ3VhWZ2mqag3IkWsDHVbplHXak= github.com/gostaticanalysis/nilerr v0.1.1/go.mod h1:wZYb6YI5YAxxq0i1+VJbY0s2YONW0HU0GPE3+5PWN4A= github.com/gostaticanalysis/testutil v0.3.1-0.20210208050101-bfb5c8eec0e4/go.mod h1:D+FIZ+7OahH3ePw/izIEeH5I06eKs1IKI4Xr64/Am3M= +github.com/gostaticanalysis/testutil v0.4.0/go.mod h1:bLIoPefWXrRi/ssLFWX1dx7Repi5x3CuviD3dgAZaBU= github.com/gotestyourself/gotestyourself v2.2.0+incompatible/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY= github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= @@ -559,6 +580,7 @@ github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfE github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7/go.mod h1:5GuXa7vkL8u9FkFuWdVvfR5ix8hRB7DbOAaYULamFpc= github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= +github.com/hudl/fargo v1.4.0/go.mod h1:9Ai6uvFy5fQNq6VPKtg+Ceq1+eTY4nKUlR2JElEOcDo= github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= github.com/hydrogen18/memlistener v0.0.0-20141126152155-54553eb933fb/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE= github.com/hydrogen18/memlistener v1.0.0/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE= @@ -581,9 +603,12 @@ github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i github.com/jdxcode/netrc v0.0.0-20221124155335-4616370d1a84/go.mod h1:Zi/ZFkEqFHTm7qkjyNJjaWH4LQA9LQhGJyF0lTYGpxw= github.com/jedisct1/go-minisign v0.0.0-20230811132847-661be99b8267/go.mod h1:h1nSAbGFqGVzn6Jyl1R/iCcBUHN4g+gW1u9CoBTrb9E= github.com/jgautheron/goconst v1.5.1/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4= +github.com/jhump/gopoet v0.1.0/go.mod h1:me9yfT6IJSlOL3FCfrg+L6yzUEZ+5jW6WHt4Sk+UPUI= +github.com/jhump/goprotoc v0.5.0/go.mod h1:VrbvcYrQOrTi3i0Vf+m+oqQWk9l72mjkJCYo7UvLHRQ= github.com/jingyugao/rowserrcheck v1.1.1/go.mod h1:4yvlZSDb3IyDTUZJUmpZfm2Hwok+Dtp+nu2qOq+er9c= github.com/jinzhu/copier v0.3.5/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af/go.mod h1:HEWGJkRDzjJY2sqdDwxccsGicWEf9BQOZsq2tV+xzM0= +github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/juju/errors v0.0.0-20181118221551-089d3ea4e4d5/go.mod h1:W54LbzXuIE0boCoNJfwqpmkKJ1O4TCTZMetAt6jGk7Q= @@ -632,11 +657,14 @@ github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM= github.com/ldez/gomoddirectives v0.2.3/go.mod h1:cpgBogWITnCfRq2qGoDkKMEVSaarhdBr6g8G04uz6d0= github.com/ldez/tagliatelle v0.4.0/go.mod h1:mNtTfrHy2haaBAw+VT7IBV6VXBThS7TCreYWbBcJ87I= +github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs= github.com/leonklingele/grouper v1.1.1/go.mod h1:uk3I3uDfi9B6PeUjsCKi6ndcf63Uy7snXgR4yDYQVDY= github.com/linxGnu/grocksdb v1.7.16/go.mod h1:JkS7pl5qWpGpuVb3bPqTz8nC12X3YtPZT+Xq7+QfQo4= github.com/linxGnu/grocksdb v1.8.4/go.mod h1:xZCIb5Muw+nhbDK4Y5UJuOrin5MceOuiXkVUR7vp4WY= github.com/lufeee/execinquery v1.2.1/go.mod h1:EC7DrEKView09ocscGHC+apXMIaorh4xqSxS/dy8SbM= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= +github.com/magefile/mage v1.14.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A= github.com/mailgun/raymond/v2 v2.0.48/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= @@ -670,21 +698,26 @@ github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfr github.com/mbilski/exhaustivestruct v1.2.0/go.mod h1:OeTBVxQWoEmB2J2JCHmXWPJ0aksxSUOUy+nvtVEfzXc= github.com/mediocregopher/mediocre-go-lib v0.0.0-20181029021733-cb65787f37ed/go.mod h1:dSsfyI2zABAdhcbvkXqgxOxrCsbYeHCPgrZkku60dSg= github.com/mediocregopher/radix/v3 v3.3.0/go.mod h1:EmfVyvspXz1uZEyPBMyGK+kjWiKQGvsUt6O3Pj+LDCQ= +github.com/mgechev/dots v0.0.0-20210922191527-e955255bf517/go.mod h1:KQ7+USdGKfpPjXk4Ga+5XxQM4Lm4e3gAogrreFAYpOg= github.com/mgechev/revive v1.3.1/go.mod h1:YlD6TTWl2B8A103R9KWJSPVI9DrEf+oqr15q21Ld+5I= github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc= github.com/microcosm-cc/bluemonday v1.0.23/go.mod h1:mN70sk7UkkF8TUr2IGBpNN0jAgStuPzlK76QuruE/z4= github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= +github.com/mitchellh/go-ps v1.0.0/go.mod h1:J4lOc8z8yJs6vUwklHw2XEIiT4z4C40KtWVN3nvg8Pg= github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= +github.com/mmcloughlin/avo v0.5.0/go.mod h1:ChHFdoV7ql95Wi7vuq2YT1bwCJqiWdZrQ1im3VujLYM= github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= github.com/moricho/tparallel v0.3.0/go.mod h1:leENX2cUv7Sv2qDgdi0D0fCftN8fRC67Bcn8pqzeYNI= github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= +github.com/mozilla/tls-observatory v0.0.0-20210609171429-7bc42856d2e5/go.mod h1:FUqVoUPHSEdDR0MnFM3Dh8AU0pZHLXUD127SAJGER/s= github.com/nakabonne/nestif v0.3.1/go.mod h1:9EtoZochLn5iUprVDmDjqGKPofoUEBL8U4Ngq6aY7OE= github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0= github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E= +github.com/nats-io/nats-server/v2 v2.5.0/go.mod h1:Kj86UtrXAL6LwYRA6H4RqzkHhK0Vcv2ZnKD5WbQ1t3g= github.com/nats-io/nats.go v1.8.1/go.mod h1:BrFz9vVn0fU3AcH9Vn4Kd7W0NpJ651tD5omQ3M8LwxM= github.com/nats-io/nats.go v1.31.0/go.mod h1:di3Bm5MLsoB4Bx61CBTsxuarI36WbhAwOm8QrW39+i8= github.com/nats-io/nkeys v0.0.2/go.mod h1:dab7URMsZm6Z/jp9Z5UGa87Uutgc2mVpXLC4B7TDb/4= @@ -695,6 +728,7 @@ github.com/nishanths/predeclared v0.2.2/go.mod h1:RROzoN6TnGQupbC+lqggsOlcgysk3L github.com/nunnatsa/ginkgolinter v0.9.0/go.mod h1:FHaMLURXP7qImeH6bvxWJUpyH+2tuqe5j4rW1gxJRmI= github.com/oasisprotocol/curve25519-voi v0.0.0-20220708102147-0a8a51822cae/go.mod h1:hVoHR2EVESiICEMbg137etN/Lx+lSrHPTD39Z/uE+2s= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/oklog/ulid/v2 v2.1.0/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.13.0/go.mod h1:+REjRxOmWfHCjfv9TTWB1jD1Frx4XydAD3zm1lskyM0= github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM= @@ -702,6 +736,7 @@ github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3ev github.com/opencontainers/runc v1.1.3/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg= github.com/opencontainers/runtime-spec v1.1.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= +github.com/openzipkin/zipkin-go v0.2.5/go.mod h1:KpXfKdgRDnnhsxw4pNIH9Md5lyFqKUa4YDFlwRYAMyE= github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0= github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= @@ -711,8 +746,10 @@ github.com/otiai10/mint v1.3.1/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo= github.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas= github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= +github.com/performancecopilot/speed/v4 v4.0.0/go.mod h1:qxrSyuDGrTOWfV+uKRFhfxw6h/4HXRGUiZiufxo49BM= github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= github.com/petermattis/goid v0.0.0-20221215004737-a150e88a970d/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= +github.com/phayes/checkstyle v0.0.0-20170904204023-bfd46e6a821d/go.mod h1:3OzsM7FXDQlpCiw2j81fOmAwQLnZnLGXVKUzeKQXIAw= github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2dXMnm1mY= github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= github.com/phpdave11/gofpdi v1.0.13/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= @@ -723,6 +760,7 @@ github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZ github.com/pkg/sftp v1.13.6/go.mod h1:tz1ryNURKu77RL+GuCzmoJYxQczL3wLNNpPWagdg4Qk= github.com/polyfloyd/go-errorlint v1.4.5/go.mod h1:sIZEbFoDOCnTYYZoVkjc4hTnM459tuWA9H/EkdXwsKk= github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= +github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= github.com/prometheus/client_golang v1.12.0/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= @@ -744,9 +782,15 @@ github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/ github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/protolambda/bls12-381-util v0.0.0-20220416220906-d8552aa452c7/go.mod h1:IToEjHuttnUzwZI5KBSM/LOOW3qLbbrHOEfp3SbECGY= github.com/quasilyte/go-ruleguard v0.4.0/go.mod h1:Eu76Z/R8IXtViWUIHkE3p8gdH3/PKk1eh3YGfaEof10= +github.com/quasilyte/go-ruleguard/dsl v0.3.22/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= +github.com/quasilyte/go-ruleguard/rules v0.0.0-20211022131956-028d6511ab71/go.mod h1:4cgAphtvu7Ftv7vOT2ZOYhC6CvBxZixcasr8qIOTA50= github.com/quasilyte/gogrep v0.5.0/go.mod h1:Cm9lpz9NZjEoL1tgZ2OgeUKPIxL1meE7eo60Z6Sk+Ng= github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727/go.mod h1:rlzQ04UMyJXu/aOvhd8qT+hvDrFpiwqp8MRXDY9szc0= github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567/go.mod h1:DWNGW8A4Y+GyBgPuaQJuWiy0XYftx4Xm/y5Jqk9I6VQ= +github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc= +github.com/remyoudompheng/go-dbus v0.0.0-20121104212943-b7232d34b1d5/go.mod h1:+u151txRmLpwxBmpYn9z3d1sdJdjRPQpsXuYeY9jNls= +github.com/remyoudompheng/go-liblzma v0.0.0-20190506200333-81bf2d431b96/go.mod h1:90HvCY7+oHHUKkbeMCiHt1WuFR2/hPJ9QrljDG+v6ls= +github.com/remyoudompheng/go-misc v0.0.0-20190427085024-2d6ac652a50e/go.mod h1:80FQABjoFzZ2M5uEa6FUaJYEmqU2UOKojlFVak1UAwI= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= @@ -756,6 +800,7 @@ github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncj github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.29.0/go.mod h1:NILgTygv/Uej1ra5XxGf82ZFSLk58MFGAUS2o6usyD0= github.com/rs/zerolog v1.30.0/go.mod h1:/tk+P47gFdPXq4QYjvCmT5/Gsug2nagsFWBWhAiSi1w= +github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY= github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w= github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245/go.mod h1:pQAZKsJ8yyVxGRWYNEm9oFB8ieLgKFnamEyDmSA0BRk= github.com/ryancurrah/gomodguard v1.3.0/go.mod h1:ggBxb3luypPEzqVtq33ee7YSN35V28XeGnid8dnni50= @@ -793,6 +838,8 @@ github.com/spf13/viper v1.18.1/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMV github.com/ssgreg/nlreturn/v2 v2.2.1/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRkkxBiELzh2I= github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= github.com/stbenjam/no-sprintf-host-port v0.1.1/go.mod h1:TLhvtIvONRzdmkFiio4O8LHsN9N74I+PhRquPsxpL0I= +github.com/streadway/amqp v1.0.0/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/handy v0.0.0-20200128134331-0f66f006fb2e/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= github.com/stretchr/objx v0.3.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/testify v1.1.4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.7.5/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= @@ -828,15 +875,19 @@ github.com/valyala/fasthttp v1.40.0/go.mod h1:t/G+3rLek+CyY9bnIE+YlMRddxVAAGjhxn 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/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= +github.com/valyala/quicktemplate v1.7.0/go.mod h1:sqKJnoaOF88V07vkO+9FL8fb9uZg/VPSJnLYn+LmLk8= github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= +github.com/vbatts/tar-split v0.11.2/go.mod h1:vV3ZuO2yWSVsz+pfFzDG/upWH1JhjOiEaWq6kXyQ3VI= github.com/vektra/mockery/v2 v2.23.1/go.mod h1:Zh3Kv1ckKs6FokhlVLcCu6UTyzfS3M8mpROz1lBNp+w= github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc= github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xhit/go-str2duration v1.2.0/go.mod h1:3cPSlfZlUHVlneIVfePFWcJZsuwf+P1v2SRTV4cUmp4= github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU= +github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= github.com/yagipy/maintidx v1.0.0/go.mod h1:0qNf/I/CCZXSMhsRsrEPDZ+DkekpKLXAJfsTACwgXLk= github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= @@ -846,6 +897,7 @@ github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FB github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc= github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= gitlab.com/bosi/decorder v0.2.3/go.mod h1:9K1RB5+VPNQYtXtTDAzd2OEftsZb1oV0IrJrzChSdGE= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= @@ -858,6 +910,7 @@ go.etcd.io/gofail v0.1.0/go.mod h1:VZBCXYGZhHAinaBiiqYvuDynvahNsAyLFwB3kEHKz1M= go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU= go.opentelemetry.io/otel/sdk v1.14.0/go.mod h1:bwIC5TjrNG6QDCHNWvW4HLHtUQ4I+VQDsnjhvyZCALM= go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8= +go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= @@ -904,6 +957,7 @@ golang.org/x/image v0.0.0-20201208152932-35266b937fa6/go.mod h1:FeLwcggjj3mMvU+o golang.org/x/image v0.0.0-20210216034530-4410531fe030/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20210607152325-775e3b0c77b9/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= +golang.org/x/image v0.0.0-20220302094943-723b81ca9867/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= @@ -1023,6 +1077,7 @@ gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6d gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= gonum.org/v1/plot v0.9.0/go.mod h1:3Pcqqmp6RHvJI72kgb8fThyUnav364FOsdDo2aGW5lY= gonum.org/v1/plot v0.10.0/go.mod h1:JWIHJ7U20drSQb/aDpTetJzfC1KlAPldJLpkSy88dvQ= +gonum.org/v1/plot v0.10.1/go.mod h1:VZW5OlhkL1mysU9vaqNHnsy86inf6Ot+jB3r+BczCEo= google.golang.org/api v0.0.0-20170206182103-3d017632ea10/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.128.0/go.mod h1:Y611qgqaE92On/7g65MQgxYul3c0rEB894kniWLY750= google.golang.org/api v0.149.0/go.mod h1:Mwn1B7JTXrzXtnvmzQE2BD6bYZQ8DShKZDZbeN9I7qI= diff --git a/proto/buf.lock b/proto/buf.lock index 570a75f9..d025fc2f 100644 --- a/proto/buf.lock +++ b/proto/buf.lock @@ -14,10 +14,10 @@ deps: - remote: buf.build owner: cosmos repository: gogo-proto - commit: 5e5b9fdd01804356895f8f79a6f1ddc1 - digest: shake256:0b85da49e2e5f9ebc4806eae058e2f56096ff3b1c59d1fb7c190413dd15f45dd456f0b69ced9059341c80795d2b6c943de15b120a9e0308b499e43e4b5fc2952 + commit: 88ef6483f90f478fb938c37dde52ece3 + digest: shake256:89c45df2aa11e0cff97b0d695436713db3d993d76792e9f8dc1ae90e6ab9a9bec55503d48ceedd6b86069ab07d3041b32001b2bfe0227fa725dd515ff381e5ba - remote: buf.build owner: googleapis repository: googleapis - commit: a86849a25cc04f4dbe9b15ddddfbc488 - digest: shake256:e19143328f8cbfe13fc226aeee5e63773ca494693a72740a7560664270039a380d94a1344234b88c7691311460df9a9b1c2982190d0a2612eae80368718e1943 + commit: e874a0be2bf140a5a4c7d4122c635823 + digest: shake256:4fe3036b4d706f6ee2b13c730bd04777f021dfd02ed27e6e40480acfe664a7548238312ee0727fd77648a38d227e296d43f4a38a34cdd46068156211016d9657 diff --git a/x/staking/keeper/keeper.go b/x/staking/keeper/keeper.go new file mode 100644 index 00000000..5b211805 --- /dev/null +++ b/x/staking/keeper/keeper.go @@ -0,0 +1,278 @@ +package keeper + +import ( + "context" + stdmath "math" + + "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" + "github.com/cosmos/cosmos-sdk/x/staking/types" +) + +type Keeper struct { + *sdkkeeper.Keeper +} + +func NewKeeper(sdkStakingKeeper *sdkkeeper.Keeper) *Keeper { + return &Keeper{ + Keeper: sdkStakingKeeper, + } +} + +func (k *Keeper) SetHooks(sh types.StakingHooks) { + k.Keeper.SetHooks(sh) +} + +// TransferDelegation changes the ownership of at most the desired number of shares. +// Returns the actual number of shares transferred. Will also transfer redelegation +// entries to ensure that all redelegations are matched by sufficient shares. +// Note that no tokens are transferred to or from any pool or account, since no +// delegation is actually changing state. +func (k Keeper) TransferDelegation(ctx context.Context, fromAddr, toAddr sdk.AccAddress, valAddr sdk.ValAddress, wantShares math.LegacyDec) (math.LegacyDec, error) { + transferred := math.LegacyZeroDec() // TO-DO + + // sanity checks + if !wantShares.IsPositive() { + return transferred, nil + } + validator, err := k.GetValidator(ctx, valAddr) + if err != nil { // TO-DO more specific check? + return transferred, nil + } + delFrom, err := k.GetDelegation(ctx, fromAddr, valAddr) + if err != nil { // TO-DO more specific check? + return transferred, nil + } + + // Check redelegation entry limits while we can still return early. + // Assume the worst case that we need to transfer all redelegation entries + mightExceedLimit := false + k.IterateDelegatorRedelegations(ctx, fromAddr, func(toRedelegation types.Redelegation) (stop bool) { + // There's no redelegation index by delegator and dstVal or vice-versa. + // The minimum cardinality is to look up by delegator, so scan and skip. + if toRedelegation.ValidatorDstAddress != valAddr.String() { + return false + } + + maxEntries, err := k.MaxEntries(ctx) + if err != nil { + // TO-DO + panic(err) + } + fromRedelegation, err := k.GetRedelegation(ctx, fromAddr, sdk.ValAddress(toRedelegation.ValidatorSrcAddress), sdk.ValAddress(toRedelegation.ValidatorDstAddress)) + if err == nil && len(toRedelegation.Entries)+len(fromRedelegation.Entries) >= int(maxEntries) { + mightExceedLimit = true + return true + } + return false + }) + if mightExceedLimit { + // avoid types.ErrMaxRedelegationEntries + return transferred, nil + } + + // compute shares to transfer, amount left behind + transferred = delFrom.Shares + if transferred.GT(wantShares) { + transferred = wantShares + } + remaining := delFrom.Shares.Sub(transferred) + + // Update or create the delTo object, calling appropriate hooks + delTo, err := k.GetDelegation(ctx, toAddr, valAddr) + if err != nil { + if err == types.ErrNoDelegation { // TO-DO + delTo = types.NewDelegation(toAddr.String(), validator.GetOperator(), math.LegacyZeroDec()) + k.Hooks().BeforeDelegationCreated(ctx, toAddr, valAddr) + } else { + return transferred, err + } + } else { + k.Hooks().BeforeDelegationSharesModified(ctx, toAddr, valAddr) + } + // if !found { + // delTo = types.NewDelegation(toAddr, validator.GetOperator(), sdk.ZeroDec()) + // } + // if found { + // k.BeforeDelegationSharesModified(ctx, toAddr, validator.GetOperator()) + // } else { + // k.BeforeDelegationCreated(ctx, toAddr, validator.GetOperator()) + // } + delTo.Shares = delTo.Shares.Add(transferred) + k.SetDelegation(ctx, delTo) + k.Hooks().AfterDelegationModified(ctx, toAddr, valAddr) + + // Update source delegation + if remaining.IsZero() { + k.Hooks().BeforeDelegationRemoved(ctx, fromAddr, valAddr) + k.RemoveDelegation(ctx, delFrom) + } else { + k.Hooks().BeforeDelegationSharesModified(ctx, fromAddr, valAddr) + delFrom.Shares = remaining + k.SetDelegation(ctx, delFrom) + k.Hooks().AfterDelegationModified(ctx, fromAddr, valAddr) + } + + // If there are not enough remaining shares to be responsible for + // the redelegations, transfer some redelegations. + // For instance, if the original delegation of 300 shares to validator A + // had redelegations for 100 shares each from validators B, C, and D, + // and if we're transferring 175 shares, then we might keep the redelegation + // from B, transfer the one from D, and split the redelegation from C + // keeping a liability for 25 shares and transferring one for 75 shares. + // Of course, the redelegations themselves can have multiple entries for + // different timestamps, so we're actually working at a finer granularity. + redelegations, err := k.GetRedelegations(ctx, fromAddr, stdmath.MaxUint16) + if err != nil { + return transferred, err + } + for _, redelegation := range redelegations { + // There's no redelegation index by delegator and dstVal or vice-versa. + // The minimum cardinality is to look up by delegator, so scan and skip. + if redelegation.ValidatorDstAddress != valAddr.String() { + continue + } + redelegationModified := false + entriesRemaining := false + for i := 0; i < len(redelegation.Entries); i++ { + entry := redelegation.Entries[i] + + // Partition SharesDst between keeping and sending + sharesToKeep := entry.SharesDst + sharesToSend := math.LegacyZeroDec() + if entry.SharesDst.GT(remaining) { + sharesToKeep = remaining + sharesToSend = entry.SharesDst.Sub(sharesToKeep) + } + remaining = remaining.Sub(sharesToKeep) // fewer local shares available to cover liability + + if sharesToSend.IsZero() { + // Leave the entry here + entriesRemaining = true + continue + } + if sharesToKeep.IsZero() { + // Transfer the whole entry, delete locally + toRed, err := k.SetRedelegationEntry( + ctx, toAddr, sdk.ValAddress(redelegation.ValidatorSrcAddress), + sdk.ValAddress(redelegation.ValidatorDstAddress), + entry.CreationHeight, entry.CompletionTime, entry.InitialBalance, math.LegacyZeroDec(), sharesToSend, + ) + if err != nil { + panic(err) // TO-DO + } + k.InsertRedelegationQueue(ctx, toRed, entry.CompletionTime) + redelegation.RemoveEntry(int64(i)) + i-- + // okay to leave an obsolete entry in the queue for the removed entry + redelegationModified = true + } else { + // Proportionally divide the entry + fracSending := sharesToSend.Quo(entry.SharesDst) + balanceToSend := fracSending.MulInt(entry.InitialBalance).TruncateInt() + balanceToKeep := entry.InitialBalance.Sub(balanceToSend) + toRed, err := k.SetRedelegationEntry( + ctx, toAddr, sdk.ValAddress(redelegation.ValidatorSrcAddress), + sdk.ValAddress(redelegation.ValidatorDstAddress), + entry.CreationHeight, entry.CompletionTime, balanceToSend, math.LegacyZeroDec(), sharesToSend, + ) + if err != nil { + panic(err) // TO-DO + } + k.InsertRedelegationQueue(ctx, toRed, entry.CompletionTime) + entry.InitialBalance = balanceToKeep + entry.SharesDst = sharesToKeep + redelegation.Entries[i] = entry + // not modifying the completion time, so no need to change the queue + redelegationModified = true + entriesRemaining = true + } + } + if redelegationModified { + if entriesRemaining { + k.SetRedelegation(ctx, redelegation) + } else { + k.RemoveRedelegation(ctx, redelegation) + } + } + } + return transferred, nil +} + +// TransferUnbonding changes the ownership of UnbondingDelegation entries +// until the desired number of tokens have changed hands. Returns the actual +// number of tokens transferred. +func (k Keeper) TransferUnbonding(ctx context.Context, fromAddr, toAddr sdk.AccAddress, valAddr sdk.ValAddress, wantAmt math.Int) math.Int { + transferred := math.ZeroInt() + ubdFrom, err := k.GetUnbondingDelegation(ctx, fromAddr, valAddr) + // if !found { + // return transferred + // } + if err != nil { + // TO-DO + return transferred + } + ubdFromModified := false + + for i := 0; i < len(ubdFrom.Entries) && wantAmt.IsPositive(); i++ { + entry := ubdFrom.Entries[i] + toXfer := entry.Balance + if toXfer.GT(wantAmt) { + toXfer = wantAmt + } + if !toXfer.IsPositive() { + continue + } + + if k.HasMaxUnbondingDelegationEntries(ctx, toAddr, valAddr) { + // TODO pre-compute the maximum entries we can add rather than checking each time + break + } + ubdTo, err := k.SetUnbondingDelegationEntry(ctx, toAddr, valAddr, entry.CreationHeight, entry.CompletionTime, toXfer) + if err != nil { + // TO-DO + panic(err) + } + k.InsertUBDQueue(ctx, ubdTo, entry.CompletionTime) + transferred = transferred.Add(toXfer) + wantAmt = wantAmt.Sub(toXfer) + + ubdFromModified = true + remaining := entry.Balance.Sub(toXfer) + if remaining.IsZero() { + ubdFrom.RemoveEntry(int64(i)) + i-- + continue + } + entry.Balance = remaining + ubdFrom.Entries[i] = entry + } + + if ubdFromModified { + if len(ubdFrom.Entries) == 0 { + k.RemoveUnbondingDelegation(ctx, ubdFrom) + } else { + k.SetUnbondingDelegation(ctx, ubdFrom) + } + } + return transferred +} + +// HasMaxUnbondingDelegationEntries - check if unbonding delegation has maximum number of entries. +func (k Keeper) HasMaxUnbondingDelegationEntries(ctx context.Context, delegatorAddr sdk.AccAddress, validatorAddr sdk.ValAddress) bool { + ubd, err := k.GetUnbondingDelegation(ctx, delegatorAddr, validatorAddr) + // if !found { + // return false + // } + if err != nil { + // TO-DO + return false + } + maxEntries, err := k.MaxEntries(ctx) + if err != nil { + // TO-DO + panic(err) + } + return len(ubd.Entries) >= int(maxEntries) +} diff --git a/x/staking/keeper/msg_server.go b/x/staking/keeper/msg_server.go index b0fb419f..4e47476a 100644 --- a/x/staking/keeper/msg_server.go +++ b/x/staking/keeper/msg_server.go @@ -9,7 +9,6 @@ import ( cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/sedaprotocol/seda-chain/x/staking/types" @@ -19,16 +18,16 @@ var _ types.MsgServer = msgServer{} type msgServer struct { stakingtypes.MsgServer - stakingKeeper *stakingkeeper.Keeper + keeper *Keeper accountKeeper types.AccountKeeper randomnessKeeper types.RandomnessKeeper validatorAddressCodec addresscodec.Codec } -func NewMsgServerImpl(keeper *stakingkeeper.Keeper, accKeeper types.AccountKeeper, randKeeper types.RandomnessKeeper) types.MsgServer { +func NewMsgServerImpl(sdkMsgServer stakingtypes.MsgServer, keeper *Keeper, accKeeper types.AccountKeeper, randKeeper types.RandomnessKeeper) types.MsgServer { ms := &msgServer{ - MsgServer: stakingkeeper.NewMsgServerImpl(keeper), - stakingKeeper: keeper, + MsgServer: sdkMsgServer, + keeper: keeper, accountKeeper: accKeeper, randomnessKeeper: randKeeper, validatorAddressCodec: keeper.ValidatorAddressCodec(), diff --git a/x/staking/module.go b/x/staking/module.go index 22ce20a0..1dc69c62 100644 --- a/x/staking/module.go +++ b/x/staking/module.go @@ -99,7 +99,7 @@ func (amb AppModuleBasic) GetTxCmd() *cobra.Command { type AppModule struct { AppModuleBasic - keeper *sdkkeeper.Keeper + keeper *keeper.Keeper accountKeeper types.AccountKeeper bankKeeper sdktypes.BankKeeper randomnessKeeper types.RandomnessKeeper @@ -108,7 +108,7 @@ type AppModule struct { // NewAppModule creates a new AppModule object func NewAppModule( cdc codec.Codec, - keeper *sdkkeeper.Keeper, + keeper *keeper.Keeper, ak types.AccountKeeper, bk sdktypes.BankKeeper, rk types.RandomnessKeeper, @@ -124,10 +124,11 @@ func NewAppModule( // RegisterServices registers module services. func (am AppModule) RegisterServices(cfg module.Configurator) { - types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper, am.accountKeeper, am.randomnessKeeper)) - sdktypes.RegisterMsgServer(cfg.MsgServer(), NewMsgServerImpl(am.keeper, am.accountKeeper)) + sdkMsgServer := NewMsgServerImpl(am.keeper.Keeper, am.accountKeeper) + sdktypes.RegisterMsgServer(cfg.MsgServer(), sdkMsgServer) + types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(sdkMsgServer, am.keeper, am.accountKeeper, am.randomnessKeeper)) - querier := sdkkeeper.Querier{Keeper: am.keeper} + querier := sdkkeeper.Querier{Keeper: am.keeper.Keeper} sdktypes.RegisterQueryServer(cfg.QueryServer(), querier) } @@ -139,7 +140,7 @@ func (am AppModule) IsAppModule() {} // RegisterInvariants registers the staking module invariants. func (am AppModule) RegisterInvariants(ir sdk.InvariantRegistry) { - sdkkeeper.RegisterInvariants(ir, am.keeper) + sdkkeeper.RegisterInvariants(ir, am.keeper.Keeper) } // InitGenesis performs genesis initialization for the staking module. diff --git a/x/vesting/client/cli/tx.go b/x/vesting/client/cli/tx.go new file mode 100644 index 00000000..09ca5be3 --- /dev/null +++ b/x/vesting/client/cli/tx.go @@ -0,0 +1,112 @@ +package cli + +import ( + "errors" + "fmt" + "strconv" + + "github.com/spf13/cobra" + + "cosmossdk.io/core/address" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/client/tx" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/sedaprotocol/seda-chain/x/vesting/types" +) + +// GetTxCmd returns vesting module's transaction commands. +func GetTxCmd(ac address.Codec) *cobra.Command { + txCmd := &cobra.Command{ + Use: types.ModuleName, + Short: fmt.Sprintf("%s transactions subcommands", types.ModuleName), + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + RunE: client.ValidateCmd, + } + + txCmd.AddCommand( + NewMsgCreateVestingAccountCmd(ac), + NewMsgClawbackCmd(ac), + ) + return txCmd +} + +// NewMsgCreateVestingAccountCmd returns a CLI command handler for creating a +// MsgCreateVestingAccount transaction. +func NewMsgCreateVestingAccountCmd(ac address.Codec) *cobra.Command { + cmd := &cobra.Command{ + Use: "create-vesting-account [to_address] [amount] [end_time]", + Short: "Create a new vesting account funded with an allocation of tokens.", + Long: `Create a new clawback continuous vesting account funded with +an allocation of tokens. The from address will be registered as the funder of +the vesting account that can be used for clawing back vesting funds. All vesting +accounts created will have their start time set by the committed block's time. +The end_time must be provided as a UNIX epoch timestamp.`, + Args: cobra.ExactArgs(3), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + toAddr, err := ac.StringToBytes(args[0]) + if err != nil { + return err + } + + if args[1] == "" { + return errors.New("amount is empty") + } + + amount, err := sdk.ParseCoinsNormalized(args[1]) + if err != nil { + return err + } + + endTime, err := strconv.ParseInt(args[2], 10, 64) + if err != nil { + return err + } + + msg := types.NewMsgCreateVestingAccount(clientCtx.GetFromAddress(), toAddr, amount, endTime) + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + + return cmd +} + +// NewMsgClawbackCmd returns a CLI command handler for clawing back unvested funds. +func NewMsgClawbackCmd(ac address.Codec) *cobra.Command { + cmd := &cobra.Command{ + Use: "clawback [address]", + Short: "Transfer vesting (un-vested) amount out of a vesting account.", + Long: `Must be requested by the funder address associated with the vesting account (--from). + + + Delegated or undelegating staking tokens will be transferred in the delegated (undelegating) state. + The recipient is vulnerable to slashing, and must act to unbond the tokens if desired.`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + addr, err := sdk.AccAddressFromBech32(args[0]) + if err != nil { + return err + } + + msg := types.NewMsgClawback(clientCtx.GetFromAddress(), addr) + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + return cmd +} diff --git a/x/vesting/keeper/msg_server.go b/x/vesting/keeper/msg_server.go new file mode 100644 index 00000000..b88e57ce --- /dev/null +++ b/x/vesting/keeper/msg_server.go @@ -0,0 +1,415 @@ +package keeper + +import ( + "context" + "fmt" + "math" + + "github.com/hashicorp/go-metrics" + + errorsmod "cosmossdk.io/errors" + + "github.com/cosmos/cosmos-sdk/telemetry" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + sdkvestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" + + "github.com/sedaprotocol/seda-chain/x/vesting/types" +) + +type msgServer struct { + ak types.AccountKeeper + bk types.BankKeeper + sk types.StakingKeeper +} + +// NewMsgServerImpl returns an implementation of the vesting MsgServer interface, +// wrapping the corresponding AccountKeeper and BankKeeper. +func NewMsgServerImpl(ak types.AccountKeeper, bk types.BankKeeper, sk types.StakingKeeper) types.MsgServer { + return &msgServer{ak: ak, bk: bk, sk: sk} +} + +var _ types.MsgServer = msgServer{} + +func (m msgServer) CreateVestingAccount(goCtx context.Context, msg *types.MsgCreateVestingAccount) (*types.MsgCreateVestingAccountResponse, error) { + from, err := m.ak.AddressCodec().StringToBytes(msg.FromAddress) + if err != nil { + return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid 'from' address: %s", err) + } + + to, err := m.ak.AddressCodec().StringToBytes(msg.ToAddress) + if err != nil { + return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid 'to' address: %s", err) + } + + if err := validateAmount(msg.Amount); err != nil { + return nil, err + } + + if msg.EndTime <= 0 { + return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "invalid end time") + } + + ctx := sdk.UnwrapSDKContext(goCtx) + if err := m.bk.IsSendEnabledCoins(ctx, msg.Amount...); err != nil { + return nil, err + } + + if m.bk.BlockedAddr(to) { + return nil, errorsmod.Wrapf(sdkerrors.ErrUnauthorized, "%s is not allowed to receive funds", msg.ToAddress) + } + + if acc := m.ak.GetAccount(ctx, to); acc != nil { + return nil, errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "account %s already exists", msg.ToAddress) + } + + baseAccount := authtypes.NewBaseAccountWithAddress(to) + baseAccount = m.ak.NewAccount(ctx, baseAccount).(*authtypes.BaseAccount) + baseVestingAccount, err := sdkvestingtypes.NewBaseVestingAccount(baseAccount, msg.Amount.Sort(), msg.EndTime) + if err != nil { + return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, err.Error()) + } + + vestingAccount := types.NewClawbackContinuousVestingAccountRaw(baseVestingAccount, ctx.BlockTime().Unix(), msg.FromAddress) + + m.ak.SetAccount(ctx, vestingAccount) + + defer func() { + telemetry.IncrCounter(1, "new", "account") + + for _, a := range msg.Amount { + if a.Amount.IsInt64() { + telemetry.SetGaugeWithLabels( + []string{"tx", "msg", "create_vesting_account"}, + float32(a.Amount.Int64()), + []metrics.Label{telemetry.NewLabel("denom", a.Denom)}, + ) + } + } + }() + + if err = m.bk.SendCoins(ctx, from, to, msg.Amount); err != nil { + return nil, err + } + + return &types.MsgCreateVestingAccountResponse{}, nil +} + +// Clawback removes the unvested amount from a ClawbackVestingAccount. +// +// Checks performed on the ValidateBasic include: +// - funder and vesting addresses are correct bech32 format +// - if destination address is not empty it is also correct bech32 format +func (m msgServer) Clawback(goCtx context.Context, msg *types.MsgClawback) (*types.MsgClawbackResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + // NOTE: errors checked during msg validation + vestingAccAddr := sdk.MustAccAddressFromBech32(msg.AccountAddress) + funderAddr := sdk.MustAccAddressFromBech32(msg.FunderAddress) + + // // NOTE: we check the destination address only for the case where it's not sent from the + // // authority account, because in that case the destination address is hardcored to the + // // community pool address anyway (see further below). + // if bk.BlockedAddr(dest) { + // return nil, errorsmod.Wrapf(sdkerrors.ErrUnauthorized, + // "%s is a blocked address and not allowed to receive funds", msg.DestAddress, + // ) + // } + + // retrieve the vesting account and perform preliminary checks + acc := m.ak.GetAccount(ctx, vestingAccAddr) + if acc == nil { + // TO-DO what to return? + return nil, errorsmod.Wrapf(sdkerrors.ErrUnknownAddress, "account at address '%s' does not exist", vestingAccAddr.String()) + } + vestingAccount, isClawback := acc.(*types.ClawbackContinuousVestingAccount) + if !isClawback { + return nil, errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "account %s is not of type ClawbackContinuousVestingAccount", vestingAccAddr.String()) + } + if vestingAccount.GetVestingCoins(ctx.BlockTime()).IsZero() { + return nil, errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "account %s does not have currently vesting coins", msg.AccountAddress) + } + if vestingAccount.FunderAddress != msg.FunderAddress { + return nil, errorsmod.Wrapf(sdkerrors.ErrUnauthorized, "clawback can only be requested by original funder: %s", vestingAccount.FunderAddress) + } + + // + // + // clawback from agoric x/auth/vesting + // + // + // + + // + // MODIFYING THIS PART + // + // Compute the clawback based on the account state only, and update account + // toClawBack := vestingAccount.computeClawback(ctx.BlockTime().Unix()) + // if toClawBack.IsZero() { + // return nil + // } + + totalVesting := vestingAccount.GetVestingCoins(ctx.BlockTime()) + + // update the vesting account + totalVested := vestingAccount.GetVestedCoins(ctx.BlockTime()) + vestingAccount.OriginalVesting = totalVested + vestingAccount.EndTime = ctx.BlockTime().Unix() // so that all of original vesting is vested now + + // + // + // + + // addr := vestingAccount.GetAddress() + bondDenom, err := m.sk.BondDenom(ctx) + if err != nil { + return nil, fmt.Errorf("failed to get bond denomination") + } + + // Compute the clawback based on bank balance and delegation, and update account + // encumbered := vestingAccount.GetVestingCoins(ctx.BlockTime()) + encumbered := totalVesting // TO-DO ????? + bondedAmt, err := m.sk.GetDelegatorBonded(ctx, vestingAccAddr) + if err != nil { + return nil, fmt.Errorf("error while getting bonded amount: %w", err) + } + unbondingAmt, err := m.sk.GetDelegatorUnbonding(ctx, vestingAccAddr) + if err != nil { + return nil, fmt.Errorf("error while getting unbonding amount: %w", err) + } + bonded := sdk.NewCoins(sdk.NewCoin(bondDenom, bondedAmt)) + unbonding := sdk.NewCoins(sdk.NewCoin(bondDenom, unbondingAmt)) + unbonded := m.bk.GetAllBalances(ctx, vestingAccAddr) + + // + // MODIFYING THIS PART + // + // toClawBack = vestingAccount.updateDelegation(encumbered, toClawBack, bonded, unbonding, unbonded) + delegated := bonded.Add(unbonding...) + oldDelegated := vestingAccount.DelegatedVesting.Add(vestingAccount.DelegatedFree...) + slashed := oldDelegated.Sub(coinsMin(delegated, oldDelegated)...) + total := delegated.Add(unbonded...) + toClawBack := coinsMin(totalVesting, total) // might have been slashed + newDelegated := coinsMin(delegated, total.Sub(totalVesting...)).Add(slashed...) + vestingAccount.DelegatedVesting = coinsMin(encumbered, newDelegated) + vestingAccount.DelegatedFree = newDelegated.Sub(vestingAccount.DelegatedVesting...) + + // Write now now so that the bank module sees unvested tokens are unlocked. + // Note that all store writes are aborted if there is a panic, so there is + // no danger in writing incomplete results. + m.ak.SetAccount(ctx, vestingAccount) + + // + // + // + + // Now that future vesting events (and associated lockup) are removed, + // the balance of the account is unlocked and can be freely transferred. + spendable := m.bk.SpendableCoins(ctx, vestingAccAddr) + toXfer := coinsMin(toClawBack, spendable) + err = m.bk.SendCoins(ctx, vestingAccAddr, funderAddr, toXfer) + if err != nil { + return nil, err // shouldn't happen, given spendable check + } + toClawBack = toClawBack.Sub(toXfer...) + + // We need to traverse the staking data structures to update the + // vesting account bookkeeping, and to recover more funds if necessary. + // Staking is the only way unvested tokens should be missing from the bank balance. + + // If we need more, transfer UnbondingDelegations. + want := toClawBack.AmountOf(bondDenom) + unbondings, err := m.sk.GetUnbondingDelegations(ctx, vestingAccAddr, math.MaxUint16) + if err != nil { + return nil, fmt.Errorf("error while getting unbonding delegations: %w", err) + } + for _, unbonding := range unbondings { + valAddr, err := sdk.ValAddressFromBech32(unbonding.ValidatorAddress) + if err != nil { + panic(err) + } + transferred := m.sk.TransferUnbonding(ctx, vestingAccAddr, funderAddr, valAddr, want) + want = want.Sub(transferred) + if !want.IsPositive() { + break + } + } + + // If we need more, transfer Delegations. + if want.IsPositive() { + delegations, err := m.sk.GetDelegatorDelegations(ctx, vestingAccAddr, math.MaxUint16) + if err != nil { + return nil, fmt.Errorf("error while getting delegations: %w", err) + } + + for _, delegation := range delegations { + validatorAddr, err := sdk.ValAddressFromBech32(delegation.ValidatorAddress) + if err != nil { + panic(err) // shouldn't happen + } + validator, err := m.sk.GetValidator(ctx, validatorAddr) + if err != nil { + // validator has been removed + // TO-DO more specific check? + continue + } + wantShares, err := validator.SharesFromTokensTruncated(want) + if err != nil { + // validator has no tokens + continue + } + transferredShares, err := m.sk.TransferDelegation(ctx, vestingAccAddr, funderAddr, validatorAddr, wantShares) + if err != nil { + panic(err) // shouldn't happen TO-DO + + } + // to be conservative in what we're clawing back, round transferred shares up + transferred := validator.TokensFromSharesRoundUp(transferredShares).RoundInt() + want = want.Sub(transferred) + if !want.IsPositive() { + // Could be slightly negative, due to rounding? + // Don't think so, due to the precautions above. + break + } + } + } + + // If we've transferred everything and still haven't transferred the desired clawback amount, + // then the account must have most some unvested tokens from slashing. + + // + // + // + // + // + // + + // // Compute clawback amount, unlock unvested tokens and remove future vesting events + // // updatedAcc, toClawBack := vestingAccount.ComputeClawback(ctx.BlockTime().Unix()) + + // // totalVested := vestingAccount.GetVestedOnly(time.Unix(clawbackTime, 0)) + // // totalUnvested := vestingAccount.GetUnvestedOnly(time.Unix(clawbackTime, 0)) + + // totalVested := vestingAccount.GetVestedCoins(ctx.BlockTime()) // consider transferred?? + // totalUnvested := vestingAccount.GetVestingCoins(ctx.BlockTime()) // clawback amount + + // // create new vesting account to overwrite + // // TO-DO: or just create a non-vesting account + // newVestingAcc := new(types.ClawbackContinuousVestingAccount) + // var err error + // newVestingAcc.ContinuousVestingAccount, err = sdkvestingtypes.NewContinuousVestingAccount(vestingAccount.BaseAccount, totalVested, vestingAccount.StartTime, vestingAccount.EndTime) + // if err != nil { + // return nil, errorsmod.Wrapf(sdkerrors.ErrUnauthorized, "failed to create continuous vesting account: %s") + // } + // newVestingAcc.OriginalVesting = totalVested + // newVestingAcc.EndTime = ctx.BlockTime().Unix() // so that all of original vesting is vested now + // newVestingAcc.BaseAccount = vestingAccount.BaseAccount + + // m.AccountKeeper.SetAccount(ctx, newVestingAcc) + + // // // Remove all unvested periods from the schedule + // // passedPeriodID := vestingAccount.GetPassedPeriodCount(time.Unix(clawbackTime, 0)) + // // newVestingPeriods := vestingAccount.VestingPeriods[:passedPeriodID] + // // newVestingEnd := vestingAccount.GetStartTime() + newVestingPeriods.TotalLength() + + // // Cap the unlocking schedule to the new total vested. + // // - If lockup has already passed, all vested coins are unlocked. + // // - If lockup has not passed, the vested coins, are still locked. + // // capPeriods := sdkvesting.Periods{ + // // { + // // Length: 0, + // // Amount: totalVested, + // // }, + // // } + + // // minimum of the 2 periods + // // _, newLockingEnd, newLockupPeriods := ConjunctPeriods(vestingAccount.GetStartTime(), vestingAccount.GetStartTime(), vestingAccount.LockupPeriods, capPeriods) + + // // Now construct the new account state + // // vestingAccount.EndTime = Max64(newVestingEnd, newLockingEnd) + // // vestingAccount.LockupPeriods = newLockupPeriods + // // vestingAccount.VestingPeriods = newVestingPeriods + + // // return vestingAccount, totalUnvested + + // /* + // // convert the account back to a normal EthAccount + // // + // // NOTE: this is necessary to allow the bank keeper to send the locked coins away to the + // // destination address. If the account is not converted, the coins will still be seen as locked, + // // and can therefore not be transferred. + // ethAccount := evmostypes.ProtoAccount().(*evmostypes.EthAccount) + // ethAccount.BaseAccount = updatedAcc.BaseAccount + + // // set the account with the updated values of the vesting schedule + // k.accountKeeper.SetAccount(ctx, ethAccount) + + // address := updatedAcc.GetAddress() + + // // NOTE: don't use `SpendableCoins` to get the minimum value to clawback since + // // the amount is retrieved from `ComputeClawback`, which ensures correctness. + // // `SpendableCoins` can result in gas exhaustion if the user has too many + // // different denoms (because of store iteration). + + // // Transfer clawback to the destination (funder) + // // return toClawBack, k.bankKeeper.SendCoins(ctx, address, destinationAddr, toClawBack) + + // // clawedBack, err + // */ + + // err = m.BankKeeper.SendCoins(ctx, newVestingAcc.GetAddress(), funderAddress, totalUnvested) + // if err != nil { + // return nil, errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "failed to claw back '%s' from '%s' to '%s'", totalUnvested.String(), accountAddress.String(), funderAddress.String()) + // } + + // /* + // ctx.EventManager().EmitEvents( + // sdk.Events{ + // sdk.NewEvent( + // types.EventTypeClawback, + // sdk.NewAttribute(types.AttributeKeyFunder, msg.FunderAddress), + // sdk.NewAttribute(types.AttributeKeyAccount, msg.AccountAddress), + // sdk.NewAttribute(types.AttributeKeyDestination, dest.String()), + // ), + // }, + // ) + // */ + + if !want.IsZero() { + panic("want not zero") + } + + return &types.MsgClawbackResponse{ + Coins: toClawBack, + }, nil +} + +func validateAmount(amount sdk.Coins) error { + if !amount.IsValid() { + return sdkerrors.ErrInvalidCoins.Wrap(amount.String()) + } + + if !amount.IsAllPositive() { + return sdkerrors.ErrInvalidCoins.Wrap(amount.String()) + } + + return nil +} + +// coinsMin returns the minimum of its inputs for all denominations. +func coinsMin(a, b sdk.Coins) sdk.Coins { + min := sdk.NewCoins() + for _, coinA := range a { + denom := coinA.Denom + bAmt := b.AmountOfNoDenomValidation(denom) + minAmt := coinA.Amount + if minAmt.GT(bAmt) { + minAmt = bAmt + } + if minAmt.IsPositive() { + min = min.Add(sdk.NewCoin(denom, minAmt)) + } + } + return min +} diff --git a/x/vesting/module.go b/x/vesting/module.go new file mode 100644 index 00000000..b6449f6e --- /dev/null +++ b/x/vesting/module.go @@ -0,0 +1,150 @@ +package vesting + +import ( + "encoding/json" + + abci "github.com/cometbft/cometbft/abci/types" + gwruntime "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/spf13/cobra" + "google.golang.org/grpc" + + "cosmossdk.io/core/address" + "cosmossdk.io/core/appmodule" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + + // "github.com/cosmos/cosmos-sdk/x/auth/vesting/client/cli" + // "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" + + "github.com/sedaprotocol/seda-chain/x/vesting/client/cli" + "github.com/sedaprotocol/seda-chain/x/vesting/keeper" + "github.com/sedaprotocol/seda-chain/x/vesting/types" +) + +var ( + _ module.AppModuleBasic = AppModule{} + + _ appmodule.AppModule = AppModule{} + _ appmodule.HasServices = AppModule{} +) + +// AppModuleBasic defines the basic application module used by the sub-vesting +// module. The module itself contain no special logic or state other than message +// handling. +type AppModuleBasic struct { + ac address.Codec +} + +// Name returns the module's name. +func (AppModuleBasic) Name() string { + return types.ModuleName +} + +// RegisterCodec registers the module's types with the given codec. +func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { + types.RegisterLegacyAminoCodec(cdc) +} + +// RegisterInterfaces registers the module's interfaces and implementations with +// the given interface registry. +func (AppModuleBasic) RegisterInterfaces(registry codectypes.InterfaceRegistry) { + types.RegisterInterfaces(registry) +} + +// DefaultGenesis returns the module's default genesis state as raw bytes. +func (AppModuleBasic) DefaultGenesis(_ codec.JSONCodec) json.RawMessage { + return []byte("{}") +} + +// ValidateGenesis performs genesis state validation. Currently, this is a no-op. +func (AppModuleBasic) ValidateGenesis(_ codec.JSONCodec, _ client.TxEncodingConfig, bz json.RawMessage) error { + return nil +} + +// RegisterGRPCGatewayRoutes registers the module's gRPC Gateway routes. Currently, this +// is a no-op. +func (AppModuleBasic) RegisterGRPCGatewayRoutes(_ client.Context, _ *gwruntime.ServeMux) {} + +// GetTxCmd returns the root tx command for the auth module. +func (ab AppModuleBasic) GetTxCmd() *cobra.Command { + return cli.GetTxCmd(ab.ac) +} + +// AppModule extends the AppModuleBasic implementation by implementing the +// AppModule interface. +type AppModule struct { + AppModuleBasic + + accountKeeper types.AccountKeeper + bankKeeper types.BankKeeper + stakingKeeper types.StakingKeeper +} + +func NewAppModule(ak types.AccountKeeper, bk types.BankKeeper, sk types.StakingKeeper) AppModule { + return AppModule{ + AppModuleBasic: AppModuleBasic{ac: ak.AddressCodec()}, + accountKeeper: ak, + bankKeeper: bk, + stakingKeeper: sk, + } +} + +// IsOnePerModuleType implements the depinject.OnePerModuleType interface. +func (am AppModule) IsOnePerModuleType() {} + +// IsAppModule implements the appmodule.AppModule interface. +func (am AppModule) IsAppModule() {} + +// RegisterServices registers module services. +func (am AppModule) RegisterServices(registrar grpc.ServiceRegistrar) error { + types.RegisterMsgServer(registrar, keeper.NewMsgServerImpl(am.accountKeeper, am.bankKeeper, am.stakingKeeper)) + return nil +} + +// InitGenesis performs a no-op. +func (am AppModule) InitGenesis(_ sdk.Context, _ codec.JSONCodec, _ json.RawMessage) []abci.ValidatorUpdate { + return []abci.ValidatorUpdate{} +} + +// ExportGenesis is always empty, as InitGenesis does nothing either. +func (am AppModule) ExportGenesis(_ sdk.Context, cdc codec.JSONCodec) json.RawMessage { + return am.DefaultGenesis(cdc) +} + +// ConsensusVersion implements AppModule/ConsensusVersion. +func (AppModule) ConsensusVersion() uint64 { return 1 } + +/* TO-DO +// +// App Wiring Setup +// + +func init() { + appmodule.Register(&modulev1.Module{}, + appmodule.Provide(ProvideModule), + ) +} + +type ModuleInputs struct { + depinject.In + + AccountKeeper authkeeper.AccountKeeper + BankKeeper types.BankKeeper +} + +type ModuleOutputs struct { + depinject.Out + + Module appmodule.AppModule +} + +func ProvideModule(in ModuleInputs) ModuleOutputs { + m := NewAppModule(in.AccountKeeper, in.BankKeeper) + + return ModuleOutputs{Module: m} +} +*/ diff --git a/x/vesting/types/codec.go b/x/vesting/types/codec.go new file mode 100644 index 00000000..f213377a --- /dev/null +++ b/x/vesting/types/codec.go @@ -0,0 +1,55 @@ +package types + +import ( + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/codec/legacy" + "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/msgservice" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/cosmos/cosmos-sdk/x/auth/vesting/exported" + authvestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" +) + +// RegisterLegacyAminoCodec registers the vesting interfaces and concrete types on the +// provided LegacyAmino codec. These types are used for Amino JSON serialization +func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { + cdc.RegisterInterface((*exported.VestingAccount)(nil), nil) + cdc.RegisterConcrete(&authvestingtypes.BaseVestingAccount{}, "cosmos-sdk/BaseVestingAccount", nil) + cdc.RegisterConcrete(&authvestingtypes.ContinuousVestingAccount{}, "cosmos-sdk/ContinuousVestingAccount", nil) + cdc.RegisterConcrete(&ClawbackContinuousVestingAccount{}, "sedachain/ClawbackContinuousVestingAccount", nil) + legacy.RegisterAminoMsg(cdc, &MsgCreateVestingAccount{}, "cosmos-sdk/MsgCreateVestingAccount") +} + +// RegisterInterface associates protoName with AccountI and VestingAccount +// Interfaces and creates a registry of it's concrete implementations +func RegisterInterfaces(registry types.InterfaceRegistry) { + registry.RegisterInterface( + "cosmos.vesting.v1beta1.VestingAccount", + (*exported.VestingAccount)(nil), + &authvestingtypes.ContinuousVestingAccount{}, + &ClawbackContinuousVestingAccount{}, + ) + + registry.RegisterImplementations( + (*sdk.AccountI)(nil), + &authvestingtypes.BaseVestingAccount{}, + &authvestingtypes.ContinuousVestingAccount{}, + &ClawbackContinuousVestingAccount{}, + ) + + registry.RegisterImplementations( + (*authtypes.GenesisAccount)(nil), + &authvestingtypes.BaseVestingAccount{}, + &authvestingtypes.ContinuousVestingAccount{}, + &ClawbackContinuousVestingAccount{}, + ) + + registry.RegisterImplementations( + (*sdk.Msg)(nil), + &MsgCreateVestingAccount{}, + &MsgClawback{}, + ) + + msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) +} diff --git a/x/vesting/types/expected_keepers.go b/x/vesting/types/expected_keepers.go new file mode 100644 index 00000000..c9a87945 --- /dev/null +++ b/x/vesting/types/expected_keepers.go @@ -0,0 +1,35 @@ +package types + +import ( + "context" + + "cosmossdk.io/core/address" + "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/staking/types" +) + +type AccountKeeper interface { + AddressCodec() address.Codec + GetAccount(ctx context.Context, addr sdk.AccAddress) sdk.AccountI + NewAccount(ctx context.Context, acc sdk.AccountI) sdk.AccountI + SetAccount(ctx context.Context, acc sdk.AccountI) +} +type BankKeeper interface { + GetAllBalances(ctx context.Context, addr sdk.AccAddress) sdk.Coins + IsSendEnabledCoins(ctx context.Context, coins ...sdk.Coin) error + SendCoins(ctx context.Context, fromAddr, toAddr sdk.AccAddress, amt sdk.Coins) error + BlockedAddr(addr sdk.AccAddress) bool + SpendableCoins(ctx context.Context, addr sdk.AccAddress) sdk.Coins +} + +type StakingKeeper interface { + BondDenom(ctx context.Context) (string, error) + GetValidator(ctx context.Context, addr sdk.ValAddress) (validator types.Validator, err error) + GetDelegatorBonded(ctx context.Context, delegator sdk.AccAddress) (math.Int, error) + GetDelegatorUnbonding(ctx context.Context, delegator sdk.AccAddress) (math.Int, error) + GetUnbondingDelegations(ctx context.Context, delegator sdk.AccAddress, maxRetrieve uint16) (unbondingDelegations []types.UnbondingDelegation, err error) + GetDelegatorDelegations(ctx context.Context, delegator sdk.AccAddress, maxRetrieve uint16) (delegations []types.Delegation, err error) + TransferUnbonding(ctx context.Context, fromAddr, toAddr sdk.AccAddress, valAddr sdk.ValAddress, wantAmt math.Int) math.Int + TransferDelegation(ctx context.Context, fromAddr, toAddr sdk.AccAddress, valAddr sdk.ValAddress, wantShares math.LegacyDec) (math.LegacyDec, error) +} diff --git a/x/vesting/types/msgs.go b/x/vesting/types/msgs.go new file mode 100644 index 00000000..2b82a50e --- /dev/null +++ b/x/vesting/types/msgs.go @@ -0,0 +1,27 @@ +package types + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +var ( + _ sdk.Msg = &MsgCreateVestingAccount{} + _ sdk.Msg = &MsgClawback{} +) + +// NewMsgCreateVestingAccount returns a reference to a new MsgCreateVestingAccount. +func NewMsgCreateVestingAccount(fromAddr, toAddr sdk.AccAddress, amount sdk.Coins, endTime int64) *MsgCreateVestingAccount { + return &MsgCreateVestingAccount{ + FromAddress: fromAddr.String(), + ToAddress: toAddr.String(), + Amount: amount, + EndTime: endTime, + } +} + +func NewMsgClawback(funder, vestingAccount sdk.AccAddress) *MsgClawback { + return &MsgClawback{ + FunderAddress: funder.String(), + AccountAddress: vestingAccount.String(), + } +} diff --git a/x/vesting/types/tx.pb.go b/x/vesting/types/tx.pb.go new file mode 100644 index 00000000..493dcd5f --- /dev/null +++ b/x/vesting/types/tx.pb.go @@ -0,0 +1,1187 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: sedachain/vesting/v1/tx.proto + +package types + +import ( + context "context" + fmt "fmt" + _ "github.com/cosmos/cosmos-proto" + github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types" + types "github.com/cosmos/cosmos-sdk/types" + _ "github.com/cosmos/cosmos-sdk/types/msgservice" + _ "github.com/cosmos/cosmos-sdk/types/tx/amino" + _ "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" + _ "github.com/cosmos/gogoproto/gogoproto" + grpc1 "github.com/cosmos/gogoproto/grpc" + proto "github.com/cosmos/gogoproto/proto" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// MsgCreateVestingAccount defines a message that creates a vesting account. +type MsgCreateVestingAccount struct { + FromAddress string `protobuf:"bytes,1,opt,name=from_address,json=fromAddress,proto3" json:"from_address,omitempty"` + ToAddress string `protobuf:"bytes,2,opt,name=to_address,json=toAddress,proto3" json:"to_address,omitempty"` + Amount github_com_cosmos_cosmos_sdk_types.Coins `protobuf:"bytes,3,rep,name=amount,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"amount"` + // end of vesting as unix time (in seconds). + EndTime int64 `protobuf:"varint,4,opt,name=end_time,json=endTime,proto3" json:"end_time,omitempty"` +} + +func (m *MsgCreateVestingAccount) Reset() { *m = MsgCreateVestingAccount{} } +func (m *MsgCreateVestingAccount) String() string { return proto.CompactTextString(m) } +func (*MsgCreateVestingAccount) ProtoMessage() {} +func (*MsgCreateVestingAccount) Descriptor() ([]byte, []int) { + return fileDescriptor_abaae49a55dd1e8c, []int{0} +} +func (m *MsgCreateVestingAccount) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgCreateVestingAccount) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgCreateVestingAccount.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgCreateVestingAccount) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgCreateVestingAccount.Merge(m, src) +} +func (m *MsgCreateVestingAccount) XXX_Size() int { + return m.Size() +} +func (m *MsgCreateVestingAccount) XXX_DiscardUnknown() { + xxx_messageInfo_MsgCreateVestingAccount.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgCreateVestingAccount proto.InternalMessageInfo + +func (m *MsgCreateVestingAccount) GetFromAddress() string { + if m != nil { + return m.FromAddress + } + return "" +} + +func (m *MsgCreateVestingAccount) GetToAddress() string { + if m != nil { + return m.ToAddress + } + return "" +} + +func (m *MsgCreateVestingAccount) GetAmount() github_com_cosmos_cosmos_sdk_types.Coins { + if m != nil { + return m.Amount + } + return nil +} + +func (m *MsgCreateVestingAccount) GetEndTime() int64 { + if m != nil { + return m.EndTime + } + return 0 +} + +// MsgCreateVestingAccountResponse defines the CreateVestingAccount response type. +type MsgCreateVestingAccountResponse struct { +} + +func (m *MsgCreateVestingAccountResponse) Reset() { *m = MsgCreateVestingAccountResponse{} } +func (m *MsgCreateVestingAccountResponse) String() string { return proto.CompactTextString(m) } +func (*MsgCreateVestingAccountResponse) ProtoMessage() {} +func (*MsgCreateVestingAccountResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_abaae49a55dd1e8c, []int{1} +} +func (m *MsgCreateVestingAccountResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgCreateVestingAccountResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgCreateVestingAccountResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgCreateVestingAccountResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgCreateVestingAccountResponse.Merge(m, src) +} +func (m *MsgCreateVestingAccountResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgCreateVestingAccountResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgCreateVestingAccountResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgCreateVestingAccountResponse proto.InternalMessageInfo + +// MsgClawback defines a message that returns the vesting funds to the funder. +type MsgClawback struct { + // funder_address is the address which funded the account. + FunderAddress string `protobuf:"bytes,1,opt,name=funder_address,json=funderAddress,proto3" json:"funder_address,omitempty"` + // account_address is the address of the vesting to claw back from. + AccountAddress string `protobuf:"bytes,2,opt,name=account_address,json=accountAddress,proto3" json:"account_address,omitempty"` +} + +func (m *MsgClawback) Reset() { *m = MsgClawback{} } +func (m *MsgClawback) String() string { return proto.CompactTextString(m) } +func (*MsgClawback) ProtoMessage() {} +func (*MsgClawback) Descriptor() ([]byte, []int) { + return fileDescriptor_abaae49a55dd1e8c, []int{2} +} +func (m *MsgClawback) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgClawback) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgClawback.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgClawback) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgClawback.Merge(m, src) +} +func (m *MsgClawback) XXX_Size() int { + return m.Size() +} +func (m *MsgClawback) XXX_DiscardUnknown() { + xxx_messageInfo_MsgClawback.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgClawback proto.InternalMessageInfo + +func (m *MsgClawback) GetFunderAddress() string { + if m != nil { + return m.FunderAddress + } + return "" +} + +func (m *MsgClawback) GetAccountAddress() string { + if m != nil { + return m.AccountAddress + } + return "" +} + +// MsgClawbackResponse defines the MsgClawback response type. +type MsgClawbackResponse struct { + // coins is the funds that have been clawed back to the funder. + Coins github_com_cosmos_cosmos_sdk_types.Coins `protobuf:"bytes,1,rep,name=coins,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"coins"` +} + +func (m *MsgClawbackResponse) Reset() { *m = MsgClawbackResponse{} } +func (m *MsgClawbackResponse) String() string { return proto.CompactTextString(m) } +func (*MsgClawbackResponse) ProtoMessage() {} +func (*MsgClawbackResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_abaae49a55dd1e8c, []int{3} +} +func (m *MsgClawbackResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgClawbackResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgClawbackResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgClawbackResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgClawbackResponse.Merge(m, src) +} +func (m *MsgClawbackResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgClawbackResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgClawbackResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgClawbackResponse proto.InternalMessageInfo + +func (m *MsgClawbackResponse) GetCoins() github_com_cosmos_cosmos_sdk_types.Coins { + if m != nil { + return m.Coins + } + return nil +} + +func init() { + proto.RegisterType((*MsgCreateVestingAccount)(nil), "sedachain.vesting.v1.MsgCreateVestingAccount") + proto.RegisterType((*MsgCreateVestingAccountResponse)(nil), "sedachain.vesting.v1.MsgCreateVestingAccountResponse") + proto.RegisterType((*MsgClawback)(nil), "sedachain.vesting.v1.MsgClawback") + proto.RegisterType((*MsgClawbackResponse)(nil), "sedachain.vesting.v1.MsgClawbackResponse") +} + +func init() { proto.RegisterFile("sedachain/vesting/v1/tx.proto", fileDescriptor_abaae49a55dd1e8c) } + +var fileDescriptor_abaae49a55dd1e8c = []byte{ + // 560 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x54, 0x4f, 0x6b, 0x13, 0x41, + 0x14, 0xcf, 0x34, 0xb6, 0xb6, 0x93, 0x5a, 0x71, 0x1b, 0x68, 0xb2, 0xe0, 0x26, 0x5d, 0x14, 0x63, + 0x20, 0xbb, 0x26, 0x22, 0x42, 0xf5, 0xd2, 0x14, 0x3c, 0xd9, 0xcb, 0x2a, 0x22, 0x5e, 0xc2, 0xec, + 0xee, 0x74, 0xbb, 0x34, 0x3b, 0x13, 0x76, 0x26, 0x31, 0x01, 0x0f, 0xe2, 0xd1, 0x93, 0x67, 0x4f, + 0x1e, 0xc5, 0x53, 0x0e, 0x7e, 0x88, 0x1e, 0x8b, 0x27, 0x4f, 0x2a, 0x89, 0x10, 0x3f, 0x86, 0xcc, + 0xce, 0xec, 0x9a, 0x4a, 0x43, 0xe8, 0x25, 0xc9, 0xbc, 0xdf, 0x9f, 0xf7, 0xe6, 0x37, 0x33, 0x81, + 0x37, 0x19, 0xf6, 0x91, 0x77, 0x8c, 0x42, 0x62, 0x0f, 0x30, 0xe3, 0x21, 0x09, 0xec, 0x41, 0xd3, + 0xe6, 0x43, 0xab, 0x17, 0x53, 0x4e, 0xb5, 0x62, 0x06, 0x5b, 0x0a, 0xb6, 0x06, 0x4d, 0xbd, 0x18, + 0xd0, 0x80, 0x26, 0x04, 0x5b, 0xfc, 0x92, 0x5c, 0xdd, 0xf0, 0x28, 0x8b, 0x28, 0xb3, 0x5d, 0xc4, + 0xb0, 0x3d, 0x68, 0xba, 0x98, 0xa3, 0xa6, 0xed, 0xd1, 0x90, 0x28, 0xbc, 0x2c, 0xf1, 0x8e, 0x14, + 0xca, 0x85, 0x82, 0x6e, 0x29, 0xe9, 0xbf, 0x11, 0xa4, 0x3a, 0xed, 0x29, 0x59, 0x3b, 0x8a, 0x15, + 0xb1, 0x64, 0xc8, 0x88, 0xa5, 0xc0, 0x0d, 0x14, 0x85, 0x84, 0xda, 0xc9, 0xa7, 0x2c, 0x99, 0xd3, + 0x15, 0xb8, 0x73, 0xc8, 0x82, 0x83, 0x18, 0x23, 0x8e, 0x5f, 0x48, 0x9b, 0x7d, 0xcf, 0xa3, 0x7d, + 0xc2, 0xb5, 0x47, 0x70, 0xf3, 0x28, 0xa6, 0x51, 0x07, 0xf9, 0x7e, 0x8c, 0x19, 0x2b, 0x81, 0x2a, + 0xa8, 0x6d, 0xb4, 0x4b, 0xdf, 0xbe, 0x36, 0x8a, 0x6a, 0xaa, 0x7d, 0x89, 0x3c, 0xe3, 0x71, 0x48, + 0x02, 0xa7, 0x20, 0xd8, 0xaa, 0xa4, 0x3d, 0x84, 0x90, 0xd3, 0x4c, 0xba, 0xb2, 0x44, 0xba, 0xc1, + 0x69, 0x2a, 0x1c, 0xc1, 0x35, 0x14, 0x89, 0xfe, 0xa5, 0x7c, 0x35, 0x5f, 0x2b, 0xb4, 0xca, 0x96, + 0x52, 0x88, 0xbc, 0x2c, 0xb5, 0x63, 0xeb, 0x80, 0x86, 0xa4, 0xfd, 0xe4, 0xf4, 0x47, 0x25, 0xf7, + 0xe5, 0x67, 0xa5, 0x16, 0x84, 0xfc, 0xb8, 0xef, 0x5a, 0x1e, 0x8d, 0x54, 0x5e, 0xea, 0xab, 0xc1, + 0xfc, 0x13, 0x9b, 0x8f, 0x7a, 0x98, 0x25, 0x02, 0xf6, 0x71, 0x36, 0xae, 0x6f, 0x76, 0x71, 0x80, + 0xbc, 0x51, 0x47, 0x24, 0xce, 0x3e, 0xcf, 0xc6, 0x75, 0xe0, 0xa8, 0x86, 0x5a, 0x19, 0xae, 0x63, + 0xe2, 0x77, 0x78, 0x18, 0xe1, 0xd2, 0x95, 0x2a, 0xa8, 0xe5, 0x9d, 0xab, 0x98, 0xf8, 0xcf, 0xc3, + 0x08, 0xef, 0x3d, 0xfe, 0xf3, 0xa9, 0x02, 0xde, 0x09, 0xf9, 0x7c, 0x24, 0xef, 0x67, 0xe3, 0xba, + 0x39, 0xd7, 0x6a, 0x41, 0x92, 0xe6, 0x2e, 0xac, 0x2c, 0x80, 0x1c, 0xcc, 0x7a, 0x94, 0x30, 0x6c, + 0xc6, 0xb0, 0x20, 0x28, 0x5d, 0xf4, 0xda, 0x45, 0xde, 0x89, 0x76, 0x1b, 0x6e, 0x1d, 0xf5, 0x89, + 0x8f, 0xe3, 0xf3, 0xe9, 0x3b, 0xd7, 0x64, 0x35, 0x0d, 0xeb, 0x0e, 0xbc, 0x8e, 0xa4, 0xd1, 0xf9, + 0xa8, 0x9d, 0x2d, 0x55, 0x56, 0xc4, 0xbd, 0x6d, 0x31, 0xfb, 0x7f, 0x96, 0xe6, 0x10, 0x6e, 0xcf, + 0xf5, 0x4c, 0x47, 0xd1, 0x10, 0x5c, 0x4d, 0xc2, 0x29, 0x81, 0x65, 0x07, 0x70, 0xef, 0xb2, 0x07, + 0xe0, 0x48, 0xe7, 0xd6, 0x6f, 0x00, 0xf3, 0x87, 0x2c, 0xd0, 0xde, 0xc0, 0xe2, 0x85, 0x57, 0xaf, + 0x61, 0x5d, 0xf4, 0xa0, 0xac, 0x05, 0x21, 0xea, 0x0f, 0x2e, 0x45, 0xcf, 0x36, 0xfa, 0x12, 0xae, + 0x67, 0x81, 0xef, 0x2e, 0xb6, 0x50, 0x14, 0xfd, 0xee, 0x52, 0x4a, 0xea, 0xac, 0xaf, 0xbe, 0x15, + 0x17, 0xab, 0xfd, 0xf4, 0x74, 0x62, 0x80, 0xb3, 0x89, 0x01, 0x7e, 0x4d, 0x0c, 0xf0, 0x61, 0x6a, + 0xe4, 0xce, 0xa6, 0x46, 0xee, 0xfb, 0xd4, 0xc8, 0xbd, 0x6a, 0xcd, 0x25, 0x26, 0x5c, 0x93, 0xd7, + 0xe8, 0xd1, 0x6e, 0xb2, 0x68, 0xc8, 0x3f, 0x9a, 0x61, 0xf6, 0xce, 0x93, 0x04, 0xdd, 0xb5, 0x84, + 0x74, 0xff, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xdc, 0x95, 0xfb, 0xaf, 0x8c, 0x04, 0x00, 0x00, +} + +func (this *MsgCreateVestingAccount) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*MsgCreateVestingAccount) + if !ok { + that2, ok := that.(MsgCreateVestingAccount) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.FromAddress != that1.FromAddress { + return false + } + if this.ToAddress != that1.ToAddress { + return false + } + if len(this.Amount) != len(that1.Amount) { + return false + } + for i := range this.Amount { + if !this.Amount[i].Equal(&that1.Amount[i]) { + return false + } + } + if this.EndTime != that1.EndTime { + return false + } + return true +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// MsgClient is the client API for Msg service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type MsgClient interface { + // CreateVestingAccount creates a new vesting account. + CreateVestingAccount(ctx context.Context, in *MsgCreateVestingAccount, opts ...grpc.CallOption) (*MsgCreateVestingAccountResponse, error) + // Clawback returns the vesting funds back to the funder. + Clawback(ctx context.Context, in *MsgClawback, opts ...grpc.CallOption) (*MsgClawbackResponse, error) +} + +type msgClient struct { + cc grpc1.ClientConn +} + +func NewMsgClient(cc grpc1.ClientConn) MsgClient { + return &msgClient{cc} +} + +func (c *msgClient) CreateVestingAccount(ctx context.Context, in *MsgCreateVestingAccount, opts ...grpc.CallOption) (*MsgCreateVestingAccountResponse, error) { + out := new(MsgCreateVestingAccountResponse) + err := c.cc.Invoke(ctx, "/sedachain.vesting.v1.Msg/CreateVestingAccount", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) Clawback(ctx context.Context, in *MsgClawback, opts ...grpc.CallOption) (*MsgClawbackResponse, error) { + out := new(MsgClawbackResponse) + err := c.cc.Invoke(ctx, "/sedachain.vesting.v1.Msg/Clawback", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// MsgServer is the server API for Msg service. +type MsgServer interface { + // CreateVestingAccount creates a new vesting account. + CreateVestingAccount(context.Context, *MsgCreateVestingAccount) (*MsgCreateVestingAccountResponse, error) + // Clawback returns the vesting funds back to the funder. + Clawback(context.Context, *MsgClawback) (*MsgClawbackResponse, error) +} + +// UnimplementedMsgServer can be embedded to have forward compatible implementations. +type UnimplementedMsgServer struct { +} + +func (*UnimplementedMsgServer) CreateVestingAccount(ctx context.Context, req *MsgCreateVestingAccount) (*MsgCreateVestingAccountResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method CreateVestingAccount not implemented") +} +func (*UnimplementedMsgServer) Clawback(ctx context.Context, req *MsgClawback) (*MsgClawbackResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Clawback not implemented") +} + +func RegisterMsgServer(s grpc1.Server, srv MsgServer) { + s.RegisterService(&_Msg_serviceDesc, srv) +} + +func _Msg_CreateVestingAccount_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgCreateVestingAccount) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).CreateVestingAccount(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/sedachain.vesting.v1.Msg/CreateVestingAccount", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).CreateVestingAccount(ctx, req.(*MsgCreateVestingAccount)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_Clawback_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgClawback) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).Clawback(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/sedachain.vesting.v1.Msg/Clawback", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).Clawback(ctx, req.(*MsgClawback)) + } + return interceptor(ctx, in, info, handler) +} + +var _Msg_serviceDesc = grpc.ServiceDesc{ + ServiceName: "sedachain.vesting.v1.Msg", + HandlerType: (*MsgServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "CreateVestingAccount", + Handler: _Msg_CreateVestingAccount_Handler, + }, + { + MethodName: "Clawback", + Handler: _Msg_Clawback_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "sedachain/vesting/v1/tx.proto", +} + +func (m *MsgCreateVestingAccount) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgCreateVestingAccount) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgCreateVestingAccount) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.EndTime != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.EndTime)) + i-- + dAtA[i] = 0x20 + } + if len(m.Amount) > 0 { + for iNdEx := len(m.Amount) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Amount[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + } + if len(m.ToAddress) > 0 { + i -= len(m.ToAddress) + copy(dAtA[i:], m.ToAddress) + i = encodeVarintTx(dAtA, i, uint64(len(m.ToAddress))) + i-- + dAtA[i] = 0x12 + } + if len(m.FromAddress) > 0 { + i -= len(m.FromAddress) + copy(dAtA[i:], m.FromAddress) + i = encodeVarintTx(dAtA, i, uint64(len(m.FromAddress))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgCreateVestingAccountResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgCreateVestingAccountResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgCreateVestingAccountResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *MsgClawback) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgClawback) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgClawback) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.AccountAddress) > 0 { + i -= len(m.AccountAddress) + copy(dAtA[i:], m.AccountAddress) + i = encodeVarintTx(dAtA, i, uint64(len(m.AccountAddress))) + i-- + dAtA[i] = 0x12 + } + if len(m.FunderAddress) > 0 { + i -= len(m.FunderAddress) + copy(dAtA[i:], m.FunderAddress) + i = encodeVarintTx(dAtA, i, uint64(len(m.FunderAddress))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgClawbackResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgClawbackResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgClawbackResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Coins) > 0 { + for iNdEx := len(m.Coins) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Coins[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func encodeVarintTx(dAtA []byte, offset int, v uint64) int { + offset -= sovTx(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *MsgCreateVestingAccount) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.FromAddress) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.ToAddress) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if len(m.Amount) > 0 { + for _, e := range m.Amount { + l = e.Size() + n += 1 + l + sovTx(uint64(l)) + } + } + if m.EndTime != 0 { + n += 1 + sovTx(uint64(m.EndTime)) + } + return n +} + +func (m *MsgCreateVestingAccountResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *MsgClawback) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.FunderAddress) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.AccountAddress) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + return n +} + +func (m *MsgClawbackResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Coins) > 0 { + for _, e := range m.Coins { + l = e.Size() + n += 1 + l + sovTx(uint64(l)) + } + } + return n +} + +func sovTx(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozTx(x uint64) (n int) { + return sovTx(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *MsgCreateVestingAccount) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgCreateVestingAccount: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgCreateVestingAccount: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field FromAddress", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.FromAddress = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ToAddress", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ToAddress = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Amount = append(m.Amount, types.Coin{}) + if err := m.Amount[len(m.Amount)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field EndTime", wireType) + } + m.EndTime = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.EndTime |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgCreateVestingAccountResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgCreateVestingAccountResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgCreateVestingAccountResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgClawback) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgClawback: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgClawback: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field FunderAddress", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.FunderAddress = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AccountAddress", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AccountAddress = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgClawbackResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgClawbackResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgClawbackResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Coins", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Coins = append(m.Coins, types.Coin{}) + if err := m.Coins[len(m.Coins)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipTx(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTx + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTx + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTx + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthTx + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupTx + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthTx + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthTx = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowTx = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupTx = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/vesting/types/types.go b/x/vesting/types/types.go new file mode 100644 index 00000000..d49af9a6 --- /dev/null +++ b/x/vesting/types/types.go @@ -0,0 +1,12 @@ +package types + +const ( + // ModuleName defines the module name + ModuleName = "vesting" + + // StoreKey defines the primary module store key + StoreKey = "vesting" + + // RouterKey defines the module's message routing key + RouterKey = ModuleName +) diff --git a/x/vesting/types/vesting.go b/x/vesting/types/vesting.go new file mode 100644 index 00000000..5d6b882c --- /dev/null +++ b/x/vesting/types/vesting.go @@ -0,0 +1,21 @@ +package types + +import ( + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + vestexported "github.com/cosmos/cosmos-sdk/x/auth/vesting/exported" + vestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" +) + +var ( + _ vestexported.VestingAccount = (*ClawbackContinuousVestingAccount)(nil) + _ authtypes.GenesisAccount = (*ClawbackContinuousVestingAccount)(nil) +) + +// NewContinuousVestingAccountRaw creates a new ContinuousVestingAccount object from BaseVestingAccount +func NewClawbackContinuousVestingAccountRaw(bva *vestingtypes.BaseVestingAccount, startTime int64, funder string) *ClawbackContinuousVestingAccount { + continuousVestingAcc := vestingtypes.NewContinuousVestingAccountRaw(bva, startTime) + return &ClawbackContinuousVestingAccount{ + ContinuousVestingAccount: continuousVestingAcc, + FunderAddress: funder, + } +} diff --git a/x/vesting/types/vesting.pb.go b/x/vesting/types/vesting.pb.go new file mode 100644 index 00000000..e5264cea --- /dev/null +++ b/x/vesting/types/vesting.pb.go @@ -0,0 +1,376 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: sedachain/vesting/v1/vesting.proto + +package types + +import ( + fmt "fmt" + types "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" + _ "github.com/cosmos/gogoproto/gogoproto" + proto "github.com/cosmos/gogoproto/proto" + _ "google.golang.org/protobuf/types/known/timestamppb" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// ClawbackContinuousVestingAccount implements the VestingAccount interface. +// It wraps a ContinuousVestingAccount provided by Cosmos SDK to provide +// additional support for clawback. +type ClawbackContinuousVestingAccount struct { + *types.ContinuousVestingAccount `protobuf:"bytes,1,opt,name=vesting_account,json=vestingAccount,proto3,embedded=vesting_account" json:"vesting_account,omitempty"` + FunderAddress string `protobuf:"bytes,2,opt,name=funder_address,json=funderAddress,proto3" json:"funder_address,omitempty"` +} + +func (m *ClawbackContinuousVestingAccount) Reset() { *m = ClawbackContinuousVestingAccount{} } +func (*ClawbackContinuousVestingAccount) ProtoMessage() {} +func (*ClawbackContinuousVestingAccount) Descriptor() ([]byte, []int) { + return fileDescriptor_f2e41653215b022f, []int{0} +} +func (m *ClawbackContinuousVestingAccount) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ClawbackContinuousVestingAccount) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ClawbackContinuousVestingAccount.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ClawbackContinuousVestingAccount) XXX_Merge(src proto.Message) { + xxx_messageInfo_ClawbackContinuousVestingAccount.Merge(m, src) +} +func (m *ClawbackContinuousVestingAccount) XXX_Size() int { + return m.Size() +} +func (m *ClawbackContinuousVestingAccount) XXX_DiscardUnknown() { + xxx_messageInfo_ClawbackContinuousVestingAccount.DiscardUnknown(m) +} + +var xxx_messageInfo_ClawbackContinuousVestingAccount proto.InternalMessageInfo + +func init() { + proto.RegisterType((*ClawbackContinuousVestingAccount)(nil), "sedachain.vesting.v1.ClawbackContinuousVestingAccount") +} + +func init() { + proto.RegisterFile("sedachain/vesting/v1/vesting.proto", fileDescriptor_f2e41653215b022f) +} + +var fileDescriptor_f2e41653215b022f = []byte{ + // 297 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x2a, 0x4e, 0x4d, 0x49, + 0x4c, 0xce, 0x48, 0xcc, 0xcc, 0xd3, 0x2f, 0x4b, 0x2d, 0x2e, 0xc9, 0xcc, 0x4b, 0xd7, 0x2f, 0x33, + 0x84, 0x31, 0xf5, 0x0a, 0x8a, 0xf2, 0x4b, 0xf2, 0x85, 0x44, 0xe0, 0x6a, 0xf4, 0x60, 0x12, 0x65, + 0x86, 0x52, 0x2a, 0xc9, 0xf9, 0xc5, 0xb9, 0xf9, 0xc5, 0x48, 0xda, 0x92, 0x52, 0x4b, 0x12, 0xd1, + 0xf4, 0x4a, 0x89, 0xa4, 0xe7, 0xa7, 0xe7, 0x83, 0x99, 0xfa, 0x20, 0x16, 0x54, 0x54, 0x3e, 0x3d, + 0x3f, 0x3f, 0x3d, 0x27, 0x55, 0x1f, 0xcc, 0x4b, 0x2a, 0x4d, 0xd3, 0x2f, 0xc9, 0xcc, 0x4d, 0x2d, + 0x2e, 0x49, 0xcc, 0x2d, 0x80, 0x28, 0x50, 0xda, 0xc2, 0xc8, 0xa5, 0xe0, 0x9c, 0x93, 0x58, 0x9e, + 0x94, 0x98, 0x9c, 0xed, 0x9c, 0x9f, 0x57, 0x92, 0x99, 0x57, 0x9a, 0x5f, 0x5a, 0x1c, 0x06, 0x31, + 0xda, 0x31, 0x39, 0x39, 0xbf, 0x34, 0xaf, 0x44, 0x28, 0x9e, 0x8b, 0x1f, 0x6a, 0x59, 0x7c, 0x22, + 0x44, 0x48, 0x82, 0x51, 0x81, 0x51, 0x83, 0xdb, 0xc8, 0x40, 0x0f, 0xe2, 0x36, 0x24, 0xe7, 0x82, + 0xdd, 0xa6, 0x87, 0xcb, 0x28, 0x27, 0x96, 0x0b, 0xf7, 0xe4, 0x19, 0x83, 0xf8, 0xca, 0x50, 0x2d, + 0x50, 0xe5, 0xe2, 0x4b, 0x2b, 0xcd, 0x4b, 0x49, 0x2d, 0x8a, 0x4f, 0x4c, 0x49, 0x29, 0x4a, 0x2d, + 0x2e, 0x96, 0x60, 0x52, 0x60, 0xd4, 0xe0, 0x0c, 0xe2, 0x85, 0x88, 0x3a, 0x42, 0x04, 0xad, 0x38, + 0x3a, 0x16, 0xc8, 0x33, 0xcc, 0x58, 0x20, 0xcf, 0xe0, 0xe4, 0x73, 0xe2, 0x91, 0x1c, 0xe3, 0x85, + 0x47, 0x72, 0x8c, 0x0f, 0x1e, 0xc9, 0x31, 0x4e, 0x78, 0x2c, 0xc7, 0x70, 0xe1, 0xb1, 0x1c, 0xc3, + 0x8d, 0xc7, 0x72, 0x0c, 0x51, 0x46, 0xe9, 0x99, 0x25, 0x19, 0xa5, 0x49, 0x7a, 0xc9, 0xf9, 0xb9, + 0xfa, 0xa0, 0xe0, 0x04, 0x7b, 0x33, 0x39, 0x3f, 0x07, 0xcc, 0xd1, 0x85, 0x44, 0x40, 0x05, 0x3c, + 0x2c, 0x4b, 0x2a, 0x0b, 0x52, 0x8b, 0x93, 0xd8, 0xc0, 0x8a, 0x8c, 0x01, 0x01, 0x00, 0x00, 0xff, + 0xff, 0xc0, 0x93, 0x9a, 0xdf, 0xa4, 0x01, 0x00, 0x00, +} + +func (m *ClawbackContinuousVestingAccount) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ClawbackContinuousVestingAccount) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ClawbackContinuousVestingAccount) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.FunderAddress) > 0 { + i -= len(m.FunderAddress) + copy(dAtA[i:], m.FunderAddress) + i = encodeVarintVesting(dAtA, i, uint64(len(m.FunderAddress))) + i-- + dAtA[i] = 0x12 + } + if m.ContinuousVestingAccount != nil { + { + size, err := m.ContinuousVestingAccount.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintVesting(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintVesting(dAtA []byte, offset int, v uint64) int { + offset -= sovVesting(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *ClawbackContinuousVestingAccount) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ContinuousVestingAccount != nil { + l = m.ContinuousVestingAccount.Size() + n += 1 + l + sovVesting(uint64(l)) + } + l = len(m.FunderAddress) + if l > 0 { + n += 1 + l + sovVesting(uint64(l)) + } + return n +} + +func sovVesting(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozVesting(x uint64) (n int) { + return sovVesting(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *ClawbackContinuousVestingAccount) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowVesting + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ClawbackContinuousVestingAccount: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ClawbackContinuousVestingAccount: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ContinuousVestingAccount", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowVesting + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthVesting + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthVesting + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.ContinuousVestingAccount == nil { + m.ContinuousVestingAccount = &types.ContinuousVestingAccount{} + } + if err := m.ContinuousVestingAccount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field FunderAddress", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowVesting + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthVesting + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthVesting + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.FunderAddress = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipVesting(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthVesting + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipVesting(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowVesting + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowVesting + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowVesting + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthVesting + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupVesting + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthVesting + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthVesting = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowVesting = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupVesting = fmt.Errorf("proto: unexpected end of group") +) From d52dbfbe4653abe70525cb6fdc1aab7c369ebe3b Mon Sep 17 00:00:00 2001 From: hacheigriega Date: Sat, 10 Feb 2024 14:40:51 -0500 Subject: [PATCH 02/15] feat: vesting bug fixes and simple integration testing --- app/integration.go | 206 ++++++++++++ proto/sedachain/vesting/v1/tx.proto | 62 ++++ proto/sedachain/vesting/v1/vesting.proto | 19 ++ x/vesting/keeper/integration_test.go | 226 +++++++++++++ x/vesting/testutil/expected_keepers_mocks.go | 333 +++++++++++++++++++ 5 files changed, 846 insertions(+) create mode 100644 app/integration.go create mode 100644 proto/sedachain/vesting/v1/tx.proto create mode 100644 proto/sedachain/vesting/v1/vesting.proto create mode 100644 x/vesting/keeper/integration_test.go create mode 100644 x/vesting/testutil/expected_keepers_mocks.go diff --git a/app/integration.go b/app/integration.go new file mode 100644 index 00000000..ef0ccab0 --- /dev/null +++ b/app/integration.go @@ -0,0 +1,206 @@ +package app + +import ( + "fmt" + "time" + + cmtabcitypes "github.com/cometbft/cometbft/abci/types" + cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" + dbm "github.com/cosmos/cosmos-db" + + "cosmossdk.io/core/appmodule" + "cosmossdk.io/log" + "cosmossdk.io/store" + "cosmossdk.io/store/metrics" + storetypes "cosmossdk.io/store/types" + + "github.com/cosmos/cosmos-sdk/baseapp" + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/runtime" + "github.com/cosmos/cosmos-sdk/testutil/integration" + simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + authtx "github.com/cosmos/cosmos-sdk/x/auth/tx" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + consensusparamkeeper "github.com/cosmos/cosmos-sdk/x/consensus/keeper" + consensusparamtypes "github.com/cosmos/cosmos-sdk/x/consensus/types" +) + +const appName = "integration-app" + +// IntegationApp is a test application that can be used to test the integration of modules. +type IntegationApp struct { + *baseapp.BaseApp + + ctx sdk.Context + logger log.Logger + moduleManager module.Manager + queryHelper *baseapp.QueryServiceTestHelper +} + +// NewIntegrationApp creates an application for testing purposes. This application +// is able to route messages to their respective handlers. +func NewIntegrationApp( + sdkCtx sdk.Context, + logger log.Logger, + keys map[string]*storetypes.KVStoreKey, + appCodec codec.Codec, + modules map[string]appmodule.AppModule, +) *IntegationApp { + db := dbm.NewMemDB() + + interfaceRegistry := codectypes.NewInterfaceRegistry() + moduleManager := module.NewManagerFromMap(modules) + basicModuleManager := module.NewBasicManagerFromManager(moduleManager, nil) + basicModuleManager.RegisterInterfaces(interfaceRegistry) + + txConfig := authtx.NewTxConfig(codec.NewProtoCodec(interfaceRegistry), authtx.DefaultSignModes) + bApp := baseapp.NewBaseApp(appName, logger, db, txConfig.TxDecoder(), baseapp.SetChainID(appName)) + bApp.MountKVStores(keys) + + bApp.SetInitChainer(func(ctx sdk.Context, _ *cmtabcitypes.RequestInitChain) (*cmtabcitypes.ResponseInitChain, error) { + for _, mod := range modules { + if m, ok := mod.(module.HasGenesis); ok { + m.InitGenesis(ctx, appCodec, m.DefaultGenesis(appCodec)) + } + } + + return &cmtabcitypes.ResponseInitChain{}, nil + }) + + bApp.SetBeginBlocker(func(_ sdk.Context) (sdk.BeginBlock, error) { + return moduleManager.BeginBlock(sdkCtx) + }) + bApp.SetEndBlocker(func(_ sdk.Context) (sdk.EndBlock, error) { + return moduleManager.EndBlock(sdkCtx) + }) + + router := baseapp.NewMsgServiceRouter() + router.SetInterfaceRegistry(interfaceRegistry) + bApp.SetMsgServiceRouter(router) + + if keys[consensusparamtypes.StoreKey] != nil { + // set baseApp param store + consensusParamsKeeper := consensusparamkeeper.NewKeeper(appCodec, runtime.NewKVStoreService(keys[consensusparamtypes.StoreKey]), authtypes.NewModuleAddress("gov").String(), runtime.EventService{}) + bApp.SetParamStore(consensusParamsKeeper.ParamsStore) + + if err := bApp.LoadLatestVersion(); err != nil { + panic(fmt.Errorf("failed to load application version from store: %w", err)) + } + + if _, err := bApp.InitChain(&cmtabcitypes.RequestInitChain{ChainId: appName, ConsensusParams: simtestutil.DefaultConsensusParams}); err != nil { + panic(fmt.Errorf("failed to initialize application: %w", err)) + } + } else { + if err := bApp.LoadLatestVersion(); err != nil { + panic(fmt.Errorf("failed to load application version from store: %w", err)) + } + + // app.NewDefaultGenesisState(bApp.AppCodec()) + // req := &abci.RequestInitChain{ + // AppStateBytes: appState, + // ChainId: appName, + // ConsensusParams: consensusParams, + // Time: genesisTimestamp, + // } + + if _, err := bApp.InitChain(&cmtabcitypes.RequestInitChain{ChainId: appName}); err != nil { + // if _, err := bApp.InitChain(req); err != nil { + panic(fmt.Errorf("failed to initialize application: %w", err)) + } + } + + bApp.Commit() + + ctx := sdkCtx.WithBlockHeader(cmtproto.Header{ChainID: appName, Time: time.Now()}).WithIsCheckTx(true) + + return &IntegationApp{ + BaseApp: bApp, + logger: logger, + ctx: ctx, + moduleManager: *moduleManager, + queryHelper: baseapp.NewQueryServerTestHelper(ctx, interfaceRegistry), + } +} + +// RunMsg provides the ability to run a message and return the response. +// In order to run a message, the application must have a handler for it. +// These handlers are registered on the application message service router. +// The result of the message execution is returned as an Any type. +// That any type can be unmarshaled to the expected response type. +// If the message execution fails, an error is returned. +func (app *IntegationApp) RunMsg(msg sdk.Msg, option ...integration.Option) (*codectypes.Any, error) { + // set options + cfg := &integration.Config{} + for _, opt := range option { + opt(cfg) + } + + if cfg.AutomaticCommit { + defer app.Commit() + } + + if cfg.AutomaticFinalizeBlock { + height := app.LastBlockHeight() + 1 + if _, err := app.FinalizeBlock(&cmtabcitypes.RequestFinalizeBlock{Height: height}); err != nil { + return nil, fmt.Errorf("failed to run finalize block: %w", err) + } + } + + app.logger.Info("Running msg", "msg", msg.String()) + + handler := app.MsgServiceRouter().Handler(msg) + if handler == nil { + return nil, fmt.Errorf("handler is nil, can't route message %s: %+v", sdk.MsgTypeURL(msg), msg) + } + + msgResult, err := handler(app.ctx, msg) + if err != nil { + return nil, fmt.Errorf("failed to execute message %s: %w", sdk.MsgTypeURL(msg), err) + } + + var response *codectypes.Any + if len(msgResult.MsgResponses) > 0 { + msgResponse := msgResult.MsgResponses[0] + if msgResponse == nil { + return nil, fmt.Errorf("got nil msg response %s in message result: %s", sdk.MsgTypeURL(msg), msgResult.String()) + } + + response = msgResponse + } + + return response, nil +} + +// Context returns the application context. It can be unwrapped to a sdk.Context, +// with the sdk.UnwrapSDKContext function. +func (app *IntegationApp) Context() sdk.Context { + return app.ctx +} + +// AddTime adds time to the application context. +func (app *IntegationApp) AddTime(seconds int64) { + newTime := app.ctx.BlockHeader().Time.Add(time.Duration(int64(time.Second) * seconds)) + app.ctx = app.ctx.WithBlockTime(newTime) +} + +// QueryHelper returns the application query helper. +// It can be used when registering query services. +func (app *IntegationApp) QueryHelper() *baseapp.QueryServiceTestHelper { + return app.queryHelper +} + +// CreateMultiStore is a helper for setting up multiple stores for provided modules. +func CreateMultiStore(keys map[string]*storetypes.KVStoreKey, logger log.Logger) storetypes.CommitMultiStore { + db := dbm.NewMemDB() + cms := store.NewCommitMultiStore(db, logger, metrics.NewNoOpMetrics()) + + for key := range keys { + cms.MountStoreWithDB(keys[key], storetypes.StoreTypeIAVL, db) + } + + _ = cms.LoadLatestVersion() + return cms +} diff --git a/proto/sedachain/vesting/v1/tx.proto b/proto/sedachain/vesting/v1/tx.proto new file mode 100644 index 00000000..e5c19218 --- /dev/null +++ b/proto/sedachain/vesting/v1/tx.proto @@ -0,0 +1,62 @@ +syntax = "proto3"; +package sedachain.vesting.v1; + +import "gogoproto/gogo.proto"; +import "cosmos/base/v1beta1/coin.proto"; +import "cosmos_proto/cosmos.proto"; +import "cosmos/vesting/v1beta1/vesting.proto"; +import "cosmos/msg/v1/msg.proto"; +import "amino/amino.proto"; + +option go_package = "github.com/sedaprotocol/seda-chain/x/vesting/types"; + +// Msg defines the bank Msg service. +service Msg { + option (cosmos.msg.v1.service) = true; + + // CreateVestingAccount creates a new vesting account. + rpc CreateVestingAccount(MsgCreateVestingAccount) returns (MsgCreateVestingAccountResponse); + + // Clawback returns the vesting funds back to the funder. + rpc Clawback(MsgClawback) returns (MsgClawbackResponse); +} + +// MsgCreateVestingAccount defines a message that creates a vesting account. +message MsgCreateVestingAccount { + option (cosmos.msg.v1.signer) = "from_address"; + option (amino.name) = "cosmos-sdk/MsgCreateVestingAccount"; + + option (gogoproto.equal) = true; + + string from_address = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + string to_address = 2 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + repeated cosmos.base.v1beta1.Coin amount = 3 [ + (gogoproto.nullable) = false, + (amino.dont_omitempty) = true, + (amino.encoding) = "legacy_coins", + (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins" + ]; + + // end of vesting as unix time (in seconds). + int64 end_time = 4; +} + +// MsgCreateVestingAccountResponse defines the CreateVestingAccount response type. +message MsgCreateVestingAccountResponse {} + +// MsgClawback defines a message that returns the vesting funds to the funder. +message MsgClawback { + option (cosmos.msg.v1.signer) = "funder_address"; + + // funder_address is the address which funded the account. + string funder_address = 1; + // account_address is the address of the vesting to claw back from. + string account_address = 2; +} + +// MsgClawbackResponse defines the MsgClawback response type. +message MsgClawbackResponse { + // coins is the funds that have been clawed back to the funder. + repeated cosmos.base.v1beta1.Coin coins = 1 + [(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins", (gogoproto.nullable) = false]; +} diff --git a/proto/sedachain/vesting/v1/vesting.proto b/proto/sedachain/vesting/v1/vesting.proto new file mode 100644 index 00000000..8556fafa --- /dev/null +++ b/proto/sedachain/vesting/v1/vesting.proto @@ -0,0 +1,19 @@ +syntax = "proto3"; +package sedachain.vesting.v1; + +import "cosmos/vesting/v1beta1/vesting.proto"; +import "gogoproto/gogo.proto"; +import "google/protobuf/timestamp.proto"; + +option go_package = "github.com/sedaprotocol/seda-chain/x/vesting/types"; + +// ClawbackContinuousVestingAccount implements the VestingAccount interface. +// It wraps a ContinuousVestingAccount provided by Cosmos SDK to provide +// additional support for clawback. +message ClawbackContinuousVestingAccount { + option (gogoproto.goproto_getters) = false; + option (gogoproto.goproto_stringer) = false; + + cosmos.vesting.v1beta1.ContinuousVestingAccount vesting_account = 1 [(gogoproto.embed) = true]; + string funder_address = 2; +} diff --git a/x/vesting/keeper/integration_test.go b/x/vesting/keeper/integration_test.go new file mode 100644 index 00000000..f4a59e23 --- /dev/null +++ b/x/vesting/keeper/integration_test.go @@ -0,0 +1,226 @@ +package keeper_test + +import ( + "fmt" + "testing" + "time" + + "cosmossdk.io/core/appmodule" + "cosmossdk.io/log" + storetypes "cosmossdk.io/store/types" + "github.com/stretchr/testify/require" + + cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" + + "github.com/cosmos/cosmos-sdk/codec" + addresscodec "github.com/cosmos/cosmos-sdk/codec/address" + "github.com/cosmos/cosmos-sdk/runtime" + "github.com/cosmos/cosmos-sdk/testutil/integration" + sdk "github.com/cosmos/cosmos-sdk/types" + moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" + "github.com/cosmos/cosmos-sdk/x/auth" + authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/cosmos/cosmos-sdk/x/bank" + bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" + banktestutil "github.com/cosmos/cosmos-sdk/x/bank/testutil" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + + minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" + sdkstakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + + "github.com/sedaprotocol/seda-chain/app" + "github.com/sedaprotocol/seda-chain/app/params" + "github.com/sedaprotocol/seda-chain/x/staking" + stakingkeeper "github.com/sedaprotocol/seda-chain/x/staking/keeper" + "github.com/sedaprotocol/seda-chain/x/vesting" + "github.com/sedaprotocol/seda-chain/x/vesting/keeper" + "github.com/sedaprotocol/seda-chain/x/vesting/types" +) + +const Bech32Prefix = "seda" + +var ( + fromAddr = sdk.AccAddress([]byte("from1________________")) + to1Addr = sdk.AccAddress([]byte("to1__________________")) + to2Addr = sdk.AccAddress([]byte("to2__________________")) + to3Addr = sdk.AccAddress([]byte("to3__________________")) + bondDenom = "aseda" + fooCoin = sdk.NewInt64Coin(bondDenom, 10000) + barCoin = sdk.NewInt64Coin(bondDenom, 7000) + zeroCoin = sdk.NewInt64Coin(bondDenom, 0) +) + +type fixture struct { + // ctx sdk.Context + + app *app.IntegationApp + // queryClient v1.QueryClient + // legacyQueryClient v1beta1.QueryClient + cdc codec.Codec + + accountKeeper authkeeper.AccountKeeper + bankKeeper bankkeeper.Keeper + stakingKeeper stakingkeeper.Keeper +} + +func initFixture(tb testing.TB) *fixture { + tb.Helper() + keys := storetypes.NewKVStoreKeys( + authtypes.StoreKey, banktypes.StoreKey, stakingtypes.StoreKey, types.StoreKey, //pooltypes.StoreKey, + ) + cdc := moduletestutil.MakeTestEncodingConfig(auth.AppModuleBasic{}, bank.AppModuleBasic{}, vesting.AppModuleBasic{}).Codec + + logger := log.NewTestLogger(tb) + cms := integration.CreateMultiStore(keys, logger) + + newCtx := sdk.NewContext(cms, cmtproto.Header{Time: time.Now().UTC()}, true, logger) + + authority := authtypes.NewModuleAddress(types.ModuleName) + + maccPerms := map[string][]string{ + minttypes.ModuleName: {authtypes.Minter}, + stakingtypes.BondedPoolName: {authtypes.Burner, authtypes.Staking}, + stakingtypes.NotBondedPoolName: {authtypes.Burner, authtypes.Staking}, + types.ModuleName: {authtypes.Burner}, + } + + accountKeeper := authkeeper.NewAccountKeeper( + cdc, + runtime.NewKVStoreService(keys[authtypes.StoreKey]), + authtypes.ProtoBaseAccount, + maccPerms, + addresscodec.NewBech32Codec(params.Bech32PrefixAccAddr), + params.Bech32PrefixAccAddr, + authority.String(), + ) + + blockedAddresses := map[string]bool{ + accountKeeper.GetAuthority(): false, + } + bankKeeper := bankkeeper.NewBaseKeeper( + cdc, + runtime.NewKVStoreService(keys[banktypes.StoreKey]), + accountKeeper, + blockedAddresses, + authority.String(), + log.NewNopLogger(), + ) + + sdkstakingKeeper := sdkstakingkeeper.NewKeeper(cdc, runtime.NewKVStoreService(keys[stakingtypes.StoreKey]), accountKeeper, bankKeeper, authority.String(), addresscodec.NewBech32Codec(params.Bech32PrefixValAddr), addresscodec.NewBech32Codec(params.Bech32PrefixConsAddr)) + stakingKeeper := stakingkeeper.NewKeeper(sdkstakingKeeper) + + // set default staking params + stakingParams := stakingtypes.DefaultParams() + stakingParams.BondDenom = "aseda" + err := stakingKeeper.SetParams(newCtx, stakingParams) + require.NoError(tb, err) + + // Create MsgServiceRouter, but don't populate it before creating the gov + // keeper. + // router := baseapp.NewMsgServiceRouter() + // router.SetInterfaceRegistry(cdc.InterfaceRegistry()) + + authModule := auth.NewAppModule(cdc, accountKeeper, app.RandomGenesisAccounts, nil) + bankModule := bank.NewAppModule(cdc, bankKeeper, accountKeeper, nil) + stakingModule := staking.NewAppModule(cdc, stakingKeeper, accountKeeper, bankKeeper, nil) + vestingModule := vesting.NewAppModule(accountKeeper, bankKeeper, stakingKeeper) + + integrationApp := app.NewIntegrationApp(newCtx, logger, keys, cdc, map[string]appmodule.AppModule{ + authtypes.ModuleName: authModule, + banktypes.ModuleName: bankModule, + stakingtypes.ModuleName: stakingModule, + types.ModuleName: vestingModule, + }) + + // sdkCtx := sdk.UnwrapSDKContext(integrationApp.Context()) + + // msgSrvr := keeper.NewMsgServerImpl(govKeeper) + // legacyMsgSrvr := keeper.NewLegacyMsgServerImpl(authority.String(), msgSrvr) + + // // Register MsgServer and QueryServer + types.RegisterMsgServer(integrationApp.MsgServiceRouter(), keeper.NewMsgServerImpl(accountKeeper, bankKeeper, stakingKeeper)) + // v1beta1.RegisterMsgServer(router, legacyMsgSrvr) + + // v1.RegisterQueryServer(integrationApp.QueryHelper(), keeper.NewQueryServer(govKeeper)) + // v1beta1.RegisterQueryServer(integrationApp.QueryHelper(), keeper.NewLegacyQueryServer(govKeeper)) + + // queryClient := v1.NewQueryClient(integrationApp.QueryHelper()) + // legacyQueryClient := v1beta1.NewQueryClient(integrationApp.QueryHelper()) + + return &fixture{ + app: integrationApp, + cdc: cdc, + // ctx: sdkCtx, + // queryClient: queryClient, + // legacyQueryClient: legacyQueryClient, + accountKeeper: accountKeeper, + bankKeeper: bankKeeper, + stakingKeeper: *stakingKeeper, + // govKeeper: govKeeper, + } +} + +func TestClawbackContinuousVesting(t *testing.T) { + f := initFixture(t) + + // _ = f.ctx + + funderAddr := sdk.MustAccAddressFromBech32("seda1gujynygp0tkwzfpt0g7dv4829jwyk8f0yhp88d") // TO-DO cosmos139f7kncmglres2nf3h4hc4tade85ekfr8sulz5 + accountAddr := sdk.MustAccAddressFromBech32("seda1ucv5709wlf9jn84ynyjzyzeavwvurmdyxat26l") // TO-DO cosmos1x33fy6rusfprkntvjsfregss7rvsvyy4lkwrqu + + originalVesting := sdk.NewCoins(fooCoin) + endTime := f.app.Context().BlockTime().Unix() + 100 + // bondedAmt := math.NewInt(0) + // unbondingAmt := math.NewInt(0) + // unbonded := originalVesting // TO-DO why? GetAllBalances + + // msg := &types.MsgClawback{ + // FunderAddress: funderAddr.String(), + // AccountAddress: accountAddr.String(), + // } + + // funderAcc := authtypes.NewBaseAccountWithAddress(funderAddr) + // baseAccount := authtypes.NewBaseAccountWithAddress(accountAddr) + // baseVestingAccount, err := sdkvestingtypes.NewBaseVestingAccount(baseAccount, originalVesting, endTime) + // require.NoError(t, err) + // vestingAccount := types.NewClawbackContinuousVestingAccountRaw(baseVestingAccount, f.ctx.BlockTime().Unix(), msg.FunderAddress) + // f.accountKeeper.SetAccount(f.ctx, vestingAccount) + + f.bankKeeper.SetSendEnabled(f.app.Context(), "aseda", true) + + err := banktestutil.FundAccount(f.app.Context(), f.bankKeeper, funderAddr, sdk.NewCoins(fooCoin)) + require.NoError(t, err) + + // 1. create clawback continuous vesting account + msg := &types.MsgCreateVestingAccount{ + FromAddress: funderAddr.String(), + ToAddress: accountAddr.String(), + Amount: originalVesting, + EndTime: endTime, + } + res, err := f.app.RunMsg(msg) + require.NoError(t, err) + fmt.Println(res) + + // 2. clawback after some time + f.app.AddTime(30) + clawbackMsg := &types.MsgClawback{ + FunderAddress: funderAddr.String(), + AccountAddress: accountAddr.String(), // TO-DO rename to RecipientAddress? + } + res, err = f.app.RunMsg(clawbackMsg) + require.NoError(t, err) + + result := types.MsgClawbackResponse{} + err = f.cdc.Unmarshal(res.Value, &result) + require.NoError(t, err) + fmt.Println(result) + + require.Equal(t, sdk.NewCoins(barCoin), result.Coins) + // createValidators(t, f, []int64{5, 5, 5}) +} + +// Test when 0 time has passed +// toXfer seems to be 0 diff --git a/x/vesting/testutil/expected_keepers_mocks.go b/x/vesting/testutil/expected_keepers_mocks.go new file mode 100644 index 00000000..4afcd75a --- /dev/null +++ b/x/vesting/testutil/expected_keepers_mocks.go @@ -0,0 +1,333 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: x/vesting/types/expected_keepers.go + +// Package testutil is a generated GoMock package. +package testutil + +import ( + context "context" + reflect "reflect" + + address "cosmossdk.io/core/address" + math "cosmossdk.io/math" + types "github.com/cosmos/cosmos-sdk/types" + types0 "github.com/cosmos/cosmos-sdk/x/staking/types" + gomock "github.com/golang/mock/gomock" +) + +// MockAccountKeeper is a mock of AccountKeeper interface. +type MockAccountKeeper struct { + ctrl *gomock.Controller + recorder *MockAccountKeeperMockRecorder +} + +// MockAccountKeeperMockRecorder is the mock recorder for MockAccountKeeper. +type MockAccountKeeperMockRecorder struct { + mock *MockAccountKeeper +} + +// NewMockAccountKeeper creates a new mock instance. +func NewMockAccountKeeper(ctrl *gomock.Controller) *MockAccountKeeper { + mock := &MockAccountKeeper{ctrl: ctrl} + mock.recorder = &MockAccountKeeperMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockAccountKeeper) EXPECT() *MockAccountKeeperMockRecorder { + return m.recorder +} + +// AddressCodec mocks base method. +func (m *MockAccountKeeper) AddressCodec() address.Codec { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "AddressCodec") + ret0, _ := ret[0].(address.Codec) + return ret0 +} + +// AddressCodec indicates an expected call of AddressCodec. +func (mr *MockAccountKeeperMockRecorder) AddressCodec() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddressCodec", reflect.TypeOf((*MockAccountKeeper)(nil).AddressCodec)) +} + +// GetAccount mocks base method. +func (m *MockAccountKeeper) GetAccount(ctx context.Context, addr types.AccAddress) types.AccountI { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetAccount", ctx, addr) + ret0, _ := ret[0].(types.AccountI) + return ret0 +} + +// GetAccount indicates an expected call of GetAccount. +func (mr *MockAccountKeeperMockRecorder) GetAccount(ctx, addr interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAccount", reflect.TypeOf((*MockAccountKeeper)(nil).GetAccount), ctx, addr) +} + +// NewAccount mocks base method. +func (m *MockAccountKeeper) NewAccount(ctx context.Context, acc types.AccountI) types.AccountI { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "NewAccount", ctx, acc) + ret0, _ := ret[0].(types.AccountI) + return ret0 +} + +// NewAccount indicates an expected call of NewAccount. +func (mr *MockAccountKeeperMockRecorder) NewAccount(ctx, acc interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewAccount", reflect.TypeOf((*MockAccountKeeper)(nil).NewAccount), ctx, acc) +} + +// SetAccount mocks base method. +func (m *MockAccountKeeper) SetAccount(ctx context.Context, acc types.AccountI) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "SetAccount", ctx, acc) +} + +// SetAccount indicates an expected call of SetAccount. +func (mr *MockAccountKeeperMockRecorder) SetAccount(ctx, acc interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetAccount", reflect.TypeOf((*MockAccountKeeper)(nil).SetAccount), ctx, acc) +} + +// MockBankKeeper is a mock of BankKeeper interface. +type MockBankKeeper struct { + ctrl *gomock.Controller + recorder *MockBankKeeperMockRecorder +} + +// MockBankKeeperMockRecorder is the mock recorder for MockBankKeeper. +type MockBankKeeperMockRecorder struct { + mock *MockBankKeeper +} + +// NewMockBankKeeper creates a new mock instance. +func NewMockBankKeeper(ctrl *gomock.Controller) *MockBankKeeper { + mock := &MockBankKeeper{ctrl: ctrl} + mock.recorder = &MockBankKeeperMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockBankKeeper) EXPECT() *MockBankKeeperMockRecorder { + return m.recorder +} + +// BlockedAddr mocks base method. +func (m *MockBankKeeper) BlockedAddr(addr types.AccAddress) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "BlockedAddr", addr) + ret0, _ := ret[0].(bool) + return ret0 +} + +// BlockedAddr indicates an expected call of BlockedAddr. +func (mr *MockBankKeeperMockRecorder) BlockedAddr(addr interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BlockedAddr", reflect.TypeOf((*MockBankKeeper)(nil).BlockedAddr), addr) +} + +// GetAllBalances mocks base method. +func (m *MockBankKeeper) GetAllBalances(ctx context.Context, addr types.AccAddress) types.Coins { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetAllBalances", ctx, addr) + ret0, _ := ret[0].(types.Coins) + return ret0 +} + +// GetAllBalances indicates an expected call of GetAllBalances. +func (mr *MockBankKeeperMockRecorder) GetAllBalances(ctx, addr interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAllBalances", reflect.TypeOf((*MockBankKeeper)(nil).GetAllBalances), ctx, addr) +} + +// IsSendEnabledCoins mocks base method. +func (m *MockBankKeeper) IsSendEnabledCoins(ctx context.Context, coins ...types.Coin) error { + m.ctrl.T.Helper() + varargs := []interface{}{ctx} + for _, a := range coins { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "IsSendEnabledCoins", varargs...) + ret0, _ := ret[0].(error) + return ret0 +} + +// IsSendEnabledCoins indicates an expected call of IsSendEnabledCoins. +func (mr *MockBankKeeperMockRecorder) IsSendEnabledCoins(ctx interface{}, coins ...interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]interface{}{ctx}, coins...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsSendEnabledCoins", reflect.TypeOf((*MockBankKeeper)(nil).IsSendEnabledCoins), varargs...) +} + +// SendCoins mocks base method. +func (m *MockBankKeeper) SendCoins(ctx context.Context, fromAddr, toAddr types.AccAddress, amt types.Coins) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SendCoins", ctx, fromAddr, toAddr, amt) + ret0, _ := ret[0].(error) + return ret0 +} + +// SendCoins indicates an expected call of SendCoins. +func (mr *MockBankKeeperMockRecorder) SendCoins(ctx, fromAddr, toAddr, amt interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendCoins", reflect.TypeOf((*MockBankKeeper)(nil).SendCoins), ctx, fromAddr, toAddr, amt) +} + +// SpendableCoins mocks base method. +func (m *MockBankKeeper) SpendableCoins(ctx context.Context, addr types.AccAddress) types.Coins { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SpendableCoins", ctx, addr) + ret0, _ := ret[0].(types.Coins) + return ret0 +} + +// SpendableCoins indicates an expected call of SpendableCoins. +func (mr *MockBankKeeperMockRecorder) SpendableCoins(ctx, addr interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SpendableCoins", reflect.TypeOf((*MockBankKeeper)(nil).SpendableCoins), ctx, addr) +} + +// MockStakingKeeper is a mock of StakingKeeper interface. +type MockStakingKeeper struct { + ctrl *gomock.Controller + recorder *MockStakingKeeperMockRecorder +} + +// MockStakingKeeperMockRecorder is the mock recorder for MockStakingKeeper. +type MockStakingKeeperMockRecorder struct { + mock *MockStakingKeeper +} + +// NewMockStakingKeeper creates a new mock instance. +func NewMockStakingKeeper(ctrl *gomock.Controller) *MockStakingKeeper { + mock := &MockStakingKeeper{ctrl: ctrl} + mock.recorder = &MockStakingKeeperMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockStakingKeeper) EXPECT() *MockStakingKeeperMockRecorder { + return m.recorder +} + +// BondDenom mocks base method. +func (m *MockStakingKeeper) BondDenom(ctx context.Context) (string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "BondDenom", ctx) + ret0, _ := ret[0].(string) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// BondDenom indicates an expected call of BondDenom. +func (mr *MockStakingKeeperMockRecorder) BondDenom(ctx interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BondDenom", reflect.TypeOf((*MockStakingKeeper)(nil).BondDenom), ctx) +} + +// GetDelegatorBonded mocks base method. +func (m *MockStakingKeeper) GetDelegatorBonded(ctx context.Context, delegator types.AccAddress) (math.Int, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetDelegatorBonded", ctx, delegator) + ret0, _ := ret[0].(math.Int) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetDelegatorBonded indicates an expected call of GetDelegatorBonded. +func (mr *MockStakingKeeperMockRecorder) GetDelegatorBonded(ctx, delegator interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDelegatorBonded", reflect.TypeOf((*MockStakingKeeper)(nil).GetDelegatorBonded), ctx, delegator) +} + +// GetDelegatorDelegations mocks base method. +func (m *MockStakingKeeper) GetDelegatorDelegations(ctx context.Context, delegator types.AccAddress, maxRetrieve uint16) ([]types0.Delegation, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetDelegatorDelegations", ctx, delegator, maxRetrieve) + ret0, _ := ret[0].([]types0.Delegation) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetDelegatorDelegations indicates an expected call of GetDelegatorDelegations. +func (mr *MockStakingKeeperMockRecorder) GetDelegatorDelegations(ctx, delegator, maxRetrieve interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDelegatorDelegations", reflect.TypeOf((*MockStakingKeeper)(nil).GetDelegatorDelegations), ctx, delegator, maxRetrieve) +} + +// GetDelegatorUnbonding mocks base method. +func (m *MockStakingKeeper) GetDelegatorUnbonding(ctx context.Context, delegator types.AccAddress) (math.Int, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetDelegatorUnbonding", ctx, delegator) + ret0, _ := ret[0].(math.Int) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetDelegatorUnbonding indicates an expected call of GetDelegatorUnbonding. +func (mr *MockStakingKeeperMockRecorder) GetDelegatorUnbonding(ctx, delegator interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDelegatorUnbonding", reflect.TypeOf((*MockStakingKeeper)(nil).GetDelegatorUnbonding), ctx, delegator) +} + +// GetUnbondingDelegations mocks base method. +func (m *MockStakingKeeper) GetUnbondingDelegations(ctx context.Context, delegator types.AccAddress, maxRetrieve uint16) ([]types0.UnbondingDelegation, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetUnbondingDelegations", ctx, delegator, maxRetrieve) + ret0, _ := ret[0].([]types0.UnbondingDelegation) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetUnbondingDelegations indicates an expected call of GetUnbondingDelegations. +func (mr *MockStakingKeeperMockRecorder) GetUnbondingDelegations(ctx, delegator, maxRetrieve interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUnbondingDelegations", reflect.TypeOf((*MockStakingKeeper)(nil).GetUnbondingDelegations), ctx, delegator, maxRetrieve) +} + +// GetValidator mocks base method. +func (m *MockStakingKeeper) GetValidator(ctx context.Context, addr types.ValAddress) (types0.Validator, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetValidator", ctx, addr) + ret0, _ := ret[0].(types0.Validator) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetValidator indicates an expected call of GetValidator. +func (mr *MockStakingKeeperMockRecorder) GetValidator(ctx, addr interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetValidator", reflect.TypeOf((*MockStakingKeeper)(nil).GetValidator), ctx, addr) +} + +// TransferDelegation mocks base method. +func (m *MockStakingKeeper) TransferDelegation(ctx context.Context, fromAddr, toAddr types.AccAddress, valAddr types.ValAddress, wantShares math.LegacyDec) (math.LegacyDec, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "TransferDelegation", ctx, fromAddr, toAddr, valAddr, wantShares) + ret0, _ := ret[0].(math.LegacyDec) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// TransferDelegation indicates an expected call of TransferDelegation. +func (mr *MockStakingKeeperMockRecorder) TransferDelegation(ctx, fromAddr, toAddr, valAddr, wantShares interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TransferDelegation", reflect.TypeOf((*MockStakingKeeper)(nil).TransferDelegation), ctx, fromAddr, toAddr, valAddr, wantShares) +} + +// TransferUnbonding mocks base method. +func (m *MockStakingKeeper) TransferUnbonding(ctx context.Context, fromAddr, toAddr types.AccAddress, valAddr types.ValAddress, wantAmt math.Int) math.Int { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "TransferUnbonding", ctx, fromAddr, toAddr, valAddr, wantAmt) + ret0, _ := ret[0].(math.Int) + return ret0 +} + +// TransferUnbonding indicates an expected call of TransferUnbonding. +func (mr *MockStakingKeeperMockRecorder) TransferUnbonding(ctx, fromAddr, toAddr, valAddr, wantAmt interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TransferUnbonding", reflect.TypeOf((*MockStakingKeeper)(nil).TransferUnbonding), ctx, fromAddr, toAddr, valAddr, wantAmt) +} From ace7837df7fde069645e83184eba590a3f369e6a Mon Sep 17 00:00:00 2001 From: hacheigriega Date: Sat, 10 Feb 2024 14:42:27 -0500 Subject: [PATCH 03/15] feat: adding missing files from prev commit --- app/app.go | 4 +- app/genesis.go | 4 +- x/vesting/keeper/msg_server.go | 288 ++++++++++----------------------- 3 files changed, 89 insertions(+), 207 deletions(-) diff --git a/app/app.go b/app/app.go index b373b9b7..38fea9c9 100644 --- a/app/app.go +++ b/app/app.go @@ -66,8 +66,6 @@ import ( txmodule "github.com/cosmos/cosmos-sdk/x/auth/tx/config" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - // "github.com/cosmos/cosmos-sdk/x/auth/vesting" - // vestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" "github.com/cosmos/cosmos-sdk/x/authz" authzkeeper "github.com/cosmos/cosmos-sdk/x/authz/keeper" authzmodule "github.com/cosmos/cosmos-sdk/x/authz/module" @@ -851,7 +849,7 @@ func NewApp( // create the simulation manager and define the order of the modules for deterministic simulations overrideModules := map[string]module.AppModuleSimulation{ - authtypes.ModuleName: auth.NewAppModule(app.appCodec, app.AccountKeeper, randomGenesisAccounts, nil), + authtypes.ModuleName: auth.NewAppModule(app.appCodec, app.AccountKeeper, RandomGenesisAccounts, nil), } app.sm = module.NewSimulationManagerFromAppModules(app.mm.Modules, overrideModules) app.sm.RegisterStoreDecoders() diff --git a/app/genesis.go b/app/genesis.go index 0d391e3b..aa577a23 100644 --- a/app/genesis.go +++ b/app/genesis.go @@ -27,11 +27,11 @@ func NewDefaultGenesisState(cdc codec.JSONCodec) GenesisState { return ModuleBasics.DefaultGenesis(cdc) } -// randomGenesisAccounts defines the default RandomGenesisAccountsFn used on the SDK. +// RandomGenesisAccounts defines the default RandomGenesisAccountsFn used on the SDK. // It creates a slice of BaseAccount, ContinuousVestingAccount and DelayedVestingAccount. // NOTE: This function is a modified version of // https://github.com/cosmos/cosmos-sdk/blob/7e6948f50cd4838a0161838a099f74e0b5b0213c/x/auth/simulation/genesis.go#L26 -func randomGenesisAccounts(simState *module.SimulationState) types.GenesisAccounts { +func RandomGenesisAccounts(simState *module.SimulationState) types.GenesisAccounts { genesisAccs := make(types.GenesisAccounts, len(simState.Accounts)) for i, acc := range simState.Accounts { bacc := types.NewBaseAccountWithAddress(acc.Address) diff --git a/x/vesting/keeper/msg_server.go b/x/vesting/keeper/msg_server.go index b88e57ce..d819e70a 100644 --- a/x/vesting/keeper/msg_server.go +++ b/x/vesting/keeper/msg_server.go @@ -65,7 +65,7 @@ func (m msgServer) CreateVestingAccount(goCtx context.Context, msg *types.MsgCre } baseAccount := authtypes.NewBaseAccountWithAddress(to) - baseAccount = m.ak.NewAccount(ctx, baseAccount).(*authtypes.BaseAccount) + baseAccount = m.ak.NewAccount(ctx, baseAccount).(*authtypes.BaseAccount) // TO-DO what is this baseVestingAccount, err := sdkvestingtypes.NewBaseVestingAccount(baseAccount, msg.Amount.Sort(), msg.EndTime) if err != nil { return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, err.Error()) @@ -96,11 +96,14 @@ func (m msgServer) CreateVestingAccount(goCtx context.Context, msg *types.MsgCre return &types.MsgCreateVestingAccountResponse{}, nil } -// Clawback removes the unvested amount from a ClawbackVestingAccount. -// -// Checks performed on the ValidateBasic include: -// - funder and vesting addresses are correct bech32 format -// - if destination address is not empty it is also correct bech32 format +// Clawback returns the vesting amount from a ClawbackVestingAccount to the funder. +// The funds are transferred from the following sources +// 1. vesting funds that have not been used towards delegation +// 2. delegations +// 3. unbonding delegations +// in this order, as much as possible, until the vesting amount is met. Note that +// due to slashing the funds from all three of these sources may still fail to meet +// the vesting amount according to the vesting schedule. func (m msgServer) Clawback(goCtx context.Context, msg *types.MsgClawback) (*types.MsgClawbackResponse, error) { ctx := sdk.UnwrapSDKContext(goCtx) @@ -108,19 +111,18 @@ func (m msgServer) Clawback(goCtx context.Context, msg *types.MsgClawback) (*typ vestingAccAddr := sdk.MustAccAddressFromBech32(msg.AccountAddress) funderAddr := sdk.MustAccAddressFromBech32(msg.FunderAddress) - // // NOTE: we check the destination address only for the case where it's not sent from the - // // authority account, because in that case the destination address is hardcored to the - // // community pool address anyway (see further below). - // if bk.BlockedAddr(dest) { - // return nil, errorsmod.Wrapf(sdkerrors.ErrUnauthorized, - // "%s is a blocked address and not allowed to receive funds", msg.DestAddress, - // ) - // } + // NOTE: we check the destination address only for the case where it's not sent from the + // authority account, because in that case the destination address is hardcored to the + // community pool address anyway (see further below). + if m.bk.BlockedAddr(funderAddr) { + return nil, errorsmod.Wrapf(sdkerrors.ErrUnauthorized, + "%s is a blocked address and not allowed to receive funds", msg.FunderAddress, + ) + } // retrieve the vesting account and perform preliminary checks acc := m.ak.GetAccount(ctx, vestingAccAddr) if acc == nil { - // TO-DO what to return? return nil, errorsmod.Wrapf(sdkerrors.ErrUnknownAddress, "account at address '%s' does not exist", vestingAccAddr.String()) } vestingAccount, isClawback := acc.(*types.ClawbackContinuousVestingAccount) @@ -134,38 +136,12 @@ func (m msgServer) Clawback(goCtx context.Context, msg *types.MsgClawback) (*typ return nil, errorsmod.Wrapf(sdkerrors.ErrUnauthorized, "clawback can only be requested by original funder: %s", vestingAccount.FunderAddress) } - // - // - // clawback from agoric x/auth/vesting - // - // - // - - // - // MODIFYING THIS PART - // - // Compute the clawback based on the account state only, and update account - // toClawBack := vestingAccount.computeClawback(ctx.BlockTime().Unix()) - // if toClawBack.IsZero() { - // return nil - // } - totalVesting := vestingAccount.GetVestingCoins(ctx.BlockTime()) - - // update the vesting account totalVested := vestingAccount.GetVestedCoins(ctx.BlockTime()) - vestingAccount.OriginalVesting = totalVested - vestingAccount.EndTime = ctx.BlockTime().Unix() // so that all of original vesting is vested now + fmt.Println(totalVested) - // - // - // - - // addr := vestingAccount.GetAddress() - bondDenom, err := m.sk.BondDenom(ctx) - if err != nil { - return nil, fmt.Errorf("failed to get bond denomination") - } + // update the vesting account so that all of original vesting is vested now + vestingAccount.EndTime = ctx.BlockTime().Unix() // Compute the clawback based on bank balance and delegation, and update account // encumbered := vestingAccount.GetVestingCoins(ctx.BlockTime()) @@ -178,6 +154,11 @@ func (m msgServer) Clawback(goCtx context.Context, msg *types.MsgClawback) (*typ if err != nil { return nil, fmt.Errorf("error while getting unbonding amount: %w", err) } + + bondDenom, err := m.sk.BondDenom(ctx) + if err != nil { + return nil, fmt.Errorf("failed to get bond denomination") + } bonded := sdk.NewCoins(sdk.NewCoin(bondDenom, bondedAmt)) unbonding := sdk.NewCoins(sdk.NewCoin(bondDenom, unbondingAmt)) unbonded := m.bk.GetAllBalances(ctx, vestingAccAddr) @@ -200,10 +181,6 @@ func (m msgServer) Clawback(goCtx context.Context, msg *types.MsgClawback) (*typ // no danger in writing incomplete results. m.ak.SetAccount(ctx, vestingAccount) - // - // - // - // Now that future vesting events (and associated lockup) are removed, // the balance of the account is unlocked and can be freely transferred. spendable := m.bk.SpendableCoins(ctx, vestingAccAddr) @@ -212,176 +189,83 @@ func (m msgServer) Clawback(goCtx context.Context, msg *types.MsgClawback) (*typ if err != nil { return nil, err // shouldn't happen, given spendable check } - toClawBack = toClawBack.Sub(toXfer...) - - // We need to traverse the staking data structures to update the - // vesting account bookkeeping, and to recover more funds if necessary. - // Staking is the only way unvested tokens should be missing from the bank balance. - // If we need more, transfer UnbondingDelegations. - want := toClawBack.AmountOf(bondDenom) - unbondings, err := m.sk.GetUnbondingDelegations(ctx, vestingAccAddr, math.MaxUint16) - if err != nil { - return nil, fmt.Errorf("error while getting unbonding delegations: %w", err) - } - for _, unbonding := range unbondings { - valAddr, err := sdk.ValAddressFromBech32(unbonding.ValidatorAddress) - if err != nil { - panic(err) - } - transferred := m.sk.TransferUnbonding(ctx, vestingAccAddr, funderAddr, valAddr, want) - want = want.Sub(transferred) - if !want.IsPositive() { - break - } - } + clawedBack := toXfer + toClawBack = toClawBack.Sub(toXfer...) + if !toClawBack.IsZero() { // TO-DO only allow bondDenom + // claw back from staking (unbonding delegations then bonded delegations) + toClawBackStaking := toClawBack.AmountOf(bondDenom) - // If we need more, transfer Delegations. - if want.IsPositive() { - delegations, err := m.sk.GetDelegatorDelegations(ctx, vestingAccAddr, math.MaxUint16) + // first from unbonding delegations + unbondings, err := m.sk.GetUnbondingDelegations(ctx, vestingAccAddr, math.MaxUint16) if err != nil { - return nil, fmt.Errorf("error while getting delegations: %w", err) + return nil, fmt.Errorf("error while getting unbonding delegations: %w", err) } - - for _, delegation := range delegations { - validatorAddr, err := sdk.ValAddressFromBech32(delegation.ValidatorAddress) - if err != nil { - panic(err) // shouldn't happen - } - validator, err := m.sk.GetValidator(ctx, validatorAddr) + for _, unbonding := range unbondings { + valAddr, err := sdk.ValAddressFromBech32(unbonding.ValidatorAddress) if err != nil { - // validator has been removed - // TO-DO more specific check? - continue + panic(err) } - wantShares, err := validator.SharesFromTokensTruncated(want) - if err != nil { - // validator has no tokens - continue - } - transferredShares, err := m.sk.TransferDelegation(ctx, vestingAccAddr, funderAddr, validatorAddr, wantShares) - if err != nil { - panic(err) // shouldn't happen TO-DO - } - // to be conservative in what we're clawing back, round transferred shares up - transferred := validator.TokensFromSharesRoundUp(transferredShares).RoundInt() - want = want.Sub(transferred) - if !want.IsPositive() { - // Could be slightly negative, due to rounding? - // Don't think so, due to the precautions above. + transferred := m.sk.TransferUnbonding(ctx, vestingAccAddr, funderAddr, valAddr, toClawBackStaking) + + clawedBack = clawedBack.Add(sdk.NewCoin(bondDenom, transferred)) + toClawBackStaking = toClawBackStaking.Sub(transferred) + if !toClawBackStaking.IsPositive() { break } } - } - // If we've transferred everything and still haven't transferred the desired clawback amount, - // then the account must have most some unvested tokens from slashing. + // then from bonded delegations + if toClawBackStaking.IsPositive() { + delegations, err := m.sk.GetDelegatorDelegations(ctx, vestingAccAddr, math.MaxUint16) + if err != nil { + return nil, fmt.Errorf("error while getting delegations: %w", err) + } - // - // - // - // - // - // + for _, delegation := range delegations { + validatorAddr, err := sdk.ValAddressFromBech32(delegation.ValidatorAddress) + if err != nil { + panic(err) // shouldn't happen + } + validator, err := m.sk.GetValidator(ctx, validatorAddr) + if err != nil { + // validator has been removed + // TO-DO more specific check? + continue + } + wantShares, err := validator.SharesFromTokensTruncated(toClawBackStaking) + if err != nil { + // validator has no tokens + continue + } + + transferredShares, err := m.sk.TransferDelegation(ctx, vestingAccAddr, funderAddr, validatorAddr, wantShares) + if err != nil { + panic(err) // shouldn't happen TO-DO + + } + + // to be conservative in what we're clawing back, round transferred shares up + transferred := validator.TokensFromSharesRoundUp(transferredShares).RoundInt() + clawedBack = clawedBack.Add(sdk.NewCoin(bondDenom, transferred)) + toClawBackStaking = toClawBackStaking.Sub(transferred) + if !toClawBackStaking.IsPositive() { + // Could be slightly negative, due to rounding? + // Don't think so, due to the precautions above. + break + } + } + } - // // Compute clawback amount, unlock unvested tokens and remove future vesting events - // // updatedAcc, toClawBack := vestingAccount.ComputeClawback(ctx.BlockTime().Unix()) - - // // totalVested := vestingAccount.GetVestedOnly(time.Unix(clawbackTime, 0)) - // // totalUnvested := vestingAccount.GetUnvestedOnly(time.Unix(clawbackTime, 0)) - - // totalVested := vestingAccount.GetVestedCoins(ctx.BlockTime()) // consider transferred?? - // totalUnvested := vestingAccount.GetVestingCoins(ctx.BlockTime()) // clawback amount - - // // create new vesting account to overwrite - // // TO-DO: or just create a non-vesting account - // newVestingAcc := new(types.ClawbackContinuousVestingAccount) - // var err error - // newVestingAcc.ContinuousVestingAccount, err = sdkvestingtypes.NewContinuousVestingAccount(vestingAccount.BaseAccount, totalVested, vestingAccount.StartTime, vestingAccount.EndTime) - // if err != nil { - // return nil, errorsmod.Wrapf(sdkerrors.ErrUnauthorized, "failed to create continuous vesting account: %s") - // } - // newVestingAcc.OriginalVesting = totalVested - // newVestingAcc.EndTime = ctx.BlockTime().Unix() // so that all of original vesting is vested now - // newVestingAcc.BaseAccount = vestingAccount.BaseAccount - - // m.AccountKeeper.SetAccount(ctx, newVestingAcc) - - // // // Remove all unvested periods from the schedule - // // passedPeriodID := vestingAccount.GetPassedPeriodCount(time.Unix(clawbackTime, 0)) - // // newVestingPeriods := vestingAccount.VestingPeriods[:passedPeriodID] - // // newVestingEnd := vestingAccount.GetStartTime() + newVestingPeriods.TotalLength() - - // // Cap the unlocking schedule to the new total vested. - // // - If lockup has already passed, all vested coins are unlocked. - // // - If lockup has not passed, the vested coins, are still locked. - // // capPeriods := sdkvesting.Periods{ - // // { - // // Length: 0, - // // Amount: totalVested, - // // }, - // // } - - // // minimum of the 2 periods - // // _, newLockingEnd, newLockupPeriods := ConjunctPeriods(vestingAccount.GetStartTime(), vestingAccount.GetStartTime(), vestingAccount.LockupPeriods, capPeriods) - - // // Now construct the new account state - // // vestingAccount.EndTime = Max64(newVestingEnd, newLockingEnd) - // // vestingAccount.LockupPeriods = newLockupPeriods - // // vestingAccount.VestingPeriods = newVestingPeriods - - // // return vestingAccount, totalUnvested - - // /* - // // convert the account back to a normal EthAccount - // // - // // NOTE: this is necessary to allow the bank keeper to send the locked coins away to the - // // destination address. If the account is not converted, the coins will still be seen as locked, - // // and can therefore not be transferred. - // ethAccount := evmostypes.ProtoAccount().(*evmostypes.EthAccount) - // ethAccount.BaseAccount = updatedAcc.BaseAccount - - // // set the account with the updated values of the vesting schedule - // k.accountKeeper.SetAccount(ctx, ethAccount) - - // address := updatedAcc.GetAddress() - - // // NOTE: don't use `SpendableCoins` to get the minimum value to clawback since - // // the amount is retrieved from `ComputeClawback`, which ensures correctness. - // // `SpendableCoins` can result in gas exhaustion if the user has too many - // // different denoms (because of store iteration). - - // // Transfer clawback to the destination (funder) - // // return toClawBack, k.bankKeeper.SendCoins(ctx, address, destinationAddr, toClawBack) - - // // clawedBack, err - // */ - - // err = m.BankKeeper.SendCoins(ctx, newVestingAcc.GetAddress(), funderAddress, totalUnvested) - // if err != nil { - // return nil, errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "failed to claw back '%s' from '%s' to '%s'", totalUnvested.String(), accountAddress.String(), funderAddress.String()) - // } - - // /* - // ctx.EventManager().EmitEvents( - // sdk.Events{ - // sdk.NewEvent( - // types.EventTypeClawback, - // sdk.NewAttribute(types.AttributeKeyFunder, msg.FunderAddress), - // sdk.NewAttribute(types.AttributeKeyAccount, msg.AccountAddress), - // sdk.NewAttribute(types.AttributeKeyDestination, dest.String()), - // ), - // }, - // ) - // */ - - if !want.IsZero() { - panic("want not zero") + // TO-DO may not be zero due to slashing + if !toClawBackStaking.IsZero() { + panic("toClawBackStaking not zero") + } } return &types.MsgClawbackResponse{ - Coins: toClawBack, + Coins: clawedBack, }, nil } From e8a1b9b04418f2be05e8fd6743918e5aa8168754 Mon Sep 17 00:00:00 2001 From: Hyoung-yoon Kim Date: Mon, 12 Feb 2024 13:09:16 -0500 Subject: [PATCH 04/15] test: add integration and simulation tests for vesting --- app/genesis.go | 28 ++-- app/integration.go | 9 -- proto/sedachain/vesting/v1/tx.proto | 11 +- simulation/simulation_test.go | 4 +- x/staking/module.go | 4 +- x/vesting/keeper/clawback_test.go | 187 ++++++++++++++++++++++ x/vesting/keeper/integration_test.go | 168 ++++++++------------ x/vesting/keeper/msg_server.go | 13 +- x/vesting/module.go | 32 +++- x/vesting/simulation/operations.go | 200 ++++++++++++++++++++++++ x/vesting/types/tx.pb.go | 223 +++++++++++++++++++++------ 11 files changed, 694 insertions(+), 185 deletions(-) create mode 100644 x/vesting/keeper/clawback_test.go create mode 100644 x/vesting/simulation/operations.go diff --git a/app/genesis.go b/app/genesis.go index aa577a23..f787dbce 100644 --- a/app/genesis.go +++ b/app/genesis.go @@ -4,13 +4,16 @@ import ( "crypto/rand" "encoding/json" + "cosmossdk.io/math" sdkmath "cosmossdk.io/math" "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" "github.com/cosmos/cosmos-sdk/types/simulation" "github.com/cosmos/cosmos-sdk/x/auth/types" - vestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" + sdkvestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" + + vestingtypes "github.com/sedaprotocol/seda-chain/x/vesting/types" ) // The genesis state of the blockchain is represented here as a map of raw json @@ -33,17 +36,28 @@ func NewDefaultGenesisState(cdc codec.JSONCodec) GenesisState { // https://github.com/cosmos/cosmos-sdk/blob/7e6948f50cd4838a0161838a099f74e0b5b0213c/x/auth/simulation/genesis.go#L26 func RandomGenesisAccounts(simState *module.SimulationState) types.GenesisAccounts { genesisAccs := make(types.GenesisAccounts, len(simState.Accounts)) + var funderAddress string + if int(simState.NumBonded) < len(simState.Accounts) { + funderAddress = simState.Accounts[simState.NumBonded].Address.String() // acc at index NumBonded is designated funder + } for i, acc := range simState.Accounts { bacc := types.NewBaseAccountWithAddress(acc.Address) // Only consider making a vesting account once the initial bonded validator // set is exhausted due to needing to track DelegatedVesting. - if !(int64(i) > simState.NumBonded && simState.Rand.Intn(100) < 50) { + if int64(i) < simState.NumBonded { + genesisAccs[i] = bacc + continue + } else if int64(i) == simState.NumBonded { + genesisAccs[i] = bacc + continue + } else if simState.Rand.Intn(100) < 50 { genesisAccs[i] = bacc continue } - initialVestingAmount, err := rand.Int(rand.Reader, simState.InitialStake.BigInt()) + maxInitialVesting := simState.InitialStake.Quo(math.NewInt(int64(len(simState.Accounts)))) + initialVestingAmount, err := rand.Int(rand.Reader, maxInitialVesting.BigInt()) if err != nil { panic(err) } @@ -58,16 +72,12 @@ func RandomGenesisAccounts(simState *module.SimulationState) types.GenesisAccoun endTime = int64(simulation.RandIntBetween(simState.Rand, int(startTime)+1, int(startTime+(60*60*12)))) } - bva, err := vestingtypes.NewBaseVestingAccount(bacc, initialVesting, endTime) + bva, err := sdkvestingtypes.NewBaseVestingAccount(bacc, initialVesting, endTime) if err != nil { panic(err) } - if simState.Rand.Intn(100) < 50 { - genesisAccs[i] = vestingtypes.NewContinuousVestingAccountRaw(bva, startTime) - } else { - genesisAccs[i] = vestingtypes.NewDelayedVestingAccountRaw(bva) - } + genesisAccs[i] = vestingtypes.NewClawbackContinuousVestingAccountRaw(bva, startTime, funderAddress) } return genesisAccs diff --git a/app/integration.go b/app/integration.go index ef0ccab0..fb6ff3d9 100644 --- a/app/integration.go +++ b/app/integration.go @@ -98,16 +98,7 @@ func NewIntegrationApp( panic(fmt.Errorf("failed to load application version from store: %w", err)) } - // app.NewDefaultGenesisState(bApp.AppCodec()) - // req := &abci.RequestInitChain{ - // AppStateBytes: appState, - // ChainId: appName, - // ConsensusParams: consensusParams, - // Time: genesisTimestamp, - // } - if _, err := bApp.InitChain(&cmtabcitypes.RequestInitChain{ChainId: appName}); err != nil { - // if _, err := bApp.InitChain(req); err != nil { panic(fmt.Errorf("failed to initialize application: %w", err)) } } diff --git a/proto/sedachain/vesting/v1/tx.proto b/proto/sedachain/vesting/v1/tx.proto index e5c19218..8e7022ea 100644 --- a/proto/sedachain/vesting/v1/tx.proto +++ b/proto/sedachain/vesting/v1/tx.proto @@ -56,7 +56,12 @@ message MsgClawback { // MsgClawbackResponse defines the MsgClawback response type. message MsgClawbackResponse { - // coins is the funds that have been clawed back to the funder. - repeated cosmos.base.v1beta1.Coin coins = 1 - [(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins", (gogoproto.nullable) = false]; + repeated cosmos.base.v1beta1.Coin clawed_unbonded = 1 + [(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins", (gogoproto.nullable) = false]; + + repeated cosmos.base.v1beta1.Coin clawed_unbonding = 2 + [(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins", (gogoproto.nullable) = false]; + + repeated cosmos.base.v1beta1.Coin clawed_bonded = 3 + [(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins", (gogoproto.nullable) = false]; } diff --git a/simulation/simulation_test.go b/simulation/simulation_test.go index 2e324061..cdd3f78a 100644 --- a/simulation/simulation_test.go +++ b/simulation/simulation_test.go @@ -10,12 +10,12 @@ import ( "testing" "time" - "cosmossdk.io/log" - evidencetypes "cosmossdk.io/x/evidence/types" "github.com/stretchr/testify/require" abci "github.com/cometbft/cometbft/abci/types" + "cosmossdk.io/log" + evidencetypes "cosmossdk.io/x/evidence/types" dbm "github.com/cosmos/cosmos-db" "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/client/flags" diff --git a/x/staking/module.go b/x/staking/module.go index 1dc69c62..3bf524ef 100644 --- a/x/staking/module.go +++ b/x/staking/module.go @@ -126,7 +126,9 @@ func NewAppModule( func (am AppModule) RegisterServices(cfg module.Configurator) { sdkMsgServer := NewMsgServerImpl(am.keeper.Keeper, am.accountKeeper) sdktypes.RegisterMsgServer(cfg.MsgServer(), sdkMsgServer) - types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(sdkMsgServer, am.keeper, am.accountKeeper, am.randomnessKeeper)) + + // To be activated later + // types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(sdkMsgServer, am.keeper, am.accountKeeper, am.randomnessKeeper)) querier := sdkkeeper.Querier{Keeper: am.keeper.Keeper} sdktypes.RegisterQueryServer(cfg.QueryServer(), querier) diff --git a/x/vesting/keeper/clawback_test.go b/x/vesting/keeper/clawback_test.go new file mode 100644 index 00000000..fa33744e --- /dev/null +++ b/x/vesting/keeper/clawback_test.go @@ -0,0 +1,187 @@ +package keeper_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + + sdk "github.com/cosmos/cosmos-sdk/types" + banktestutil "github.com/cosmos/cosmos-sdk/x/bank/testutil" + sdkstakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" // TO-DO rename + + "github.com/sedaprotocol/seda-chain/x/vesting/types" +) + +func TestClawback(t *testing.T) { + f := initFixture(t) + f.bankKeeper.SetSendEnabled(f.Context(), "aseda", true) + err := banktestutil.FundAccount(f.Context(), f.bankKeeper, funderAddr, sdk.NewCoins(coin100000)) + require.NoError(t, err) + + _, valAddrs := createValidators(t, f, []int64{5, 5, 5}) + require.NoError(t, err) + + testCases := []struct { + testName string + funder sdk.AccAddress + recipient sdk.AccAddress + vestingTime int64 + timeUntilClawback int64 + originalVesting sdk.Coin + delegation sdk.Coin + delegation2 sdk.Coin + undelegation sdk.Coin + undelegation2 sdk.Coin + expClawedUnbonded sdk.Coins + expClawedUnbonding sdk.Coins + expClawedBonded sdk.Coins + }{ + { + testName: "clawback from unbonded", + funder: sdk.MustAccAddressFromBech32("seda1gujynygp0tkwzfpt0g7dv4829jwyk8f0yhp88d"), + recipient: testAddrs[0], + vestingTime: 100, + timeUntilClawback: 30, + originalVesting: sdk.NewInt64Coin(bondDenom, 10000), + delegation: sdk.NewInt64Coin(bondDenom, 0), + undelegation: sdk.NewInt64Coin(bondDenom, 0), + expClawedUnbonded: sdk.NewCoins(sdk.NewInt64Coin(bondDenom, 7000)), + expClawedUnbonding: zeroCoins, + expClawedBonded: zeroCoins, + }, + { + testName: "clawback from unbonded and bonded", + funder: sdk.MustAccAddressFromBech32("seda1gujynygp0tkwzfpt0g7dv4829jwyk8f0yhp88d"), + recipient: testAddrs[1], + vestingTime: 100, + timeUntilClawback: 30, + originalVesting: sdk.NewInt64Coin(bondDenom, 10000), + delegation: sdk.NewInt64Coin(bondDenom, 5000), + delegation2: sdk.NewInt64Coin(bondDenom, 0), + undelegation: sdk.NewInt64Coin(bondDenom, 0), + undelegation2: sdk.NewInt64Coin(bondDenom, 0), + expClawedUnbonded: sdk.NewCoins(sdk.NewInt64Coin(bondDenom, 5000)), + expClawedUnbonding: zeroCoins, + expClawedBonded: sdk.NewCoins(sdk.NewInt64Coin(bondDenom, 2000)), + }, + { + testName: "clawback from bonded", + funder: sdk.MustAccAddressFromBech32("seda1gujynygp0tkwzfpt0g7dv4829jwyk8f0yhp88d"), + recipient: testAddrs[2], + vestingTime: 100, + timeUntilClawback: 60, + originalVesting: sdk.NewInt64Coin(bondDenom, 27500), + delegation: sdk.NewInt64Coin(bondDenom, 27500), + delegation2: sdk.NewInt64Coin(bondDenom, 0), + undelegation: sdk.NewInt64Coin(bondDenom, 0), + undelegation2: sdk.NewInt64Coin(bondDenom, 0), + expClawedUnbonded: zeroCoins, + expClawedUnbonding: zeroCoins, + expClawedBonded: sdk.NewCoins(sdk.NewInt64Coin(bondDenom, 11000)), + }, + { + testName: "clawback from unbonding", + funder: sdk.MustAccAddressFromBech32("seda1gujynygp0tkwzfpt0g7dv4829jwyk8f0yhp88d"), + recipient: testAddrs[3], + vestingTime: 50000, + timeUntilClawback: 30000, + originalVesting: sdk.NewInt64Coin(bondDenom, 27500), + delegation: sdk.NewInt64Coin(bondDenom, 27500), + delegation2: sdk.NewInt64Coin(bondDenom, 0), + undelegation: sdk.NewInt64Coin(bondDenom, 27500), + undelegation2: sdk.NewInt64Coin(bondDenom, 0), + expClawedUnbonded: zeroCoins, + expClawedUnbonding: sdk.NewCoins(sdk.NewInt64Coin(bondDenom, 11000)), + expClawedBonded: zeroCoins, + }, + { + testName: "clawback from unbonded, unbonding, and bonded", + funder: sdk.MustAccAddressFromBech32("seda1gujynygp0tkwzfpt0g7dv4829jwyk8f0yhp88d"), + recipient: testAddrs[4], + vestingTime: 750000, + timeUntilClawback: 600000, + originalVesting: sdk.NewInt64Coin(bondDenom, 13000), + delegation: sdk.NewInt64Coin(bondDenom, 10000), + delegation2: sdk.NewInt64Coin(bondDenom, 2000), + undelegation: sdk.NewInt64Coin(bondDenom, 400), + undelegation2: sdk.NewInt64Coin(bondDenom, 100), + expClawedUnbonded: sdk.NewCoins(sdk.NewInt64Coin(bondDenom, 1000)), + expClawedUnbonding: sdk.NewCoins(sdk.NewInt64Coin(bondDenom, 500)), + expClawedBonded: sdk.NewCoins(sdk.NewInt64Coin(bondDenom, 1100)), + }, + } + for i := range testCases { + tc := testCases[i] + t.Run(tc.testName, func(t *testing.T) { + // 1. create clawback continuous vesting account + createVestingMsg := &types.MsgCreateVestingAccount{ + FromAddress: tc.funder.String(), + ToAddress: tc.recipient.String(), + Amount: sdk.NewCoins(tc.originalVesting), + EndTime: f.Context().BlockTime().Unix() + tc.vestingTime, + } + _, err = f.RunMsg(createVestingMsg) + require.NoError(t, err) + + // 2. delegate + if tc.delegation.IsPositive() { + delegateMsg := &sdkstakingtypes.MsgDelegate{ + DelegatorAddress: tc.recipient.String(), + ValidatorAddress: valAddrs[0].String(), + Amount: tc.delegation, + } + _, err = f.RunMsg(delegateMsg) + require.NoError(t, err) + + if tc.delegation2.IsPositive() { + delegateMsg := &sdkstakingtypes.MsgDelegate{ + DelegatorAddress: tc.recipient.String(), + ValidatorAddress: valAddrs[1].String(), + Amount: tc.delegation2, + } + _, err = f.RunMsg(delegateMsg) + require.NoError(t, err) + } + } + + f.AddTime(tc.timeUntilClawback) + + // 3. initiate unbonding after some time + if tc.undelegation.IsPositive() { + undelegateMsg := &sdkstakingtypes.MsgUndelegate{ + DelegatorAddress: tc.recipient.String(), + ValidatorAddress: valAddrs[0].String(), + Amount: tc.undelegation, + } + _, err = f.RunMsg(undelegateMsg) + require.NoError(t, err) + + if tc.undelegation2.IsPositive() { + undelegateMsg := &sdkstakingtypes.MsgUndelegate{ + DelegatorAddress: tc.recipient.String(), + ValidatorAddress: valAddrs[1].String(), + Amount: tc.undelegation2, + } + _, err = f.RunMsg(undelegateMsg) + require.NoError(t, err) + } + } + + // 4. clawback after some time + clawbackMsg := &types.MsgClawback{ + FunderAddress: tc.funder.String(), + AccountAddress: tc.recipient.String(), + } + res, err := f.RunMsg(clawbackMsg) + require.NoError(t, err) + + result := types.MsgClawbackResponse{} + err = f.cdc.Unmarshal(res.Value, &result) + require.NoError(t, err) + + require.Equal(t, tc.expClawedUnbonded, result.ClawedUnbonded) + require.Equal(t, tc.expClawedUnbonding, result.ClawedUnbonding) + require.Equal(t, tc.expClawedBonded, result.ClawedBonded) + }) + } +} diff --git a/x/vesting/keeper/integration_test.go b/x/vesting/keeper/integration_test.go index f4a59e23..c8b1001a 100644 --- a/x/vesting/keeper/integration_test.go +++ b/x/vesting/keeper/integration_test.go @@ -1,12 +1,12 @@ package keeper_test import ( - "fmt" "testing" "time" "cosmossdk.io/core/appmodule" "cosmossdk.io/log" + "cosmossdk.io/math" storetypes "cosmossdk.io/store/types" "github.com/stretchr/testify/require" @@ -16,6 +16,7 @@ import ( addresscodec "github.com/cosmos/cosmos-sdk/codec/address" "github.com/cosmos/cosmos-sdk/runtime" "github.com/cosmos/cosmos-sdk/testutil/integration" + simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" sdk "github.com/cosmos/cosmos-sdk/types" moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" "github.com/cosmos/cosmos-sdk/x/auth" @@ -23,12 +24,11 @@ import ( authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" "github.com/cosmos/cosmos-sdk/x/bank" bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" - banktestutil "github.com/cosmos/cosmos-sdk/x/bank/testutil" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" - sdkstakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" - stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + sdkstakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" // TO-DO rename + sdkstakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" // TO-DO rename "github.com/sedaprotocol/seda-chain/app" "github.com/sedaprotocol/seda-chain/app/params" @@ -42,24 +42,30 @@ import ( const Bech32Prefix = "seda" var ( - fromAddr = sdk.AccAddress([]byte("from1________________")) - to1Addr = sdk.AccAddress([]byte("to1__________________")) - to2Addr = sdk.AccAddress([]byte("to2__________________")) - to3Addr = sdk.AccAddress([]byte("to3__________________")) - bondDenom = "aseda" - fooCoin = sdk.NewInt64Coin(bondDenom, 10000) - barCoin = sdk.NewInt64Coin(bondDenom, 7000) - zeroCoin = sdk.NewInt64Coin(bondDenom, 0) + bondDenom = "aseda" + coin100000 = sdk.NewInt64Coin(bondDenom, 100000) + coin10000 = sdk.NewInt64Coin(bondDenom, 10000) + coin7000 = sdk.NewInt64Coin(bondDenom, 7000) + coin5000 = sdk.NewInt64Coin(bondDenom, 5000) + coin2000 = sdk.NewInt64Coin(bondDenom, 2000) + zeroCoins sdk.Coins + + // + funderAddr = sdk.MustAccAddressFromBech32("seda1gujynygp0tkwzfpt0g7dv4829jwyk8f0yhp88d") // TO-DO cosmos139f7kncmglres2nf3h4hc4tade85ekfr8sulz5 + accountAddr = sdk.MustAccAddressFromBech32("seda1ucv5709wlf9jn84ynyjzyzeavwvurmdyxat26l") // TO-DO cosmos1x33fy6rusfprkntvjsfregss7rvsvyy4lkwrqu + // + testAddrs = []sdk.AccAddress{ + sdk.AccAddress([]byte("to0_________________")), + sdk.AccAddress([]byte("to1_________________")), + sdk.AccAddress([]byte("to2_________________")), + sdk.AccAddress([]byte("to3_________________")), + sdk.AccAddress([]byte("to4_________________")), + } ) type fixture struct { - // ctx sdk.Context - - app *app.IntegationApp - // queryClient v1.QueryClient - // legacyQueryClient v1beta1.QueryClient - cdc codec.Codec - + *app.IntegationApp + cdc codec.Codec accountKeeper authkeeper.AccountKeeper bankKeeper bankkeeper.Keeper stakingKeeper stakingkeeper.Keeper @@ -68,7 +74,7 @@ type fixture struct { func initFixture(tb testing.TB) *fixture { tb.Helper() keys := storetypes.NewKVStoreKeys( - authtypes.StoreKey, banktypes.StoreKey, stakingtypes.StoreKey, types.StoreKey, //pooltypes.StoreKey, + authtypes.StoreKey, banktypes.StoreKey, sdkstakingtypes.StoreKey, types.StoreKey, //pooltypes.StoreKey, ) cdc := moduletestutil.MakeTestEncodingConfig(auth.AppModuleBasic{}, bank.AppModuleBasic{}, vesting.AppModuleBasic{}).Codec @@ -80,10 +86,10 @@ func initFixture(tb testing.TB) *fixture { authority := authtypes.NewModuleAddress(types.ModuleName) maccPerms := map[string][]string{ - minttypes.ModuleName: {authtypes.Minter}, - stakingtypes.BondedPoolName: {authtypes.Burner, authtypes.Staking}, - stakingtypes.NotBondedPoolName: {authtypes.Burner, authtypes.Staking}, - types.ModuleName: {authtypes.Burner}, + minttypes.ModuleName: {authtypes.Minter}, + sdkstakingtypes.BondedPoolName: {authtypes.Burner, authtypes.Staking}, + sdkstakingtypes.NotBondedPoolName: {authtypes.Burner, authtypes.Staking}, + types.ModuleName: {authtypes.Burner}, } accountKeeper := authkeeper.NewAccountKeeper( @@ -108,11 +114,11 @@ func initFixture(tb testing.TB) *fixture { log.NewNopLogger(), ) - sdkstakingKeeper := sdkstakingkeeper.NewKeeper(cdc, runtime.NewKVStoreService(keys[stakingtypes.StoreKey]), accountKeeper, bankKeeper, authority.String(), addresscodec.NewBech32Codec(params.Bech32PrefixValAddr), addresscodec.NewBech32Codec(params.Bech32PrefixConsAddr)) + sdkstakingKeeper := sdkstakingkeeper.NewKeeper(cdc, runtime.NewKVStoreService(keys[sdkstakingtypes.StoreKey]), accountKeeper, bankKeeper, authority.String(), addresscodec.NewBech32Codec(params.Bech32PrefixValAddr), addresscodec.NewBech32Codec(params.Bech32PrefixConsAddr)) stakingKeeper := stakingkeeper.NewKeeper(sdkstakingKeeper) // set default staking params - stakingParams := stakingtypes.DefaultParams() + stakingParams := sdkstakingtypes.DefaultParams() stakingParams.BondDenom = "aseda" err := stakingKeeper.SetParams(newCtx, stakingParams) require.NoError(tb, err) @@ -121,106 +127,58 @@ func initFixture(tb testing.TB) *fixture { // keeper. // router := baseapp.NewMsgServiceRouter() // router.SetInterfaceRegistry(cdc.InterfaceRegistry()) - authModule := auth.NewAppModule(cdc, accountKeeper, app.RandomGenesisAccounts, nil) bankModule := bank.NewAppModule(cdc, bankKeeper, accountKeeper, nil) stakingModule := staking.NewAppModule(cdc, stakingKeeper, accountKeeper, bankKeeper, nil) vestingModule := vesting.NewAppModule(accountKeeper, bankKeeper, stakingKeeper) integrationApp := app.NewIntegrationApp(newCtx, logger, keys, cdc, map[string]appmodule.AppModule{ - authtypes.ModuleName: authModule, - banktypes.ModuleName: bankModule, - stakingtypes.ModuleName: stakingModule, - types.ModuleName: vestingModule, + authtypes.ModuleName: authModule, + banktypes.ModuleName: bankModule, + sdkstakingtypes.ModuleName: stakingModule, + types.ModuleName: vestingModule, }) - // sdkCtx := sdk.UnwrapSDKContext(integrationApp.Context()) - - // msgSrvr := keeper.NewMsgServerImpl(govKeeper) - // legacyMsgSrvr := keeper.NewLegacyMsgServerImpl(authority.String(), msgSrvr) - - // // Register MsgServer and QueryServer types.RegisterMsgServer(integrationApp.MsgServiceRouter(), keeper.NewMsgServerImpl(accountKeeper, bankKeeper, stakingKeeper)) - // v1beta1.RegisterMsgServer(router, legacyMsgSrvr) - - // v1.RegisterQueryServer(integrationApp.QueryHelper(), keeper.NewQueryServer(govKeeper)) - // v1beta1.RegisterQueryServer(integrationApp.QueryHelper(), keeper.NewLegacyQueryServer(govKeeper)) - - // queryClient := v1.NewQueryClient(integrationApp.QueryHelper()) - // legacyQueryClient := v1beta1.NewQueryClient(integrationApp.QueryHelper()) + sdkstakingtypes.RegisterMsgServer(integrationApp.MsgServiceRouter(), sdkstakingkeeper.NewMsgServerImpl(sdkstakingKeeper)) return &fixture{ - app: integrationApp, - cdc: cdc, - // ctx: sdkCtx, - // queryClient: queryClient, - // legacyQueryClient: legacyQueryClient, + IntegationApp: integrationApp, + cdc: cdc, accountKeeper: accountKeeper, bankKeeper: bankKeeper, stakingKeeper: *stakingKeeper, - // govKeeper: govKeeper, } } -func TestClawbackContinuousVesting(t *testing.T) { - f := initFixture(t) - - // _ = f.ctx - - funderAddr := sdk.MustAccAddressFromBech32("seda1gujynygp0tkwzfpt0g7dv4829jwyk8f0yhp88d") // TO-DO cosmos139f7kncmglres2nf3h4hc4tade85ekfr8sulz5 - accountAddr := sdk.MustAccAddressFromBech32("seda1ucv5709wlf9jn84ynyjzyzeavwvurmdyxat26l") // TO-DO cosmos1x33fy6rusfprkntvjsfregss7rvsvyy4lkwrqu +func createValidators(t *testing.T, f *fixture, powers []int64) ([]sdk.AccAddress, []sdk.ValAddress) { + t.Helper() + addrs := simtestutil.AddTestAddrsIncremental(f.bankKeeper, f.stakingKeeper, f.Context(), 5, math.NewInt(30000000)) + valAddrs := simtestutil.ConvertAddrsToValAddrs(addrs) + pks := simtestutil.CreateTestPubKeys(5) - originalVesting := sdk.NewCoins(fooCoin) - endTime := f.app.Context().BlockTime().Unix() + 100 - // bondedAmt := math.NewInt(0) - // unbondingAmt := math.NewInt(0) - // unbonded := originalVesting // TO-DO why? GetAllBalances - - // msg := &types.MsgClawback{ - // FunderAddress: funderAddr.String(), - // AccountAddress: accountAddr.String(), - // } - - // funderAcc := authtypes.NewBaseAccountWithAddress(funderAddr) - // baseAccount := authtypes.NewBaseAccountWithAddress(accountAddr) - // baseVestingAccount, err := sdkvestingtypes.NewBaseVestingAccount(baseAccount, originalVesting, endTime) - // require.NoError(t, err) - // vestingAccount := types.NewClawbackContinuousVestingAccountRaw(baseVestingAccount, f.ctx.BlockTime().Unix(), msg.FunderAddress) - // f.accountKeeper.SetAccount(f.ctx, vestingAccount) - - f.bankKeeper.SetSendEnabled(f.app.Context(), "aseda", true) - - err := banktestutil.FundAccount(f.app.Context(), f.bankKeeper, funderAddr, sdk.NewCoins(fooCoin)) + val1, err := sdkstakingtypes.NewValidator(valAddrs[0].String(), pks[0], sdkstakingtypes.Description{}) require.NoError(t, err) - - // 1. create clawback continuous vesting account - msg := &types.MsgCreateVestingAccount{ - FromAddress: funderAddr.String(), - ToAddress: accountAddr.String(), - Amount: originalVesting, - EndTime: endTime, - } - res, err := f.app.RunMsg(msg) + val2, err := sdkstakingtypes.NewValidator(valAddrs[1].String(), pks[1], sdkstakingtypes.Description{}) require.NoError(t, err) - fmt.Println(res) - - // 2. clawback after some time - f.app.AddTime(30) - clawbackMsg := &types.MsgClawback{ - FunderAddress: funderAddr.String(), - AccountAddress: accountAddr.String(), // TO-DO rename to RecipientAddress? - } - res, err = f.app.RunMsg(clawbackMsg) + val3, err := sdkstakingtypes.NewValidator(valAddrs[2].String(), pks[2], sdkstakingtypes.Description{}) require.NoError(t, err) - result := types.MsgClawbackResponse{} - err = f.cdc.Unmarshal(res.Value, &result) + require.NoError(t, f.stakingKeeper.SetValidator(f.Context(), val1)) + require.NoError(t, f.stakingKeeper.SetValidator(f.Context(), val2)) + require.NoError(t, f.stakingKeeper.SetValidator(f.Context(), val3)) + require.NoError(t, f.stakingKeeper.SetValidatorByConsAddr(f.Context(), val1)) + require.NoError(t, f.stakingKeeper.SetValidatorByConsAddr(f.Context(), val2)) + require.NoError(t, f.stakingKeeper.SetValidatorByConsAddr(f.Context(), val3)) + require.NoError(t, f.stakingKeeper.SetNewValidatorByPowerIndex(f.Context(), val1)) + require.NoError(t, f.stakingKeeper.SetNewValidatorByPowerIndex(f.Context(), val2)) + require.NoError(t, f.stakingKeeper.SetNewValidatorByPowerIndex(f.Context(), val3)) + + _, _ = f.stakingKeeper.Delegate(f.Context(), addrs[0], f.stakingKeeper.TokensFromConsensusPower(f.Context(), powers[0]), sdkstakingtypes.Unbonded, val1, true) + _, _ = f.stakingKeeper.Delegate(f.Context(), addrs[1], f.stakingKeeper.TokensFromConsensusPower(f.Context(), powers[1]), sdkstakingtypes.Unbonded, val2, true) + _, _ = f.stakingKeeper.Delegate(f.Context(), addrs[2], f.stakingKeeper.TokensFromConsensusPower(f.Context(), powers[2]), sdkstakingtypes.Unbonded, val3, true) + + _, err = f.stakingKeeper.EndBlocker(f.Context()) require.NoError(t, err) - fmt.Println(result) - - require.Equal(t, sdk.NewCoins(barCoin), result.Coins) - // createValidators(t, f, []int64{5, 5, 5}) + return addrs, valAddrs } - -// Test when 0 time has passed -// toXfer seems to be 0 diff --git a/x/vesting/keeper/msg_server.go b/x/vesting/keeper/msg_server.go index d819e70a..aed05f1a 100644 --- a/x/vesting/keeper/msg_server.go +++ b/x/vesting/keeper/msg_server.go @@ -8,7 +8,6 @@ import ( "github.com/hashicorp/go-metrics" errorsmod "cosmossdk.io/errors" - "github.com/cosmos/cosmos-sdk/telemetry" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" @@ -190,7 +189,9 @@ func (m msgServer) Clawback(goCtx context.Context, msg *types.MsgClawback) (*typ return nil, err // shouldn't happen, given spendable check } - clawedBack := toXfer + clawedBackUnbonded := toXfer + clawedBackUnbonding := sdk.NewCoins() + clawedBackBonded := sdk.NewCoins() toClawBack = toClawBack.Sub(toXfer...) if !toClawBack.IsZero() { // TO-DO only allow bondDenom // claw back from staking (unbonding delegations then bonded delegations) @@ -209,7 +210,7 @@ func (m msgServer) Clawback(goCtx context.Context, msg *types.MsgClawback) (*typ transferred := m.sk.TransferUnbonding(ctx, vestingAccAddr, funderAddr, valAddr, toClawBackStaking) - clawedBack = clawedBack.Add(sdk.NewCoin(bondDenom, transferred)) + clawedBackUnbonding = clawedBackUnbonding.Add(sdk.NewCoin(bondDenom, transferred)) toClawBackStaking = toClawBackStaking.Sub(transferred) if !toClawBackStaking.IsPositive() { break @@ -248,7 +249,7 @@ func (m msgServer) Clawback(goCtx context.Context, msg *types.MsgClawback) (*typ // to be conservative in what we're clawing back, round transferred shares up transferred := validator.TokensFromSharesRoundUp(transferredShares).RoundInt() - clawedBack = clawedBack.Add(sdk.NewCoin(bondDenom, transferred)) + clawedBackBonded = clawedBackBonded.Add(sdk.NewCoin(bondDenom, transferred)) toClawBackStaking = toClawBackStaking.Sub(transferred) if !toClawBackStaking.IsPositive() { // Could be slightly negative, due to rounding? @@ -265,7 +266,9 @@ func (m msgServer) Clawback(goCtx context.Context, msg *types.MsgClawback) (*typ } return &types.MsgClawbackResponse{ - Coins: clawedBack, + ClawedUnbonded: clawedBackUnbonded, + ClawedUnbonding: clawedBackUnbonding, + ClawedBonded: clawedBackBonded, }, nil } diff --git a/x/vesting/module.go b/x/vesting/module.go index b6449f6e..c6af4e31 100644 --- a/x/vesting/module.go +++ b/x/vesting/module.go @@ -16,12 +16,11 @@ import ( codectypes "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" - - // "github.com/cosmos/cosmos-sdk/x/auth/vesting/client/cli" - // "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" "github.com/sedaprotocol/seda-chain/x/vesting/client/cli" "github.com/sedaprotocol/seda-chain/x/vesting/keeper" + "github.com/sedaprotocol/seda-chain/x/vesting/simulation" "github.com/sedaprotocol/seda-chain/x/vesting/types" ) @@ -118,6 +117,33 @@ func (am AppModule) ExportGenesis(_ sdk.Context, cdc codec.JSONCodec) json.RawMe // ConsensusVersion implements AppModule/ConsensusVersion. func (AppModule) ConsensusVersion() uint64 { return 1 } +// AppModuleSimulation functions + +// GenerateGenesisState creates a randomized GenState of the slashing module. +func (AppModule) GenerateGenesisState(simState *module.SimulationState) { + // simulation.RandomizedGenState(simState) +} + +// ProposalMsgs returns msgs used for governance proposals for simulations. +func (AppModule) ProposalMsgs(simState module.SimulationState) []simtypes.WeightedProposalMsg { + // return simulation.ProposalMsgs() + return []simtypes.WeightedProposalMsg{} +} + +// RegisterStoreDecoder registers a decoder for slashing module's types +func (am AppModule) RegisterStoreDecoder(sdr simtypes.StoreDecoderRegistry) { + // sdr[types.StoreKey] = simulation.NewDecodeStore(am.cdc) +} + +// WeightedOperations returns the all the slashing module operations with their respective weights. +func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation { + return simulation.WeightedOperations( + // am.registry, + simState.AppParams, simState.Cdc, simState.TxConfig, + am.accountKeeper, am.bankKeeper, am.stakingKeeper, + ) +} + /* TO-DO // // App Wiring Setup diff --git a/x/vesting/simulation/operations.go b/x/vesting/simulation/operations.go new file mode 100644 index 00000000..9328f5e1 --- /dev/null +++ b/x/vesting/simulation/operations.go @@ -0,0 +1,200 @@ +package simulation + +import ( + "math/rand" + + "github.com/cosmos/cosmos-sdk/baseapp" + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/codec" + + // codectypes "github.com/cosmos/cosmos-sdk/codec/types" + simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" + sdk "github.com/cosmos/cosmos-sdk/types" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/cosmos-sdk/x/simulation" + + "github.com/sedaprotocol/seda-chain/x/vesting/types" +) + +// Simulation operation weights constants +const ( + OpWeightMsgCreateVestingAccount = "op_weight_msg_create_vesting_account" + OpWeightMsgClawback = "op_weight_msg_create_vesting_account" + + DefaultWeightMsgCreateVestingAccount = 100 + DefaultWeightMsgClawback = 100 +) + +// WeightedOperations returns all the operations from the module with their respective weights +func WeightedOperations( + // registry codectypes.InterfaceRegistry, + appParams simtypes.AppParams, + cdc codec.JSONCodec, + txGen client.TxConfig, + ak types.AccountKeeper, + bk types.BankKeeper, + sk types.StakingKeeper, +) simulation.WeightedOperations { + var ( + weightMsgCreateVestingAccount int + weightMsgClawback int + ) + appParams.GetOrGenerate(OpWeightMsgCreateVestingAccount, &weightMsgCreateVestingAccount, nil, func(_ *rand.Rand) { + weightMsgCreateVestingAccount = DefaultWeightMsgCreateVestingAccount + }) + appParams.GetOrGenerate(OpWeightMsgClawback, &weightMsgClawback, nil, func(_ *rand.Rand) { + weightMsgClawback = DefaultWeightMsgClawback + }) + + return simulation.WeightedOperations{ + simulation.NewWeightedOperation( + weightMsgCreateVestingAccount, + SimulateMsgCreateVestingAccount( + // codec.NewProtoCodec(registry), + txGen, + ak, bk, sk), + ), + simulation.NewWeightedOperation( + weightMsgClawback, + SimulateMsgClawback( + // codec.NewProtoCodec(registry), + txGen, + ak, bk, sk), + ), + } +} + +// SimulateMsgCreateVestingAccount generates a MsgCreateVestingAccount with random values. +func SimulateMsgCreateVestingAccount( + // cdc *codec.ProtoCodec, + txGen client.TxConfig, + ak types.AccountKeeper, + bk types.BankKeeper, + sk types.StakingKeeper, +) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, + accs []simtypes.Account, chainID string, + ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { + msgType := sdk.MsgTypeURL(&types.MsgCreateVestingAccount{}) + + funder, _ := simtypes.RandomAcc(r, accs) + funderAcc := ak.GetAccount(ctx, funder.Address) + spendableCoins := bk.SpendableCoins(ctx, funderAcc.GetAddress()) + + if err := bk.IsSendEnabledCoins(ctx, spendableCoins...); err != nil { + return simtypes.NoOpMsg(types.ModuleName, msgType, err.Error()), nil, nil + } + + sendCoins := simtypes.RandSubsetCoins(r, spendableCoins) + if sendCoins.Empty() { + return simtypes.NoOpMsg(types.ModuleName, msgType, "empty coins slice"), nil, nil + } + + spendableCoins, hasNeg := spendableCoins.SafeSub(sendCoins...) + var fees sdk.Coins + var err error + if !hasNeg { + fees, err = simtypes.RandomFees(r, ctx, spendableCoins) + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to generate fees"), nil, err + } + } + + recipient := simtypes.RandomAccounts(r, 1)[0] + + msg := types.NewMsgCreateVestingAccount( + funderAcc.GetAddress(), + recipient.Address, + sendCoins, + ctx.BlockTime().Unix()+1000, + ) + + tx, err := simtestutil.GenSignedMockTx( + r, + txGen, + []sdk.Msg{msg}, + fees, + simtestutil.DefaultGenTxGas, + chainID, + []uint64{funderAcc.GetAccountNumber()}, + []uint64{funderAcc.GetSequence()}, + funder.PrivKey, + ) + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "unable to generate mock tx"), nil, err + } + + _, _, err = app.SimDeliver(txGen.TxEncoder(), tx) + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "unable to deliver tx"), nil, err + } + return simtypes.NewOperationMsg(msg, true, ""), nil, nil + } +} + +// SimulateMsgCreateVestingAccount generates a MsgCreateVestingAccount with random values. +func SimulateMsgClawback( + txGen client.TxConfig, + ak types.AccountKeeper, + bk types.BankKeeper, + sk types.StakingKeeper, +) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, + accs []simtypes.Account, chainID string, + ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { + msgType := sdk.MsgTypeURL(&types.MsgClawback{}) + + recipient, _ := simtypes.RandomAcc(r, accs) + recipientAcc := ak.GetAccount(ctx, recipient.Address) + vestingAcc, isClawback := recipientAcc.(*types.ClawbackContinuousVestingAccount) + if !isClawback { + return simtypes.NoOpMsg(types.ModuleName, msgType, "not a vesting account"), nil, nil + } + if vestingAcc.GetVestingCoins(ctx.BlockTime()).IsZero() { + return simtypes.NoOpMsg(types.ModuleName, msgType, "vesting account not vesting anymore"), nil, nil + } + + funder, found := simtypes.FindAccount(accs, sdk.MustAccAddressFromBech32(vestingAcc.FunderAddress)) + if !found { + return simtypes.NoOpMsg(types.ModuleName, msgType, "failed to find funder account"), nil, nil + } + funderAcc := ak.GetAccount(ctx, funder.Address) + spendableCoins := bk.SpendableCoins(ctx, funderAcc.GetAddress()) + if err := bk.IsSendEnabledCoins(ctx, spendableCoins...); err != nil { + return simtypes.NoOpMsg(types.ModuleName, msgType, err.Error()), nil, nil + } + + fees, err := simtypes.RandomFees(r, ctx, spendableCoins) + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to generate fees"), nil, err + } + + msg := types.NewMsgClawback( + funderAcc.GetAddress(), + recipient.Address, + ) + + tx, err := simtestutil.GenSignedMockTx( + r, + txGen, + []sdk.Msg{msg}, + fees, + simtestutil.DefaultGenTxGas, + chainID, + []uint64{funderAcc.GetAccountNumber()}, + []uint64{funderAcc.GetSequence()}, + funder.PrivKey, + ) + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "unable to generate mock tx"), nil, err + } + + _, _, err = app.SimDeliver(txGen.TxEncoder(), tx) + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "unable to deliver tx"), nil, err + } + return simtypes.NewOperationMsg(msg, true, ""), nil, nil + } +} diff --git a/x/vesting/types/tx.pb.go b/x/vesting/types/tx.pb.go index 493dcd5f..0e43e06b 100644 --- a/x/vesting/types/tx.pb.go +++ b/x/vesting/types/tx.pb.go @@ -198,8 +198,9 @@ func (m *MsgClawback) GetAccountAddress() string { // MsgClawbackResponse defines the MsgClawback response type. type MsgClawbackResponse struct { - // coins is the funds that have been clawed back to the funder. - Coins github_com_cosmos_cosmos_sdk_types.Coins `protobuf:"bytes,1,rep,name=coins,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"coins"` + ClawedUnbonded github_com_cosmos_cosmos_sdk_types.Coins `protobuf:"bytes,1,rep,name=clawed_unbonded,json=clawedUnbonded,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"clawed_unbonded"` + ClawedUnbonding github_com_cosmos_cosmos_sdk_types.Coins `protobuf:"bytes,2,rep,name=clawed_unbonding,json=clawedUnbonding,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"clawed_unbonding"` + ClawedBonded github_com_cosmos_cosmos_sdk_types.Coins `protobuf:"bytes,3,rep,name=clawed_bonded,json=clawedBonded,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"clawed_bonded"` } func (m *MsgClawbackResponse) Reset() { *m = MsgClawbackResponse{} } @@ -235,9 +236,23 @@ func (m *MsgClawbackResponse) XXX_DiscardUnknown() { var xxx_messageInfo_MsgClawbackResponse proto.InternalMessageInfo -func (m *MsgClawbackResponse) GetCoins() github_com_cosmos_cosmos_sdk_types.Coins { +func (m *MsgClawbackResponse) GetClawedUnbonded() github_com_cosmos_cosmos_sdk_types.Coins { if m != nil { - return m.Coins + return m.ClawedUnbonded + } + return nil +} + +func (m *MsgClawbackResponse) GetClawedUnbonding() github_com_cosmos_cosmos_sdk_types.Coins { + if m != nil { + return m.ClawedUnbonding + } + return nil +} + +func (m *MsgClawbackResponse) GetClawedBonded() github_com_cosmos_cosmos_sdk_types.Coins { + if m != nil { + return m.ClawedBonded } return nil } @@ -252,42 +267,46 @@ func init() { func init() { proto.RegisterFile("sedachain/vesting/v1/tx.proto", fileDescriptor_abaae49a55dd1e8c) } var fileDescriptor_abaae49a55dd1e8c = []byte{ - // 560 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x54, 0x4f, 0x6b, 0x13, 0x41, - 0x14, 0xcf, 0x34, 0xb6, 0xb6, 0x93, 0x5a, 0x71, 0x1b, 0x68, 0xb2, 0xe0, 0x26, 0x5d, 0x14, 0x63, - 0x20, 0xbb, 0x26, 0x22, 0x42, 0xf5, 0xd2, 0x14, 0x3c, 0xd9, 0xcb, 0x2a, 0x22, 0x5e, 0xc2, 0xec, - 0xee, 0x74, 0xbb, 0x34, 0x3b, 0x13, 0x76, 0x26, 0x31, 0x01, 0x0f, 0xe2, 0xd1, 0x93, 0x67, 0x4f, - 0x1e, 0xc5, 0x53, 0x0e, 0x7e, 0x88, 0x1e, 0x8b, 0x27, 0x4f, 0x2a, 0x89, 0x10, 0x3f, 0x86, 0xcc, - 0xce, 0xec, 0x9a, 0x4a, 0x43, 0xe8, 0x25, 0xc9, 0xbc, 0xdf, 0x9f, 0xf7, 0xe6, 0x37, 0x33, 0x81, - 0x37, 0x19, 0xf6, 0x91, 0x77, 0x8c, 0x42, 0x62, 0x0f, 0x30, 0xe3, 0x21, 0x09, 0xec, 0x41, 0xd3, - 0xe6, 0x43, 0xab, 0x17, 0x53, 0x4e, 0xb5, 0x62, 0x06, 0x5b, 0x0a, 0xb6, 0x06, 0x4d, 0xbd, 0x18, - 0xd0, 0x80, 0x26, 0x04, 0x5b, 0xfc, 0x92, 0x5c, 0xdd, 0xf0, 0x28, 0x8b, 0x28, 0xb3, 0x5d, 0xc4, - 0xb0, 0x3d, 0x68, 0xba, 0x98, 0xa3, 0xa6, 0xed, 0xd1, 0x90, 0x28, 0xbc, 0x2c, 0xf1, 0x8e, 0x14, - 0xca, 0x85, 0x82, 0x6e, 0x29, 0xe9, 0xbf, 0x11, 0xa4, 0x3a, 0xed, 0x29, 0x59, 0x3b, 0x8a, 0x15, - 0xb1, 0x64, 0xc8, 0x88, 0xa5, 0xc0, 0x0d, 0x14, 0x85, 0x84, 0xda, 0xc9, 0xa7, 0x2c, 0x99, 0xd3, - 0x15, 0xb8, 0x73, 0xc8, 0x82, 0x83, 0x18, 0x23, 0x8e, 0x5f, 0x48, 0x9b, 0x7d, 0xcf, 0xa3, 0x7d, - 0xc2, 0xb5, 0x47, 0x70, 0xf3, 0x28, 0xa6, 0x51, 0x07, 0xf9, 0x7e, 0x8c, 0x19, 0x2b, 0x81, 0x2a, - 0xa8, 0x6d, 0xb4, 0x4b, 0xdf, 0xbe, 0x36, 0x8a, 0x6a, 0xaa, 0x7d, 0x89, 0x3c, 0xe3, 0x71, 0x48, - 0x02, 0xa7, 0x20, 0xd8, 0xaa, 0xa4, 0x3d, 0x84, 0x90, 0xd3, 0x4c, 0xba, 0xb2, 0x44, 0xba, 0xc1, - 0x69, 0x2a, 0x1c, 0xc1, 0x35, 0x14, 0x89, 0xfe, 0xa5, 0x7c, 0x35, 0x5f, 0x2b, 0xb4, 0xca, 0x96, - 0x52, 0x88, 0xbc, 0x2c, 0xb5, 0x63, 0xeb, 0x80, 0x86, 0xa4, 0xfd, 0xe4, 0xf4, 0x47, 0x25, 0xf7, - 0xe5, 0x67, 0xa5, 0x16, 0x84, 0xfc, 0xb8, 0xef, 0x5a, 0x1e, 0x8d, 0x54, 0x5e, 0xea, 0xab, 0xc1, - 0xfc, 0x13, 0x9b, 0x8f, 0x7a, 0x98, 0x25, 0x02, 0xf6, 0x71, 0x36, 0xae, 0x6f, 0x76, 0x71, 0x80, - 0xbc, 0x51, 0x47, 0x24, 0xce, 0x3e, 0xcf, 0xc6, 0x75, 0xe0, 0xa8, 0x86, 0x5a, 0x19, 0xae, 0x63, - 0xe2, 0x77, 0x78, 0x18, 0xe1, 0xd2, 0x95, 0x2a, 0xa8, 0xe5, 0x9d, 0xab, 0x98, 0xf8, 0xcf, 0xc3, - 0x08, 0xef, 0x3d, 0xfe, 0xf3, 0xa9, 0x02, 0xde, 0x09, 0xf9, 0x7c, 0x24, 0xef, 0x67, 0xe3, 0xba, - 0x39, 0xd7, 0x6a, 0x41, 0x92, 0xe6, 0x2e, 0xac, 0x2c, 0x80, 0x1c, 0xcc, 0x7a, 0x94, 0x30, 0x6c, - 0xc6, 0xb0, 0x20, 0x28, 0x5d, 0xf4, 0xda, 0x45, 0xde, 0x89, 0x76, 0x1b, 0x6e, 0x1d, 0xf5, 0x89, - 0x8f, 0xe3, 0xf3, 0xe9, 0x3b, 0xd7, 0x64, 0x35, 0x0d, 0xeb, 0x0e, 0xbc, 0x8e, 0xa4, 0xd1, 0xf9, - 0xa8, 0x9d, 0x2d, 0x55, 0x56, 0xc4, 0xbd, 0x6d, 0x31, 0xfb, 0x7f, 0x96, 0xe6, 0x10, 0x6e, 0xcf, - 0xf5, 0x4c, 0x47, 0xd1, 0x10, 0x5c, 0x4d, 0xc2, 0x29, 0x81, 0x65, 0x07, 0x70, 0xef, 0xb2, 0x07, - 0xe0, 0x48, 0xe7, 0xd6, 0x6f, 0x00, 0xf3, 0x87, 0x2c, 0xd0, 0xde, 0xc0, 0xe2, 0x85, 0x57, 0xaf, - 0x61, 0x5d, 0xf4, 0xa0, 0xac, 0x05, 0x21, 0xea, 0x0f, 0x2e, 0x45, 0xcf, 0x36, 0xfa, 0x12, 0xae, - 0x67, 0x81, 0xef, 0x2e, 0xb6, 0x50, 0x14, 0xfd, 0xee, 0x52, 0x4a, 0xea, 0xac, 0xaf, 0xbe, 0x15, - 0x17, 0xab, 0xfd, 0xf4, 0x74, 0x62, 0x80, 0xb3, 0x89, 0x01, 0x7e, 0x4d, 0x0c, 0xf0, 0x61, 0x6a, - 0xe4, 0xce, 0xa6, 0x46, 0xee, 0xfb, 0xd4, 0xc8, 0xbd, 0x6a, 0xcd, 0x25, 0x26, 0x5c, 0x93, 0xd7, - 0xe8, 0xd1, 0x6e, 0xb2, 0x68, 0xc8, 0x3f, 0x9a, 0x61, 0xf6, 0xce, 0x93, 0x04, 0xdd, 0xb5, 0x84, - 0x74, 0xff, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xdc, 0x95, 0xfb, 0xaf, 0x8c, 0x04, 0x00, 0x00, + // 611 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x54, 0xbf, 0x6f, 0xd3, 0x40, + 0x18, 0x8d, 0x13, 0x28, 0xed, 0x25, 0x4d, 0xc0, 0x8d, 0x54, 0x27, 0x12, 0x4e, 0x1a, 0x81, 0x08, + 0x91, 0x62, 0x93, 0x20, 0x84, 0x54, 0x58, 0x9a, 0x4a, 0x4c, 0x74, 0x31, 0x3f, 0x84, 0x58, 0xa2, + 0xb3, 0x7d, 0x75, 0x4f, 0x8d, 0xef, 0x22, 0xdf, 0x25, 0x6d, 0x24, 0x06, 0xc4, 0xc8, 0xc4, 0xcc, + 0xc4, 0x88, 0x98, 0x32, 0xf0, 0x47, 0x74, 0xac, 0x98, 0x98, 0x00, 0x25, 0x48, 0xe1, 0x1f, 0x60, + 0x47, 0xf6, 0x9d, 0x43, 0x52, 0x35, 0x8a, 0x2a, 0x75, 0x49, 0xec, 0xef, 0xbd, 0xf7, 0xbd, 0xcf, + 0xef, 0xec, 0x0f, 0xdc, 0x64, 0xc8, 0x85, 0xce, 0x01, 0xc4, 0xc4, 0xec, 0x23, 0xc6, 0x31, 0xf1, + 0xcc, 0x7e, 0xc3, 0xe4, 0xc7, 0x46, 0x37, 0xa0, 0x9c, 0xaa, 0xf9, 0x29, 0x6c, 0x48, 0xd8, 0xe8, + 0x37, 0x8a, 0x79, 0x8f, 0x7a, 0x34, 0x22, 0x98, 0xe1, 0x95, 0xe0, 0x16, 0x75, 0x87, 0x32, 0x9f, + 0x32, 0xd3, 0x86, 0x0c, 0x99, 0xfd, 0x86, 0x8d, 0x38, 0x6c, 0x98, 0x0e, 0xc5, 0x44, 0xe2, 0x05, + 0x81, 0xb7, 0x85, 0x50, 0xdc, 0x48, 0xe8, 0x96, 0x94, 0xfe, 0x1f, 0x41, 0xa8, 0x63, 0x4f, 0xc1, + 0xda, 0x94, 0x2c, 0x9f, 0x45, 0x43, 0xfa, 0x2c, 0x06, 0x6e, 0x40, 0x1f, 0x13, 0x6a, 0x46, 0xbf, + 0xa2, 0x54, 0x19, 0x27, 0xc1, 0xe6, 0x1e, 0xf3, 0x76, 0x03, 0x04, 0x39, 0x7a, 0x29, 0xda, 0xec, + 0x38, 0x0e, 0xed, 0x11, 0xae, 0x3e, 0x02, 0x99, 0xfd, 0x80, 0xfa, 0x6d, 0xe8, 0xba, 0x01, 0x62, + 0x4c, 0x53, 0xca, 0x4a, 0x75, 0xad, 0xa5, 0x7d, 0xfb, 0x5a, 0xcf, 0xcb, 0xa9, 0x76, 0x04, 0xf2, + 0x8c, 0x07, 0x98, 0x78, 0x56, 0x3a, 0x64, 0xcb, 0x92, 0xfa, 0x10, 0x00, 0x4e, 0xa7, 0xd2, 0xe4, + 0x12, 0xe9, 0x1a, 0xa7, 0xb1, 0x70, 0x00, 0x56, 0xa0, 0x1f, 0xfa, 0x6b, 0xa9, 0x72, 0xaa, 0x9a, + 0x6e, 0x16, 0x0c, 0xa9, 0x08, 0xf3, 0x32, 0xe4, 0x13, 0x1b, 0xbb, 0x14, 0x93, 0xd6, 0x93, 0x93, + 0x1f, 0xa5, 0xc4, 0x97, 0x9f, 0xa5, 0xaa, 0x87, 0xf9, 0x41, 0xcf, 0x36, 0x1c, 0xea, 0xcb, 0xbc, + 0xe4, 0x5f, 0x9d, 0xb9, 0x87, 0x26, 0x1f, 0x74, 0x11, 0x8b, 0x04, 0xec, 0xe3, 0x64, 0x58, 0xcb, + 0x74, 0x90, 0x07, 0x9d, 0x41, 0x3b, 0x4c, 0x9c, 0x7d, 0x9e, 0x0c, 0x6b, 0x8a, 0x25, 0x0d, 0xd5, + 0x02, 0x58, 0x45, 0xc4, 0x6d, 0x73, 0xec, 0x23, 0xed, 0x4a, 0x59, 0xa9, 0xa6, 0xac, 0x6b, 0x88, + 0xb8, 0xcf, 0xb1, 0x8f, 0xb6, 0x1f, 0xff, 0xf9, 0x54, 0x52, 0xde, 0x85, 0xf2, 0xd9, 0x48, 0xde, + 0x4f, 0x86, 0xb5, 0xca, 0x8c, 0xd5, 0x82, 0x24, 0x2b, 0x5b, 0xa0, 0xb4, 0x00, 0xb2, 0x10, 0xeb, + 0x52, 0xc2, 0x50, 0x25, 0x00, 0xe9, 0x90, 0xd2, 0x81, 0x47, 0x36, 0x74, 0x0e, 0xd5, 0xdb, 0x20, + 0xbb, 0xdf, 0x23, 0x2e, 0x0a, 0xe6, 0xd3, 0xb7, 0xd6, 0x45, 0x35, 0x0e, 0xeb, 0x0e, 0xc8, 0x41, + 0xd1, 0x68, 0x3e, 0x6a, 0x2b, 0x2b, 0xcb, 0x92, 0xb8, 0xbd, 0x11, 0xce, 0x7e, 0xa6, 0x65, 0xe5, + 0x6f, 0x12, 0x6c, 0xcc, 0x98, 0xc6, 0xb3, 0xa8, 0x1c, 0xe4, 0x9c, 0x0e, 0x3c, 0x42, 0x6e, 0xbb, + 0x47, 0x6c, 0x4a, 0x5c, 0xe4, 0x6a, 0xca, 0xb2, 0xb3, 0xb8, 0x77, 0xd1, 0xb3, 0xb0, 0xb2, 0xc2, + 0xe3, 0x85, 0xb4, 0x50, 0xfb, 0xe0, 0xfa, 0x9c, 0x2b, 0x26, 0x9e, 0x96, 0xbc, 0x7c, 0xdb, 0xdc, + 0xac, 0x2d, 0x26, 0x9e, 0xda, 0x05, 0xeb, 0xd2, 0x57, 0x3e, 0x6b, 0xea, 0xf2, 0x4d, 0x33, 0xc2, + 0xa1, 0x15, 0x19, 0x34, 0x7f, 0x2b, 0x20, 0xb5, 0xc7, 0x3c, 0xf5, 0x0d, 0xc8, 0x9f, 0xfb, 0xe1, + 0xd5, 0x8d, 0xf3, 0xd6, 0x89, 0xb1, 0xe0, 0x15, 0x2a, 0x3e, 0xb8, 0x10, 0x7d, 0x7a, 0xca, 0xaf, + 0xc0, 0xea, 0xf4, 0x75, 0xdb, 0x5a, 0xdc, 0x42, 0x52, 0x8a, 0x77, 0x97, 0x52, 0xe2, 0xce, 0xc5, + 0xab, 0x6f, 0xc3, 0xcf, 0xaa, 0xf5, 0xf4, 0x64, 0xa4, 0x2b, 0xa7, 0x23, 0x5d, 0xf9, 0x35, 0xd2, + 0x95, 0x0f, 0x63, 0x3d, 0x71, 0x3a, 0xd6, 0x13, 0xdf, 0xc7, 0x7a, 0xe2, 0x75, 0x73, 0x26, 0xb8, + 0xb0, 0x6b, 0xb4, 0x8b, 0x1c, 0xda, 0x89, 0x6e, 0xea, 0x62, 0xcd, 0x1e, 0x4f, 0xb7, 0x5c, 0x14, + 0xa4, 0xbd, 0x12, 0x91, 0xee, 0xff, 0x0b, 0x00, 0x00, 0xff, 0xff, 0x24, 0x17, 0x9e, 0x14, 0x8a, + 0x05, 0x00, 0x00, } func (this *MsgCreateVestingAccount) Equal(that interface{}) bool { @@ -585,10 +604,38 @@ func (m *MsgClawbackResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l - if len(m.Coins) > 0 { - for iNdEx := len(m.Coins) - 1; iNdEx >= 0; iNdEx-- { + if len(m.ClawedBonded) > 0 { + for iNdEx := len(m.ClawedBonded) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.ClawedBonded[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + } + if len(m.ClawedUnbonding) > 0 { + for iNdEx := len(m.ClawedUnbonding) - 1; iNdEx >= 0; iNdEx-- { { - size, err := m.Coins[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + size, err := m.ClawedUnbonding[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + if len(m.ClawedUnbonded) > 0 { + for iNdEx := len(m.ClawedUnbonded) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.ClawedUnbonded[iNdEx].MarshalToSizedBuffer(dAtA[:i]) if err != nil { return 0, err } @@ -671,8 +718,20 @@ func (m *MsgClawbackResponse) Size() (n int) { } var l int _ = l - if len(m.Coins) > 0 { - for _, e := range m.Coins { + if len(m.ClawedUnbonded) > 0 { + for _, e := range m.ClawedUnbonded { + l = e.Size() + n += 1 + l + sovTx(uint64(l)) + } + } + if len(m.ClawedUnbonding) > 0 { + for _, e := range m.ClawedUnbonding { + l = e.Size() + n += 1 + l + sovTx(uint64(l)) + } + } + if len(m.ClawedBonded) > 0 { + for _, e := range m.ClawedBonded { l = e.Size() n += 1 + l + sovTx(uint64(l)) } @@ -1048,7 +1107,75 @@ func (m *MsgClawbackResponse) Unmarshal(dAtA []byte) error { switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Coins", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field ClawedUnbonded", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ClawedUnbonded = append(m.ClawedUnbonded, types.Coin{}) + if err := m.ClawedUnbonded[len(m.ClawedUnbonded)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ClawedUnbonding", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ClawedUnbonding = append(m.ClawedUnbonding, types.Coin{}) + if err := m.ClawedUnbonding[len(m.ClawedUnbonding)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ClawedBonded", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -1075,8 +1202,8 @@ func (m *MsgClawbackResponse) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Coins = append(m.Coins, types.Coin{}) - if err := m.Coins[len(m.Coins)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + m.ClawedBonded = append(m.ClawedBonded, types.Coin{}) + if err := m.ClawedBonded[len(m.ClawedBonded)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex From 76ccb870b887967fbb2d5f3788dd988df3e0d604 Mon Sep 17 00:00:00 2001 From: hacheigriega Date: Tue, 13 Feb 2024 13:28:04 -0500 Subject: [PATCH 05/15] test: more comprehensive integration testing and clawback code cleanup --- app/integration.go | 5 + x/vesting/keeper/clawback_test.go | 225 +++++++++++++++++---------- x/vesting/keeper/integration_test.go | 60 ++++--- x/vesting/keeper/msg_server.go | 20 +-- 4 files changed, 180 insertions(+), 130 deletions(-) diff --git a/app/integration.go b/app/integration.go index fb6ff3d9..5c5c3222 100644 --- a/app/integration.go +++ b/app/integration.go @@ -177,6 +177,11 @@ func (app *IntegationApp) AddTime(seconds int64) { app.ctx = app.ctx.WithBlockTime(newTime) } +// AddBlock increments the block number of the application context. +func (app *IntegationApp) AddBlock() { + app.ctx = app.ctx.WithBlockHeight(app.ctx.BlockHeader().Height + 1) +} + // QueryHelper returns the application query helper. // It can be used when registering query services. func (app *IntegationApp) QueryHelper() *baseapp.QueryServiceTestHelper { diff --git a/x/vesting/keeper/clawback_test.go b/x/vesting/keeper/clawback_test.go index fa33744e..308b945a 100644 --- a/x/vesting/keeper/clawback_test.go +++ b/x/vesting/keeper/clawback_test.go @@ -3,11 +3,12 @@ package keeper_test import ( "testing" + "cosmossdk.io/math" "github.com/stretchr/testify/require" sdk "github.com/cosmos/cosmos-sdk/types" banktestutil "github.com/cosmos/cosmos-sdk/x/bank/testutil" - sdkstakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" // TO-DO rename + sdkstakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/sedaprotocol/seda-chain/x/vesting/types" ) @@ -15,104 +16,152 @@ import ( func TestClawback(t *testing.T) { f := initFixture(t) f.bankKeeper.SetSendEnabled(f.Context(), "aseda", true) - err := banktestutil.FundAccount(f.Context(), f.bankKeeper, funderAddr, sdk.NewCoins(coin100000)) + err := banktestutil.FundAccount(f.Context(), f.bankKeeper, funderAddr, sdk.NewCoins(sdk.NewInt64Coin(bondDenom, 100000))) require.NoError(t, err) - _, valAddrs := createValidators(t, f, []int64{5, 5, 5}) + _, valAddrs, valPks := createValidators(t, f, []int64{5, 5, 5}) require.NoError(t, err) testCases := []struct { - testName string - funder sdk.AccAddress - recipient sdk.AccAddress - vestingTime int64 - timeUntilClawback int64 - originalVesting sdk.Coin - delegation sdk.Coin - delegation2 sdk.Coin - undelegation sdk.Coin - undelegation2 sdk.Coin - expClawedUnbonded sdk.Coins - expClawedUnbonding sdk.Coins - expClawedBonded sdk.Coins + testName string + funder sdk.AccAddress + recipient sdk.AccAddress + vestingTime int64 + timeUntilClawback int64 + originalVesting sdk.Coin + delegation sdk.Coin + delegation2 sdk.Coin + undelegation sdk.Coin + undelegation2 sdk.Coin + expClawedUnbonded sdk.Coins + expClawedUnbonding sdk.Coins + expClawedBonded sdk.Coins + slashingFraction math.LegacyDec + recipientFinalSpendable sdk.Coins }{ { - testName: "clawback from unbonded", - funder: sdk.MustAccAddressFromBech32("seda1gujynygp0tkwzfpt0g7dv4829jwyk8f0yhp88d"), - recipient: testAddrs[0], - vestingTime: 100, - timeUntilClawback: 30, - originalVesting: sdk.NewInt64Coin(bondDenom, 10000), - delegation: sdk.NewInt64Coin(bondDenom, 0), - undelegation: sdk.NewInt64Coin(bondDenom, 0), - expClawedUnbonded: sdk.NewCoins(sdk.NewInt64Coin(bondDenom, 7000)), - expClawedUnbonding: zeroCoins, - expClawedBonded: zeroCoins, + testName: "clawback from unbonded", + funder: sdk.MustAccAddressFromBech32("seda1gujynygp0tkwzfpt0g7dv4829jwyk8f0yhp88d"), + recipient: testAddrs[0], + vestingTime: 100, + timeUntilClawback: 30, + originalVesting: sdk.NewInt64Coin(bondDenom, 10000), + delegation: sdk.NewInt64Coin(bondDenom, 0), + undelegation: sdk.NewInt64Coin(bondDenom, 0), + expClawedUnbonded: sdk.NewCoins(sdk.NewInt64Coin(bondDenom, 7000)), + expClawedUnbonding: zeroCoins, + expClawedBonded: zeroCoins, + slashingFraction: math.LegacyZeroDec(), + recipientFinalSpendable: sdk.NewCoins(sdk.NewInt64Coin(bondDenom, 3000)), }, { - testName: "clawback from unbonded and bonded", - funder: sdk.MustAccAddressFromBech32("seda1gujynygp0tkwzfpt0g7dv4829jwyk8f0yhp88d"), - recipient: testAddrs[1], - vestingTime: 100, - timeUntilClawback: 30, - originalVesting: sdk.NewInt64Coin(bondDenom, 10000), - delegation: sdk.NewInt64Coin(bondDenom, 5000), - delegation2: sdk.NewInt64Coin(bondDenom, 0), - undelegation: sdk.NewInt64Coin(bondDenom, 0), - undelegation2: sdk.NewInt64Coin(bondDenom, 0), - expClawedUnbonded: sdk.NewCoins(sdk.NewInt64Coin(bondDenom, 5000)), - expClawedUnbonding: zeroCoins, - expClawedBonded: sdk.NewCoins(sdk.NewInt64Coin(bondDenom, 2000)), + testName: "clawback from unbonded and bonded", + funder: sdk.MustAccAddressFromBech32("seda1gujynygp0tkwzfpt0g7dv4829jwyk8f0yhp88d"), + recipient: testAddrs[1], + vestingTime: 100, + timeUntilClawback: 30, + originalVesting: sdk.NewInt64Coin(bondDenom, 10000), + delegation: sdk.NewInt64Coin(bondDenom, 5000), + delegation2: sdk.NewInt64Coin(bondDenom, 0), + undelegation: sdk.NewInt64Coin(bondDenom, 0), + undelegation2: sdk.NewInt64Coin(bondDenom, 0), + expClawedUnbonded: sdk.NewCoins(sdk.NewInt64Coin(bondDenom, 5000)), + expClawedUnbonding: zeroCoins, + expClawedBonded: sdk.NewCoins(sdk.NewInt64Coin(bondDenom, 2000)), + slashingFraction: math.LegacyZeroDec(), + recipientFinalSpendable: sdk.NewCoins(), }, { - testName: "clawback from bonded", - funder: sdk.MustAccAddressFromBech32("seda1gujynygp0tkwzfpt0g7dv4829jwyk8f0yhp88d"), - recipient: testAddrs[2], - vestingTime: 100, - timeUntilClawback: 60, - originalVesting: sdk.NewInt64Coin(bondDenom, 27500), - delegation: sdk.NewInt64Coin(bondDenom, 27500), - delegation2: sdk.NewInt64Coin(bondDenom, 0), - undelegation: sdk.NewInt64Coin(bondDenom, 0), - undelegation2: sdk.NewInt64Coin(bondDenom, 0), - expClawedUnbonded: zeroCoins, - expClawedUnbonding: zeroCoins, - expClawedBonded: sdk.NewCoins(sdk.NewInt64Coin(bondDenom, 11000)), + testName: "clawback from bonded", + funder: sdk.MustAccAddressFromBech32("seda1gujynygp0tkwzfpt0g7dv4829jwyk8f0yhp88d"), + recipient: testAddrs[2], + vestingTime: 100, + timeUntilClawback: 60, + originalVesting: sdk.NewInt64Coin(bondDenom, 27500), + delegation: sdk.NewInt64Coin(bondDenom, 27500), + delegation2: sdk.NewInt64Coin(bondDenom, 0), + undelegation: sdk.NewInt64Coin(bondDenom, 0), + undelegation2: sdk.NewInt64Coin(bondDenom, 0), + expClawedUnbonded: zeroCoins, + expClawedUnbonding: zeroCoins, + expClawedBonded: sdk.NewCoins(sdk.NewInt64Coin(bondDenom, 11000)), + slashingFraction: math.LegacyZeroDec(), + recipientFinalSpendable: sdk.NewCoins(), }, { - testName: "clawback from unbonding", - funder: sdk.MustAccAddressFromBech32("seda1gujynygp0tkwzfpt0g7dv4829jwyk8f0yhp88d"), - recipient: testAddrs[3], - vestingTime: 50000, - timeUntilClawback: 30000, - originalVesting: sdk.NewInt64Coin(bondDenom, 27500), - delegation: sdk.NewInt64Coin(bondDenom, 27500), - delegation2: sdk.NewInt64Coin(bondDenom, 0), - undelegation: sdk.NewInt64Coin(bondDenom, 27500), - undelegation2: sdk.NewInt64Coin(bondDenom, 0), - expClawedUnbonded: zeroCoins, - expClawedUnbonding: sdk.NewCoins(sdk.NewInt64Coin(bondDenom, 11000)), - expClawedBonded: zeroCoins, + testName: "clawback from unbonding", + funder: sdk.MustAccAddressFromBech32("seda1gujynygp0tkwzfpt0g7dv4829jwyk8f0yhp88d"), + recipient: testAddrs[3], + vestingTime: 50000, + timeUntilClawback: 30000, + originalVesting: sdk.NewInt64Coin(bondDenom, 27500), + delegation: sdk.NewInt64Coin(bondDenom, 27500), + delegation2: sdk.NewInt64Coin(bondDenom, 0), + undelegation: sdk.NewInt64Coin(bondDenom, 27500), + undelegation2: sdk.NewInt64Coin(bondDenom, 0), + expClawedUnbonded: zeroCoins, + expClawedUnbonding: sdk.NewCoins(sdk.NewInt64Coin(bondDenom, 11000)), + expClawedBonded: zeroCoins, + slashingFraction: math.LegacyZeroDec(), + recipientFinalSpendable: sdk.NewCoins(), }, { - testName: "clawback from unbonded, unbonding, and bonded", - funder: sdk.MustAccAddressFromBech32("seda1gujynygp0tkwzfpt0g7dv4829jwyk8f0yhp88d"), - recipient: testAddrs[4], - vestingTime: 750000, - timeUntilClawback: 600000, - originalVesting: sdk.NewInt64Coin(bondDenom, 13000), - delegation: sdk.NewInt64Coin(bondDenom, 10000), - delegation2: sdk.NewInt64Coin(bondDenom, 2000), - undelegation: sdk.NewInt64Coin(bondDenom, 400), - undelegation2: sdk.NewInt64Coin(bondDenom, 100), - expClawedUnbonded: sdk.NewCoins(sdk.NewInt64Coin(bondDenom, 1000)), - expClawedUnbonding: sdk.NewCoins(sdk.NewInt64Coin(bondDenom, 500)), - expClawedBonded: sdk.NewCoins(sdk.NewInt64Coin(bondDenom, 1100)), + testName: "clawback from unbonded, unbonding, and bonded", + funder: sdk.MustAccAddressFromBech32("seda1gujynygp0tkwzfpt0g7dv4829jwyk8f0yhp88d"), + recipient: testAddrs[4], + vestingTime: 750000, + timeUntilClawback: 600000, + originalVesting: sdk.NewInt64Coin(bondDenom, 13000), + delegation: sdk.NewInt64Coin(bondDenom, 10000), + delegation2: sdk.NewInt64Coin(bondDenom, 2000), + undelegation: sdk.NewInt64Coin(bondDenom, 400), + undelegation2: sdk.NewInt64Coin(bondDenom, 100), + expClawedUnbonded: sdk.NewCoins(sdk.NewInt64Coin(bondDenom, 1000)), + expClawedUnbonding: sdk.NewCoins(sdk.NewInt64Coin(bondDenom, 500)), + expClawedBonded: sdk.NewCoins(sdk.NewInt64Coin(bondDenom, 1100)), + slashingFraction: math.LegacyZeroDec(), + recipientFinalSpendable: sdk.NewCoins(), + }, + { + testName: "clawback from unbonded and bonded with slashing", + funder: sdk.MustAccAddressFromBech32("seda1gujynygp0tkwzfpt0g7dv4829jwyk8f0yhp88d"), + recipient: testAddrs[6], + vestingTime: 100, + timeUntilClawback: 30, + originalVesting: sdk.NewInt64Coin(bondDenom, 10000), + delegation: sdk.NewInt64Coin(bondDenom, 5000), + delegation2: sdk.NewInt64Coin(bondDenom, 0), + undelegation: sdk.NewInt64Coin(bondDenom, 0), + undelegation2: sdk.NewInt64Coin(bondDenom, 0), + expClawedUnbonded: sdk.NewCoins(sdk.NewInt64Coin(bondDenom, 5000)), + expClawedUnbonding: zeroCoins, + expClawedBonded: sdk.NewCoins(sdk.NewInt64Coin(bondDenom, 2000)), + slashingFraction: math.LegacyNewDecWithPrec(5, 2), + recipientFinalSpendable: sdk.NewCoins(), + }, + { + testName: "clawback from unbonded, unbonding, and bonded with slashing", + funder: sdk.MustAccAddressFromBech32("seda1gujynygp0tkwzfpt0g7dv4829jwyk8f0yhp88d"), + recipient: testAddrs[5], + vestingTime: 750000, + timeUntilClawback: 600000, + originalVesting: sdk.NewInt64Coin(bondDenom, 13000), + delegation: sdk.NewInt64Coin(bondDenom, 10000), + delegation2: sdk.NewInt64Coin(bondDenom, 2000), + undelegation: sdk.NewInt64Coin(bondDenom, 400), + undelegation2: sdk.NewInt64Coin(bondDenom, 100), + expClawedUnbonded: sdk.NewCoins(sdk.NewInt64Coin(bondDenom, 1000)), + expClawedUnbonding: sdk.NewCoins(sdk.NewInt64Coin(bondDenom, 180)), + expClawedBonded: sdk.NewCoins(sdk.NewInt64Coin(bondDenom, 1420)), + slashingFraction: math.LegacyNewDecWithPrec(8, 1), // 0.8 + recipientFinalSpendable: sdk.NewCoins(), }, } for i := range testCases { tc := testCases[i] t.Run(tc.testName, func(t *testing.T) { + f.AddBlock() + // 1. create clawback continuous vesting account createVestingMsg := &types.MsgCreateVestingAccount{ FromAddress: tc.funder.String(), @@ -144,8 +193,6 @@ func TestClawback(t *testing.T) { } } - f.AddTime(tc.timeUntilClawback) - // 3. initiate unbonding after some time if tc.undelegation.IsPositive() { undelegateMsg := &sdkstakingtypes.MsgUndelegate{ @@ -167,7 +214,19 @@ func TestClawback(t *testing.T) { } } + // possible slashing + if tc.slashingFraction.IsPositive() { + _, err = f.stakingKeeper.Slash(f.Context(), sdk.ConsAddress(valPks[0].Address()), f.Context().BlockHeight()-1, 5, tc.slashingFraction) + require.NoError(t, err) + } + + _, err = f.stakingKeeper.EndBlocker(f.Context()) + require.NoError(t, err) + f.AddBlock() + // 4. clawback after some time + f.AddTime(tc.timeUntilClawback) + clawbackMsg := &types.MsgClawback{ FunderAddress: tc.funder.String(), AccountAddress: tc.recipient.String(), @@ -182,6 +241,10 @@ func TestClawback(t *testing.T) { require.Equal(t, tc.expClawedUnbonded, result.ClawedUnbonded) require.Equal(t, tc.expClawedUnbonding, result.ClawedUnbonding) require.Equal(t, tc.expClawedBonded, result.ClawedBonded) + + // + recipientSpendable := f.bankKeeper.SpendableCoins(f.Context(), tc.recipient) + require.Equal(t, tc.recipientFinalSpendable, recipientSpendable) }) } } diff --git a/x/vesting/keeper/integration_test.go b/x/vesting/keeper/integration_test.go index c8b1001a..07b149a2 100644 --- a/x/vesting/keeper/integration_test.go +++ b/x/vesting/keeper/integration_test.go @@ -14,6 +14,7 @@ import ( "github.com/cosmos/cosmos-sdk/codec" addresscodec "github.com/cosmos/cosmos-sdk/codec/address" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" "github.com/cosmos/cosmos-sdk/runtime" "github.com/cosmos/cosmos-sdk/testutil/integration" simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" @@ -25,10 +26,10 @@ import ( "github.com/cosmos/cosmos-sdk/x/bank" bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" - + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" - sdkstakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" // TO-DO rename - sdkstakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" // TO-DO rename + sdkstakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" + sdkstakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/sedaprotocol/seda-chain/app" "github.com/sedaprotocol/seda-chain/app/params" @@ -39,27 +40,23 @@ import ( "github.com/sedaprotocol/seda-chain/x/vesting/types" ) -const Bech32Prefix = "seda" +const ( + bech32Prefix = "seda" + bondDenom = "aseda" +) var ( - bondDenom = "aseda" - coin100000 = sdk.NewInt64Coin(bondDenom, 100000) - coin10000 = sdk.NewInt64Coin(bondDenom, 10000) - coin7000 = sdk.NewInt64Coin(bondDenom, 7000) - coin5000 = sdk.NewInt64Coin(bondDenom, 5000) - coin2000 = sdk.NewInt64Coin(bondDenom, 2000) zeroCoins sdk.Coins - - // - funderAddr = sdk.MustAccAddressFromBech32("seda1gujynygp0tkwzfpt0g7dv4829jwyk8f0yhp88d") // TO-DO cosmos139f7kncmglres2nf3h4hc4tade85ekfr8sulz5 - accountAddr = sdk.MustAccAddressFromBech32("seda1ucv5709wlf9jn84ynyjzyzeavwvurmdyxat26l") // TO-DO cosmos1x33fy6rusfprkntvjsfregss7rvsvyy4lkwrqu - // - testAddrs = []sdk.AccAddress{ + funderAddr = sdk.MustAccAddressFromBech32("seda1gujynygp0tkwzfpt0g7dv4829jwyk8f0yhp88d") + testAddrs = []sdk.AccAddress{ sdk.AccAddress([]byte("to0_________________")), sdk.AccAddress([]byte("to1_________________")), sdk.AccAddress([]byte("to2_________________")), sdk.AccAddress([]byte("to3_________________")), sdk.AccAddress([]byte("to4_________________")), + sdk.AccAddress([]byte("to5_________________")), + sdk.AccAddress([]byte("to6_________________")), + sdk.AccAddress([]byte("to7_________________")), } ) @@ -74,7 +71,7 @@ type fixture struct { func initFixture(tb testing.TB) *fixture { tb.Helper() keys := storetypes.NewKVStoreKeys( - authtypes.StoreKey, banktypes.StoreKey, sdkstakingtypes.StoreKey, types.StoreKey, //pooltypes.StoreKey, + authtypes.StoreKey, banktypes.StoreKey, sdkstakingtypes.StoreKey, types.StoreKey, ) cdc := moduletestutil.MakeTestEncodingConfig(auth.AppModuleBasic{}, bank.AppModuleBasic{}, vesting.AppModuleBasic{}).Codec @@ -83,7 +80,7 @@ func initFixture(tb testing.TB) *fixture { newCtx := sdk.NewContext(cms, cmtproto.Header{Time: time.Now().UTC()}, true, logger) - authority := authtypes.NewModuleAddress(types.ModuleName) + authority := authtypes.NewModuleAddress(govtypes.ModuleName) maccPerms := map[string][]string{ minttypes.ModuleName: {authtypes.Minter}, @@ -117,16 +114,11 @@ func initFixture(tb testing.TB) *fixture { sdkstakingKeeper := sdkstakingkeeper.NewKeeper(cdc, runtime.NewKVStoreService(keys[sdkstakingtypes.StoreKey]), accountKeeper, bankKeeper, authority.String(), addresscodec.NewBech32Codec(params.Bech32PrefixValAddr), addresscodec.NewBech32Codec(params.Bech32PrefixConsAddr)) stakingKeeper := stakingkeeper.NewKeeper(sdkstakingKeeper) - // set default staking params stakingParams := sdkstakingtypes.DefaultParams() - stakingParams.BondDenom = "aseda" + stakingParams.BondDenom = bondDenom err := stakingKeeper.SetParams(newCtx, stakingParams) require.NoError(tb, err) - // Create MsgServiceRouter, but don't populate it before creating the gov - // keeper. - // router := baseapp.NewMsgServiceRouter() - // router.SetInterfaceRegistry(cdc.InterfaceRegistry()) authModule := auth.NewAppModule(cdc, accountKeeper, app.RandomGenesisAccounts, nil) bankModule := bank.NewAppModule(cdc, bankKeeper, accountKeeper, nil) stakingModule := staking.NewAppModule(cdc, stakingKeeper, accountKeeper, bankKeeper, nil) @@ -151,17 +143,17 @@ func initFixture(tb testing.TB) *fixture { } } -func createValidators(t *testing.T, f *fixture, powers []int64) ([]sdk.AccAddress, []sdk.ValAddress) { +func createValidators(t *testing.T, f *fixture, powers []int64) ([]sdk.AccAddress, []sdk.ValAddress, []cryptotypes.PubKey) { t.Helper() - addrs := simtestutil.AddTestAddrsIncremental(f.bankKeeper, f.stakingKeeper, f.Context(), 5, math.NewInt(30000000)) + addrs := simtestutil.AddTestAddrsIncremental(f.bankKeeper, f.stakingKeeper, f.Context(), 5, math.NewInt(5e18)) valAddrs := simtestutil.ConvertAddrsToValAddrs(addrs) - pks := simtestutil.CreateTestPubKeys(5) + valPks := simtestutil.CreateTestPubKeys(5) - val1, err := sdkstakingtypes.NewValidator(valAddrs[0].String(), pks[0], sdkstakingtypes.Description{}) + val1, err := sdkstakingtypes.NewValidator(valAddrs[0].String(), valPks[0], sdkstakingtypes.Description{}) require.NoError(t, err) - val2, err := sdkstakingtypes.NewValidator(valAddrs[1].String(), pks[1], sdkstakingtypes.Description{}) + val2, err := sdkstakingtypes.NewValidator(valAddrs[1].String(), valPks[1], sdkstakingtypes.Description{}) require.NoError(t, err) - val3, err := sdkstakingtypes.NewValidator(valAddrs[2].String(), pks[2], sdkstakingtypes.Description{}) + val3, err := sdkstakingtypes.NewValidator(valAddrs[2].String(), valPks[2], sdkstakingtypes.Description{}) require.NoError(t, err) require.NoError(t, f.stakingKeeper.SetValidator(f.Context(), val1)) @@ -174,11 +166,15 @@ func createValidators(t *testing.T, f *fixture, powers []int64) ([]sdk.AccAddres require.NoError(t, f.stakingKeeper.SetNewValidatorByPowerIndex(f.Context(), val2)) require.NoError(t, f.stakingKeeper.SetNewValidatorByPowerIndex(f.Context(), val3)) - _, _ = f.stakingKeeper.Delegate(f.Context(), addrs[0], f.stakingKeeper.TokensFromConsensusPower(f.Context(), powers[0]), sdkstakingtypes.Unbonded, val1, true) + _, err = f.stakingKeeper.Delegate(f.Context(), addrs[0], f.stakingKeeper.TokensFromConsensusPower(f.Context(), powers[0]), sdkstakingtypes.Unbonded, val1, true) + require.NoError(t, err) _, _ = f.stakingKeeper.Delegate(f.Context(), addrs[1], f.stakingKeeper.TokensFromConsensusPower(f.Context(), powers[1]), sdkstakingtypes.Unbonded, val2, true) + require.NoError(t, err) _, _ = f.stakingKeeper.Delegate(f.Context(), addrs[2], f.stakingKeeper.TokensFromConsensusPower(f.Context(), powers[2]), sdkstakingtypes.Unbonded, val3, true) + require.NoError(t, err) _, err = f.stakingKeeper.EndBlocker(f.Context()) require.NoError(t, err) - return addrs, valAddrs + + return addrs, valAddrs, valPks } diff --git a/x/vesting/keeper/msg_server.go b/x/vesting/keeper/msg_server.go index aed05f1a..fb7d22cf 100644 --- a/x/vesting/keeper/msg_server.go +++ b/x/vesting/keeper/msg_server.go @@ -143,8 +143,6 @@ func (m msgServer) Clawback(goCtx context.Context, msg *types.MsgClawback) (*typ vestingAccount.EndTime = ctx.BlockTime().Unix() // Compute the clawback based on bank balance and delegation, and update account - // encumbered := vestingAccount.GetVestingCoins(ctx.BlockTime()) - encumbered := totalVesting // TO-DO ????? bondedAmt, err := m.sk.GetDelegatorBonded(ctx, vestingAccAddr) if err != nil { return nil, fmt.Errorf("error while getting bonded amount: %w", err) @@ -153,27 +151,16 @@ func (m msgServer) Clawback(goCtx context.Context, msg *types.MsgClawback) (*typ if err != nil { return nil, fmt.Errorf("error while getting unbonding amount: %w", err) } - bondDenom, err := m.sk.BondDenom(ctx) if err != nil { return nil, fmt.Errorf("failed to get bond denomination") } + bonded := sdk.NewCoins(sdk.NewCoin(bondDenom, bondedAmt)) unbonding := sdk.NewCoins(sdk.NewCoin(bondDenom, unbondingAmt)) unbonded := m.bk.GetAllBalances(ctx, vestingAccAddr) - - // - // MODIFYING THIS PART - // - // toClawBack = vestingAccount.updateDelegation(encumbered, toClawBack, bonded, unbonding, unbonded) - delegated := bonded.Add(unbonding...) - oldDelegated := vestingAccount.DelegatedVesting.Add(vestingAccount.DelegatedFree...) - slashed := oldDelegated.Sub(coinsMin(delegated, oldDelegated)...) - total := delegated.Add(unbonded...) + total := bonded.Add(unbonding...).Add(unbonded...) toClawBack := coinsMin(totalVesting, total) // might have been slashed - newDelegated := coinsMin(delegated, total.Sub(totalVesting...)).Add(slashed...) - vestingAccount.DelegatedVesting = coinsMin(encumbered, newDelegated) - vestingAccount.DelegatedFree = newDelegated.Sub(vestingAccount.DelegatedVesting...) // Write now now so that the bank module sees unvested tokens are unlocked. // Note that all store writes are aborted if there is a panic, so there is @@ -259,9 +246,8 @@ func (m msgServer) Clawback(goCtx context.Context, msg *types.MsgClawback) (*typ } } - // TO-DO may not be zero due to slashing if !toClawBackStaking.IsZero() { - panic("toClawBackStaking not zero") + panic("failed to claw back full amount") } } From 4d94950b1398e5804c9ed9b83ad91fdd2e12431f Mon Sep 17 00:00:00 2001 From: hacheigriega Date: Tue, 13 Feb 2024 20:17:52 -0500 Subject: [PATCH 06/15] test: adding delegate and clawback sim ops --- simulation/helpers_test.go | 5 + x/vesting/module.go | 10 +- x/vesting/simulation/operations.go | 216 +++++++++++++++++++++++++--- x/vesting/types/expected_keepers.go | 2 + 4 files changed, 206 insertions(+), 27 deletions(-) diff --git a/simulation/helpers_test.go b/simulation/helpers_test.go index 3dea59c2..00c6fb8c 100644 --- a/simulation/helpers_test.go +++ b/simulation/helpers_test.go @@ -159,6 +159,11 @@ func appStateFn(cdc codec.JSONCodec, simManager *module.SimulationManager, genes panic(err) } + bankState.SendEnabled = append(bankState.SendEnabled, banktypes.SendEnabled{ + Denom: sdk.DefaultBondDenom, + Enabled: true, + }) + stakingAddr := authtypes.NewModuleAddress(stakingtypes.NotBondedPoolName).String() var found bool for _, balance := range bankState.Balances { diff --git a/x/vesting/module.go b/x/vesting/module.go index c6af4e31..65ee4ce1 100644 --- a/x/vesting/module.go +++ b/x/vesting/module.go @@ -120,25 +120,19 @@ func (AppModule) ConsensusVersion() uint64 { return 1 } // AppModuleSimulation functions // GenerateGenesisState creates a randomized GenState of the slashing module. -func (AppModule) GenerateGenesisState(simState *module.SimulationState) { - // simulation.RandomizedGenState(simState) -} +func (AppModule) GenerateGenesisState(simState *module.SimulationState) {} // ProposalMsgs returns msgs used for governance proposals for simulations. func (AppModule) ProposalMsgs(simState module.SimulationState) []simtypes.WeightedProposalMsg { - // return simulation.ProposalMsgs() return []simtypes.WeightedProposalMsg{} } // RegisterStoreDecoder registers a decoder for slashing module's types -func (am AppModule) RegisterStoreDecoder(sdr simtypes.StoreDecoderRegistry) { - // sdr[types.StoreKey] = simulation.NewDecodeStore(am.cdc) -} +func (am AppModule) RegisterStoreDecoder(sdr simtypes.StoreDecoderRegistry) {} // WeightedOperations returns the all the slashing module operations with their respective weights. func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation { return simulation.WeightedOperations( - // am.registry, simState.AppParams, simState.Cdc, simState.TxConfig, am.accountKeeper, am.bankKeeper, am.stakingKeeper, ) diff --git a/x/vesting/simulation/operations.go b/x/vesting/simulation/operations.go index 9328f5e1..833b2409 100644 --- a/x/vesting/simulation/operations.go +++ b/x/vesting/simulation/operations.go @@ -6,12 +6,14 @@ import ( "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/testutil" // codectypes "github.com/cosmos/cosmos-sdk/codec/types" simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" sdk "github.com/cosmos/cosmos-sdk/types" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" "github.com/cosmos/cosmos-sdk/x/simulation" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/sedaprotocol/seda-chain/x/vesting/types" ) @@ -19,7 +21,7 @@ import ( // Simulation operation weights constants const ( OpWeightMsgCreateVestingAccount = "op_weight_msg_create_vesting_account" - OpWeightMsgClawback = "op_weight_msg_create_vesting_account" + OpWeightMsgClawback = "op_weight_msg_clawback" DefaultWeightMsgCreateVestingAccount = 100 DefaultWeightMsgClawback = 100 @@ -27,7 +29,6 @@ const ( // WeightedOperations returns all the operations from the module with their respective weights func WeightedOperations( - // registry codectypes.InterfaceRegistry, appParams simtypes.AppParams, cdc codec.JSONCodec, txGen client.TxConfig, @@ -37,36 +38,29 @@ func WeightedOperations( ) simulation.WeightedOperations { var ( weightMsgCreateVestingAccount int - weightMsgClawback int + // weightMsgClawback int ) appParams.GetOrGenerate(OpWeightMsgCreateVestingAccount, &weightMsgCreateVestingAccount, nil, func(_ *rand.Rand) { weightMsgCreateVestingAccount = DefaultWeightMsgCreateVestingAccount }) - appParams.GetOrGenerate(OpWeightMsgClawback, &weightMsgClawback, nil, func(_ *rand.Rand) { - weightMsgClawback = DefaultWeightMsgClawback - }) + // appParams.GetOrGenerate(OpWeightMsgClawback, &weightMsgClawback, nil, func(_ *rand.Rand) { + // weightMsgClawback = DefaultWeightMsgClawback + // }) return simulation.WeightedOperations{ simulation.NewWeightedOperation( weightMsgCreateVestingAccount, - SimulateMsgCreateVestingAccount( - // codec.NewProtoCodec(registry), - txGen, - ak, bk, sk), - ), - simulation.NewWeightedOperation( - weightMsgClawback, - SimulateMsgClawback( - // codec.NewProtoCodec(registry), - txGen, - ak, bk, sk), + SimulateMsgCreateVestingAccount(txGen, ak, bk, sk), ), + // simulation.NewWeightedOperation( + // weightMsgClawback, + // SimulateMsgClawback(txGen, ak, bk, sk), + // ), } } // SimulateMsgCreateVestingAccount generates a MsgCreateVestingAccount with random values. func SimulateMsgCreateVestingAccount( - // cdc *codec.ProtoCodec, txGen client.TxConfig, ak types.AccountKeeper, bk types.BankKeeper, @@ -129,7 +123,29 @@ func SimulateMsgCreateVestingAccount( if err != nil { return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "unable to deliver tx"), nil, err } - return simtypes.NewOperationMsg(msg, true, ""), nil, nil + + // sanity := ak.GetAccount(ctx, sdk.AccAddress(msg.ToAddress)) + // if sanity == nil { + // panic("why me") + // } + + // future operations + var futureOps []simtypes.FutureOperation + // // recipient stakes + // op := simulateMsgDelegate(txGen, ak, bk, sk, recipient, sendCoins) + // futureOps = append(futureOps, simtypes.FutureOperation{ + // BlockHeight: int(ctx.BlockHeight()) + 1, + // Op: op, + // }) + + // then funder claws back + op2 := simulateMsgClawbackFutureOp(txGen, ak, bk, sk, recipient, funder) + futureOps = append(futureOps, simtypes.FutureOperation{ + BlockHeight: int(ctx.BlockHeight()) + 10, + Op: op2, + }) + + return simtypes.NewOperationMsg(msg, true, ""), futureOps, nil } } @@ -198,3 +214,165 @@ func SimulateMsgClawback( return simtypes.NewOperationMsg(msg, true, ""), nil, nil } } + +func simulateMsgDelegate( + txGen client.TxConfig, + ak types.AccountKeeper, + bk types.BankKeeper, + sk types.StakingKeeper, + acc simtypes.Account, + originalVesting sdk.Coins, +) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accs []simtypes.Account, chainID string, + ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { + msgType := sdk.MsgTypeURL(&stakingtypes.MsgDelegate{}) + denom, err := sk.BondDenom(ctx) + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, msgType, "bond denom not found"), nil, err + } + + vals, err := sk.GetAllValidators(ctx) + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to get validators"), nil, err + } + + if len(vals) < 3 { + return simtypes.NoOpMsg(types.ModuleName, msgType, "number of validators equal zero"), nil, nil + } + + // simAccount, _ := simtypes.RandomAcc(r, accs) + + // TO-DO: spare first two validators so we don't crash the network + val, ok := testutil.RandSliceElem(r, vals[2:]) + if !ok { + return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to pick a validator"), nil, nil + } + + if val.InvalidExRate() { + return simtypes.NoOpMsg(types.ModuleName, msgType, "validator's invalid echange rate"), nil, nil + } + + // amount := bk.GetBalance(ctx, acc.Address, denom).Amount + // if !amount.IsPositive() { + // return simtypes.NoOpMsg(types.ModuleName, msgType, "balance is negative"), nil, nil + // } + + // amount, err = simtypes.RandPositiveInt(r, amount) + // if err != nil { + // return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to generate positive amount"), nil, err + // } + + // bondAmt := sdk.NewCoin(denom, amount) + + // account := ak.GetAccount(ctx, acc.Address) + // spendable := bk.SpendableCoins(ctx, account.GetAddress()) + + // fees := sdk.NewCoins() + + // coins, hasNeg := spendable.SafeSub(bondAmt) + // if !hasNeg { + // fees, err = simtypes.RandomFees(r, ctx, coins) + // if err != nil { + // return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to generate fees"), nil, err + // } + // } + found, bondAmt := originalVesting.Find(denom) + if !found { + panic("no bond denom in original vesting coins") + } + msg := stakingtypes.NewMsgDelegate(acc.Address.String(), val.GetOperator(), bondAmt) + + // Removing sim check since we cannot know the account number in advance + // tx, err := simtestutil.GenSignedMockTx( + // r, + // txGen, + // []sdk.Msg{msg}, + // fees, + // simtestutil.DefaultGenTxGas, + // chainID, + // []uint64{uint64(numAccs)}, //[]uint64{account.GetAccountNumber()}, + // []uint64{0}, //[]uint64{account.GetSequence()}, + // acc.PrivKey, + // ) + // if err != nil { + // return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "unable to generate mock tx"), nil, err + // } + + // _, _, err = app.SimDeliver(txGen.TxEncoder(), tx) + // if err != nil { + // return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "unable to deliver tx"), nil, err + // } + return simtypes.NewOperationMsg(msg, true, ""), nil, nil + } +} + +func simulateMsgClawbackFutureOp( + txGen client.TxConfig, + ak types.AccountKeeper, + bk types.BankKeeper, + sk types.StakingKeeper, + recipient simtypes.Account, + funder simtypes.Account, +) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, + accs []simtypes.Account, chainID string, + ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { + msgType := sdk.MsgTypeURL(&types.MsgClawback{}) + + sanity := ak.GetAccount(ctx, recipient.Address) + if sanity != nil { + panic("this is it") + } + // recipientAcc := ak.GetAccount(ctx, recipient.Address) + // vestingAcc, isClawback := recipientAcc.(*types.ClawbackContinuousVestingAccount) + // if !isClawback { + // return simtypes.NoOpMsg(types.ModuleName, msgType, "not a vesting account"), nil, nil + // } + // if vestingAcc.GetVestingCoins(ctx.BlockTime()).IsZero() { + // return simtypes.NoOpMsg(types.ModuleName, msgType, "vesting account not vesting anymore"), nil, nil + // } + + funder, found := simtypes.FindAccount(accs, funder.Address) + if !found { + return simtypes.NoOpMsg(types.ModuleName, msgType, "failed to find funder account"), nil, nil + } + funderAcc := ak.GetAccount(ctx, funder.Address) + spendableCoins := bk.SpendableCoins(ctx, funderAcc.GetAddress()) + if err := bk.IsSendEnabledCoins(ctx, spendableCoins...); err != nil { + return simtypes.NoOpMsg(types.ModuleName, msgType, err.Error()), nil, nil + } + + // fees, err := simtypes.RandomFees(r, ctx, spendableCoins) + // if err != nil { + // return simtypes.NoOpMsg(types.ModuleName, msgType, "unable to generate fees"), nil, err + // } + + msg := types.NewMsgClawback( + funderAcc.GetAddress(), + recipient.Address, + ) + + tx, err := simtestutil.GenSignedMockTx( + r, + txGen, + []sdk.Msg{msg}, + sdk.NewCoins(), //fees, + simtestutil.DefaultGenTxGas, + chainID, + []uint64{funderAcc.GetAccountNumber()}, + []uint64{funderAcc.GetSequence()}, + funder.PrivKey, + ) + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "unable to generate mock tx"), nil, err + } + + _, _, err = app.SimDeliver(txGen.TxEncoder(), tx) + if err != nil { + return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "unable to deliver tx"), nil, err + } + return simtypes.NewOperationMsg(msg, true, ""), nil, nil + } +} diff --git a/x/vesting/types/expected_keepers.go b/x/vesting/types/expected_keepers.go index c9a87945..f2f0980c 100644 --- a/x/vesting/types/expected_keepers.go +++ b/x/vesting/types/expected_keepers.go @@ -16,6 +16,7 @@ type AccountKeeper interface { SetAccount(ctx context.Context, acc sdk.AccountI) } type BankKeeper interface { + GetBalance(ctx context.Context, addr sdk.AccAddress, denom string) sdk.Coin GetAllBalances(ctx context.Context, addr sdk.AccAddress) sdk.Coins IsSendEnabledCoins(ctx context.Context, coins ...sdk.Coin) error SendCoins(ctx context.Context, fromAddr, toAddr sdk.AccAddress, amt sdk.Coins) error @@ -26,6 +27,7 @@ type BankKeeper interface { type StakingKeeper interface { BondDenom(ctx context.Context) (string, error) GetValidator(ctx context.Context, addr sdk.ValAddress) (validator types.Validator, err error) + GetAllValidators(ctx context.Context) ([]types.Validator, error) GetDelegatorBonded(ctx context.Context, delegator sdk.AccAddress) (math.Int, error) GetDelegatorUnbonding(ctx context.Context, delegator sdk.AccAddress) (math.Int, error) GetUnbondingDelegations(ctx context.Context, delegator sdk.AccAddress, maxRetrieve uint16) (unbondingDelegations []types.UnbondingDelegation, err error) From dcb9413d37de85b8e548dddbf60c730dd778233c Mon Sep 17 00:00:00 2001 From: Hyoung-yoon Kim Date: Tue, 13 Feb 2024 23:51:53 -0500 Subject: [PATCH 07/15] fix: test and fix clawback with redelegation --- x/staking/keeper/keeper.go | 30 +- x/vesting/keeper/clawback_test.go | 161 +++++---- x/vesting/keeper/integration_test.go | 2 + x/vesting/keeper/msg_server.go | 20 +- x/vesting/simulation/operations.go | 15 +- x/vesting/testutil/expected_keepers_mocks.go | 333 ------------------- 6 files changed, 133 insertions(+), 428 deletions(-) delete mode 100644 x/vesting/testutil/expected_keepers_mocks.go diff --git a/x/staking/keeper/keeper.go b/x/staking/keeper/keeper.go index 5b211805..e35b6ff5 100644 --- a/x/staking/keeper/keeper.go +++ b/x/staking/keeper/keeper.go @@ -60,7 +60,19 @@ func (k Keeper) TransferDelegation(ctx context.Context, fromAddr, toAddr sdk.Acc // TO-DO panic(err) } - fromRedelegation, err := k.GetRedelegation(ctx, fromAddr, sdk.ValAddress(toRedelegation.ValidatorSrcAddress), sdk.ValAddress(toRedelegation.ValidatorDstAddress)) + + valSrcAddr, err := sdk.ValAddressFromBech32(toRedelegation.ValidatorSrcAddress) + if err != nil { + // TO-DO + panic(err) + } + valDstAddr, err := sdk.ValAddressFromBech32(toRedelegation.ValidatorDstAddress) + if err != nil { + // TO-DO + panic(err) + } + + fromRedelegation, err := k.GetRedelegation(ctx, fromAddr, valSrcAddr, valDstAddr) if err == nil && len(toRedelegation.Entries)+len(fromRedelegation.Entries) >= int(maxEntries) { mightExceedLimit = true return true @@ -133,6 +145,16 @@ func (k Keeper) TransferDelegation(ctx context.Context, fromAddr, toAddr sdk.Acc if redelegation.ValidatorDstAddress != valAddr.String() { continue } + + valSrcAddr, err := sdk.ValAddressFromBech32(redelegation.ValidatorSrcAddress) + if err != nil { + return transferred, err + } + valDstAddr, err := sdk.ValAddressFromBech32(redelegation.ValidatorDstAddress) + if err != nil { + return transferred, err + } + redelegationModified := false entriesRemaining := false for i := 0; i < len(redelegation.Entries); i++ { @@ -155,8 +177,7 @@ func (k Keeper) TransferDelegation(ctx context.Context, fromAddr, toAddr sdk.Acc if sharesToKeep.IsZero() { // Transfer the whole entry, delete locally toRed, err := k.SetRedelegationEntry( - ctx, toAddr, sdk.ValAddress(redelegation.ValidatorSrcAddress), - sdk.ValAddress(redelegation.ValidatorDstAddress), + ctx, toAddr, valSrcAddr, valDstAddr, entry.CreationHeight, entry.CompletionTime, entry.InitialBalance, math.LegacyZeroDec(), sharesToSend, ) if err != nil { @@ -173,8 +194,7 @@ func (k Keeper) TransferDelegation(ctx context.Context, fromAddr, toAddr sdk.Acc balanceToSend := fracSending.MulInt(entry.InitialBalance).TruncateInt() balanceToKeep := entry.InitialBalance.Sub(balanceToSend) toRed, err := k.SetRedelegationEntry( - ctx, toAddr, sdk.ValAddress(redelegation.ValidatorSrcAddress), - sdk.ValAddress(redelegation.ValidatorDstAddress), + ctx, toAddr, valSrcAddr, valDstAddr, entry.CreationHeight, entry.CompletionTime, balanceToSend, math.LegacyZeroDec(), sharesToSend, ) if err != nil { diff --git a/x/vesting/keeper/clawback_test.go b/x/vesting/keeper/clawback_test.go index 308b945a..426b190a 100644 --- a/x/vesting/keeper/clawback_test.go +++ b/x/vesting/keeper/clawback_test.go @@ -16,7 +16,7 @@ import ( func TestClawback(t *testing.T) { f := initFixture(t) f.bankKeeper.SetSendEnabled(f.Context(), "aseda", true) - err := banktestutil.FundAccount(f.Context(), f.bankKeeper, funderAddr, sdk.NewCoins(sdk.NewInt64Coin(bondDenom, 100000))) + err := banktestutil.FundAccount(f.Context(), f.bankKeeper, funderAddr, sdk.NewCoins(sdk.NewInt64Coin(bondDenom, 500000))) require.NoError(t, err) _, valAddrs, valPks := createValidators(t, f, []int64{5, 5, 5}) @@ -29,14 +29,13 @@ func TestClawback(t *testing.T) { vestingTime int64 timeUntilClawback int64 originalVesting sdk.Coin - delegation sdk.Coin - delegation2 sdk.Coin - undelegation sdk.Coin - undelegation2 sdk.Coin + delegations []sdk.Coin // to val0 and val1 + undelegations []sdk.Coin // from val0 and val1 + redelegations []sdk.Coin // (val0 -> val1) and (val1 -> val0) expClawedUnbonded sdk.Coins expClawedUnbonding sdk.Coins expClawedBonded sdk.Coins - slashingFraction math.LegacyDec + slashFractions []math.LegacyDec // on val0 and val1 recipientFinalSpendable sdk.Coins }{ { @@ -46,12 +45,13 @@ func TestClawback(t *testing.T) { vestingTime: 100, timeUntilClawback: 30, originalVesting: sdk.NewInt64Coin(bondDenom, 10000), - delegation: sdk.NewInt64Coin(bondDenom, 0), - undelegation: sdk.NewInt64Coin(bondDenom, 0), + delegations: []sdk.Coin{sdk.NewInt64Coin(bondDenom, 0), sdk.NewInt64Coin(bondDenom, 0)}, + undelegations: []sdk.Coin{sdk.NewInt64Coin(bondDenom, 0), sdk.NewInt64Coin(bondDenom, 0)}, + redelegations: []sdk.Coin{sdk.NewInt64Coin(bondDenom, 0), sdk.NewInt64Coin(bondDenom, 0)}, expClawedUnbonded: sdk.NewCoins(sdk.NewInt64Coin(bondDenom, 7000)), expClawedUnbonding: zeroCoins, expClawedBonded: zeroCoins, - slashingFraction: math.LegacyZeroDec(), + slashFractions: []math.LegacyDec{math.LegacyZeroDec(), math.LegacyZeroDec()}, recipientFinalSpendable: sdk.NewCoins(sdk.NewInt64Coin(bondDenom, 3000)), }, { @@ -61,14 +61,13 @@ func TestClawback(t *testing.T) { vestingTime: 100, timeUntilClawback: 30, originalVesting: sdk.NewInt64Coin(bondDenom, 10000), - delegation: sdk.NewInt64Coin(bondDenom, 5000), - delegation2: sdk.NewInt64Coin(bondDenom, 0), - undelegation: sdk.NewInt64Coin(bondDenom, 0), - undelegation2: sdk.NewInt64Coin(bondDenom, 0), + delegations: []sdk.Coin{sdk.NewInt64Coin(bondDenom, 5000), sdk.NewInt64Coin(bondDenom, 0)}, + undelegations: []sdk.Coin{sdk.NewInt64Coin(bondDenom, 0), sdk.NewInt64Coin(bondDenom, 0)}, + redelegations: []sdk.Coin{sdk.NewInt64Coin(bondDenom, 0), sdk.NewInt64Coin(bondDenom, 0)}, expClawedUnbonded: sdk.NewCoins(sdk.NewInt64Coin(bondDenom, 5000)), expClawedUnbonding: zeroCoins, expClawedBonded: sdk.NewCoins(sdk.NewInt64Coin(bondDenom, 2000)), - slashingFraction: math.LegacyZeroDec(), + slashFractions: []math.LegacyDec{math.LegacyZeroDec(), math.LegacyZeroDec()}, recipientFinalSpendable: sdk.NewCoins(), }, { @@ -78,14 +77,13 @@ func TestClawback(t *testing.T) { vestingTime: 100, timeUntilClawback: 60, originalVesting: sdk.NewInt64Coin(bondDenom, 27500), - delegation: sdk.NewInt64Coin(bondDenom, 27500), - delegation2: sdk.NewInt64Coin(bondDenom, 0), - undelegation: sdk.NewInt64Coin(bondDenom, 0), - undelegation2: sdk.NewInt64Coin(bondDenom, 0), + delegations: []sdk.Coin{sdk.NewInt64Coin(bondDenom, 27500), sdk.NewInt64Coin(bondDenom, 0)}, + undelegations: []sdk.Coin{sdk.NewInt64Coin(bondDenom, 0), sdk.NewInt64Coin(bondDenom, 0)}, + redelegations: []sdk.Coin{sdk.NewInt64Coin(bondDenom, 0), sdk.NewInt64Coin(bondDenom, 0)}, expClawedUnbonded: zeroCoins, expClawedUnbonding: zeroCoins, expClawedBonded: sdk.NewCoins(sdk.NewInt64Coin(bondDenom, 11000)), - slashingFraction: math.LegacyZeroDec(), + slashFractions: []math.LegacyDec{math.LegacyZeroDec(), math.LegacyZeroDec()}, recipientFinalSpendable: sdk.NewCoins(), }, { @@ -95,14 +93,13 @@ func TestClawback(t *testing.T) { vestingTime: 50000, timeUntilClawback: 30000, originalVesting: sdk.NewInt64Coin(bondDenom, 27500), - delegation: sdk.NewInt64Coin(bondDenom, 27500), - delegation2: sdk.NewInt64Coin(bondDenom, 0), - undelegation: sdk.NewInt64Coin(bondDenom, 27500), - undelegation2: sdk.NewInt64Coin(bondDenom, 0), + delegations: []sdk.Coin{sdk.NewInt64Coin(bondDenom, 27500), sdk.NewInt64Coin(bondDenom, 0)}, + undelegations: []sdk.Coin{sdk.NewInt64Coin(bondDenom, 27500), sdk.NewInt64Coin(bondDenom, 0)}, + redelegations: []sdk.Coin{sdk.NewInt64Coin(bondDenom, 0), sdk.NewInt64Coin(bondDenom, 0)}, expClawedUnbonded: zeroCoins, expClawedUnbonding: sdk.NewCoins(sdk.NewInt64Coin(bondDenom, 11000)), expClawedBonded: zeroCoins, - slashingFraction: math.LegacyZeroDec(), + slashFractions: []math.LegacyDec{math.LegacyZeroDec(), math.LegacyZeroDec()}, recipientFinalSpendable: sdk.NewCoins(), }, { @@ -112,48 +109,61 @@ func TestClawback(t *testing.T) { vestingTime: 750000, timeUntilClawback: 600000, originalVesting: sdk.NewInt64Coin(bondDenom, 13000), - delegation: sdk.NewInt64Coin(bondDenom, 10000), - delegation2: sdk.NewInt64Coin(bondDenom, 2000), - undelegation: sdk.NewInt64Coin(bondDenom, 400), - undelegation2: sdk.NewInt64Coin(bondDenom, 100), + delegations: []sdk.Coin{sdk.NewInt64Coin(bondDenom, 10000), sdk.NewInt64Coin(bondDenom, 2000)}, + undelegations: []sdk.Coin{sdk.NewInt64Coin(bondDenom, 400), sdk.NewInt64Coin(bondDenom, 100)}, + redelegations: []sdk.Coin{sdk.NewInt64Coin(bondDenom, 0), sdk.NewInt64Coin(bondDenom, 0)}, expClawedUnbonded: sdk.NewCoins(sdk.NewInt64Coin(bondDenom, 1000)), expClawedUnbonding: sdk.NewCoins(sdk.NewInt64Coin(bondDenom, 500)), expClawedBonded: sdk.NewCoins(sdk.NewInt64Coin(bondDenom, 1100)), - slashingFraction: math.LegacyZeroDec(), + slashFractions: []math.LegacyDec{math.LegacyZeroDec(), math.LegacyZeroDec()}, recipientFinalSpendable: sdk.NewCoins(), }, { testName: "clawback from unbonded and bonded with slashing", funder: sdk.MustAccAddressFromBech32("seda1gujynygp0tkwzfpt0g7dv4829jwyk8f0yhp88d"), - recipient: testAddrs[6], + recipient: testAddrs[5], vestingTime: 100, timeUntilClawback: 30, originalVesting: sdk.NewInt64Coin(bondDenom, 10000), - delegation: sdk.NewInt64Coin(bondDenom, 5000), - delegation2: sdk.NewInt64Coin(bondDenom, 0), - undelegation: sdk.NewInt64Coin(bondDenom, 0), - undelegation2: sdk.NewInt64Coin(bondDenom, 0), + delegations: []sdk.Coin{sdk.NewInt64Coin(bondDenom, 5000), sdk.NewInt64Coin(bondDenom, 0)}, + undelegations: []sdk.Coin{sdk.NewInt64Coin(bondDenom, 0), sdk.NewInt64Coin(bondDenom, 0)}, + redelegations: []sdk.Coin{sdk.NewInt64Coin(bondDenom, 0), sdk.NewInt64Coin(bondDenom, 0)}, expClawedUnbonded: sdk.NewCoins(sdk.NewInt64Coin(bondDenom, 5000)), expClawedUnbonding: zeroCoins, expClawedBonded: sdk.NewCoins(sdk.NewInt64Coin(bondDenom, 2000)), - slashingFraction: math.LegacyNewDecWithPrec(5, 2), + slashFractions: []math.LegacyDec{math.LegacyNewDecWithPrec(5, 2), math.LegacyZeroDec()}, // 0.05 and 0 recipientFinalSpendable: sdk.NewCoins(), }, { testName: "clawback from unbonded, unbonding, and bonded with slashing", funder: sdk.MustAccAddressFromBech32("seda1gujynygp0tkwzfpt0g7dv4829jwyk8f0yhp88d"), - recipient: testAddrs[5], + recipient: testAddrs[6], vestingTime: 750000, timeUntilClawback: 600000, originalVesting: sdk.NewInt64Coin(bondDenom, 13000), - delegation: sdk.NewInt64Coin(bondDenom, 10000), - delegation2: sdk.NewInt64Coin(bondDenom, 2000), - undelegation: sdk.NewInt64Coin(bondDenom, 400), - undelegation2: sdk.NewInt64Coin(bondDenom, 100), + delegations: []sdk.Coin{sdk.NewInt64Coin(bondDenom, 10000), sdk.NewInt64Coin(bondDenom, 2000)}, + undelegations: []sdk.Coin{sdk.NewInt64Coin(bondDenom, 400), sdk.NewInt64Coin(bondDenom, 100)}, + redelegations: []sdk.Coin{sdk.NewInt64Coin(bondDenom, 0), sdk.NewInt64Coin(bondDenom, 0)}, expClawedUnbonded: sdk.NewCoins(sdk.NewInt64Coin(bondDenom, 1000)), expClawedUnbonding: sdk.NewCoins(sdk.NewInt64Coin(bondDenom, 180)), expClawedBonded: sdk.NewCoins(sdk.NewInt64Coin(bondDenom, 1420)), - slashingFraction: math.LegacyNewDecWithPrec(8, 1), // 0.8 + slashFractions: []math.LegacyDec{math.LegacyNewDecWithPrec(8, 1), math.LegacyZeroDec()}, // 0.8 and 0 + recipientFinalSpendable: sdk.NewCoins(), + }, + { + testName: "clawback from redelegation with slashing", + funder: sdk.MustAccAddressFromBech32("seda1gujynygp0tkwzfpt0g7dv4829jwyk8f0yhp88d"), + recipient: testAddrs[7], + vestingTime: 50000, + timeUntilClawback: 30000, + originalVesting: sdk.NewInt64Coin(bondDenom, 27500), + delegations: []sdk.Coin{sdk.NewInt64Coin(bondDenom, 27500), sdk.NewInt64Coin(bondDenom, 0)}, + undelegations: []sdk.Coin{sdk.NewInt64Coin(bondDenom, 0), sdk.NewInt64Coin(bondDenom, 0)}, + redelegations: []sdk.Coin{sdk.NewInt64Coin(bondDenom, 27500), sdk.NewInt64Coin(bondDenom, 0)}, + expClawedUnbonded: zeroCoins, + expClawedUnbonding: zeroCoins, + expClawedBonded: sdk.NewCoins(sdk.NewInt64Coin(bondDenom, 9625)), + slashFractions: []math.LegacyDec{math.LegacyZeroDec(), math.LegacyNewDecWithPrec(65, 2)}, // 0 and 0.65 recipientFinalSpendable: sdk.NewCoins(), }, } @@ -173,50 +183,73 @@ func TestClawback(t *testing.T) { require.NoError(t, err) // 2. delegate - if tc.delegation.IsPositive() { + if tc.delegations[0].IsPositive() { delegateMsg := &sdkstakingtypes.MsgDelegate{ DelegatorAddress: tc.recipient.String(), ValidatorAddress: valAddrs[0].String(), - Amount: tc.delegation, + Amount: tc.delegations[0], } _, err = f.RunMsg(delegateMsg) require.NoError(t, err) - - if tc.delegation2.IsPositive() { - delegateMsg := &sdkstakingtypes.MsgDelegate{ - DelegatorAddress: tc.recipient.String(), - ValidatorAddress: valAddrs[1].String(), - Amount: tc.delegation2, - } - _, err = f.RunMsg(delegateMsg) - require.NoError(t, err) + } + if tc.delegations[1].IsPositive() { + delegateMsg := &sdkstakingtypes.MsgDelegate{ + DelegatorAddress: tc.recipient.String(), + ValidatorAddress: valAddrs[1].String(), + Amount: tc.delegations[1], } + _, err = f.RunMsg(delegateMsg) + require.NoError(t, err) } // 3. initiate unbonding after some time - if tc.undelegation.IsPositive() { + if tc.undelegations[0].IsPositive() { undelegateMsg := &sdkstakingtypes.MsgUndelegate{ DelegatorAddress: tc.recipient.String(), ValidatorAddress: valAddrs[0].String(), - Amount: tc.undelegation, + Amount: tc.undelegations[0], + } + _, err = f.RunMsg(undelegateMsg) + require.NoError(t, err) + } + if tc.undelegations[1].IsPositive() { + undelegateMsg := &sdkstakingtypes.MsgUndelegate{ + DelegatorAddress: tc.recipient.String(), + ValidatorAddress: valAddrs[1].String(), + Amount: tc.undelegations[1], } _, err = f.RunMsg(undelegateMsg) require.NoError(t, err) + } - if tc.undelegation2.IsPositive() { - undelegateMsg := &sdkstakingtypes.MsgUndelegate{ - DelegatorAddress: tc.recipient.String(), - ValidatorAddress: valAddrs[1].String(), - Amount: tc.undelegation2, - } - _, err = f.RunMsg(undelegateMsg) - require.NoError(t, err) + if tc.redelegations[0].IsPositive() { + redelegateMsg := &sdkstakingtypes.MsgBeginRedelegate{ + DelegatorAddress: tc.recipient.String(), + ValidatorSrcAddress: valAddrs[0].String(), + ValidatorDstAddress: valAddrs[1].String(), + Amount: tc.redelegations[0], + } + _, err = f.RunMsg(redelegateMsg) + require.NoError(t, err) + } + if tc.redelegations[1].IsPositive() { + redelegateMsg := &sdkstakingtypes.MsgBeginRedelegate{ + DelegatorAddress: tc.recipient.String(), + ValidatorSrcAddress: valAddrs[1].String(), + ValidatorDstAddress: valAddrs[0].String(), + Amount: tc.redelegations[1], } + _, err = f.RunMsg(redelegateMsg) + require.NoError(t, err) } // possible slashing - if tc.slashingFraction.IsPositive() { - _, err = f.stakingKeeper.Slash(f.Context(), sdk.ConsAddress(valPks[0].Address()), f.Context().BlockHeight()-1, 5, tc.slashingFraction) + if tc.slashFractions[0].IsPositive() { + _, err = f.stakingKeeper.Slash(f.Context(), sdk.ConsAddress(valPks[0].Address()), f.Context().BlockHeight()-1, 5, tc.slashFractions[0]) + require.NoError(t, err) + } + if tc.slashFractions[1].IsPositive() { + _, err = f.stakingKeeper.Slash(f.Context(), sdk.ConsAddress(valPks[1].Address()), f.Context().BlockHeight()-1, 5, tc.slashFractions[1]) require.NoError(t, err) } diff --git a/x/vesting/keeper/integration_test.go b/x/vesting/keeper/integration_test.go index 07b149a2..d0c4a07b 100644 --- a/x/vesting/keeper/integration_test.go +++ b/x/vesting/keeper/integration_test.go @@ -57,6 +57,8 @@ var ( sdk.AccAddress([]byte("to5_________________")), sdk.AccAddress([]byte("to6_________________")), sdk.AccAddress([]byte("to7_________________")), + sdk.AccAddress([]byte("to8_________________")), + sdk.AccAddress([]byte("to9_________________")), } ) diff --git a/x/vesting/keeper/msg_server.go b/x/vesting/keeper/msg_server.go index fb7d22cf..6c10b13e 100644 --- a/x/vesting/keeper/msg_server.go +++ b/x/vesting/keeper/msg_server.go @@ -135,13 +135,6 @@ func (m msgServer) Clawback(goCtx context.Context, msg *types.MsgClawback) (*typ return nil, errorsmod.Wrapf(sdkerrors.ErrUnauthorized, "clawback can only be requested by original funder: %s", vestingAccount.FunderAddress) } - totalVesting := vestingAccount.GetVestingCoins(ctx.BlockTime()) - totalVested := vestingAccount.GetVestedCoins(ctx.BlockTime()) - fmt.Println(totalVested) - - // update the vesting account so that all of original vesting is vested now - vestingAccount.EndTime = ctx.BlockTime().Unix() - // Compute the clawback based on bank balance and delegation, and update account bondedAmt, err := m.sk.GetDelegatorBonded(ctx, vestingAccAddr) if err != nil { @@ -160,20 +153,24 @@ func (m msgServer) Clawback(goCtx context.Context, msg *types.MsgClawback) (*typ unbonding := sdk.NewCoins(sdk.NewCoin(bondDenom, unbondingAmt)) unbonded := m.bk.GetAllBalances(ctx, vestingAccAddr) total := bonded.Add(unbonding...).Add(unbonded...) - toClawBack := coinsMin(totalVesting, total) // might have been slashed + + toClawBack := coinsMin(vestingAccount.GetVestingCoins(ctx.BlockTime()), total) // might have been slashed // Write now now so that the bank module sees unvested tokens are unlocked. // Note that all store writes are aborted if there is a panic, so there is // no danger in writing incomplete results. + vestingAccount.EndTime = ctx.BlockTime().Unix() // so that all of original vesting is vested now m.ak.SetAccount(ctx, vestingAccount) // Now that future vesting events (and associated lockup) are removed, // the balance of the account is unlocked and can be freely transferred. spendable := m.bk.SpendableCoins(ctx, vestingAccAddr) toXfer := coinsMin(toClawBack, spendable) - err = m.bk.SendCoins(ctx, vestingAccAddr, funderAddr, toXfer) - if err != nil { - return nil, err // shouldn't happen, given spendable check + if toXfer.IsAllPositive() { + err = m.bk.SendCoins(ctx, vestingAccAddr, funderAddr, toXfer) + if err != nil { + return nil, err // shouldn't happen, given spendable check + } } clawedBackUnbonded := toXfer @@ -231,7 +228,6 @@ func (m msgServer) Clawback(goCtx context.Context, msg *types.MsgClawback) (*typ transferredShares, err := m.sk.TransferDelegation(ctx, vestingAccAddr, funderAddr, validatorAddr, wantShares) if err != nil { panic(err) // shouldn't happen TO-DO - } // to be conservative in what we're clawing back, round transferred shares up diff --git a/x/vesting/simulation/operations.go b/x/vesting/simulation/operations.go index 833b2409..4c895564 100644 --- a/x/vesting/simulation/operations.go +++ b/x/vesting/simulation/operations.go @@ -141,7 +141,7 @@ func SimulateMsgCreateVestingAccount( // then funder claws back op2 := simulateMsgClawbackFutureOp(txGen, ak, bk, sk, recipient, funder) futureOps = append(futureOps, simtypes.FutureOperation{ - BlockHeight: int(ctx.BlockHeight()) + 10, + BlockHeight: int(ctx.BlockHeight()) + 1, Op: op2, }) @@ -321,19 +321,6 @@ func simulateMsgClawbackFutureOp( ) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { msgType := sdk.MsgTypeURL(&types.MsgClawback{}) - sanity := ak.GetAccount(ctx, recipient.Address) - if sanity != nil { - panic("this is it") - } - // recipientAcc := ak.GetAccount(ctx, recipient.Address) - // vestingAcc, isClawback := recipientAcc.(*types.ClawbackContinuousVestingAccount) - // if !isClawback { - // return simtypes.NoOpMsg(types.ModuleName, msgType, "not a vesting account"), nil, nil - // } - // if vestingAcc.GetVestingCoins(ctx.BlockTime()).IsZero() { - // return simtypes.NoOpMsg(types.ModuleName, msgType, "vesting account not vesting anymore"), nil, nil - // } - funder, found := simtypes.FindAccount(accs, funder.Address) if !found { return simtypes.NoOpMsg(types.ModuleName, msgType, "failed to find funder account"), nil, nil diff --git a/x/vesting/testutil/expected_keepers_mocks.go b/x/vesting/testutil/expected_keepers_mocks.go deleted file mode 100644 index 4afcd75a..00000000 --- a/x/vesting/testutil/expected_keepers_mocks.go +++ /dev/null @@ -1,333 +0,0 @@ -// Code generated by MockGen. DO NOT EDIT. -// Source: x/vesting/types/expected_keepers.go - -// Package testutil is a generated GoMock package. -package testutil - -import ( - context "context" - reflect "reflect" - - address "cosmossdk.io/core/address" - math "cosmossdk.io/math" - types "github.com/cosmos/cosmos-sdk/types" - types0 "github.com/cosmos/cosmos-sdk/x/staking/types" - gomock "github.com/golang/mock/gomock" -) - -// MockAccountKeeper is a mock of AccountKeeper interface. -type MockAccountKeeper struct { - ctrl *gomock.Controller - recorder *MockAccountKeeperMockRecorder -} - -// MockAccountKeeperMockRecorder is the mock recorder for MockAccountKeeper. -type MockAccountKeeperMockRecorder struct { - mock *MockAccountKeeper -} - -// NewMockAccountKeeper creates a new mock instance. -func NewMockAccountKeeper(ctrl *gomock.Controller) *MockAccountKeeper { - mock := &MockAccountKeeper{ctrl: ctrl} - mock.recorder = &MockAccountKeeperMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockAccountKeeper) EXPECT() *MockAccountKeeperMockRecorder { - return m.recorder -} - -// AddressCodec mocks base method. -func (m *MockAccountKeeper) AddressCodec() address.Codec { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "AddressCodec") - ret0, _ := ret[0].(address.Codec) - return ret0 -} - -// AddressCodec indicates an expected call of AddressCodec. -func (mr *MockAccountKeeperMockRecorder) AddressCodec() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddressCodec", reflect.TypeOf((*MockAccountKeeper)(nil).AddressCodec)) -} - -// GetAccount mocks base method. -func (m *MockAccountKeeper) GetAccount(ctx context.Context, addr types.AccAddress) types.AccountI { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetAccount", ctx, addr) - ret0, _ := ret[0].(types.AccountI) - return ret0 -} - -// GetAccount indicates an expected call of GetAccount. -func (mr *MockAccountKeeperMockRecorder) GetAccount(ctx, addr interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAccount", reflect.TypeOf((*MockAccountKeeper)(nil).GetAccount), ctx, addr) -} - -// NewAccount mocks base method. -func (m *MockAccountKeeper) NewAccount(ctx context.Context, acc types.AccountI) types.AccountI { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "NewAccount", ctx, acc) - ret0, _ := ret[0].(types.AccountI) - return ret0 -} - -// NewAccount indicates an expected call of NewAccount. -func (mr *MockAccountKeeperMockRecorder) NewAccount(ctx, acc interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewAccount", reflect.TypeOf((*MockAccountKeeper)(nil).NewAccount), ctx, acc) -} - -// SetAccount mocks base method. -func (m *MockAccountKeeper) SetAccount(ctx context.Context, acc types.AccountI) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "SetAccount", ctx, acc) -} - -// SetAccount indicates an expected call of SetAccount. -func (mr *MockAccountKeeperMockRecorder) SetAccount(ctx, acc interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetAccount", reflect.TypeOf((*MockAccountKeeper)(nil).SetAccount), ctx, acc) -} - -// MockBankKeeper is a mock of BankKeeper interface. -type MockBankKeeper struct { - ctrl *gomock.Controller - recorder *MockBankKeeperMockRecorder -} - -// MockBankKeeperMockRecorder is the mock recorder for MockBankKeeper. -type MockBankKeeperMockRecorder struct { - mock *MockBankKeeper -} - -// NewMockBankKeeper creates a new mock instance. -func NewMockBankKeeper(ctrl *gomock.Controller) *MockBankKeeper { - mock := &MockBankKeeper{ctrl: ctrl} - mock.recorder = &MockBankKeeperMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockBankKeeper) EXPECT() *MockBankKeeperMockRecorder { - return m.recorder -} - -// BlockedAddr mocks base method. -func (m *MockBankKeeper) BlockedAddr(addr types.AccAddress) bool { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "BlockedAddr", addr) - ret0, _ := ret[0].(bool) - return ret0 -} - -// BlockedAddr indicates an expected call of BlockedAddr. -func (mr *MockBankKeeperMockRecorder) BlockedAddr(addr interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BlockedAddr", reflect.TypeOf((*MockBankKeeper)(nil).BlockedAddr), addr) -} - -// GetAllBalances mocks base method. -func (m *MockBankKeeper) GetAllBalances(ctx context.Context, addr types.AccAddress) types.Coins { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetAllBalances", ctx, addr) - ret0, _ := ret[0].(types.Coins) - return ret0 -} - -// GetAllBalances indicates an expected call of GetAllBalances. -func (mr *MockBankKeeperMockRecorder) GetAllBalances(ctx, addr interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAllBalances", reflect.TypeOf((*MockBankKeeper)(nil).GetAllBalances), ctx, addr) -} - -// IsSendEnabledCoins mocks base method. -func (m *MockBankKeeper) IsSendEnabledCoins(ctx context.Context, coins ...types.Coin) error { - m.ctrl.T.Helper() - varargs := []interface{}{ctx} - for _, a := range coins { - varargs = append(varargs, a) - } - ret := m.ctrl.Call(m, "IsSendEnabledCoins", varargs...) - ret0, _ := ret[0].(error) - return ret0 -} - -// IsSendEnabledCoins indicates an expected call of IsSendEnabledCoins. -func (mr *MockBankKeeperMockRecorder) IsSendEnabledCoins(ctx interface{}, coins ...interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - varargs := append([]interface{}{ctx}, coins...) - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsSendEnabledCoins", reflect.TypeOf((*MockBankKeeper)(nil).IsSendEnabledCoins), varargs...) -} - -// SendCoins mocks base method. -func (m *MockBankKeeper) SendCoins(ctx context.Context, fromAddr, toAddr types.AccAddress, amt types.Coins) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SendCoins", ctx, fromAddr, toAddr, amt) - ret0, _ := ret[0].(error) - return ret0 -} - -// SendCoins indicates an expected call of SendCoins. -func (mr *MockBankKeeperMockRecorder) SendCoins(ctx, fromAddr, toAddr, amt interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendCoins", reflect.TypeOf((*MockBankKeeper)(nil).SendCoins), ctx, fromAddr, toAddr, amt) -} - -// SpendableCoins mocks base method. -func (m *MockBankKeeper) SpendableCoins(ctx context.Context, addr types.AccAddress) types.Coins { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SpendableCoins", ctx, addr) - ret0, _ := ret[0].(types.Coins) - return ret0 -} - -// SpendableCoins indicates an expected call of SpendableCoins. -func (mr *MockBankKeeperMockRecorder) SpendableCoins(ctx, addr interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SpendableCoins", reflect.TypeOf((*MockBankKeeper)(nil).SpendableCoins), ctx, addr) -} - -// MockStakingKeeper is a mock of StakingKeeper interface. -type MockStakingKeeper struct { - ctrl *gomock.Controller - recorder *MockStakingKeeperMockRecorder -} - -// MockStakingKeeperMockRecorder is the mock recorder for MockStakingKeeper. -type MockStakingKeeperMockRecorder struct { - mock *MockStakingKeeper -} - -// NewMockStakingKeeper creates a new mock instance. -func NewMockStakingKeeper(ctrl *gomock.Controller) *MockStakingKeeper { - mock := &MockStakingKeeper{ctrl: ctrl} - mock.recorder = &MockStakingKeeperMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockStakingKeeper) EXPECT() *MockStakingKeeperMockRecorder { - return m.recorder -} - -// BondDenom mocks base method. -func (m *MockStakingKeeper) BondDenom(ctx context.Context) (string, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "BondDenom", ctx) - ret0, _ := ret[0].(string) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// BondDenom indicates an expected call of BondDenom. -func (mr *MockStakingKeeperMockRecorder) BondDenom(ctx interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BondDenom", reflect.TypeOf((*MockStakingKeeper)(nil).BondDenom), ctx) -} - -// GetDelegatorBonded mocks base method. -func (m *MockStakingKeeper) GetDelegatorBonded(ctx context.Context, delegator types.AccAddress) (math.Int, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetDelegatorBonded", ctx, delegator) - ret0, _ := ret[0].(math.Int) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetDelegatorBonded indicates an expected call of GetDelegatorBonded. -func (mr *MockStakingKeeperMockRecorder) GetDelegatorBonded(ctx, delegator interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDelegatorBonded", reflect.TypeOf((*MockStakingKeeper)(nil).GetDelegatorBonded), ctx, delegator) -} - -// GetDelegatorDelegations mocks base method. -func (m *MockStakingKeeper) GetDelegatorDelegations(ctx context.Context, delegator types.AccAddress, maxRetrieve uint16) ([]types0.Delegation, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetDelegatorDelegations", ctx, delegator, maxRetrieve) - ret0, _ := ret[0].([]types0.Delegation) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetDelegatorDelegations indicates an expected call of GetDelegatorDelegations. -func (mr *MockStakingKeeperMockRecorder) GetDelegatorDelegations(ctx, delegator, maxRetrieve interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDelegatorDelegations", reflect.TypeOf((*MockStakingKeeper)(nil).GetDelegatorDelegations), ctx, delegator, maxRetrieve) -} - -// GetDelegatorUnbonding mocks base method. -func (m *MockStakingKeeper) GetDelegatorUnbonding(ctx context.Context, delegator types.AccAddress) (math.Int, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetDelegatorUnbonding", ctx, delegator) - ret0, _ := ret[0].(math.Int) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetDelegatorUnbonding indicates an expected call of GetDelegatorUnbonding. -func (mr *MockStakingKeeperMockRecorder) GetDelegatorUnbonding(ctx, delegator interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDelegatorUnbonding", reflect.TypeOf((*MockStakingKeeper)(nil).GetDelegatorUnbonding), ctx, delegator) -} - -// GetUnbondingDelegations mocks base method. -func (m *MockStakingKeeper) GetUnbondingDelegations(ctx context.Context, delegator types.AccAddress, maxRetrieve uint16) ([]types0.UnbondingDelegation, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetUnbondingDelegations", ctx, delegator, maxRetrieve) - ret0, _ := ret[0].([]types0.UnbondingDelegation) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetUnbondingDelegations indicates an expected call of GetUnbondingDelegations. -func (mr *MockStakingKeeperMockRecorder) GetUnbondingDelegations(ctx, delegator, maxRetrieve interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUnbondingDelegations", reflect.TypeOf((*MockStakingKeeper)(nil).GetUnbondingDelegations), ctx, delegator, maxRetrieve) -} - -// GetValidator mocks base method. -func (m *MockStakingKeeper) GetValidator(ctx context.Context, addr types.ValAddress) (types0.Validator, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetValidator", ctx, addr) - ret0, _ := ret[0].(types0.Validator) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetValidator indicates an expected call of GetValidator. -func (mr *MockStakingKeeperMockRecorder) GetValidator(ctx, addr interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetValidator", reflect.TypeOf((*MockStakingKeeper)(nil).GetValidator), ctx, addr) -} - -// TransferDelegation mocks base method. -func (m *MockStakingKeeper) TransferDelegation(ctx context.Context, fromAddr, toAddr types.AccAddress, valAddr types.ValAddress, wantShares math.LegacyDec) (math.LegacyDec, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "TransferDelegation", ctx, fromAddr, toAddr, valAddr, wantShares) - ret0, _ := ret[0].(math.LegacyDec) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// TransferDelegation indicates an expected call of TransferDelegation. -func (mr *MockStakingKeeperMockRecorder) TransferDelegation(ctx, fromAddr, toAddr, valAddr, wantShares interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TransferDelegation", reflect.TypeOf((*MockStakingKeeper)(nil).TransferDelegation), ctx, fromAddr, toAddr, valAddr, wantShares) -} - -// TransferUnbonding mocks base method. -func (m *MockStakingKeeper) TransferUnbonding(ctx context.Context, fromAddr, toAddr types.AccAddress, valAddr types.ValAddress, wantAmt math.Int) math.Int { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "TransferUnbonding", ctx, fromAddr, toAddr, valAddr, wantAmt) - ret0, _ := ret[0].(math.Int) - return ret0 -} - -// TransferUnbonding indicates an expected call of TransferUnbonding. -func (mr *MockStakingKeeperMockRecorder) TransferUnbonding(ctx, fromAddr, toAddr, valAddr, wantAmt interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TransferUnbonding", reflect.TypeOf((*MockStakingKeeper)(nil).TransferUnbonding), ctx, fromAddr, toAddr, valAddr, wantAmt) -} From cf1d5213b2cb1cacb958a80a9782ff4ebb7c15aa Mon Sep 17 00:00:00 2001 From: hacheigriega Date: Wed, 14 Feb 2024 09:20:34 -0500 Subject: [PATCH 08/15] refactor: relocate integration testing utils --- {app => integration}/integration.go | 2 +- x/vesting/keeper/integration_test.go | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) rename {app => integration}/integration.go (99%) diff --git a/app/integration.go b/integration/integration.go similarity index 99% rename from app/integration.go rename to integration/integration.go index 5c5c3222..d81aeb92 100644 --- a/app/integration.go +++ b/integration/integration.go @@ -1,4 +1,4 @@ -package app +package integration import ( "fmt" diff --git a/x/vesting/keeper/integration_test.go b/x/vesting/keeper/integration_test.go index d0c4a07b..dc79916d 100644 --- a/x/vesting/keeper/integration_test.go +++ b/x/vesting/keeper/integration_test.go @@ -16,7 +16,7 @@ import ( addresscodec "github.com/cosmos/cosmos-sdk/codec/address" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" "github.com/cosmos/cosmos-sdk/runtime" - "github.com/cosmos/cosmos-sdk/testutil/integration" + sdkintegration "github.com/cosmos/cosmos-sdk/testutil/integration" simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" sdk "github.com/cosmos/cosmos-sdk/types" moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" @@ -33,6 +33,7 @@ import ( "github.com/sedaprotocol/seda-chain/app" "github.com/sedaprotocol/seda-chain/app/params" + "github.com/sedaprotocol/seda-chain/integration" "github.com/sedaprotocol/seda-chain/x/staking" stakingkeeper "github.com/sedaprotocol/seda-chain/x/staking/keeper" "github.com/sedaprotocol/seda-chain/x/vesting" @@ -63,7 +64,7 @@ var ( ) type fixture struct { - *app.IntegationApp + *integration.IntegationApp cdc codec.Codec accountKeeper authkeeper.AccountKeeper bankKeeper bankkeeper.Keeper @@ -78,7 +79,7 @@ func initFixture(tb testing.TB) *fixture { cdc := moduletestutil.MakeTestEncodingConfig(auth.AppModuleBasic{}, bank.AppModuleBasic{}, vesting.AppModuleBasic{}).Codec logger := log.NewTestLogger(tb) - cms := integration.CreateMultiStore(keys, logger) + cms := sdkintegration.CreateMultiStore(keys, logger) newCtx := sdk.NewContext(cms, cmtproto.Header{Time: time.Now().UTC()}, true, logger) @@ -126,7 +127,7 @@ func initFixture(tb testing.TB) *fixture { stakingModule := staking.NewAppModule(cdc, stakingKeeper, accountKeeper, bankKeeper, nil) vestingModule := vesting.NewAppModule(accountKeeper, bankKeeper, stakingKeeper) - integrationApp := app.NewIntegrationApp(newCtx, logger, keys, cdc, map[string]appmodule.AppModule{ + integrationApp := integration.NewIntegrationApp(newCtx, logger, keys, cdc, map[string]appmodule.AppModule{ authtypes.ModuleName: authModule, banktypes.ModuleName: bankModule, sdkstakingtypes.ModuleName: stakingModule, From c0abc24a02371fd95e575b9c9f58ddd875d21a01 Mon Sep 17 00:00:00 2001 From: hacheigriega Date: Wed, 14 Feb 2024 13:22:05 -0500 Subject: [PATCH 09/15] refactor: lint and improve error handling --- app/app.go | 8 +- app/genesis.go | 11 +-- integration/integration.go | 11 ++- x/staking/client/cli/tx.go | 1 - x/staking/keeper/keeper.go | 145 ++++++++++++++++------------ x/staking/module.go | 48 +++++++-- x/vesting/client/cli/tx.go | 4 +- x/vesting/keeper/msg_server.go | 18 ++-- x/vesting/module.go | 8 +- x/vesting/simulation/operations.go | 42 ++++---- x/vesting/types/expected_keepers.go | 2 +- 11 files changed, 176 insertions(+), 122 deletions(-) diff --git a/app/app.go b/app/app.go index 38fea9c9..247ca118 100644 --- a/app/app.go +++ b/app/app.go @@ -96,7 +96,6 @@ import ( "github.com/cosmos/cosmos-sdk/x/slashing" slashingkeeper "github.com/cosmos/cosmos-sdk/x/slashing/keeper" slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" - "github.com/cosmos/cosmos-sdk/x/staking" sdkstakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/cosmos/gogoproto/proto" @@ -133,6 +132,7 @@ import ( "github.com/sedaprotocol/seda-chain/app/keepers" appparams "github.com/sedaprotocol/seda-chain/app/params" "github.com/sedaprotocol/seda-chain/docs" + "github.com/sedaprotocol/seda-chain/x/staking" stakingkeeper "github.com/sedaprotocol/seda-chain/x/staking/keeper" "github.com/sedaprotocol/seda-chain/x/vesting" vestingtypes "github.com/sedaprotocol/seda-chain/x/vesting/types" @@ -699,7 +699,7 @@ func NewApp( mint.NewAppModule(appCodec, app.MintKeeper, app.AccountKeeper, nil, nil), slashing.NewAppModule(appCodec, app.SlashingKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper, nil, app.interfaceRegistry), distr.NewAppModule(appCodec, app.DistrKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper, nil), - staking.NewAppModule(appCodec, sdkStakingKeeper, app.AccountKeeper, app.BankKeeper, nil), + staking.NewAppModule(appCodec, app.StakingKeeper, app.AccountKeeper, app.BankKeeper, nil), upgrade.NewAppModule(app.UpgradeKeeper, app.AccountKeeper.AddressCodec()), evidence.NewAppModule(app.EvidenceKeeper), consensus.NewAppModule(appCodec, app.ConsensusParamsKeeper), @@ -736,7 +736,7 @@ func NewApp( // During begin block slashing happens after distr.BeginBlocker so that // there is nothing left over in the validator fee pool, so as to keep the // CanWithdrawInvariant invariant. - // NOTE: staking module is required if HistoricalEntries param > 0 + // NOTE: sdkstaking module is required if HistoricalEntries param > 0 app.mm.SetOrderPreBlockers( upgradetypes.ModuleName, ) @@ -794,7 +794,7 @@ func NewApp( packetforwardtypes.ModuleName, ) - // NOTE: The genutils module must occur after staking so that pools are + // NOTE: The genutils module must occur after sdkstaking so that pools are // properly initialized with tokens from genesis accounts. // NOTE: Capability module must occur first so that it can initialize any capabilities // so that other modules that want to create or claim capabilities afterwards in InitChain diff --git a/app/genesis.go b/app/genesis.go index f787dbce..d6ce593d 100644 --- a/app/genesis.go +++ b/app/genesis.go @@ -5,7 +5,6 @@ import ( "encoding/json" "cosmossdk.io/math" - sdkmath "cosmossdk.io/math" "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" @@ -45,13 +44,7 @@ func RandomGenesisAccounts(simState *module.SimulationState) types.GenesisAccoun // Only consider making a vesting account once the initial bonded validator // set is exhausted due to needing to track DelegatedVesting. - if int64(i) < simState.NumBonded { - genesisAccs[i] = bacc - continue - } else if int64(i) == simState.NumBonded { - genesisAccs[i] = bacc - continue - } else if simState.Rand.Intn(100) < 50 { + if int64(i) <= simState.NumBonded || simState.Rand.Intn(100) < 50 { genesisAccs[i] = bacc continue } @@ -61,7 +54,7 @@ func RandomGenesisAccounts(simState *module.SimulationState) types.GenesisAccoun if err != nil { panic(err) } - initialVesting := sdk.NewCoins(sdk.NewCoin(simState.BondDenom, sdkmath.NewIntFromBigInt(initialVestingAmount))) + initialVesting := sdk.NewCoins(sdk.NewCoin(simState.BondDenom, math.NewIntFromBigInt(initialVestingAmount))) var endTime int64 startTime := simState.GenTimestamp.Unix() diff --git a/integration/integration.go b/integration/integration.go index d81aeb92..bd0ecedf 100644 --- a/integration/integration.go +++ b/integration/integration.go @@ -103,7 +103,10 @@ func NewIntegrationApp( } } - bApp.Commit() + _, err := bApp.Commit() + if err != nil { + panic(err) + } ctx := sdkCtx.WithBlockHeader(cmtproto.Header{ChainID: appName, Time: time.Now()}).WithIsCheckTx(true) @@ -130,7 +133,11 @@ func (app *IntegationApp) RunMsg(msg sdk.Msg, option ...integration.Option) (*co } if cfg.AutomaticCommit { - defer app.Commit() + defer func() { + if _, err := app.Commit(); err != nil { + fmt.Println("error while committing:", err) + } + }() } if cfg.AutomaticFinalizeBlock { diff --git a/x/staking/client/cli/tx.go b/x/staking/client/cli/tx.go index 5dc825d8..f958c0bd 100644 --- a/x/staking/client/cli/tx.go +++ b/x/staking/client/cli/tx.go @@ -47,7 +47,6 @@ func NewTxCmd(valAddrCodec, ac address.Codec) *cobra.Command { stakingTxCmd.AddCommand( NewCreateValidatorWithVRFCmd(valAddrCodec), - // NewCreateValidatorCmd(valAddrCodec), stakingcli.NewEditValidatorCmd(valAddrCodec), stakingcli.NewDelegateCmd(valAddrCodec, ac), stakingcli.NewRedelegateCmd(valAddrCodec, ac), diff --git a/x/staking/keeper/keeper.go b/x/staking/keeper/keeper.go index e35b6ff5..aef09bd2 100644 --- a/x/staking/keeper/keeper.go +++ b/x/staking/keeper/keeper.go @@ -24,31 +24,35 @@ func (k *Keeper) SetHooks(sh types.StakingHooks) { k.Keeper.SetHooks(sh) } +// NOTE: This code was taken from +// https://github.com/agoric-labs/cosmos-sdk/blob/f42d86980ddfc07869846c391a03622cbd7e9188/x/staking/keeper/delegation.go#L701 +// with slight modifications. +// // TransferDelegation changes the ownership of at most the desired number of shares. // Returns the actual number of shares transferred. Will also transfer redelegation // entries to ensure that all redelegations are matched by sufficient shares. // Note that no tokens are transferred to or from any pool or account, since no // delegation is actually changing state. func (k Keeper) TransferDelegation(ctx context.Context, fromAddr, toAddr sdk.AccAddress, valAddr sdk.ValAddress, wantShares math.LegacyDec) (math.LegacyDec, error) { - transferred := math.LegacyZeroDec() // TO-DO + transferred := math.LegacyZeroDec() // sanity checks if !wantShares.IsPositive() { return transferred, nil } validator, err := k.GetValidator(ctx, valAddr) - if err != nil { // TO-DO more specific check? + if err != nil { return transferred, nil } delFrom, err := k.GetDelegation(ctx, fromAddr, valAddr) - if err != nil { // TO-DO more specific check? + if err != nil { return transferred, nil } // Check redelegation entry limits while we can still return early. // Assume the worst case that we need to transfer all redelegation entries mightExceedLimit := false - k.IterateDelegatorRedelegations(ctx, fromAddr, func(toRedelegation types.Redelegation) (stop bool) { + err = k.IterateDelegatorRedelegations(ctx, fromAddr, func(toRedelegation types.Redelegation) (stop bool) { // There's no redelegation index by delegator and dstVal or vice-versa. // The minimum cardinality is to look up by delegator, so scan and skip. if toRedelegation.ValidatorDstAddress != valAddr.String() { @@ -57,18 +61,15 @@ func (k Keeper) TransferDelegation(ctx context.Context, fromAddr, toAddr sdk.Acc maxEntries, err := k.MaxEntries(ctx) if err != nil { - // TO-DO panic(err) } valSrcAddr, err := sdk.ValAddressFromBech32(toRedelegation.ValidatorSrcAddress) if err != nil { - // TO-DO panic(err) } valDstAddr, err := sdk.ValAddressFromBech32(toRedelegation.ValidatorDstAddress) if err != nil { - // TO-DO panic(err) } @@ -79,6 +80,9 @@ func (k Keeper) TransferDelegation(ctx context.Context, fromAddr, toAddr sdk.Acc } return false }) + if err != nil { + return transferred, nil + } if mightExceedLimit { // avoid types.ErrMaxRedelegationEntries return transferred, nil @@ -96,34 +100,51 @@ func (k Keeper) TransferDelegation(ctx context.Context, fromAddr, toAddr sdk.Acc if err != nil { if err == types.ErrNoDelegation { // TO-DO delTo = types.NewDelegation(toAddr.String(), validator.GetOperator(), math.LegacyZeroDec()) - k.Hooks().BeforeDelegationCreated(ctx, toAddr, valAddr) + err = k.Hooks().BeforeDelegationCreated(ctx, toAddr, valAddr) } else { return transferred, err } } else { - k.Hooks().BeforeDelegationSharesModified(ctx, toAddr, valAddr) + err = k.Hooks().BeforeDelegationSharesModified(ctx, toAddr, valAddr) } - // if !found { - // delTo = types.NewDelegation(toAddr, validator.GetOperator(), sdk.ZeroDec()) - // } - // if found { - // k.BeforeDelegationSharesModified(ctx, toAddr, validator.GetOperator()) - // } else { - // k.BeforeDelegationCreated(ctx, toAddr, validator.GetOperator()) - // } + if err != nil { + return transferred, nil + } + delTo.Shares = delTo.Shares.Add(transferred) - k.SetDelegation(ctx, delTo) - k.Hooks().AfterDelegationModified(ctx, toAddr, valAddr) + err = k.SetDelegation(ctx, delTo) + if err != nil { + return transferred, nil + } + err = k.Hooks().AfterDelegationModified(ctx, toAddr, valAddr) + if err != nil { + return transferred, nil + } // Update source delegation if remaining.IsZero() { - k.Hooks().BeforeDelegationRemoved(ctx, fromAddr, valAddr) - k.RemoveDelegation(ctx, delFrom) + err = k.Hooks().BeforeDelegationRemoved(ctx, fromAddr, valAddr) + if err != nil { + return transferred, nil + } + err = k.RemoveDelegation(ctx, delFrom) + if err != nil { + return transferred, nil + } } else { - k.Hooks().BeforeDelegationSharesModified(ctx, fromAddr, valAddr) + err = k.Hooks().BeforeDelegationSharesModified(ctx, fromAddr, valAddr) + if err != nil { + return transferred, nil + } delFrom.Shares = remaining - k.SetDelegation(ctx, delFrom) - k.Hooks().AfterDelegationModified(ctx, fromAddr, valAddr) + err = k.SetDelegation(ctx, delFrom) + if err != nil { + return transferred, nil + } + err = k.Hooks().AfterDelegationModified(ctx, fromAddr, valAddr) + if err != nil { + return transferred, nil + } } // If there are not enough remaining shares to be responsible for @@ -181,9 +202,12 @@ func (k Keeper) TransferDelegation(ctx context.Context, fromAddr, toAddr sdk.Acc entry.CreationHeight, entry.CompletionTime, entry.InitialBalance, math.LegacyZeroDec(), sharesToSend, ) if err != nil { - panic(err) // TO-DO + return transferred, err + } + err = k.InsertRedelegationQueue(ctx, toRed, entry.CompletionTime) + if err != nil { + return transferred, err } - k.InsertRedelegationQueue(ctx, toRed, entry.CompletionTime) redelegation.RemoveEntry(int64(i)) i-- // okay to leave an obsolete entry in the queue for the removed entry @@ -198,9 +222,12 @@ func (k Keeper) TransferDelegation(ctx context.Context, fromAddr, toAddr sdk.Acc entry.CreationHeight, entry.CompletionTime, balanceToSend, math.LegacyZeroDec(), sharesToSend, ) if err != nil { - panic(err) // TO-DO + return transferred, err + } + err = k.InsertRedelegationQueue(ctx, toRed, entry.CompletionTime) + if err != nil { + return transferred, err } - k.InsertRedelegationQueue(ctx, toRed, entry.CompletionTime) entry.InitialBalance = balanceToKeep entry.SharesDst = sharesToKeep redelegation.Entries[i] = entry @@ -211,28 +238,32 @@ func (k Keeper) TransferDelegation(ctx context.Context, fromAddr, toAddr sdk.Acc } if redelegationModified { if entriesRemaining { - k.SetRedelegation(ctx, redelegation) + err = k.SetRedelegation(ctx, redelegation) } else { - k.RemoveRedelegation(ctx, redelegation) + err = k.RemoveRedelegation(ctx, redelegation) + } + if err != nil { + return transferred, err } } } return transferred, nil } +// NOTE: This code was taken from +// https://github.com/agoric-labs/cosmos-sdk/blob/f42d86980ddfc07869846c391a03622cbd7e9188/x/staking/keeper/delegation.go#L979 +// with slight modifications. +// // TransferUnbonding changes the ownership of UnbondingDelegation entries // until the desired number of tokens have changed hands. Returns the actual // number of tokens transferred. -func (k Keeper) TransferUnbonding(ctx context.Context, fromAddr, toAddr sdk.AccAddress, valAddr sdk.ValAddress, wantAmt math.Int) math.Int { +func (k Keeper) TransferUnbonding(ctx context.Context, fromAddr, toAddr sdk.AccAddress, valAddr sdk.ValAddress, wantAmt math.Int) (math.Int, error) { transferred := math.ZeroInt() ubdFrom, err := k.GetUnbondingDelegation(ctx, fromAddr, valAddr) - // if !found { - // return transferred - // } if err != nil { - // TO-DO - return transferred + return transferred, err } + ubdFromModified := false for i := 0; i < len(ubdFrom.Entries) && wantAmt.IsPositive(); i++ { @@ -245,16 +276,23 @@ func (k Keeper) TransferUnbonding(ctx context.Context, fromAddr, toAddr sdk.AccA continue } - if k.HasMaxUnbondingDelegationEntries(ctx, toAddr, valAddr) { + maxed, err := k.HasMaxUnbondingDelegationEntries(ctx, toAddr, valAddr) + if err != nil { + return transferred, err + } + if maxed { // TODO pre-compute the maximum entries we can add rather than checking each time break } ubdTo, err := k.SetUnbondingDelegationEntry(ctx, toAddr, valAddr, entry.CreationHeight, entry.CompletionTime, toXfer) if err != nil { - // TO-DO - panic(err) + return transferred, err + } + err = k.InsertUBDQueue(ctx, ubdTo, entry.CompletionTime) + if err != nil { + return transferred, err } - k.InsertUBDQueue(ctx, ubdTo, entry.CompletionTime) + transferred = transferred.Add(toXfer) wantAmt = wantAmt.Sub(toXfer) @@ -271,28 +309,13 @@ func (k Keeper) TransferUnbonding(ctx context.Context, fromAddr, toAddr sdk.AccA if ubdFromModified { if len(ubdFrom.Entries) == 0 { - k.RemoveUnbondingDelegation(ctx, ubdFrom) + err = k.RemoveUnbondingDelegation(ctx, ubdFrom) } else { - k.SetUnbondingDelegation(ctx, ubdFrom) + err = k.SetUnbondingDelegation(ctx, ubdFrom) + } + if err != nil { + return transferred, err } } - return transferred -} - -// HasMaxUnbondingDelegationEntries - check if unbonding delegation has maximum number of entries. -func (k Keeper) HasMaxUnbondingDelegationEntries(ctx context.Context, delegatorAddr sdk.AccAddress, validatorAddr sdk.ValAddress) bool { - ubd, err := k.GetUnbondingDelegation(ctx, delegatorAddr, validatorAddr) - // if !found { - // return false - // } - if err != nil { - // TO-DO - return false - } - maxEntries, err := k.MaxEntries(ctx) - if err != nil { - // TO-DO - panic(err) - } - return len(ubd.Entries) >= int(maxEntries) + return transferred, nil } diff --git a/x/staking/module.go b/x/staking/module.go index 3bf524ef..1f733713 100644 --- a/x/staking/module.go +++ b/x/staking/module.go @@ -15,11 +15,13 @@ import ( cdctypes "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" "github.com/cosmos/cosmos-sdk/x/staking" + sdkcli "github.com/cosmos/cosmos-sdk/x/staking/client/cli" sdkkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" + "github.com/cosmos/cosmos-sdk/x/staking/simulation" sdktypes "github.com/cosmos/cosmos-sdk/x/staking/types" - "github.com/sedaprotocol/seda-chain/x/staking/client/cli" "github.com/sedaprotocol/seda-chain/x/staking/keeper" "github.com/sedaprotocol/seda-chain/x/staking/types" ) @@ -55,11 +57,13 @@ func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { // RegisterInterfaces registers the module's interface types func (AppModuleBasic) RegisterInterfaces(registry cdctypes.InterfaceRegistry) { - types.RegisterInterfaces(registry) - err := registry.EnsureRegistered(&types.MsgCreateValidatorWithVRF{}) - if err != nil { - fmt.Println("error") - } + // TO-DO to be activated later + // types.RegisterInterfaces(registry) + // err := registry.EnsureRegistered(&types.MsgCreateValidatorWithVRF{}) + // if err != nil { + // fmt.Println("error") + // } + sdktypes.RegisterInterfaces(registry) } @@ -88,7 +92,10 @@ func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *g // GetTxCmd returns the root tx command for the staking module. func (amb AppModuleBasic) GetTxCmd() *cobra.Command { - return cli.NewTxCmd(amb.cdc.InterfaceRegistry().SigningContext().ValidatorAddressCodec(), amb.cdc.InterfaceRegistry().SigningContext().AddressCodec()) + // TO-DO to be activated later + // return cli.NewTxCmd(amb.cdc.InterfaceRegistry().SigningContext().ValidatorAddressCodec(), amb.cdc.InterfaceRegistry().SigningContext().AddressCodec()) + + return sdkcli.NewTxCmd(amb.cdc.InterfaceRegistry().SigningContext().ValidatorAddressCodec(), amb.cdc.InterfaceRegistry().SigningContext().AddressCodec()) } // ---------------------------------------------------------------------------- @@ -127,7 +134,7 @@ func (am AppModule) RegisterServices(cfg module.Configurator) { sdkMsgServer := NewMsgServerImpl(am.keeper.Keeper, am.accountKeeper) sdktypes.RegisterMsgServer(cfg.MsgServer(), sdkMsgServer) - // To be activated later + // TO-DO to be activated later // types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(sdkMsgServer, am.keeper, am.accountKeeper, am.randomnessKeeper)) querier := sdkkeeper.Querier{Keeper: am.keeper.Keeper} @@ -171,3 +178,28 @@ func (am AppModule) BeginBlock(ctx context.Context) error { func (am AppModule) EndBlock(ctx context.Context) ([]abci.ValidatorUpdate, error) { return am.keeper.EndBlocker(ctx) } + +// AppModuleSimulation functions + +// GenerateGenesisState creates a randomized GenState of the staking module. +func (AppModule) GenerateGenesisState(simState *module.SimulationState) { + simulation.RandomizedGenState(simState) +} + +// ProposalMsgs returns msgs used for governance proposals for simulations. +func (AppModule) ProposalMsgs(_ module.SimulationState) []simtypes.WeightedProposalMsg { + return simulation.ProposalMsgs() +} + +// RegisterStoreDecoder registers a decoder for staking module's types +func (am AppModule) RegisterStoreDecoder(sdr simtypes.StoreDecoderRegistry) { + sdr[sdktypes.StoreKey] = simulation.NewDecodeStore(am.cdc) +} + +// WeightedOperations returns the all the staking module operations with their respective weights. +func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation { + return simulation.WeightedOperations( + simState.AppParams, simState.Cdc, simState.TxConfig, + am.accountKeeper, am.bankKeeper, am.keeper.Keeper, + ) +} diff --git a/x/vesting/client/cli/tx.go b/x/vesting/client/cli/tx.go index 09ca5be3..4760705c 100644 --- a/x/vesting/client/cli/tx.go +++ b/x/vesting/client/cli/tx.go @@ -29,7 +29,7 @@ func GetTxCmd(ac address.Codec) *cobra.Command { txCmd.AddCommand( NewMsgCreateVestingAccountCmd(ac), - NewMsgClawbackCmd(ac), + NewMsgClawbackCmd(), ) return txCmd } @@ -81,7 +81,7 @@ The end_time must be provided as a UNIX epoch timestamp.`, } // NewMsgClawbackCmd returns a CLI command handler for clawing back unvested funds. -func NewMsgClawbackCmd(ac address.Codec) *cobra.Command { +func NewMsgClawbackCmd() *cobra.Command { cmd := &cobra.Command{ Use: "clawback [address]", Short: "Transfer vesting (un-vested) amount out of a vesting account.", diff --git a/x/vesting/keeper/msg_server.go b/x/vesting/keeper/msg_server.go index 6c10b13e..9a14360d 100644 --- a/x/vesting/keeper/msg_server.go +++ b/x/vesting/keeper/msg_server.go @@ -13,6 +13,7 @@ import ( sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" sdkvestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/sedaprotocol/seda-chain/x/vesting/types" ) @@ -177,7 +178,7 @@ func (m msgServer) Clawback(goCtx context.Context, msg *types.MsgClawback) (*typ clawedBackUnbonding := sdk.NewCoins() clawedBackBonded := sdk.NewCoins() toClawBack = toClawBack.Sub(toXfer...) - if !toClawBack.IsZero() { // TO-DO only allow bondDenom + if !toClawBack.IsZero() { // claw back from staking (unbonding delegations then bonded delegations) toClawBackStaking := toClawBack.AmountOf(bondDenom) @@ -189,10 +190,13 @@ func (m msgServer) Clawback(goCtx context.Context, msg *types.MsgClawback) (*typ for _, unbonding := range unbondings { valAddr, err := sdk.ValAddressFromBech32(unbonding.ValidatorAddress) if err != nil { - panic(err) + return nil, err } - transferred := m.sk.TransferUnbonding(ctx, vestingAccAddr, funderAddr, valAddr, toClawBackStaking) + transferred, err := m.sk.TransferUnbonding(ctx, vestingAccAddr, funderAddr, valAddr, toClawBackStaking) + if err != nil { + return nil, err + } clawedBackUnbonding = clawedBackUnbonding.Add(sdk.NewCoin(bondDenom, transferred)) toClawBackStaking = toClawBackStaking.Sub(transferred) @@ -211,12 +215,14 @@ func (m msgServer) Clawback(goCtx context.Context, msg *types.MsgClawback) (*typ for _, delegation := range delegations { validatorAddr, err := sdk.ValAddressFromBech32(delegation.ValidatorAddress) if err != nil { - panic(err) // shouldn't happen + return nil, err } validator, err := m.sk.GetValidator(ctx, validatorAddr) if err != nil { + if err != stakingtypes.ErrNoValidatorFound { + return nil, err + } // validator has been removed - // TO-DO more specific check? continue } wantShares, err := validator.SharesFromTokensTruncated(toClawBackStaking) @@ -227,7 +233,7 @@ func (m msgServer) Clawback(goCtx context.Context, msg *types.MsgClawback) (*typ transferredShares, err := m.sk.TransferDelegation(ctx, vestingAccAddr, funderAddr, validatorAddr, wantShares) if err != nil { - panic(err) // shouldn't happen TO-DO + return nil, err } // to be conservative in what we're clawing back, round transferred shares up diff --git a/x/vesting/module.go b/x/vesting/module.go index 65ee4ce1..2f1521d3 100644 --- a/x/vesting/module.go +++ b/x/vesting/module.go @@ -60,7 +60,7 @@ func (AppModuleBasic) DefaultGenesis(_ codec.JSONCodec) json.RawMessage { } // ValidateGenesis performs genesis state validation. Currently, this is a no-op. -func (AppModuleBasic) ValidateGenesis(_ codec.JSONCodec, _ client.TxEncodingConfig, bz json.RawMessage) error { +func (AppModuleBasic) ValidateGenesis(_ codec.JSONCodec, _ client.TxEncodingConfig, _ json.RawMessage) error { return nil } @@ -120,15 +120,15 @@ func (AppModule) ConsensusVersion() uint64 { return 1 } // AppModuleSimulation functions // GenerateGenesisState creates a randomized GenState of the slashing module. -func (AppModule) GenerateGenesisState(simState *module.SimulationState) {} +func (AppModule) GenerateGenesisState(_ *module.SimulationState) {} // ProposalMsgs returns msgs used for governance proposals for simulations. -func (AppModule) ProposalMsgs(simState module.SimulationState) []simtypes.WeightedProposalMsg { +func (AppModule) ProposalMsgs(_ module.SimulationState) []simtypes.WeightedProposalMsg { return []simtypes.WeightedProposalMsg{} } // RegisterStoreDecoder registers a decoder for slashing module's types -func (am AppModule) RegisterStoreDecoder(sdr simtypes.StoreDecoderRegistry) {} +func (am AppModule) RegisterStoreDecoder(_ simtypes.StoreDecoderRegistry) {} // WeightedOperations returns the all the slashing module operations with their respective weights. func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation { diff --git a/x/vesting/simulation/operations.go b/x/vesting/simulation/operations.go index 4c895564..53a64596 100644 --- a/x/vesting/simulation/operations.go +++ b/x/vesting/simulation/operations.go @@ -20,8 +20,8 @@ import ( // Simulation operation weights constants const ( - OpWeightMsgCreateVestingAccount = "op_weight_msg_create_vesting_account" - OpWeightMsgClawback = "op_weight_msg_clawback" + OpWeightMsgCreateVestingAccount = "op_weight_msg_create_vesting_account" //nolint:gosec + OpWeightMsgClawback = "op_weight_msg_clawback" //nolint:gosec DefaultWeightMsgCreateVestingAccount = 100 DefaultWeightMsgClawback = 100 @@ -30,16 +30,15 @@ const ( // WeightedOperations returns all the operations from the module with their respective weights func WeightedOperations( appParams simtypes.AppParams, - cdc codec.JSONCodec, + _ codec.JSONCodec, txGen client.TxConfig, ak types.AccountKeeper, bk types.BankKeeper, sk types.StakingKeeper, ) simulation.WeightedOperations { - var ( - weightMsgCreateVestingAccount int - // weightMsgClawback int - ) + var weightMsgCreateVestingAccount int + // var weightMsgClawback int + appParams.GetOrGenerate(OpWeightMsgCreateVestingAccount, &weightMsgCreateVestingAccount, nil, func(_ *rand.Rand) { weightMsgCreateVestingAccount = DefaultWeightMsgCreateVestingAccount }) @@ -124,19 +123,14 @@ func SimulateMsgCreateVestingAccount( return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "unable to deliver tx"), nil, err } - // sanity := ak.GetAccount(ctx, sdk.AccAddress(msg.ToAddress)) - // if sanity == nil { - // panic("why me") - // } - // future operations var futureOps []simtypes.FutureOperation - // // recipient stakes - // op := simulateMsgDelegate(txGen, ak, bk, sk, recipient, sendCoins) - // futureOps = append(futureOps, simtypes.FutureOperation{ - // BlockHeight: int(ctx.BlockHeight()) + 1, - // Op: op, - // }) + // recipient stakes + op := simulateMsgDelegate(txGen, ak, bk, sk, recipient, sendCoins) + futureOps = append(futureOps, simtypes.FutureOperation{ + BlockHeight: int(ctx.BlockHeight()) + 1, + Op: op, + }) // then funder claws back op2 := simulateMsgClawbackFutureOp(txGen, ak, bk, sk, recipient, funder) @@ -154,7 +148,7 @@ func SimulateMsgClawback( txGen client.TxConfig, ak types.AccountKeeper, bk types.BankKeeper, - sk types.StakingKeeper, + _ types.StakingKeeper, ) simtypes.Operation { return func( r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, @@ -216,9 +210,9 @@ func SimulateMsgClawback( } func simulateMsgDelegate( - txGen client.TxConfig, - ak types.AccountKeeper, - bk types.BankKeeper, + _ client.TxConfig, + _ types.AccountKeeper, + _ types.BankKeeper, sk types.StakingKeeper, acc simtypes.Account, originalVesting sdk.Coins, @@ -311,7 +305,7 @@ func simulateMsgClawbackFutureOp( txGen client.TxConfig, ak types.AccountKeeper, bk types.BankKeeper, - sk types.StakingKeeper, + _ types.StakingKeeper, recipient simtypes.Account, funder simtypes.Account, ) simtypes.Operation { @@ -345,7 +339,7 @@ func simulateMsgClawbackFutureOp( r, txGen, []sdk.Msg{msg}, - sdk.NewCoins(), //fees, + sdk.NewCoins(), // fees, simtestutil.DefaultGenTxGas, chainID, []uint64{funderAcc.GetAccountNumber()}, diff --git a/x/vesting/types/expected_keepers.go b/x/vesting/types/expected_keepers.go index f2f0980c..2b046f00 100644 --- a/x/vesting/types/expected_keepers.go +++ b/x/vesting/types/expected_keepers.go @@ -32,6 +32,6 @@ type StakingKeeper interface { GetDelegatorUnbonding(ctx context.Context, delegator sdk.AccAddress) (math.Int, error) GetUnbondingDelegations(ctx context.Context, delegator sdk.AccAddress, maxRetrieve uint16) (unbondingDelegations []types.UnbondingDelegation, err error) GetDelegatorDelegations(ctx context.Context, delegator sdk.AccAddress, maxRetrieve uint16) (delegations []types.Delegation, err error) - TransferUnbonding(ctx context.Context, fromAddr, toAddr sdk.AccAddress, valAddr sdk.ValAddress, wantAmt math.Int) math.Int + TransferUnbonding(ctx context.Context, fromAddr, toAddr sdk.AccAddress, valAddr sdk.ValAddress, wantAmt math.Int) (math.Int, error) TransferDelegation(ctx context.Context, fromAddr, toAddr sdk.AccAddress, valAddr sdk.ValAddress, wantShares math.LegacyDec) (math.LegacyDec, error) } From b23fee81ba3bd8f8eaa7f3baece1063f47e98267 Mon Sep 17 00:00:00 2001 From: Hyoung-yoon Kim Date: Wed, 14 Feb 2024 15:46:48 -0500 Subject: [PATCH 10/15] fix: temporary fix by copying over staking autocli code --- x/staking/autocli.go | 184 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 x/staking/autocli.go diff --git a/x/staking/autocli.go b/x/staking/autocli.go new file mode 100644 index 00000000..16335d38 --- /dev/null +++ b/x/staking/autocli.go @@ -0,0 +1,184 @@ +package staking + +import ( + "fmt" + + autocliv1 "cosmossdk.io/api/cosmos/autocli/v1" + _ "cosmossdk.io/api/cosmos/crypto/ed25519" // register to that it shows up in protoregistry.GlobalTypes + stakingv1beta "cosmossdk.io/api/cosmos/staking/v1beta1" + + "github.com/cosmos/cosmos-sdk/version" +) + +func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions { + return &autocliv1.ModuleOptions{ + Query: &autocliv1.ServiceCommandDescriptor{ + Service: stakingv1beta.Query_ServiceDesc.ServiceName, + RpcCommandOptions: []*autocliv1.RpcCommandOptions{ + { + RpcMethod: "Validators", + Short: "Query for all validators", + Long: "Query details about all validators on a network.", + }, + { + RpcMethod: "Validator", + Use: "validator [validator-addr]", + Short: "Query a validator", + Long: "Query details about an individual validator.", + PositionalArgs: []*autocliv1.PositionalArgDescriptor{ + {ProtoField: "validator_addr"}, + }, + }, + { + RpcMethod: "ValidatorDelegations", + Use: "delegations-to [validator-addr]", + Short: "Query all delegations made to one validator", + Long: "Query delegations on an individual validator.", + PositionalArgs: []*autocliv1.PositionalArgDescriptor{ + { + ProtoField: "validator_addr", + }, + }, + }, + { + RpcMethod: "ValidatorUnbondingDelegations", + Use: "unbonding-delegations-from [validator-addr]", + Short: "Query all unbonding delegatations from a validator", + Long: "Query delegations that are unbonding _from_ a validator.", + Example: fmt.Sprintf("$ %s query staking unbonding-delegations-from [val-addr]", version.AppName), + PositionalArgs: []*autocliv1.PositionalArgDescriptor{ + {ProtoField: "validator_addr"}, + }, + }, + { + RpcMethod: "Delegation", + Use: "delegation [delegator-addr] [validator-addr]", + Short: "Query a delegation based on address and validator address", + Long: "Query delegations for an individual delegator on an individual validator", + PositionalArgs: []*autocliv1.PositionalArgDescriptor{ + {ProtoField: "delegator_addr"}, + {ProtoField: "validator_addr"}, + }, + }, + { + RpcMethod: "UnbondingDelegation", + Use: "unbonding-delegation [delegator-addr] [validator-addr]", + Short: "Query an unbonding-delegation record based on delegator and validator address", + Long: "Query unbonding delegations for an individual delegator on an individual validator.", + PositionalArgs: []*autocliv1.PositionalArgDescriptor{ + {ProtoField: "delegator_addr"}, + {ProtoField: "validator_addr"}, + }, + }, + { + RpcMethod: "DelegatorDelegations", + Use: "delegations [delegator-addr]", + Short: "Query all delegations made by one delegator", + Long: "Query delegations for an individual delegator on all validators.", + PositionalArgs: []*autocliv1.PositionalArgDescriptor{ + {ProtoField: "delegator_addr"}, + }, + }, + { + RpcMethod: "DelegatorValidators", + Use: "delegator-validators [delegator-addr]", + Short: "Query all validators info for given delegator address", + PositionalArgs: []*autocliv1.PositionalArgDescriptor{ + {ProtoField: "delegator_addr"}, + }, + }, + { + RpcMethod: "DelegatorValidator", + Use: "delegator-validator [delegator-addr] [validator-addr]", + Short: "Query validator info for given delegator validator pair", + PositionalArgs: []*autocliv1.PositionalArgDescriptor{ + {ProtoField: "delegator_addr"}, + {ProtoField: "validator_addr"}, + }, + }, + { + RpcMethod: "DelegatorUnbondingDelegations", + Use: "unbonding-delegations [delegator-addr]", + Short: "Query all unbonding-delegations records for one delegator", + Long: "Query unbonding delegations for an individual delegator.", + PositionalArgs: []*autocliv1.PositionalArgDescriptor{ + {ProtoField: "delegator_addr"}, + }, + }, + { + RpcMethod: "Redelegations", + Use: "redelegation [delegator-addr] [src-validator-addr] [dst-validator-addr]", + Short: "Query a redelegation record based on delegator and a source and destination validator address", + Long: "Query a redelegation record for an individual delegator between a source and destination validator.", + PositionalArgs: []*autocliv1.PositionalArgDescriptor{ + {ProtoField: "delegator_addr"}, + {ProtoField: "src_validator_addr"}, + {ProtoField: "dst_validator_addr"}, + }, + }, + { + RpcMethod: "HistoricalInfo", + Use: "historical-info [height]", + Short: "Query historical info at given height", + Example: fmt.Sprintf("$ %s query staking historical-info 5", version.AppName), + PositionalArgs: []*autocliv1.PositionalArgDescriptor{ + {ProtoField: "height"}, + }, + }, + { + RpcMethod: "Pool", + Use: "pool", + Short: "Query the current staking pool values", + Long: "Query values for amounts stored in the staking pool.", + }, + { + RpcMethod: "Params", + Use: "params", + Short: "Query the current staking parameters information", + Long: "Query values set as staking parameters.", + }, + }, + }, + Tx: &autocliv1.ServiceCommandDescriptor{ + Service: stakingv1beta.Msg_ServiceDesc.ServiceName, + RpcCommandOptions: []*autocliv1.RpcCommandOptions{ + { + RpcMethod: "Delegate", + Use: "delegate [validator-addr] [amount] --from [delegator_address]", + Short: "Delegate liquid tokens to a validator", + Long: "Delegate an amount of liquid coins to a validator from your wallet.", + Example: fmt.Sprintf("%s tx staking delegate cosmosvaloper... 1000stake --from mykey", version.AppName), + PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "validator_address"}, {ProtoField: "amount"}}, + }, + { + RpcMethod: "BeginRedelegate", + Use: "redelegate [src-validator-addr] [dst-validator-addr] [amount] --from [delegator]", + Short: "Generate multisig signatures for transactions generated offline", + Long: "Redelegate an amount of illiquid staking tokens from one validator to another.", + Example: fmt.Sprintf(`%s tx staking redelegate cosmosvaloper... cosmosvaloper... 100stake --from mykey`, version.AppName), + PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "validator_src_address"}, {ProtoField: "validator_dst_address"}, {ProtoField: "amount"}}, + }, + { + RpcMethod: "Undelegate", + Use: "unbond [validator-addr] [amount] --from [delegator_address]", + Short: "Unbond shares from a validator", + Long: "Unbond an amount of bonded shares from a validator.", + Example: fmt.Sprintf(`%s tx staking unbond cosmosvaloper... 100stake --from mykey`, version.AppName), + PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "validator_address"}, {ProtoField: "amount"}}, + }, + { + RpcMethod: "CancelUnbondingDelegation", + Use: "cancel-unbond [validator-addr] [amount] [creation-height]", + Short: "Cancel unbonding delegation and delegate back to the validator", + Example: fmt.Sprintf(`%s tx staking cancel-unbond cosmosvaloper... 100stake 2 --from mykey`, version.AppName), + PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "validator_address"}, {ProtoField: "amount"}, {ProtoField: "creation_height"}}, + }, + { + RpcMethod: "UpdateParams", + Skip: true, // skipped because authority gated + }, + }, + EnhanceCustomCommand: false, // use custom commands only until v0.51 + }, + } +} From 43d0cfbe7ae34e5d61f13a5db8be0a7d39997fc6 Mon Sep 17 00:00:00 2001 From: Hyoung-yoon Kim Date: Wed, 14 Feb 2024 17:09:16 -0500 Subject: [PATCH 11/15] chore: lint --- app/genesis.go | 1 - app/modules.go | 2 +- proto/sedachain/vesting/v1/tx.proto | 3 +-- proto/sedachain/vesting/v1/vesting.proto | 1 - x/vesting/module.go | 31 ------------------------ 5 files changed, 2 insertions(+), 36 deletions(-) diff --git a/app/genesis.go b/app/genesis.go index d6ce593d..21a9bd7d 100644 --- a/app/genesis.go +++ b/app/genesis.go @@ -30,7 +30,6 @@ func NewDefaultGenesisState(cdc codec.JSONCodec) GenesisState { } // RandomGenesisAccounts defines the default RandomGenesisAccountsFn used on the SDK. -// It creates a slice of BaseAccount, ContinuousVestingAccount and DelayedVestingAccount. // NOTE: This function is a modified version of // https://github.com/cosmos/cosmos-sdk/blob/7e6948f50cd4838a0161838a099f74e0b5b0213c/x/auth/simulation/genesis.go#L26 func RandomGenesisAccounts(simState *module.SimulationState) types.GenesisAccounts { diff --git a/app/modules.go b/app/modules.go index b914c4bb..9f8ab29f 100644 --- a/app/modules.go +++ b/app/modules.go @@ -10,10 +10,10 @@ import ( distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" "github.com/cosmos/cosmos-sdk/x/mint" minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" - "github.com/cosmos/cosmos-sdk/x/staking" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/sedaprotocol/seda-chain/app/params" + "github.com/sedaprotocol/seda-chain/x/staking" ) // stakingModule wraps the x/staking module to overwrite some genesis diff --git a/proto/sedachain/vesting/v1/tx.proto b/proto/sedachain/vesting/v1/tx.proto index 8e7022ea..66b48332 100644 --- a/proto/sedachain/vesting/v1/tx.proto +++ b/proto/sedachain/vesting/v1/tx.proto @@ -4,13 +4,12 @@ package sedachain.vesting.v1; import "gogoproto/gogo.proto"; import "cosmos/base/v1beta1/coin.proto"; import "cosmos_proto/cosmos.proto"; -import "cosmos/vesting/v1beta1/vesting.proto"; import "cosmos/msg/v1/msg.proto"; import "amino/amino.proto"; option go_package = "github.com/sedaprotocol/seda-chain/x/vesting/types"; -// Msg defines the bank Msg service. +// Msg defines the vesting Msg service. service Msg { option (cosmos.msg.v1.service) = true; diff --git a/proto/sedachain/vesting/v1/vesting.proto b/proto/sedachain/vesting/v1/vesting.proto index 8556fafa..b53c5ae7 100644 --- a/proto/sedachain/vesting/v1/vesting.proto +++ b/proto/sedachain/vesting/v1/vesting.proto @@ -3,7 +3,6 @@ package sedachain.vesting.v1; import "cosmos/vesting/v1beta1/vesting.proto"; import "gogoproto/gogo.proto"; -import "google/protobuf/timestamp.proto"; option go_package = "github.com/sedaprotocol/seda-chain/x/vesting/types"; diff --git a/x/vesting/module.go b/x/vesting/module.go index 2f1521d3..e027a0ef 100644 --- a/x/vesting/module.go +++ b/x/vesting/module.go @@ -137,34 +137,3 @@ func (am AppModule) WeightedOperations(simState module.SimulationState) []simtyp am.accountKeeper, am.bankKeeper, am.stakingKeeper, ) } - -/* TO-DO -// -// App Wiring Setup -// - -func init() { - appmodule.Register(&modulev1.Module{}, - appmodule.Provide(ProvideModule), - ) -} - -type ModuleInputs struct { - depinject.In - - AccountKeeper authkeeper.AccountKeeper - BankKeeper types.BankKeeper -} - -type ModuleOutputs struct { - depinject.Out - - Module appmodule.AppModule -} - -func ProvideModule(in ModuleInputs) ModuleOutputs { - m := NewAppModule(in.AccountKeeper, in.BankKeeper) - - return ModuleOutputs{Module: m} -} -*/ From 78d3b2a0eaeba4447eb90bbd464c4ccaa08809e4 Mon Sep 17 00:00:00 2001 From: Hyoung-yoon Kim Date: Wed, 14 Feb 2024 17:27:02 -0500 Subject: [PATCH 12/15] chore: proto lint --- proto/sedachain/vesting/v1/tx.proto | 38 ++++++----- proto/sedachain/vesting/v1/vesting.proto | 15 ++--- x/vesting/types/tx.pb.go | 80 ++++++++++++------------ x/vesting/types/vesting.pb.go | 31 +++++---- 4 files changed, 84 insertions(+), 80 deletions(-) diff --git a/proto/sedachain/vesting/v1/tx.proto b/proto/sedachain/vesting/v1/tx.proto index 66b48332..9ac587c0 100644 --- a/proto/sedachain/vesting/v1/tx.proto +++ b/proto/sedachain/vesting/v1/tx.proto @@ -14,7 +14,8 @@ service Msg { option (cosmos.msg.v1.service) = true; // CreateVestingAccount creates a new vesting account. - rpc CreateVestingAccount(MsgCreateVestingAccount) returns (MsgCreateVestingAccountResponse); + rpc CreateVestingAccount(MsgCreateVestingAccount) + returns (MsgCreateVestingAccountResponse); // Clawback returns the vesting funds back to the funder. rpc Clawback(MsgClawback) returns (MsgClawbackResponse); @@ -23,16 +24,16 @@ service Msg { // MsgCreateVestingAccount defines a message that creates a vesting account. message MsgCreateVestingAccount { option (cosmos.msg.v1.signer) = "from_address"; - option (amino.name) = "cosmos-sdk/MsgCreateVestingAccount"; + option (amino.name) = "cosmos-sdk/MsgCreateVestingAccount"; option (gogoproto.equal) = true; - string from_address = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; - string to_address = 2 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + string from_address = 1 [ (cosmos_proto.scalar) = "cosmos.AddressString" ]; + string to_address = 2 [ (cosmos_proto.scalar) = "cosmos.AddressString" ]; repeated cosmos.base.v1beta1.Coin amount = 3 [ - (gogoproto.nullable) = false, - (amino.dont_omitempty) = true, - (amino.encoding) = "legacy_coins", + (gogoproto.nullable) = false, + (amino.dont_omitempty) = true, + (amino.encoding) = "legacy_coins", (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins" ]; @@ -40,7 +41,8 @@ message MsgCreateVestingAccount { int64 end_time = 4; } -// MsgCreateVestingAccountResponse defines the CreateVestingAccount response type. +// MsgCreateVestingAccountResponse defines the CreateVestingAccount response +// type. message MsgCreateVestingAccountResponse {} // MsgClawback defines a message that returns the vesting funds to the funder. @@ -55,12 +57,18 @@ message MsgClawback { // MsgClawbackResponse defines the MsgClawback response type. message MsgClawbackResponse { - repeated cosmos.base.v1beta1.Coin clawed_unbonded = 1 - [(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins", (gogoproto.nullable) = false]; - - repeated cosmos.base.v1beta1.Coin clawed_unbonding = 2 - [(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins", (gogoproto.nullable) = false]; + repeated cosmos.base.v1beta1.Coin clawed_unbonded = 1 [ + (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins", + (gogoproto.nullable) = false + ]; + + repeated cosmos.base.v1beta1.Coin clawed_unbonding = 2 [ + (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins", + (gogoproto.nullable) = false + ]; - repeated cosmos.base.v1beta1.Coin clawed_bonded = 3 - [(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins", (gogoproto.nullable) = false]; + repeated cosmos.base.v1beta1.Coin clawed_bonded = 3 [ + (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins", + (gogoproto.nullable) = false + ]; } diff --git a/proto/sedachain/vesting/v1/vesting.proto b/proto/sedachain/vesting/v1/vesting.proto index b53c5ae7..82ff8de1 100644 --- a/proto/sedachain/vesting/v1/vesting.proto +++ b/proto/sedachain/vesting/v1/vesting.proto @@ -6,13 +6,14 @@ import "gogoproto/gogo.proto"; option go_package = "github.com/sedaprotocol/seda-chain/x/vesting/types"; -// ClawbackContinuousVestingAccount implements the VestingAccount interface. -// It wraps a ContinuousVestingAccount provided by Cosmos SDK to provide +// ClawbackContinuousVestingAccount implements the VestingAccount interface. +// It wraps a ContinuousVestingAccount provided by Cosmos SDK to provide // additional support for clawback. message ClawbackContinuousVestingAccount { - option (gogoproto.goproto_getters) = false; - option (gogoproto.goproto_stringer) = false; - - cosmos.vesting.v1beta1.ContinuousVestingAccount vesting_account = 1 [(gogoproto.embed) = true]; - string funder_address = 2; + option (gogoproto.goproto_getters) = false; + option (gogoproto.goproto_stringer) = false; + + cosmos.vesting.v1beta1.ContinuousVestingAccount vesting_account = 1 + [ (gogoproto.embed) = true ]; + string funder_address = 2; } diff --git a/x/vesting/types/tx.pb.go b/x/vesting/types/tx.pb.go index 0e43e06b..e29db6f7 100644 --- a/x/vesting/types/tx.pb.go +++ b/x/vesting/types/tx.pb.go @@ -11,7 +11,6 @@ import ( types "github.com/cosmos/cosmos-sdk/types" _ "github.com/cosmos/cosmos-sdk/types/msgservice" _ "github.com/cosmos/cosmos-sdk/types/tx/amino" - _ "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" _ "github.com/cosmos/gogoproto/gogoproto" grpc1 "github.com/cosmos/gogoproto/grpc" proto "github.com/cosmos/gogoproto/proto" @@ -267,46 +266,45 @@ func init() { func init() { proto.RegisterFile("sedachain/vesting/v1/tx.proto", fileDescriptor_abaae49a55dd1e8c) } var fileDescriptor_abaae49a55dd1e8c = []byte{ - // 611 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x54, 0xbf, 0x6f, 0xd3, 0x40, - 0x18, 0x8d, 0x13, 0x28, 0xed, 0x25, 0x4d, 0xc0, 0x8d, 0x54, 0x27, 0x12, 0x4e, 0x1a, 0x81, 0x08, - 0x91, 0x62, 0x93, 0x20, 0x84, 0x54, 0x58, 0x9a, 0x4a, 0x4c, 0x74, 0x31, 0x3f, 0x84, 0x58, 0xa2, - 0xb3, 0x7d, 0x75, 0x4f, 0x8d, 0xef, 0x22, 0xdf, 0x25, 0x6d, 0x24, 0x06, 0xc4, 0xc8, 0xc4, 0xcc, - 0xc4, 0x88, 0x98, 0x32, 0xf0, 0x47, 0x74, 0xac, 0x98, 0x98, 0x00, 0x25, 0x48, 0xe1, 0x1f, 0x60, - 0x47, 0xf6, 0x9d, 0x43, 0x52, 0x35, 0x8a, 0x2a, 0x75, 0x49, 0xec, 0xef, 0xbd, 0xf7, 0xbd, 0xcf, - 0xef, 0xec, 0x0f, 0xdc, 0x64, 0xc8, 0x85, 0xce, 0x01, 0xc4, 0xc4, 0xec, 0x23, 0xc6, 0x31, 0xf1, - 0xcc, 0x7e, 0xc3, 0xe4, 0xc7, 0x46, 0x37, 0xa0, 0x9c, 0xaa, 0xf9, 0x29, 0x6c, 0x48, 0xd8, 0xe8, - 0x37, 0x8a, 0x79, 0x8f, 0x7a, 0x34, 0x22, 0x98, 0xe1, 0x95, 0xe0, 0x16, 0x75, 0x87, 0x32, 0x9f, - 0x32, 0xd3, 0x86, 0x0c, 0x99, 0xfd, 0x86, 0x8d, 0x38, 0x6c, 0x98, 0x0e, 0xc5, 0x44, 0xe2, 0x05, - 0x81, 0xb7, 0x85, 0x50, 0xdc, 0x48, 0xe8, 0x96, 0x94, 0xfe, 0x1f, 0x41, 0xa8, 0x63, 0x4f, 0xc1, - 0xda, 0x94, 0x2c, 0x9f, 0x45, 0x43, 0xfa, 0x2c, 0x06, 0x6e, 0x40, 0x1f, 0x13, 0x6a, 0x46, 0xbf, - 0xa2, 0x54, 0x19, 0x27, 0xc1, 0xe6, 0x1e, 0xf3, 0x76, 0x03, 0x04, 0x39, 0x7a, 0x29, 0xda, 0xec, - 0x38, 0x0e, 0xed, 0x11, 0xae, 0x3e, 0x02, 0x99, 0xfd, 0x80, 0xfa, 0x6d, 0xe8, 0xba, 0x01, 0x62, - 0x4c, 0x53, 0xca, 0x4a, 0x75, 0xad, 0xa5, 0x7d, 0xfb, 0x5a, 0xcf, 0xcb, 0xa9, 0x76, 0x04, 0xf2, - 0x8c, 0x07, 0x98, 0x78, 0x56, 0x3a, 0x64, 0xcb, 0x92, 0xfa, 0x10, 0x00, 0x4e, 0xa7, 0xd2, 0xe4, - 0x12, 0xe9, 0x1a, 0xa7, 0xb1, 0x70, 0x00, 0x56, 0xa0, 0x1f, 0xfa, 0x6b, 0xa9, 0x72, 0xaa, 0x9a, - 0x6e, 0x16, 0x0c, 0xa9, 0x08, 0xf3, 0x32, 0xe4, 0x13, 0x1b, 0xbb, 0x14, 0x93, 0xd6, 0x93, 0x93, - 0x1f, 0xa5, 0xc4, 0x97, 0x9f, 0xa5, 0xaa, 0x87, 0xf9, 0x41, 0xcf, 0x36, 0x1c, 0xea, 0xcb, 0xbc, - 0xe4, 0x5f, 0x9d, 0xb9, 0x87, 0x26, 0x1f, 0x74, 0x11, 0x8b, 0x04, 0xec, 0xe3, 0x64, 0x58, 0xcb, - 0x74, 0x90, 0x07, 0x9d, 0x41, 0x3b, 0x4c, 0x9c, 0x7d, 0x9e, 0x0c, 0x6b, 0x8a, 0x25, 0x0d, 0xd5, - 0x02, 0x58, 0x45, 0xc4, 0x6d, 0x73, 0xec, 0x23, 0xed, 0x4a, 0x59, 0xa9, 0xa6, 0xac, 0x6b, 0x88, - 0xb8, 0xcf, 0xb1, 0x8f, 0xb6, 0x1f, 0xff, 0xf9, 0x54, 0x52, 0xde, 0x85, 0xf2, 0xd9, 0x48, 0xde, - 0x4f, 0x86, 0xb5, 0xca, 0x8c, 0xd5, 0x82, 0x24, 0x2b, 0x5b, 0xa0, 0xb4, 0x00, 0xb2, 0x10, 0xeb, - 0x52, 0xc2, 0x50, 0x25, 0x00, 0xe9, 0x90, 0xd2, 0x81, 0x47, 0x36, 0x74, 0x0e, 0xd5, 0xdb, 0x20, - 0xbb, 0xdf, 0x23, 0x2e, 0x0a, 0xe6, 0xd3, 0xb7, 0xd6, 0x45, 0x35, 0x0e, 0xeb, 0x0e, 0xc8, 0x41, - 0xd1, 0x68, 0x3e, 0x6a, 0x2b, 0x2b, 0xcb, 0x92, 0xb8, 0xbd, 0x11, 0xce, 0x7e, 0xa6, 0x65, 0xe5, - 0x6f, 0x12, 0x6c, 0xcc, 0x98, 0xc6, 0xb3, 0xa8, 0x1c, 0xe4, 0x9c, 0x0e, 0x3c, 0x42, 0x6e, 0xbb, - 0x47, 0x6c, 0x4a, 0x5c, 0xe4, 0x6a, 0xca, 0xb2, 0xb3, 0xb8, 0x77, 0xd1, 0xb3, 0xb0, 0xb2, 0xc2, - 0xe3, 0x85, 0xb4, 0x50, 0xfb, 0xe0, 0xfa, 0x9c, 0x2b, 0x26, 0x9e, 0x96, 0xbc, 0x7c, 0xdb, 0xdc, - 0xac, 0x2d, 0x26, 0x9e, 0xda, 0x05, 0xeb, 0xd2, 0x57, 0x3e, 0x6b, 0xea, 0xf2, 0x4d, 0x33, 0xc2, - 0xa1, 0x15, 0x19, 0x34, 0x7f, 0x2b, 0x20, 0xb5, 0xc7, 0x3c, 0xf5, 0x0d, 0xc8, 0x9f, 0xfb, 0xe1, - 0xd5, 0x8d, 0xf3, 0xd6, 0x89, 0xb1, 0xe0, 0x15, 0x2a, 0x3e, 0xb8, 0x10, 0x7d, 0x7a, 0xca, 0xaf, - 0xc0, 0xea, 0xf4, 0x75, 0xdb, 0x5a, 0xdc, 0x42, 0x52, 0x8a, 0x77, 0x97, 0x52, 0xe2, 0xce, 0xc5, - 0xab, 0x6f, 0xc3, 0xcf, 0xaa, 0xf5, 0xf4, 0x64, 0xa4, 0x2b, 0xa7, 0x23, 0x5d, 0xf9, 0x35, 0xd2, - 0x95, 0x0f, 0x63, 0x3d, 0x71, 0x3a, 0xd6, 0x13, 0xdf, 0xc7, 0x7a, 0xe2, 0x75, 0x73, 0x26, 0xb8, - 0xb0, 0x6b, 0xb4, 0x8b, 0x1c, 0xda, 0x89, 0x6e, 0xea, 0x62, 0xcd, 0x1e, 0x4f, 0xb7, 0x5c, 0x14, - 0xa4, 0xbd, 0x12, 0x91, 0xee, 0xff, 0x0b, 0x00, 0x00, 0xff, 0xff, 0x24, 0x17, 0x9e, 0x14, 0x8a, - 0x05, 0x00, 0x00, + // 602 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x54, 0xcf, 0x6f, 0x12, 0x4f, + 0x1c, 0x65, 0xe1, 0xfb, 0xad, 0xed, 0x40, 0x41, 0xb7, 0x24, 0x5d, 0x48, 0x5c, 0x28, 0x89, 0x11, + 0x49, 0xd8, 0x15, 0x8c, 0x31, 0xa9, 0x5e, 0x4a, 0x13, 0x4f, 0xf6, 0xb2, 0xfe, 0x88, 0xf1, 0x42, + 0x66, 0x77, 0xa7, 0xd3, 0x49, 0xd9, 0x19, 0xb2, 0x33, 0xd0, 0x92, 0x78, 0x30, 0x1e, 0x3d, 0x79, + 0xf6, 0xe4, 0xd1, 0x78, 0xe2, 0xe0, 0x1f, 0xd1, 0x63, 0xe3, 0xc9, 0x93, 0x1a, 0x30, 0xc1, 0x7f, + 0xc0, 0xbb, 0xd9, 0x9d, 0x81, 0x80, 0x29, 0x21, 0x4d, 0x7a, 0x01, 0xe6, 0xf3, 0xde, 0xfb, 0xbc, + 0xe1, 0xcd, 0xcc, 0x07, 0xdc, 0xe4, 0xc8, 0x87, 0xde, 0x11, 0x24, 0xd4, 0xee, 0x23, 0x2e, 0x08, + 0xc5, 0x76, 0xbf, 0x61, 0x8b, 0x53, 0xab, 0x1b, 0x32, 0xc1, 0xf4, 0xfc, 0x0c, 0xb6, 0x14, 0x6c, + 0xf5, 0x1b, 0xc5, 0x3c, 0x66, 0x98, 0xc5, 0x04, 0x3b, 0xfa, 0x25, 0xb9, 0x45, 0xd3, 0x63, 0x3c, + 0x60, 0xdc, 0x76, 0x21, 0x47, 0x76, 0xbf, 0xe1, 0x22, 0x01, 0x1b, 0xb6, 0xc7, 0x08, 0x55, 0x78, + 0x41, 0xe2, 0x6d, 0x29, 0x94, 0x0b, 0x05, 0x6d, 0x2b, 0x69, 0xc0, 0x63, 0xfb, 0x80, 0x63, 0x05, + 0xdc, 0x80, 0x01, 0xa1, 0xcc, 0x8e, 0x3f, 0x65, 0xa9, 0x32, 0x4e, 0x82, 0xed, 0x03, 0x8e, 0xf7, + 0x43, 0x04, 0x05, 0x7a, 0x21, 0x37, 0xb5, 0xe7, 0x79, 0xac, 0x47, 0x85, 0xfe, 0x10, 0x64, 0x0e, + 0x43, 0x16, 0xb4, 0xa1, 0xef, 0x87, 0x88, 0x73, 0x43, 0x2b, 0x6b, 0xd5, 0x8d, 0x96, 0xf1, 0xf5, + 0x4b, 0x3d, 0xaf, 0xfc, 0xf6, 0x24, 0xf2, 0x54, 0x84, 0x84, 0x62, 0x27, 0x1d, 0xb1, 0x55, 0x49, + 0x7f, 0x00, 0x80, 0x60, 0x33, 0x69, 0x72, 0x85, 0x74, 0x43, 0xb0, 0xa9, 0x70, 0x00, 0xd6, 0x60, + 0x10, 0xf9, 0x1b, 0xa9, 0x72, 0xaa, 0x9a, 0x6e, 0x16, 0x2c, 0xa5, 0x88, 0x92, 0xb0, 0x54, 0x12, + 0xd6, 0x3e, 0x23, 0xb4, 0xf5, 0xf8, 0xec, 0x7b, 0x29, 0xf1, 0xf9, 0x47, 0xa9, 0x8a, 0x89, 0x38, + 0xea, 0xb9, 0x96, 0xc7, 0x02, 0x95, 0x84, 0xfa, 0xaa, 0x73, 0xff, 0xd8, 0x16, 0x83, 0x2e, 0xe2, + 0xb1, 0x80, 0x7f, 0x98, 0x0c, 0x6b, 0x99, 0x0e, 0xc2, 0xd0, 0x1b, 0xb4, 0xa3, 0x2c, 0xf9, 0xa7, + 0xc9, 0xb0, 0xa6, 0x39, 0xca, 0x50, 0x2f, 0x80, 0x75, 0x44, 0xfd, 0xb6, 0x20, 0x01, 0x32, 0xfe, + 0x2b, 0x6b, 0xd5, 0x94, 0x73, 0x0d, 0x51, 0xff, 0x19, 0x09, 0xd0, 0xee, 0xa3, 0xdf, 0x1f, 0x4b, + 0xda, 0xdb, 0x48, 0x3e, 0x1f, 0xc9, 0xbb, 0xc9, 0xb0, 0x56, 0x99, 0xb3, 0x5a, 0x92, 0x64, 0x65, + 0x07, 0x94, 0x96, 0x40, 0x0e, 0xe2, 0x5d, 0x46, 0x39, 0xaa, 0x84, 0x20, 0x1d, 0x51, 0x3a, 0xf0, + 0xc4, 0x85, 0xde, 0xb1, 0x7e, 0x0b, 0x64, 0x0f, 0x7b, 0xd4, 0x47, 0xe1, 0x62, 0xfa, 0xce, 0xa6, + 0xac, 0x4e, 0xc3, 0xba, 0x0d, 0x72, 0x50, 0x36, 0x5a, 0x8c, 0xda, 0xc9, 0xaa, 0xb2, 0x22, 0xee, + 0x6e, 0x45, 0x7b, 0xff, 0xa7, 0x65, 0xe5, 0x4f, 0x12, 0x6c, 0xcd, 0x99, 0x4e, 0xf7, 0xa2, 0x0b, + 0x90, 0xf3, 0x3a, 0xf0, 0x04, 0xf9, 0xed, 0x1e, 0x75, 0x19, 0xf5, 0x91, 0x6f, 0x68, 0xab, 0xce, + 0xe2, 0xee, 0x65, 0xcf, 0xc2, 0xc9, 0x4a, 0x8f, 0xe7, 0xca, 0x42, 0xef, 0x83, 0xeb, 0x0b, 0xae, + 0x84, 0x62, 0x23, 0x79, 0xf5, 0xb6, 0xb9, 0x79, 0x5b, 0x42, 0xb1, 0xde, 0x05, 0x9b, 0xca, 0x57, + 0xfd, 0xd7, 0xd4, 0xd5, 0x9b, 0x66, 0xa4, 0x43, 0x2b, 0x36, 0x68, 0xfe, 0xd2, 0x40, 0xea, 0x80, + 0x63, 0xfd, 0x35, 0xc8, 0x5f, 0xf8, 0xf0, 0xea, 0xd6, 0x45, 0x83, 0xc2, 0x5a, 0x72, 0x85, 0x8a, + 0xf7, 0x2f, 0x45, 0x9f, 0x9d, 0xf2, 0x4b, 0xb0, 0x3e, 0xbb, 0x6e, 0x3b, 0xcb, 0x5b, 0x28, 0x4a, + 0xf1, 0xce, 0x4a, 0xca, 0xb4, 0x73, 0xf1, 0xff, 0x37, 0xd1, 0xb3, 0x6a, 0x3d, 0x39, 0x1b, 0x99, + 0xda, 0xf9, 0xc8, 0xd4, 0x7e, 0x8e, 0x4c, 0xed, 0xfd, 0xd8, 0x4c, 0x9c, 0x8f, 0xcd, 0xc4, 0xb7, + 0xb1, 0x99, 0x78, 0xd5, 0x9c, 0x0b, 0x2e, 0xea, 0x1a, 0xcf, 0x22, 0x8f, 0x75, 0xe2, 0x45, 0x5d, + 0x0e, 0xd0, 0xd3, 0xd9, 0x08, 0x8d, 0x83, 0x74, 0xd7, 0x62, 0xd2, 0xbd, 0xbf, 0x01, 0x00, 0x00, + 0xff, 0xff, 0x9e, 0xfc, 0xb6, 0x87, 0x64, 0x05, 0x00, 0x00, } func (this *MsgCreateVestingAccount) Equal(that interface{}) bool { diff --git a/x/vesting/types/vesting.pb.go b/x/vesting/types/vesting.pb.go index e5264cea..66a6b007 100644 --- a/x/vesting/types/vesting.pb.go +++ b/x/vesting/types/vesting.pb.go @@ -8,7 +8,6 @@ import ( types "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" _ "github.com/cosmos/gogoproto/gogoproto" proto "github.com/cosmos/gogoproto/proto" - _ "google.golang.org/protobuf/types/known/timestamppb" io "io" math "math" math_bits "math/bits" @@ -74,26 +73,24 @@ func init() { } var fileDescriptor_f2e41653215b022f = []byte{ - // 297 bytes of a gzipped FileDescriptorProto + // 272 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x2a, 0x4e, 0x4d, 0x49, 0x4c, 0xce, 0x48, 0xcc, 0xcc, 0xd3, 0x2f, 0x4b, 0x2d, 0x2e, 0xc9, 0xcc, 0x4b, 0xd7, 0x2f, 0x33, 0x84, 0x31, 0xf5, 0x0a, 0x8a, 0xf2, 0x4b, 0xf2, 0x85, 0x44, 0xe0, 0x6a, 0xf4, 0x60, 0x12, 0x65, 0x86, 0x52, 0x2a, 0xc9, 0xf9, 0xc5, 0xb9, 0xf9, 0xc5, 0x48, 0xda, 0x92, 0x52, 0x4b, 0x12, 0xd1, - 0xf4, 0x4a, 0x89, 0xa4, 0xe7, 0xa7, 0xe7, 0x83, 0x99, 0xfa, 0x20, 0x16, 0x54, 0x54, 0x3e, 0x3d, - 0x3f, 0x3f, 0x3d, 0x27, 0x55, 0x1f, 0xcc, 0x4b, 0x2a, 0x4d, 0xd3, 0x2f, 0xc9, 0xcc, 0x4d, 0x2d, - 0x2e, 0x49, 0xcc, 0x2d, 0x80, 0x28, 0x50, 0xda, 0xc2, 0xc8, 0xa5, 0xe0, 0x9c, 0x93, 0x58, 0x9e, - 0x94, 0x98, 0x9c, 0xed, 0x9c, 0x9f, 0x57, 0x92, 0x99, 0x57, 0x9a, 0x5f, 0x5a, 0x1c, 0x06, 0x31, - 0xda, 0x31, 0x39, 0x39, 0xbf, 0x34, 0xaf, 0x44, 0x28, 0x9e, 0x8b, 0x1f, 0x6a, 0x59, 0x7c, 0x22, - 0x44, 0x48, 0x82, 0x51, 0x81, 0x51, 0x83, 0xdb, 0xc8, 0x40, 0x0f, 0xe2, 0x36, 0x24, 0xe7, 0x82, - 0xdd, 0xa6, 0x87, 0xcb, 0x28, 0x27, 0x96, 0x0b, 0xf7, 0xe4, 0x19, 0x83, 0xf8, 0xca, 0x50, 0x2d, - 0x50, 0xe5, 0xe2, 0x4b, 0x2b, 0xcd, 0x4b, 0x49, 0x2d, 0x8a, 0x4f, 0x4c, 0x49, 0x29, 0x4a, 0x2d, - 0x2e, 0x96, 0x60, 0x52, 0x60, 0xd4, 0xe0, 0x0c, 0xe2, 0x85, 0x88, 0x3a, 0x42, 0x04, 0xad, 0x38, - 0x3a, 0x16, 0xc8, 0x33, 0xcc, 0x58, 0x20, 0xcf, 0xe0, 0xe4, 0x73, 0xe2, 0x91, 0x1c, 0xe3, 0x85, - 0x47, 0x72, 0x8c, 0x0f, 0x1e, 0xc9, 0x31, 0x4e, 0x78, 0x2c, 0xc7, 0x70, 0xe1, 0xb1, 0x1c, 0xc3, - 0x8d, 0xc7, 0x72, 0x0c, 0x51, 0x46, 0xe9, 0x99, 0x25, 0x19, 0xa5, 0x49, 0x7a, 0xc9, 0xf9, 0xb9, - 0xfa, 0xa0, 0xe0, 0x04, 0x7b, 0x33, 0x39, 0x3f, 0x07, 0xcc, 0xd1, 0x85, 0x44, 0x40, 0x05, 0x3c, - 0x2c, 0x4b, 0x2a, 0x0b, 0x52, 0x8b, 0x93, 0xd8, 0xc0, 0x8a, 0x8c, 0x01, 0x01, 0x00, 0x00, 0xff, - 0xff, 0xc0, 0x93, 0x9a, 0xdf, 0xa4, 0x01, 0x00, 0x00, + 0xf4, 0x4a, 0x89, 0xa4, 0xe7, 0xa7, 0xe7, 0x83, 0x99, 0xfa, 0x20, 0x16, 0x44, 0x54, 0x69, 0x0b, + 0x23, 0x97, 0x82, 0x73, 0x4e, 0x62, 0x79, 0x52, 0x62, 0x72, 0xb6, 0x73, 0x7e, 0x5e, 0x49, 0x66, + 0x5e, 0x69, 0x7e, 0x69, 0x71, 0x18, 0x44, 0xa7, 0x63, 0x72, 0x72, 0x7e, 0x69, 0x5e, 0x89, 0x50, + 0x3c, 0x17, 0x3f, 0xd4, 0xac, 0xf8, 0x44, 0x88, 0x90, 0x04, 0xa3, 0x02, 0xa3, 0x06, 0xb7, 0x91, + 0x81, 0x1e, 0xc4, 0x6a, 0x24, 0xd7, 0x80, 0xad, 0xd6, 0xc3, 0x65, 0x94, 0x13, 0xcb, 0x85, 0x7b, + 0xf2, 0x8c, 0x41, 0x7c, 0x65, 0xa8, 0x16, 0xa8, 0x72, 0xf1, 0xa5, 0x95, 0xe6, 0xa5, 0xa4, 0x16, + 0xc5, 0x27, 0xa6, 0xa4, 0x14, 0xa5, 0x16, 0x17, 0x4b, 0x30, 0x29, 0x30, 0x6a, 0x70, 0x06, 0xf1, + 0x42, 0x44, 0x1d, 0x21, 0x82, 0x56, 0x1c, 0x1d, 0x0b, 0xe4, 0x19, 0x66, 0x2c, 0x90, 0x67, 0x70, + 0xf2, 0x39, 0xf1, 0x48, 0x8e, 0xf1, 0xc2, 0x23, 0x39, 0xc6, 0x07, 0x8f, 0xe4, 0x18, 0x27, 0x3c, + 0x96, 0x63, 0xb8, 0xf0, 0x58, 0x8e, 0xe1, 0xc6, 0x63, 0x39, 0x86, 0x28, 0xa3, 0xf4, 0xcc, 0x92, + 0x8c, 0xd2, 0x24, 0xbd, 0xe4, 0xfc, 0x5c, 0x7d, 0x50, 0x68, 0x81, 0xbd, 0x99, 0x9c, 0x9f, 0x03, + 0xe6, 0xe8, 0x42, 0xc2, 0xb7, 0x02, 0x1e, 0x54, 0x25, 0x95, 0x05, 0xa9, 0xc5, 0x49, 0x6c, 0x60, + 0x45, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0x63, 0xa3, 0x68, 0xd1, 0x83, 0x01, 0x00, 0x00, } func (m *ClawbackContinuousVestingAccount) Marshal() (dAtA []byte, err error) { From f9286d4a678521a19c431d66006665eefadb569d Mon Sep 17 00:00:00 2001 From: hacheigriega Date: Thu, 15 Feb 2024 08:09:06 -0500 Subject: [PATCH 13/15] test: deactivate future ops in sim test for now --- x/vesting/simulation/operations.go | 45 +++++++++++++++--------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/x/vesting/simulation/operations.go b/x/vesting/simulation/operations.go index 53a64596..2381598b 100644 --- a/x/vesting/simulation/operations.go +++ b/x/vesting/simulation/operations.go @@ -37,24 +37,24 @@ func WeightedOperations( sk types.StakingKeeper, ) simulation.WeightedOperations { var weightMsgCreateVestingAccount int - // var weightMsgClawback int + var weightMsgClawback int appParams.GetOrGenerate(OpWeightMsgCreateVestingAccount, &weightMsgCreateVestingAccount, nil, func(_ *rand.Rand) { weightMsgCreateVestingAccount = DefaultWeightMsgCreateVestingAccount }) - // appParams.GetOrGenerate(OpWeightMsgClawback, &weightMsgClawback, nil, func(_ *rand.Rand) { - // weightMsgClawback = DefaultWeightMsgClawback - // }) + appParams.GetOrGenerate(OpWeightMsgClawback, &weightMsgClawback, nil, func(_ *rand.Rand) { + weightMsgClawback = DefaultWeightMsgClawback + }) return simulation.WeightedOperations{ simulation.NewWeightedOperation( weightMsgCreateVestingAccount, SimulateMsgCreateVestingAccount(txGen, ak, bk, sk), ), - // simulation.NewWeightedOperation( - // weightMsgClawback, - // SimulateMsgClawback(txGen, ak, bk, sk), - // ), + simulation.NewWeightedOperation( + weightMsgClawback, + SimulateMsgClawback(txGen, ak, bk, sk), + ), } } @@ -123,21 +123,22 @@ func SimulateMsgCreateVestingAccount( return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "unable to deliver tx"), nil, err } - // future operations + // TO-DO activate future operations + // // future operations var futureOps []simtypes.FutureOperation - // recipient stakes - op := simulateMsgDelegate(txGen, ak, bk, sk, recipient, sendCoins) - futureOps = append(futureOps, simtypes.FutureOperation{ - BlockHeight: int(ctx.BlockHeight()) + 1, - Op: op, - }) - - // then funder claws back - op2 := simulateMsgClawbackFutureOp(txGen, ak, bk, sk, recipient, funder) - futureOps = append(futureOps, simtypes.FutureOperation{ - BlockHeight: int(ctx.BlockHeight()) + 1, - Op: op2, - }) + // // recipient stakes + // op := simulateMsgDelegate(txGen, ak, bk, sk, recipient, sendCoins) + // futureOps = append(futureOps, simtypes.FutureOperation{ + // BlockHeight: int(ctx.BlockHeight()) + 1, + // Op: op, + // }) + + // // then funder claws back + // op2 := simulateMsgClawbackFutureOp(txGen, ak, bk, sk, recipient, funder) + // futureOps = append(futureOps, simtypes.FutureOperation{ + // BlockHeight: int(ctx.BlockHeight()) + 1, + // Op: op2, + // }) return simtypes.NewOperationMsg(msg, true, ""), futureOps, nil } From b274cb5e8b04f6a3642dcbf20e30ba3355b95424 Mon Sep 17 00:00:00 2001 From: hacheigriega Date: Thu, 15 Feb 2024 11:42:17 -0500 Subject: [PATCH 14/15] feat: add flag for disabling clawback --- proto/sedachain/vesting/v1/tx.proto | 3 + x/staking/msg_server.go | 1 - x/vesting/client/cli/tx.go | 11 ++- x/vesting/keeper/msg_server.go | 8 +- x/vesting/module.go | 4 +- x/vesting/simulation/operations.go | 3 +- x/vesting/types/msgs.go | 11 +-- x/vesting/types/tx.pb.go | 128 +++++++++++++++++++--------- 8 files changed, 115 insertions(+), 54 deletions(-) diff --git a/proto/sedachain/vesting/v1/tx.proto b/proto/sedachain/vesting/v1/tx.proto index 9ac587c0..9afa7a98 100644 --- a/proto/sedachain/vesting/v1/tx.proto +++ b/proto/sedachain/vesting/v1/tx.proto @@ -39,6 +39,9 @@ message MsgCreateVestingAccount { // end of vesting as unix time (in seconds). int64 end_time = 4; + + // if true, leave funder field empty and disable clawback + bool disable_clawback = 5; } // MsgCreateVestingAccountResponse defines the CreateVestingAccount response diff --git a/x/staking/msg_server.go b/x/staking/msg_server.go index 3021a677..1ff360c9 100644 --- a/x/staking/msg_server.go +++ b/x/staking/msg_server.go @@ -25,7 +25,6 @@ func NewMsgServerImpl(keeper *stakingkeeper.Keeper, accKeeper types.AccountKeepe } func (k msgServer) CreateValidator(ctx context.Context, msg *stakingtypes.MsgCreateValidator) (*stakingtypes.MsgCreateValidatorResponse, error) { - // TO-DO disable? return k.MsgServer.CreateValidator(ctx, msg) } diff --git a/x/vesting/client/cli/tx.go b/x/vesting/client/cli/tx.go index 4760705c..6081f599 100644 --- a/x/vesting/client/cli/tx.go +++ b/x/vesting/client/cli/tx.go @@ -17,6 +17,8 @@ import ( "github.com/sedaprotocol/seda-chain/x/vesting/types" ) +const FlagDisableClawback = "disable-clawback" + // GetTxCmd returns vesting module's transaction commands. func GetTxCmd(ac address.Codec) *cobra.Command { txCmd := &cobra.Command{ @@ -70,11 +72,14 @@ The end_time must be provided as a UNIX epoch timestamp.`, return err } - msg := types.NewMsgCreateVestingAccount(clientCtx.GetFromAddress(), toAddr, amount, endTime) + disableClawback, _ := cmd.Flags().GetBool(FlagDisableClawback) + + msg := types.NewMsgCreateVestingAccount(clientCtx.GetFromAddress(), toAddr, amount, endTime, disableClawback) return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) }, } + cmd.Flags().Bool(FlagDisableClawback, false, "Disable clawback") flags.AddTxFlagsToCmd(cmd) return cmd @@ -86,9 +91,7 @@ func NewMsgClawbackCmd() *cobra.Command { Use: "clawback [address]", Short: "Transfer vesting (un-vested) amount out of a vesting account.", Long: `Must be requested by the funder address associated with the vesting account (--from). - - - Delegated or undelegating staking tokens will be transferred in the delegated (undelegating) state. + Bonded and unbonding tokens will be transferred in bonded and unbonding states, respectively. The recipient is vulnerable to slashing, and must act to unbond the tokens if desired.`, Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/x/vesting/keeper/msg_server.go b/x/vesting/keeper/msg_server.go index 9a14360d..b816fe08 100644 --- a/x/vesting/keeper/msg_server.go +++ b/x/vesting/keeper/msg_server.go @@ -65,13 +65,16 @@ func (m msgServer) CreateVestingAccount(goCtx context.Context, msg *types.MsgCre } baseAccount := authtypes.NewBaseAccountWithAddress(to) - baseAccount = m.ak.NewAccount(ctx, baseAccount).(*authtypes.BaseAccount) // TO-DO what is this + baseAccount = m.ak.NewAccount(ctx, baseAccount).(*authtypes.BaseAccount) baseVestingAccount, err := sdkvestingtypes.NewBaseVestingAccount(baseAccount, msg.Amount.Sort(), msg.EndTime) if err != nil { return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, err.Error()) } vestingAccount := types.NewClawbackContinuousVestingAccountRaw(baseVestingAccount, ctx.BlockTime().Unix(), msg.FromAddress) + if msg.DisableClawback { + vestingAccount.FunderAddress = "" + } m.ak.SetAccount(ctx, vestingAccount) @@ -132,6 +135,9 @@ func (m msgServer) Clawback(goCtx context.Context, msg *types.MsgClawback) (*typ if vestingAccount.GetVestingCoins(ctx.BlockTime()).IsZero() { return nil, errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "account %s does not have currently vesting coins", msg.AccountAddress) } + if vestingAccount.FunderAddress == "" { + return nil, errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "vesting account has no funder registered (clawback disabled): %s", msg.AccountAddress) + } if vestingAccount.FunderAddress != msg.FunderAddress { return nil, errorsmod.Wrapf(sdkerrors.ErrUnauthorized, "clawback can only be requested by original funder: %s", vestingAccount.FunderAddress) } diff --git a/x/vesting/module.go b/x/vesting/module.go index e027a0ef..e8d68861 100644 --- a/x/vesting/module.go +++ b/x/vesting/module.go @@ -3,14 +3,14 @@ package vesting import ( "encoding/json" - abci "github.com/cometbft/cometbft/abci/types" gwruntime "github.com/grpc-ecosystem/grpc-gateway/runtime" "github.com/spf13/cobra" "google.golang.org/grpc" + abci "github.com/cometbft/cometbft/abci/types" + "cosmossdk.io/core/address" "cosmossdk.io/core/appmodule" - "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/codec" codectypes "github.com/cosmos/cosmos-sdk/codec/types" diff --git a/x/vesting/simulation/operations.go b/x/vesting/simulation/operations.go index 2381598b..3b779b2e 100644 --- a/x/vesting/simulation/operations.go +++ b/x/vesting/simulation/operations.go @@ -24,7 +24,7 @@ const ( OpWeightMsgClawback = "op_weight_msg_clawback" //nolint:gosec DefaultWeightMsgCreateVestingAccount = 100 - DefaultWeightMsgClawback = 100 + DefaultWeightMsgClawback = 75 ) // WeightedOperations returns all the operations from the module with their respective weights @@ -101,6 +101,7 @@ func SimulateMsgCreateVestingAccount( recipient.Address, sendCoins, ctx.BlockTime().Unix()+1000, + false, ) tx, err := simtestutil.GenSignedMockTx( diff --git a/x/vesting/types/msgs.go b/x/vesting/types/msgs.go index 2b82a50e..ac6a4862 100644 --- a/x/vesting/types/msgs.go +++ b/x/vesting/types/msgs.go @@ -10,12 +10,13 @@ var ( ) // NewMsgCreateVestingAccount returns a reference to a new MsgCreateVestingAccount. -func NewMsgCreateVestingAccount(fromAddr, toAddr sdk.AccAddress, amount sdk.Coins, endTime int64) *MsgCreateVestingAccount { +func NewMsgCreateVestingAccount(fromAddr, toAddr sdk.AccAddress, amount sdk.Coins, endTime int64, disableClawback bool) *MsgCreateVestingAccount { return &MsgCreateVestingAccount{ - FromAddress: fromAddr.String(), - ToAddress: toAddr.String(), - Amount: amount, - EndTime: endTime, + FromAddress: fromAddr.String(), + ToAddress: toAddr.String(), + Amount: amount, + EndTime: endTime, + DisableClawback: disableClawback, } } diff --git a/x/vesting/types/tx.pb.go b/x/vesting/types/tx.pb.go index e29db6f7..70e43041 100644 --- a/x/vesting/types/tx.pb.go +++ b/x/vesting/types/tx.pb.go @@ -40,6 +40,8 @@ type MsgCreateVestingAccount struct { Amount github_com_cosmos_cosmos_sdk_types.Coins `protobuf:"bytes,3,rep,name=amount,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"amount"` // end of vesting as unix time (in seconds). EndTime int64 `protobuf:"varint,4,opt,name=end_time,json=endTime,proto3" json:"end_time,omitempty"` + // if true, leave funder field empty and disable clawback + DisableClawback bool `protobuf:"varint,5,opt,name=disable_clawback,json=disableClawback,proto3" json:"disable_clawback,omitempty"` } func (m *MsgCreateVestingAccount) Reset() { *m = MsgCreateVestingAccount{} } @@ -103,7 +105,15 @@ func (m *MsgCreateVestingAccount) GetEndTime() int64 { return 0 } -// MsgCreateVestingAccountResponse defines the CreateVestingAccount response type. +func (m *MsgCreateVestingAccount) GetDisableClawback() bool { + if m != nil { + return m.DisableClawback + } + return false +} + +// MsgCreateVestingAccountResponse defines the CreateVestingAccount response +// type. type MsgCreateVestingAccountResponse struct { } @@ -266,45 +276,47 @@ func init() { func init() { proto.RegisterFile("sedachain/vesting/v1/tx.proto", fileDescriptor_abaae49a55dd1e8c) } var fileDescriptor_abaae49a55dd1e8c = []byte{ - // 602 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x54, 0xcf, 0x6f, 0x12, 0x4f, - 0x1c, 0x65, 0xe1, 0xfb, 0xad, 0xed, 0x40, 0x41, 0xb7, 0x24, 0x5d, 0x48, 0x5c, 0x28, 0x89, 0x11, - 0x49, 0xd8, 0x15, 0x8c, 0x31, 0xa9, 0x5e, 0x4a, 0x13, 0x4f, 0xf6, 0xb2, 0xfe, 0x88, 0xf1, 0x42, - 0x66, 0x77, 0xa7, 0xd3, 0x49, 0xd9, 0x19, 0xb2, 0x33, 0xd0, 0x92, 0x78, 0x30, 0x1e, 0x3d, 0x79, - 0xf6, 0xe4, 0xd1, 0x78, 0xe2, 0xe0, 0x1f, 0xd1, 0x63, 0xe3, 0xc9, 0x93, 0x1a, 0x30, 0xc1, 0x7f, - 0xc0, 0xbb, 0xd9, 0x9d, 0x81, 0x80, 0x29, 0x21, 0x4d, 0x7a, 0x01, 0xe6, 0xf3, 0xde, 0xfb, 0xbc, - 0xe1, 0xcd, 0xcc, 0x07, 0xdc, 0xe4, 0xc8, 0x87, 0xde, 0x11, 0x24, 0xd4, 0xee, 0x23, 0x2e, 0x08, - 0xc5, 0x76, 0xbf, 0x61, 0x8b, 0x53, 0xab, 0x1b, 0x32, 0xc1, 0xf4, 0xfc, 0x0c, 0xb6, 0x14, 0x6c, - 0xf5, 0x1b, 0xc5, 0x3c, 0x66, 0x98, 0xc5, 0x04, 0x3b, 0xfa, 0x25, 0xb9, 0x45, 0xd3, 0x63, 0x3c, - 0x60, 0xdc, 0x76, 0x21, 0x47, 0x76, 0xbf, 0xe1, 0x22, 0x01, 0x1b, 0xb6, 0xc7, 0x08, 0x55, 0x78, - 0x41, 0xe2, 0x6d, 0x29, 0x94, 0x0b, 0x05, 0x6d, 0x2b, 0x69, 0xc0, 0x63, 0xfb, 0x80, 0x63, 0x05, - 0xdc, 0x80, 0x01, 0xa1, 0xcc, 0x8e, 0x3f, 0x65, 0xa9, 0x32, 0x4e, 0x82, 0xed, 0x03, 0x8e, 0xf7, - 0x43, 0x04, 0x05, 0x7a, 0x21, 0x37, 0xb5, 0xe7, 0x79, 0xac, 0x47, 0x85, 0xfe, 0x10, 0x64, 0x0e, - 0x43, 0x16, 0xb4, 0xa1, 0xef, 0x87, 0x88, 0x73, 0x43, 0x2b, 0x6b, 0xd5, 0x8d, 0x96, 0xf1, 0xf5, - 0x4b, 0x3d, 0xaf, 0xfc, 0xf6, 0x24, 0xf2, 0x54, 0x84, 0x84, 0x62, 0x27, 0x1d, 0xb1, 0x55, 0x49, - 0x7f, 0x00, 0x80, 0x60, 0x33, 0x69, 0x72, 0x85, 0x74, 0x43, 0xb0, 0xa9, 0x70, 0x00, 0xd6, 0x60, - 0x10, 0xf9, 0x1b, 0xa9, 0x72, 0xaa, 0x9a, 0x6e, 0x16, 0x2c, 0xa5, 0x88, 0x92, 0xb0, 0x54, 0x12, - 0xd6, 0x3e, 0x23, 0xb4, 0xf5, 0xf8, 0xec, 0x7b, 0x29, 0xf1, 0xf9, 0x47, 0xa9, 0x8a, 0x89, 0x38, - 0xea, 0xb9, 0x96, 0xc7, 0x02, 0x95, 0x84, 0xfa, 0xaa, 0x73, 0xff, 0xd8, 0x16, 0x83, 0x2e, 0xe2, - 0xb1, 0x80, 0x7f, 0x98, 0x0c, 0x6b, 0x99, 0x0e, 0xc2, 0xd0, 0x1b, 0xb4, 0xa3, 0x2c, 0xf9, 0xa7, - 0xc9, 0xb0, 0xa6, 0x39, 0xca, 0x50, 0x2f, 0x80, 0x75, 0x44, 0xfd, 0xb6, 0x20, 0x01, 0x32, 0xfe, - 0x2b, 0x6b, 0xd5, 0x94, 0x73, 0x0d, 0x51, 0xff, 0x19, 0x09, 0xd0, 0xee, 0xa3, 0xdf, 0x1f, 0x4b, - 0xda, 0xdb, 0x48, 0x3e, 0x1f, 0xc9, 0xbb, 0xc9, 0xb0, 0x56, 0x99, 0xb3, 0x5a, 0x92, 0x64, 0x65, - 0x07, 0x94, 0x96, 0x40, 0x0e, 0xe2, 0x5d, 0x46, 0x39, 0xaa, 0x84, 0x20, 0x1d, 0x51, 0x3a, 0xf0, - 0xc4, 0x85, 0xde, 0xb1, 0x7e, 0x0b, 0x64, 0x0f, 0x7b, 0xd4, 0x47, 0xe1, 0x62, 0xfa, 0xce, 0xa6, - 0xac, 0x4e, 0xc3, 0xba, 0x0d, 0x72, 0x50, 0x36, 0x5a, 0x8c, 0xda, 0xc9, 0xaa, 0xb2, 0x22, 0xee, - 0x6e, 0x45, 0x7b, 0xff, 0xa7, 0x65, 0xe5, 0x4f, 0x12, 0x6c, 0xcd, 0x99, 0x4e, 0xf7, 0xa2, 0x0b, - 0x90, 0xf3, 0x3a, 0xf0, 0x04, 0xf9, 0xed, 0x1e, 0x75, 0x19, 0xf5, 0x91, 0x6f, 0x68, 0xab, 0xce, - 0xe2, 0xee, 0x65, 0xcf, 0xc2, 0xc9, 0x4a, 0x8f, 0xe7, 0xca, 0x42, 0xef, 0x83, 0xeb, 0x0b, 0xae, - 0x84, 0x62, 0x23, 0x79, 0xf5, 0xb6, 0xb9, 0x79, 0x5b, 0x42, 0xb1, 0xde, 0x05, 0x9b, 0xca, 0x57, - 0xfd, 0xd7, 0xd4, 0xd5, 0x9b, 0x66, 0xa4, 0x43, 0x2b, 0x36, 0x68, 0xfe, 0xd2, 0x40, 0xea, 0x80, - 0x63, 0xfd, 0x35, 0xc8, 0x5f, 0xf8, 0xf0, 0xea, 0xd6, 0x45, 0x83, 0xc2, 0x5a, 0x72, 0x85, 0x8a, - 0xf7, 0x2f, 0x45, 0x9f, 0x9d, 0xf2, 0x4b, 0xb0, 0x3e, 0xbb, 0x6e, 0x3b, 0xcb, 0x5b, 0x28, 0x4a, - 0xf1, 0xce, 0x4a, 0xca, 0xb4, 0x73, 0xf1, 0xff, 0x37, 0xd1, 0xb3, 0x6a, 0x3d, 0x39, 0x1b, 0x99, - 0xda, 0xf9, 0xc8, 0xd4, 0x7e, 0x8e, 0x4c, 0xed, 0xfd, 0xd8, 0x4c, 0x9c, 0x8f, 0xcd, 0xc4, 0xb7, - 0xb1, 0x99, 0x78, 0xd5, 0x9c, 0x0b, 0x2e, 0xea, 0x1a, 0xcf, 0x22, 0x8f, 0x75, 0xe2, 0x45, 0x5d, - 0x0e, 0xd0, 0xd3, 0xd9, 0x08, 0x8d, 0x83, 0x74, 0xd7, 0x62, 0xd2, 0xbd, 0xbf, 0x01, 0x00, 0x00, - 0xff, 0xff, 0x9e, 0xfc, 0xb6, 0x87, 0x64, 0x05, 0x00, 0x00, + // 625 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x94, 0xcf, 0x6b, 0x13, 0x41, + 0x14, 0xc7, 0xb3, 0x5d, 0x5b, 0xdb, 0x69, 0x9b, 0xd4, 0x6d, 0xa0, 0x9b, 0x80, 0x9b, 0x34, 0x20, + 0xa6, 0x81, 0xec, 0x9a, 0x88, 0x08, 0xd5, 0x4b, 0x13, 0xf0, 0x64, 0x2f, 0xeb, 0x0f, 0xc4, 0xcb, + 0x32, 0xbb, 0x3b, 0xdd, 0x0e, 0xcd, 0xce, 0x84, 0x9d, 0x49, 0x6c, 0xc0, 0x83, 0x78, 0xf4, 0x20, + 0x9e, 0x3d, 0x79, 0x14, 0x4f, 0x39, 0xf8, 0x47, 0xf4, 0x58, 0x3c, 0x79, 0x52, 0x49, 0x84, 0xf8, + 0x0f, 0x78, 0x97, 0xdd, 0x99, 0x84, 0x44, 0x1a, 0x42, 0xa1, 0x97, 0x24, 0xfb, 0xde, 0xf7, 0xbd, + 0xcf, 0xe4, 0xfb, 0x76, 0x1e, 0xb8, 0xc9, 0x90, 0x0f, 0xbd, 0x63, 0x88, 0x89, 0xd5, 0x45, 0x8c, + 0x63, 0x12, 0x58, 0xdd, 0x9a, 0xc5, 0x4f, 0xcd, 0x76, 0x44, 0x39, 0xd5, 0xb2, 0x93, 0xb4, 0x29, + 0xd3, 0x66, 0xb7, 0x96, 0xcf, 0x06, 0x34, 0xa0, 0x89, 0xc0, 0x8a, 0x7f, 0x09, 0x6d, 0xde, 0xf0, + 0x28, 0x0b, 0x29, 0xb3, 0x5c, 0xc8, 0x90, 0xd5, 0xad, 0xb9, 0x88, 0xc3, 0x9a, 0xe5, 0x51, 0x4c, + 0x64, 0x3e, 0x27, 0xf2, 0x8e, 0x28, 0x14, 0x0f, 0x32, 0xb5, 0x23, 0x4b, 0x43, 0x96, 0xe0, 0x43, + 0x16, 0xc8, 0xc4, 0x0d, 0x18, 0x62, 0x42, 0xad, 0xe4, 0x53, 0x84, 0x4a, 0xef, 0x55, 0xb0, 0x73, + 0xc8, 0x82, 0x66, 0x84, 0x20, 0x47, 0xcf, 0xc5, 0xa1, 0x0e, 0x3c, 0x8f, 0x76, 0x08, 0xd7, 0x1e, + 0x80, 0x8d, 0xa3, 0x88, 0x86, 0x0e, 0xf4, 0xfd, 0x08, 0x31, 0xa6, 0x2b, 0x45, 0xa5, 0xbc, 0xd6, + 0xd0, 0xbf, 0x7d, 0xad, 0x66, 0x25, 0xef, 0x40, 0x64, 0x9e, 0xf0, 0x08, 0x93, 0xc0, 0x5e, 0x8f, + 0xd5, 0x32, 0xa4, 0xdd, 0x07, 0x80, 0xd3, 0x49, 0xe9, 0xd2, 0x82, 0xd2, 0x35, 0x4e, 0xc7, 0x85, + 0x3d, 0xb0, 0x02, 0xc3, 0x98, 0xaf, 0xab, 0x45, 0xb5, 0xbc, 0x5e, 0xcf, 0x99, 0xb2, 0x22, 0x76, + 0xc2, 0x94, 0x4e, 0x98, 0x4d, 0x8a, 0x49, 0xe3, 0xd1, 0xd9, 0x8f, 0x42, 0xea, 0xcb, 0xcf, 0x42, + 0x39, 0xc0, 0xfc, 0xb8, 0xe3, 0x9a, 0x1e, 0x0d, 0xa5, 0x13, 0xf2, 0xab, 0xca, 0xfc, 0x13, 0x8b, + 0xf7, 0xda, 0x88, 0x25, 0x05, 0xec, 0xe3, 0xa8, 0x5f, 0xd9, 0x68, 0xa1, 0x00, 0x7a, 0x3d, 0x27, + 0xf6, 0x92, 0x7d, 0x1e, 0xf5, 0x2b, 0x8a, 0x2d, 0x81, 0x5a, 0x0e, 0xac, 0x22, 0xe2, 0x3b, 0x1c, + 0x87, 0x48, 0xbf, 0x56, 0x54, 0xca, 0xaa, 0x7d, 0x1d, 0x11, 0xff, 0x29, 0x0e, 0x91, 0xb6, 0x07, + 0xb6, 0x7c, 0xcc, 0xa0, 0xdb, 0x42, 0x8e, 0xd7, 0x82, 0xaf, 0x5c, 0xe8, 0x9d, 0xe8, 0xcb, 0x45, + 0xa5, 0xbc, 0x6a, 0x67, 0x64, 0xbc, 0x29, 0xc3, 0xfb, 0x0f, 0xff, 0x7c, 0x2a, 0x28, 0x6f, 0x63, + 0xd2, 0xb4, 0x7b, 0xef, 0x46, 0xfd, 0x4a, 0x69, 0xea, 0x54, 0x73, 0x4c, 0x2f, 0xed, 0x82, 0xc2, + 0x9c, 0x94, 0x8d, 0x58, 0x9b, 0x12, 0x86, 0x4a, 0x11, 0x58, 0x8f, 0x25, 0x92, 0xa7, 0xdd, 0x02, + 0xe9, 0xa3, 0x0e, 0xf1, 0x51, 0x34, 0x3b, 0x28, 0x7b, 0x53, 0x44, 0xc7, 0xbe, 0xde, 0x06, 0x19, + 0x28, 0x1a, 0xcd, 0x4e, 0xc5, 0x4e, 0xcb, 0xb0, 0x14, 0xee, 0x6f, 0xc7, 0x67, 0xff, 0xaf, 0x65, + 0xe9, 0xef, 0x12, 0xd8, 0x9e, 0x82, 0x8e, 0xcf, 0xa2, 0x71, 0x90, 0x89, 0xfd, 0x40, 0xbe, 0xd3, + 0x21, 0x2e, 0x25, 0x3e, 0xf2, 0x75, 0x65, 0xd1, 0xd8, 0xee, 0x5c, 0x76, 0x6c, 0x76, 0x5a, 0x30, + 0x9e, 0x49, 0x84, 0xd6, 0x05, 0x5b, 0x33, 0x54, 0x4c, 0x02, 0x7d, 0xe9, 0xea, 0xb1, 0x99, 0x69, + 0x2c, 0x26, 0x81, 0xd6, 0x06, 0x9b, 0x92, 0x2b, 0xff, 0xab, 0x7a, 0xf5, 0xd0, 0x0d, 0x41, 0x68, + 0x24, 0x80, 0xfa, 0x6f, 0x05, 0xa8, 0x87, 0x2c, 0xd0, 0x5e, 0x83, 0xec, 0x85, 0x77, 0xb4, 0x6a, + 0x5e, 0xb4, 0x53, 0xcc, 0x39, 0xaf, 0x50, 0xfe, 0xde, 0xa5, 0xe4, 0x93, 0x29, 0xbf, 0x00, 0xab, + 0x93, 0xd7, 0x6d, 0x77, 0x7e, 0x0b, 0x29, 0xc9, 0xef, 0x2d, 0x94, 0x8c, 0x3b, 0xe7, 0x97, 0xdf, + 0xc4, 0x37, 0xb0, 0xf1, 0xf8, 0x6c, 0x60, 0x28, 0xe7, 0x03, 0x43, 0xf9, 0x35, 0x30, 0x94, 0x0f, + 0x43, 0x23, 0x75, 0x3e, 0x34, 0x52, 0xdf, 0x87, 0x46, 0xea, 0x65, 0x7d, 0xca, 0xb8, 0xb8, 0x6b, + 0xb2, 0xb6, 0x3c, 0xda, 0x4a, 0x1e, 0xaa, 0x62, 0xd7, 0x9e, 0x4e, 0xb6, 0x6d, 0x62, 0xa4, 0xbb, + 0x92, 0x88, 0xee, 0xfe, 0x0b, 0x00, 0x00, 0xff, 0xff, 0x4d, 0x33, 0x4a, 0xf4, 0x8f, 0x05, 0x00, + 0x00, } func (this *MsgCreateVestingAccount) Equal(that interface{}) bool { @@ -343,6 +355,9 @@ func (this *MsgCreateVestingAccount) Equal(that interface{}) bool { if this.EndTime != that1.EndTime { return false } + if this.DisableClawback != that1.DisableClawback { + return false + } return true } @@ -486,6 +501,16 @@ func (m *MsgCreateVestingAccount) MarshalToSizedBuffer(dAtA []byte) (int, error) _ = i var l int _ = l + if m.DisableClawback { + i-- + if m.DisableClawback { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x28 + } if m.EndTime != 0 { i = encodeVarintTx(dAtA, i, uint64(m.EndTime)) i-- @@ -681,6 +706,9 @@ func (m *MsgCreateVestingAccount) Size() (n int) { if m.EndTime != 0 { n += 1 + sovTx(uint64(m.EndTime)) } + if m.DisableClawback { + n += 2 + } return n } @@ -889,6 +917,26 @@ func (m *MsgCreateVestingAccount) Unmarshal(dAtA []byte) error { break } } + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field DisableClawback", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.DisableClawback = bool(v != 0) default: iNdEx = preIndex skippy, err := skipTx(dAtA[iNdEx:]) From 3a60cd987694933cbe4f17c24e580efb6c065ea1 Mon Sep 17 00:00:00 2001 From: hacheigriega Date: Thu, 15 Feb 2024 14:39:42 -0500 Subject: [PATCH 15/15] chore: update add-genesis-account command to use clawback vesting acc --- cmd/seda-chaind/cmd/genaccounts.go | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/cmd/seda-chaind/cmd/genaccounts.go b/cmd/seda-chaind/cmd/genaccounts.go index 758ee42b..121705ee 100644 --- a/cmd/seda-chaind/cmd/genaccounts.go +++ b/cmd/seda-chaind/cmd/genaccounts.go @@ -18,12 +18,15 @@ import ( banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" "github.com/cosmos/cosmos-sdk/x/genutil" genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" + + vestingtypes "github.com/sedaprotocol/seda-chain/x/vesting/types" ) const ( flagVestingStart = "vesting-start-time" flagVestingEnd = "vesting-end-time" flagVestingAmt = "vesting-amount" + flagFunder = "funder" ) // addGenesisAccountCmd returns add-genesis-account cobra Command. @@ -111,14 +114,17 @@ contain valid denominations. Accounts may optionally be supplied with vesting pa return errors.New("vesting amount cannot be greater than total amount") } - switch { - case vestingStart != 0 && vestingEnd != 0: - genAccount = authvesting.NewContinuousVestingAccountRaw(baseVestingAccount, vestingStart) - - case vestingEnd != 0: - genAccount = authvesting.NewDelayedVestingAccountRaw(baseVestingAccount) - - default: + if vestingEnd != 0 && vestingStart != 0 { + funder, err := cmd.Flags().GetString(flagFunder) + if err != nil { + return err + } + funderAddr, err := sdk.AccAddressFromBech32(funder) + if err != nil { + return errors.New("funder of vesting account must be provided using from flag") + } + genAccount = vestingtypes.NewClawbackContinuousVestingAccountRaw(baseVestingAccount, vestingStart, funderAddr.String()) + } else { return errors.New("invalid vesting parameters; must supply start and end time or end time") } } else { @@ -190,6 +196,7 @@ contain valid denominations. Accounts may optionally be supplied with vesting pa cmd.Flags().String(flagVestingAmt, "", "amount of coins for vesting accounts") cmd.Flags().Int64(flagVestingStart, 0, "schedule start time (unix epoch) for vesting accounts") cmd.Flags().Int64(flagVestingEnd, 0, "schedule end time (unix epoch) for vesting accounts") + cmd.Flags().String(flagFunder, "", "funder address for creating clawback vesting account") flags.AddQueryFlagsToCmd(cmd) return cmd