diff --git a/app/app.go b/app/app.go index 10f24f7a..247ca118 100644 --- a/app/app.go +++ b/app/app.go @@ -65,8 +65,7 @@ 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/authz" authzkeeper "github.com/cosmos/cosmos-sdk/x/authz/keeper" authzmodule "github.com/cosmos/cosmos-sdk/x/authz/module" @@ -97,8 +96,7 @@ 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" - 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 +132,10 @@ 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" ) const ( @@ -375,7 +377,7 @@ func NewApp( } app.txConfig = txConfig - app.StakingKeeper = stakingkeeper.NewKeeper( + sdkStakingKeeper := sdkstakingkeeper.NewKeeper( appCodec, runtime.NewKVStoreService(keys[stakingtypes.StoreKey]), app.AccountKeeper, @@ -384,6 +386,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 +691,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 +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, app.StakingKeeper, app.AccountKeeper, app.BankKeeper, nil), // customstaking.NewAppModule(appCodec, app.StakingKeeper, app.AccountKeeper, app.BankKeeper, app.RandomnessKeeper), + 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), @@ -733,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, ) @@ -791,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 @@ -846,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/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/genesis.go b/app/genesis.go index 0d391e3b..21a9bd7d 100644 --- a/app/genesis.go +++ b/app/genesis.go @@ -4,13 +4,15 @@ import ( "crypto/rand" "encoding/json" - sdkmath "cosmossdk.io/math" + "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 @@ -27,27 +29,31 @@ func NewDefaultGenesisState(cdc codec.JSONCodec) GenesisState { return ModuleBasics.DefaultGenesis(cdc) } -// randomGenesisAccounts defines the default RandomGenesisAccountsFn used on the SDK. -// It creates a slice of BaseAccount, ContinuousVestingAccount and DelayedVestingAccount. +// RandomGenesisAccounts defines the default RandomGenesisAccountsFn used on the SDK. // 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)) + 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 || 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) } - 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() @@ -58,16 +64,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/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/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/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 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/integration/integration.go b/integration/integration.go new file mode 100644 index 00000000..bd0ecedf --- /dev/null +++ b/integration/integration.go @@ -0,0 +1,209 @@ +package integration + +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)) + } + + if _, err := bApp.InitChain(&cmtabcitypes.RequestInitChain{ChainId: appName}); err != nil { + panic(fmt.Errorf("failed to initialize application: %w", err)) + } + } + + _, err := bApp.Commit() + if err != nil { + panic(err) + } + + 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 func() { + if _, err := app.Commit(); err != nil { + fmt.Println("error while committing:", err) + } + }() + } + + 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) +} + +// 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 { + 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/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/proto/sedachain/vesting/v1/tx.proto b/proto/sedachain/vesting/v1/tx.proto new file mode 100644 index 00000000..9afa7a98 --- /dev/null +++ b/proto/sedachain/vesting/v1/tx.proto @@ -0,0 +1,77 @@ +syntax = "proto3"; +package sedachain.vesting.v1; + +import "gogoproto/gogo.proto"; +import "cosmos/base/v1beta1/coin.proto"; +import "cosmos_proto/cosmos.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 vesting 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; + + // if true, leave funder field empty and disable clawback + bool disable_clawback = 5; +} + +// 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 { + 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/proto/sedachain/vesting/v1/vesting.proto b/proto/sedachain/vesting/v1/vesting.proto new file mode 100644 index 00000000..82ff8de1 --- /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"; + +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/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/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/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 + }, + } +} 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 new file mode 100644 index 00000000..aef09bd2 --- /dev/null +++ b/x/staking/keeper/keeper.go @@ -0,0 +1,321 @@ +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) +} + +// 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() + + // sanity checks + if !wantShares.IsPositive() { + return transferred, nil + } + validator, err := k.GetValidator(ctx, valAddr) + if err != nil { + return transferred, nil + } + delFrom, err := k.GetDelegation(ctx, fromAddr, valAddr) + 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 + 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() { + return false + } + + maxEntries, err := k.MaxEntries(ctx) + if err != nil { + panic(err) + } + + valSrcAddr, err := sdk.ValAddressFromBech32(toRedelegation.ValidatorSrcAddress) + if err != nil { + panic(err) + } + valDstAddr, err := sdk.ValAddressFromBech32(toRedelegation.ValidatorDstAddress) + if err != nil { + 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 + } + return false + }) + if err != nil { + return transferred, nil + } + 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()) + err = k.Hooks().BeforeDelegationCreated(ctx, toAddr, valAddr) + } else { + return transferred, err + } + } else { + err = k.Hooks().BeforeDelegationSharesModified(ctx, toAddr, valAddr) + } + if err != nil { + return transferred, nil + } + + delTo.Shares = delTo.Shares.Add(transferred) + 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() { + 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 { + err = k.Hooks().BeforeDelegationSharesModified(ctx, fromAddr, valAddr) + if err != nil { + return transferred, nil + } + delFrom.Shares = remaining + 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 + // 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 + } + + 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++ { + 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, valSrcAddr, valDstAddr, + entry.CreationHeight, entry.CompletionTime, entry.InitialBalance, math.LegacyZeroDec(), sharesToSend, + ) + if err != nil { + return transferred, err + } + err = k.InsertRedelegationQueue(ctx, toRed, entry.CompletionTime) + if err != nil { + return transferred, err + } + 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, valSrcAddr, valDstAddr, + entry.CreationHeight, entry.CompletionTime, balanceToSend, math.LegacyZeroDec(), sharesToSend, + ) + if err != nil { + return transferred, err + } + err = k.InsertRedelegationQueue(ctx, toRed, entry.CompletionTime) + if err != nil { + return transferred, err + } + 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 { + err = k.SetRedelegation(ctx, redelegation) + } else { + 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, error) { + transferred := math.ZeroInt() + ubdFrom, err := k.GetUnbondingDelegation(ctx, fromAddr, valAddr) + if err != nil { + return transferred, err + } + + 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 + } + + 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 { + return transferred, err + } + err = k.InsertUBDQueue(ctx, ubdTo, entry.CompletionTime) + if err != nil { + return transferred, err + } + + 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 { + err = k.RemoveUnbondingDelegation(ctx, ubdFrom) + } else { + err = k.SetUnbondingDelegation(ctx, ubdFrom) + } + if err != nil { + return transferred, err + } + } + return transferred, nil +} 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..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()) } // ---------------------------------------------------------------------------- @@ -99,7 +106,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 +115,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 +131,13 @@ 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) + + // 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} + querier := sdkkeeper.Querier{Keeper: am.keeper.Keeper} sdktypes.RegisterQueryServer(cfg.QueryServer(), querier) } @@ -139,7 +149,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. @@ -168,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/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 new file mode 100644 index 00000000..6081f599 --- /dev/null +++ b/x/vesting/client/cli/tx.go @@ -0,0 +1,115 @@ +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" +) + +const FlagDisableClawback = "disable-clawback" + +// 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(), + ) + 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 + } + + 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 +} + +// NewMsgClawbackCmd returns a CLI command handler for clawing back unvested funds. +func NewMsgClawbackCmd() *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). + 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 { + 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/clawback_test.go b/x/vesting/keeper/clawback_test.go new file mode 100644 index 00000000..426b190a --- /dev/null +++ b/x/vesting/keeper/clawback_test.go @@ -0,0 +1,283 @@ +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" + + "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(sdk.NewInt64Coin(bondDenom, 500000))) + require.NoError(t, err) + + _, 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 + 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 + slashFractions []math.LegacyDec // on val0 and val1 + recipientFinalSpendable sdk.Coins + }{ + { + testName: "clawback from unbonded", + funder: sdk.MustAccAddressFromBech32("seda1gujynygp0tkwzfpt0g7dv4829jwyk8f0yhp88d"), + recipient: testAddrs[0], + vestingTime: 100, + timeUntilClawback: 30, + originalVesting: sdk.NewInt64Coin(bondDenom, 10000), + 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, + slashFractions: []math.LegacyDec{math.LegacyZeroDec(), 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), + 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)), + slashFractions: []math.LegacyDec{math.LegacyZeroDec(), 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), + 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)), + slashFractions: []math.LegacyDec{math.LegacyZeroDec(), 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), + 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, + slashFractions: []math.LegacyDec{math.LegacyZeroDec(), 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), + 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)), + slashFractions: []math.LegacyDec{math.LegacyZeroDec(), math.LegacyZeroDec()}, + recipientFinalSpendable: sdk.NewCoins(), + }, + { + testName: "clawback from unbonded and bonded with slashing", + funder: sdk.MustAccAddressFromBech32("seda1gujynygp0tkwzfpt0g7dv4829jwyk8f0yhp88d"), + recipient: testAddrs[5], + vestingTime: 100, + timeUntilClawback: 30, + originalVesting: sdk.NewInt64Coin(bondDenom, 10000), + 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)), + 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[6], + vestingTime: 750000, + timeUntilClawback: 600000, + originalVesting: sdk.NewInt64Coin(bondDenom, 13000), + 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)), + 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(), + }, + } + 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(), + 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.delegations[0].IsPositive() { + delegateMsg := &sdkstakingtypes.MsgDelegate{ + DelegatorAddress: tc.recipient.String(), + ValidatorAddress: valAddrs[0].String(), + Amount: tc.delegations[0], + } + _, 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.undelegations[0].IsPositive() { + undelegateMsg := &sdkstakingtypes.MsgUndelegate{ + DelegatorAddress: tc.recipient.String(), + ValidatorAddress: valAddrs[0].String(), + 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.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.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) + } + + _, 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(), + } + 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) + + // + 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 new file mode 100644 index 00000000..dc79916d --- /dev/null +++ b/x/vesting/keeper/integration_test.go @@ -0,0 +1,183 @@ +package keeper_test + +import ( + "testing" + "time" + + "cosmossdk.io/core/appmodule" + "cosmossdk.io/log" + "cosmossdk.io/math" + 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" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + "github.com/cosmos/cosmos-sdk/runtime" + 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" + "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" + 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" + sdkstakingtypes "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/integration" + "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" + bondDenom = "aseda" +) + +var ( + zeroCoins sdk.Coins + 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_________________")), + sdk.AccAddress([]byte("to8_________________")), + sdk.AccAddress([]byte("to9_________________")), + } +) + +type fixture struct { + *integration.IntegationApp + 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, sdkstakingtypes.StoreKey, types.StoreKey, + ) + cdc := moduletestutil.MakeTestEncodingConfig(auth.AppModuleBasic{}, bank.AppModuleBasic{}, vesting.AppModuleBasic{}).Codec + + logger := log.NewTestLogger(tb) + cms := sdkintegration.CreateMultiStore(keys, logger) + + newCtx := sdk.NewContext(cms, cmtproto.Header{Time: time.Now().UTC()}, true, logger) + + authority := authtypes.NewModuleAddress(govtypes.ModuleName) + + maccPerms := map[string][]string{ + minttypes.ModuleName: {authtypes.Minter}, + sdkstakingtypes.BondedPoolName: {authtypes.Burner, authtypes.Staking}, + sdkstakingtypes.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[sdkstakingtypes.StoreKey]), accountKeeper, bankKeeper, authority.String(), addresscodec.NewBech32Codec(params.Bech32PrefixValAddr), addresscodec.NewBech32Codec(params.Bech32PrefixConsAddr)) + stakingKeeper := stakingkeeper.NewKeeper(sdkstakingKeeper) + + stakingParams := sdkstakingtypes.DefaultParams() + stakingParams.BondDenom = bondDenom + err := stakingKeeper.SetParams(newCtx, stakingParams) + require.NoError(tb, err) + + 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 := integration.NewIntegrationApp(newCtx, logger, keys, cdc, map[string]appmodule.AppModule{ + authtypes.ModuleName: authModule, + banktypes.ModuleName: bankModule, + sdkstakingtypes.ModuleName: stakingModule, + types.ModuleName: vestingModule, + }) + + types.RegisterMsgServer(integrationApp.MsgServiceRouter(), keeper.NewMsgServerImpl(accountKeeper, bankKeeper, stakingKeeper)) + sdkstakingtypes.RegisterMsgServer(integrationApp.MsgServiceRouter(), sdkstakingkeeper.NewMsgServerImpl(sdkstakingKeeper)) + + return &fixture{ + IntegationApp: integrationApp, + cdc: cdc, + accountKeeper: accountKeeper, + bankKeeper: bankKeeper, + stakingKeeper: *stakingKeeper, + } +} + +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(5e18)) + valAddrs := simtestutil.ConvertAddrsToValAddrs(addrs) + valPks := simtestutil.CreateTestPubKeys(5) + + val1, err := sdkstakingtypes.NewValidator(valAddrs[0].String(), valPks[0], sdkstakingtypes.Description{}) + require.NoError(t, err) + val2, err := sdkstakingtypes.NewValidator(valAddrs[1].String(), valPks[1], sdkstakingtypes.Description{}) + require.NoError(t, err) + val3, err := sdkstakingtypes.NewValidator(valAddrs[2].String(), valPks[2], sdkstakingtypes.Description{}) + require.NoError(t, err) + + 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)) + + _, 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, valPks +} diff --git a/x/vesting/keeper/msg_server.go b/x/vesting/keeper/msg_server.go new file mode 100644 index 00000000..b816fe08 --- /dev/null +++ b/x/vesting/keeper/msg_server.go @@ -0,0 +1,296 @@ +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" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/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) + if msg.DisableClawback { + vestingAccount.FunderAddress = "" + } + + 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 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) + + // 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 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 { + 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 == "" { + 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) + } + + // Compute the clawback based on bank balance and delegation, and update account + 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) + } + 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) + total := bonded.Add(unbonding...).Add(unbonded...) + + 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) + 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 + clawedBackUnbonding := sdk.NewCoins() + clawedBackBonded := sdk.NewCoins() + toClawBack = toClawBack.Sub(toXfer...) + if !toClawBack.IsZero() { + // claw back from staking (unbonding delegations then bonded delegations) + toClawBackStaking := toClawBack.AmountOf(bondDenom) + + // first from unbonding delegations + 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 { + return nil, err + } + + 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) + if !toClawBackStaking.IsPositive() { + break + } + } + + // 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 { + return nil, err + } + validator, err := m.sk.GetValidator(ctx, validatorAddr) + if err != nil { + if err != stakingtypes.ErrNoValidatorFound { + return nil, err + } + // validator has been removed + 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 { + return nil, err + } + + // to be conservative in what we're clawing back, round transferred shares up + transferred := validator.TokensFromSharesRoundUp(transferredShares).RoundInt() + clawedBackBonded = clawedBackBonded.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 + } + } + } + + if !toClawBackStaking.IsZero() { + panic("failed to claw back full amount") + } + } + + return &types.MsgClawbackResponse{ + ClawedUnbonded: clawedBackUnbonded, + ClawedUnbonding: clawedBackUnbonding, + ClawedBonded: clawedBackBonded, + }, 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..e8d68861 --- /dev/null +++ b/x/vesting/module.go @@ -0,0 +1,139 @@ +package vesting + +import ( + "encoding/json" + + 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" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + 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" +) + +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, _ 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 } + +// AppModuleSimulation functions + +// GenerateGenesisState creates a randomized GenState of the slashing module. +func (AppModule) GenerateGenesisState(_ *module.SimulationState) {} + +// ProposalMsgs returns msgs used for governance proposals for simulations. +func (AppModule) ProposalMsgs(_ module.SimulationState) []simtypes.WeightedProposalMsg { + return []simtypes.WeightedProposalMsg{} +} + +// RegisterStoreDecoder registers a decoder for slashing module's types +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 { + return simulation.WeightedOperations( + 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 new file mode 100644 index 00000000..3b779b2e --- /dev/null +++ b/x/vesting/simulation/operations.go @@ -0,0 +1,361 @@ +package simulation + +import ( + "math/rand" + + "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" +) + +// Simulation operation weights constants +const ( + OpWeightMsgCreateVestingAccount = "op_weight_msg_create_vesting_account" //nolint:gosec + OpWeightMsgClawback = "op_weight_msg_clawback" //nolint:gosec + + DefaultWeightMsgCreateVestingAccount = 100 + DefaultWeightMsgClawback = 75 +) + +// WeightedOperations returns all the operations from the module with their respective weights +func WeightedOperations( + appParams simtypes.AppParams, + _ codec.JSONCodec, + txGen client.TxConfig, + ak types.AccountKeeper, + bk types.BankKeeper, + sk types.StakingKeeper, +) simulation.WeightedOperations { + var weightMsgCreateVestingAccount int + var 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(txGen, ak, bk, sk), + ), + simulation.NewWeightedOperation( + weightMsgClawback, + SimulateMsgClawback(txGen, ak, bk, sk), + ), + } +} + +// SimulateMsgCreateVestingAccount generates a MsgCreateVestingAccount with random values. +func SimulateMsgCreateVestingAccount( + 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, + false, + ) + + 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 + } + + // 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, + // }) + + return simtypes.NewOperationMsg(msg, true, ""), futureOps, nil + } +} + +// SimulateMsgCreateVestingAccount generates a MsgCreateVestingAccount with random values. +func SimulateMsgClawback( + txGen client.TxConfig, + ak types.AccountKeeper, + bk types.BankKeeper, + _ 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 + } +} + +func simulateMsgDelegate( + _ client.TxConfig, + _ types.AccountKeeper, + _ 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, + _ 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{}) + + 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/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..2b046f00 --- /dev/null +++ b/x/vesting/types/expected_keepers.go @@ -0,0 +1,37 @@ +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 { + 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 + 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) + 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) + 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, error) + 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..ac6a4862 --- /dev/null +++ b/x/vesting/types/msgs.go @@ -0,0 +1,28 @@ +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, disableClawback bool) *MsgCreateVestingAccount { + return &MsgCreateVestingAccount{ + FromAddress: fromAddr.String(), + ToAddress: toAddr.String(), + Amount: amount, + EndTime: endTime, + DisableClawback: disableClawback, + } +} + +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..70e43041 --- /dev/null +++ b/x/vesting/types/tx.pb.go @@ -0,0 +1,1360 @@ +// 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/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"` + // 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{} } +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 +} + +func (m *MsgCreateVestingAccount) GetDisableClawback() bool { + if m != nil { + return m.DisableClawback + } + return false +} + +// 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 { + 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{} } +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) GetClawedUnbonded() github_com_cosmos_cosmos_sdk_types.Coins { + if m != nil { + 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 +} + +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{ + // 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 { + 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 + } + if this.DisableClawback != that1.DisableClawback { + 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.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-- + 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.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.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 + } + 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)) + } + if m.DisableClawback { + n += 2 + } + 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.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)) + } + } + 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 + } + } + 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:]) + 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 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 { + 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.ClawedBonded = append(m.ClawedBonded, types.Coin{}) + if err := m.ClawedBonded[len(m.ClawedBonded)-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..66a6b007 --- /dev/null +++ b/x/vesting/types/vesting.pb.go @@ -0,0 +1,373 @@ +// 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" + 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{ + // 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, 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) { + 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") +)