Skip to content

Commit 47c7a7e

Browse files
committed
feat(cmd/testnetify): backport testnetify from live blockchain state
Signed-off-by: Artur Troian <[email protected]>
1 parent 759fe47 commit 47c7a7e

File tree

16 files changed

+934
-1819
lines changed

16 files changed

+934
-1819
lines changed

app/testnet.go

Lines changed: 249 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,249 @@
1+
package app
2+
3+
import (
4+
"fmt"
5+
"strings"
6+
"time"
7+
8+
"github.com/cosmos/cosmos-sdk/codec/types"
9+
storetypes "github.com/cosmos/cosmos-sdk/store/types"
10+
sdk "github.com/cosmos/cosmos-sdk/types"
11+
distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
12+
minttypes "github.com/cosmos/cosmos-sdk/x/mint/types"
13+
slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types"
14+
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
15+
upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types"
16+
tmos "github.com/tendermint/tendermint/libs/os"
17+
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
18+
19+
utypes "github.com/akash-network/node/upgrades/types"
20+
)
21+
22+
type TestnetValidator struct {
23+
OperatorAddress sdk.ValAddress
24+
ConsensusAddress sdk.ConsAddress
25+
ConsensusPubKey *types.Any
26+
Moniker string
27+
Commission stakingtypes.Commission
28+
MinSelfDelegation sdk.Int
29+
}
30+
31+
type TestnetUpgrade struct {
32+
Name string
33+
}
34+
35+
type TestnetVotingPeriod struct {
36+
time.Duration
37+
}
38+
39+
type TestnetGovConfig struct {
40+
VotingParams *struct {
41+
VotingPeriod TestnetVotingPeriod `json:"voting_period,omitempty"`
42+
} `json:"voting_params,omitempty"`
43+
}
44+
45+
type TestnetConfig struct {
46+
Accounts []sdk.AccAddress
47+
Validators []TestnetValidator
48+
Gov TestnetGovConfig
49+
Upgrade TestnetUpgrade
50+
}
51+
52+
func TrimQuotes(data string) string {
53+
data = strings.TrimPrefix(data, "\"")
54+
return strings.TrimSuffix(data, "\"")
55+
}
56+
57+
func (t *TestnetVotingPeriod) UnmarshalJSON(data []byte) error {
58+
val := TrimQuotes(string(data))
59+
60+
if !strings.HasSuffix(val, "s") {
61+
return fmt.Errorf("invalid format of voting period. must contain time unit. Valid time units are ns|us(µs)|ms|s|m|h") // nolint: goerr113
62+
}
63+
64+
var err error
65+
t.Duration, err = time.ParseDuration(val)
66+
if err != nil {
67+
return err
68+
}
69+
70+
return nil
71+
}
72+
73+
// InitAkashAppForTestnet is broken down into two sections:
74+
// Required Changes: Changes that, if not made, will cause the testnet to halt or panic
75+
// Optional Changes: Changes to customize the testnet to one's liking (lower vote times, fund accounts, etc)
76+
func InitAkashAppForTestnet(
77+
app *AkashApp,
78+
tcfg *TestnetConfig,
79+
) *AkashApp {
80+
//
81+
// Required Changes:
82+
//
83+
84+
var err error
85+
86+
defer func() {
87+
if err != nil {
88+
tmos.Exit(err.Error())
89+
}
90+
}()
91+
92+
ctx := app.BaseApp.NewUncachedContext(true, tmproto.Header{})
93+
94+
// Remove all validators from power store
95+
stakingKey := app.GetKey(stakingtypes.ModuleName)
96+
stakingStore := ctx.KVStore(stakingKey)
97+
iterator := app.Keepers.Cosmos.Staking.ValidatorsPowerStoreIterator(ctx)
98+
99+
for ; iterator.Valid(); iterator.Next() {
100+
stakingStore.Delete(iterator.Key())
101+
}
102+
_ = iterator.Close()
103+
104+
// Remove all validators from last validators store
105+
iterator = app.Keepers.Cosmos.Staking.LastValidatorsIterator(ctx)
106+
107+
for ; iterator.Valid(); iterator.Next() {
108+
stakingStore.Delete(iterator.Key())
109+
}
110+
_ = iterator.Close()
111+
112+
// Remove all validators from validator store
113+
iterator = storetypes.KVStorePrefixIterator(stakingStore, stakingtypes.ValidatorsKey)
114+
for ; iterator.Valid(); iterator.Next() {
115+
stakingStore.Delete(iterator.Key())
116+
}
117+
_ = iterator.Close()
118+
119+
// Remove all validators from unbonding queue
120+
iterator = storetypes.KVStorePrefixIterator(stakingStore, stakingtypes.ValidatorQueueKey)
121+
for ; iterator.Valid(); iterator.Next() {
122+
stakingStore.Delete(iterator.Key())
123+
}
124+
_ = iterator.Close()
125+
126+
for _, val := range tcfg.Validators {
127+
// Create Validator struct for our new validator.
128+
newVal := stakingtypes.Validator{
129+
OperatorAddress: val.OperatorAddress.String(),
130+
ConsensusPubkey: val.ConsensusPubKey,
131+
Jailed: false,
132+
Status: stakingtypes.Bonded,
133+
Tokens: sdk.NewInt(900000000000000),
134+
DelegatorShares: sdk.MustNewDecFromStr("10000000"),
135+
Description: stakingtypes.Description{
136+
Moniker: "Testnet Validator",
137+
},
138+
Commission: stakingtypes.Commission{
139+
CommissionRates: stakingtypes.CommissionRates{
140+
Rate: sdk.MustNewDecFromStr("0.05"),
141+
MaxRate: sdk.MustNewDecFromStr("0.1"),
142+
MaxChangeRate: sdk.MustNewDecFromStr("0.05"),
143+
},
144+
},
145+
MinSelfDelegation: sdk.OneInt(),
146+
}
147+
148+
// Add our validator to power and last validators store
149+
app.Keepers.Cosmos.Staking.SetValidator(ctx, newVal)
150+
err = app.Keepers.Cosmos.Staking.SetValidatorByConsAddr(ctx, newVal)
151+
if err != nil {
152+
return nil
153+
}
154+
155+
app.Keepers.Cosmos.Staking.SetValidatorByPowerIndex(ctx, newVal)
156+
157+
valAddr := newVal.GetOperator()
158+
app.Keepers.Cosmos.Staking.SetLastValidatorPower(ctx, valAddr, 0)
159+
160+
app.Keepers.Cosmos.Distr.Hooks().AfterValidatorCreated(ctx, valAddr)
161+
app.Keepers.Cosmos.Slashing.Hooks().AfterValidatorCreated(ctx, valAddr)
162+
163+
// DISTRIBUTION
164+
//
165+
166+
// Initialize records for this validator across all distribution stores
167+
app.Keepers.Cosmos.Distr.SetValidatorHistoricalRewards(ctx, valAddr, 0, distrtypes.NewValidatorHistoricalRewards(sdk.DecCoins{}, 1))
168+
app.Keepers.Cosmos.Distr.SetValidatorCurrentRewards(ctx, valAddr, distrtypes.NewValidatorCurrentRewards(sdk.DecCoins{}, 1))
169+
app.Keepers.Cosmos.Distr.SetValidatorAccumulatedCommission(ctx, valAddr, distrtypes.InitialValidatorAccumulatedCommission())
170+
app.Keepers.Cosmos.Distr.SetValidatorOutstandingRewards(ctx, valAddr, distrtypes.ValidatorOutstandingRewards{Rewards: sdk.DecCoins{}})
171+
172+
// SLASHING
173+
//
174+
175+
newConsAddr := val.ConsensusAddress
176+
177+
// Set validator signing info for our new validator.
178+
newValidatorSigningInfo := slashingtypes.ValidatorSigningInfo{
179+
Address: newConsAddr.String(),
180+
StartHeight: app.LastBlockHeight() - 1,
181+
Tombstoned: false,
182+
}
183+
184+
_, _ = app.Keepers.Cosmos.Staking.ApplyAndReturnValidatorSetUpdates(ctx)
185+
186+
app.Keepers.Cosmos.Slashing.SetValidatorSigningInfo(ctx, newConsAddr, newValidatorSigningInfo)
187+
}
188+
189+
//
190+
// Optional Changes:
191+
//
192+
193+
// GOV
194+
//
195+
196+
voteParams := app.Keepers.Cosmos.Gov.GetVotingParams(ctx)
197+
voteParams.VotingPeriod = tcfg.Gov.VotingParams.VotingPeriod.Duration
198+
app.Keepers.Cosmos.Gov.SetVotingParams(ctx, voteParams)
199+
200+
// BANK
201+
//
202+
203+
defaultCoins := sdk.NewCoins(
204+
sdk.NewInt64Coin("uakt", 1000000000000),
205+
sdk.NewInt64Coin("ibc/12C6A0C374171B595A0A9E18B83FA09D295FB1F2D8C6DAA3AC28683471752D84", 1000000000000), // axlUSDC
206+
)
207+
208+
for _, account := range tcfg.Accounts {
209+
err := app.Keepers.Cosmos.Bank.MintCoins(ctx, minttypes.ModuleName, defaultCoins)
210+
if err != nil {
211+
return nil
212+
}
213+
err = app.Keepers.Cosmos.Bank.SendCoinsFromModuleToAccount(ctx, minttypes.ModuleName, account, defaultCoins)
214+
if err != nil {
215+
return nil
216+
}
217+
}
218+
219+
// UPGRADE
220+
//
221+
if tcfg.Upgrade.Name != "" {
222+
upgradePlan := upgradetypes.Plan{
223+
Name: tcfg.Upgrade.Name,
224+
Height: app.LastBlockHeight() + 10,
225+
}
226+
227+
err = app.Keepers.Cosmos.Upgrade.ScheduleUpgrade(ctx, upgradePlan)
228+
if err != nil {
229+
panic(err)
230+
}
231+
232+
for name, fn := range utypes.GetUpgradesList() {
233+
upgrade, err := fn(app.Logger(), &app.App)
234+
if err != nil {
235+
panic(err)
236+
}
237+
238+
if tcfg.Upgrade.Name == name {
239+
app.Logger().Info(fmt.Sprintf("configuring upgrade `%s`", name))
240+
if storeUpgrades := upgrade.StoreLoader(); storeUpgrades != nil && tcfg.Upgrade.Name == name {
241+
app.Logger().Info(fmt.Sprintf("setting up store upgrades for `%s`", name))
242+
app.SetStoreLoader(upgradetypes.UpgradeStoreLoader(app.LastBlockHeight(), storeUpgrades))
243+
}
244+
}
245+
}
246+
}
247+
248+
return app
249+
}

