From d3180b83778379d003e14f5b811a61d93fdc4017 Mon Sep 17 00:00:00 2001 From: Thomas Bruyelle Date: Mon, 26 Feb 2024 19:36:57 +0100 Subject: [PATCH 1/4] feat: InitChainer auto stakes genesis accounts --- app/app.go | 85 +++++++++++++++++++++++++++++++++++++++++++- x/gov/module_test.go | 3 +- 2 files changed, 86 insertions(+), 2 deletions(-) diff --git a/app/app.go b/app/app.go index cb8cbd4..b72f177 100644 --- a/app/app.go +++ b/app/app.go @@ -6,6 +6,7 @@ import ( "net/http" "os" "path/filepath" + "sort" "github.com/gorilla/mux" "github.com/rakyll/statik/fs" @@ -15,6 +16,7 @@ import ( "github.com/tendermint/tendermint/libs/log" tmos "github.com/tendermint/tendermint/libs/os" dbm "github.com/tendermint/tm-db" + "golang.org/x/exp/slices" // unnamed import of statik for swagger UI support _ "github.com/cosmos/cosmos-sdk/client/docs/statik" @@ -37,6 +39,7 @@ import ( authrest "github.com/cosmos/cosmos-sdk/x/auth/client/rest" authtx "github.com/cosmos/cosmos-sdk/x/auth/tx" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" "github.com/cosmos/cosmos-sdk/x/crisis" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" @@ -241,7 +244,87 @@ func (app *GovGenApp) InitChainer(ctx sdk.Context, req abci.RequestInitChain) ab app.UpgradeKeeper.SetModuleVersionMap(ctx, app.mm.GetVersionMap()) - return app.mm.InitGenesis(ctx, app.appCodec, genesisState) + res := app.mm.InitGenesis(ctx, app.appCodec, genesisState) + + // auto stake genesis accounts + app.setInitialStakingDistribution(ctx, genesisState) + + return res +} + +// setInitialStakingDistribution auto stakes genesis accounts in a fairly +// distributed manner. +func (app *GovGenApp) setInitialStakingDistribution(ctx sdk.Context, genesisState GenesisState) { + var bankState banktypes.GenesisState + app.appCodec.MustUnmarshalJSON(genesisState[banktypes.ModuleName], &bankState) + // Sort balances in descending order + sort.Slice(bankState.Balances, func(i, j int) bool { + return bankState.Balances[i].Coins.IsAllGT(bankState.Balances[j].Coins) + }) + + var ( + minTokens = sdk.NewInt(25_000_000) + powerReduction = app.StakingKeeper.PowerReduction(ctx) + ) + // Extend validator to track delegations + type validator struct { + stakingtypes.Validator + totalDelegations int64 + } + var validators []*validator + for _, val := range app.StakingKeeper.GetAllValidators(ctx) { + validators = append(validators, &validator{ + Validator: val, + }) + } + if len(validators) == 0 { + return + } + for _, balance := range bankState.Balances { + tokens := balance.Coins.AmountOf("ugovgen") + if tokens.LTE(minTokens) { + // Don't stake when tokens <= minToken + continue + } + // Take 50% of the balance for staking + stake := tokens.QuoRaw(2) + + // Determine the number of validators that will receive a delegation + var splitStake sdk.Int + switch { + case stake.LT(sdk.NewInt(500_000_000)): + splitStake = stake.QuoRaw(5) + case stake.LT(sdk.NewInt(10_000_000_000)): + splitStake = stake.QuoRaw(10) + default: + splitStake = stake.QuoRaw(20) + } + + // Delegation loop for each selected validator + for ; stake.GTE(powerReduction); stake = stake.Sub(splitStake) { + bondAmt := sdk.MinInt(stake, splitStake) + // Delegate to validator which has the less delegations + validator := slices.MinFunc(validators, func(val1, val2 *validator) int { + return int(val1.totalDelegations - val2.totalDelegations) + }) + if _, err := app.StakingKeeper.Delegate( + ctx, + balance.GetAddress(), + bondAmt, + stakingtypes.Unbonded, + validator.Validator, + true, + ); err != nil { + panic(err) + } + + // track delegation for the sake of the algorithm + validator.totalDelegations += bondAmt.Int64() + + // reload validator to avoid power index problem + validator.Validator, _ = app.StakingKeeper.GetValidator(ctx, validator.GetOperator()) + } + } } // LoadHeight loads a particular height diff --git a/x/gov/module_test.go b/x/gov/module_test.go index fec882c..b67392a 100644 --- a/x/gov/module_test.go +++ b/x/gov/module_test.go @@ -19,7 +19,8 @@ func TestItCreatesModuleAccountOnInitBlock(t *testing.T) { app.InitChain( abcitypes.RequestInitChain{ - AppStateBytes: []byte("{}"), + // bank module must be present because of app.setInitialStakingDistribution + AppStateBytes: []byte(`{"bank":{}}`), ChainId: "test-chain-id", }, ) From 38aef3932613aeb652b11db1a5f49c83ab49f364 Mon Sep 17 00:00:00 2001 From: Thomas Bruyelle Date: Mon, 26 Feb 2024 20:32:09 +0100 Subject: [PATCH 2/4] doc: CL and README --- CHANGELOG.md | 2 ++ README.md | 1 + 2 files changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f97fde..6e976ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,5 +20,7 @@ ([#13](https://github.com/atomone-hub/govgen/pull/13)). * Adapt voting period to proposal type. ([#16](https://github.com/atomone-hub/govgen/pull/16)). +* Auto stake genesis accounts + ([#26](https://github.com/atomone-hub/govgen/pull/26)). ### STATE BREAKING diff --git a/README.md b/README.md index 3706233..e918b4e 100644 --- a/README.md +++ b/README.md @@ -14,3 +14,4 @@ The following modifications have been made to the Cosmos Hub software to create 7. Removed ability for validators to vote on proposals with delegations, they can only use their own stake 8. Removed community spend proposal 9. Allowed setting different voting periods for different proposal types + 10. Auto stake genesis accounts From ed46360b337ee78f5bff98993dd7e9a7f5184ff0 Mon Sep 17 00:00:00 2001 From: Giuseppe Natale <12249307+giunatale@users.noreply.github.com> Date: Mon, 26 Feb 2024 21:05:12 +0100 Subject: [PATCH 3/4] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e976ed..c14a140 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,7 +20,7 @@ ([#13](https://github.com/atomone-hub/govgen/pull/13)). * Adapt voting period to proposal type. ([#16](https://github.com/atomone-hub/govgen/pull/16)). -* Auto stake genesis accounts +* `InitChainer` auto stakes uniformly to validators at genesis ([#26](https://github.com/atomone-hub/govgen/pull/26)). ### STATE BREAKING From f39db5d542b2d141ec75b7cbac7bfe17094aebb9 Mon Sep 17 00:00:00 2001 From: Giuseppe Natale <12249307+giunatale@users.noreply.github.com> Date: Mon, 26 Feb 2024 21:05:42 +0100 Subject: [PATCH 4/4] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e918b4e..534559f 100644 --- a/README.md +++ b/README.md @@ -14,4 +14,5 @@ The following modifications have been made to the Cosmos Hub software to create 7. Removed ability for validators to vote on proposals with delegations, they can only use their own stake 8. Removed community spend proposal 9. Allowed setting different voting periods for different proposal types - 10. Auto stake genesis accounts + 10. Stake automatically 50% of balance for accounts that have more than 25 $GOVGEN at genesis initialization. The resulting stake distribution will provide approximately the same voting power to all genesis validators. Accounts will automatically stake to 5 validators if balance is less than 500 $GOVGEN, 10 validators if balance is less than 10000 $GOVGEN and 20 validators if more, uniformly. +