cmd/akash/cmd/app_creator.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package cmd
2+
3+
import (
4+
"io"
5+
6+
"github.com/tendermint/tendermint/libs/log"
7+
dbm "github.com/tendermint/tm-db"
8+
9+
servertypes "github.com/cosmos/cosmos-sdk/server/types"
10+
11+
akash "github.com/akash-network/node/app"
12+
"github.com/akash-network/node/cmd/akash/cmd/testnetify"
13+
)
14+
15+
// for a testnet to be created from the provided app.
16+
func newTestnetApp(logger log.Logger, db dbm.DB, traceStore io.Writer, appOpts servertypes.AppOptions) servertypes.Application {
17+
// Create an app and type cast to an AkashApp
18+
app := newApp(logger, db, traceStore, appOpts)
19+
akashApp, ok := app.(*akash.AkashApp)
20+
if !ok {
21+
panic("app created from newApp is not of type AkashApp")
22+
}
23+
24+
tcfg, valid := appOpts.Get(testnetify.KeyTestnetConfig).(*akash.TestnetConfig)
25+
if !valid {
26+
panic("cflags.KeyTestnetConfig is not of type akash.TestnetConfig")
27+
}
28+
29+
// Make modifications to the normal AkashApp required to run the network locally
30+
return akash.InitAkashAppForTestnet(akashApp, tcfg)
31+
}

cmd/akash/cmd/root.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,6 @@ func ExecuteWithCtx(ctx context.Context, rootCmd *cobra.Command, envPrefix strin
138138
func initRootCmd(rootCmd *cobra.Command, encodingConfig params.EncodingConfig) {
139139
debugCmd := debug.Cmd()
140140
debugCmd.AddCommand(ConvertBech32Cmd())
141-
debugCmd.AddCommand(testnetify.Cmd())
142141

143142
rootCmd.AddCommand(
144143
rpc.StatusCommand(),
@@ -158,6 +157,7 @@ func initRootCmd(rootCmd *cobra.Command, encodingConfig params.EncodingConfig) {
158157
sdkserver.RosettaCommand(encodingConfig.InterfaceRegistry, encodingConfig.Marshaler),
159158
)
160159

160+
rootCmd.AddCommand(testnetify.GetCmd(newTestnetApp))
161161
rootCmd.AddCommand(server.Commands(app.DefaultHome, newApp, createAppAndExport, addModuleInitFlags)...)
162162

163163
rootCmd.SetOut(rootCmd.OutOrStdout())

cmd/akash/cmd/testnetify/accounts.go

Lines changed: 0 additions & 31 deletions
This file was deleted.

0 commit comments

Comments
 (0)