Skip to content

Commit aef7c5a

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

File tree

16 files changed

+944
-1819
lines changed

16 files changed

+944
-1819
lines changed

app/testnet.go

Lines changed: 257 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,257 @@
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+
if err := iterator.Close(); err != nil {
103+
panic(err)
104+
}
105+
106+
// Remove all validators from last validators store
107+
iterator = app.Keepers.Cosmos.Staking.LastValidatorsIterator(ctx)
108+
109+
for ; iterator.Valid(); iterator.Next() {
110+
stakingStore.Delete(iterator.Key())
111+
}
112+
if err := iterator.Close(); err != nil {
113+
panic(err)
114+
}
115+
116+
// Remove all validators from validator store
117+
iterator = storetypes.KVStorePrefixIterator(stakingStore, stakingtypes.ValidatorsKey)
118+
for ; iterator.Valid(); iterator.Next() {
119+
stakingStore.Delete(iterator.Key())
120+
}
121+
if err := iterator.Close(); err != nil {
122+
panic(err)
123+
}
124+
125+
// Remove all validators from unbonding queue
126+
iterator = storetypes.KVStorePrefixIterator(stakingStore, stakingtypes.ValidatorQueueKey)
127+
for ; iterator.Valid(); iterator.Next() {
128+
stakingStore.Delete(iterator.Key())
129+
}
130+
if err := iterator.Close(); err != nil {
131+
panic(err)
132+
}
133+
134+
for _, val := range tcfg.Validators {
135+
// Create Validator struct for our new validator.
136+
newVal := stakingtypes.Validator{
137+
OperatorAddress: val.OperatorAddress.String(),
138+
ConsensusPubkey: val.ConsensusPubKey,
139+
Jailed: false,
140+
Status: stakingtypes.Bonded,
141+
Tokens: sdk.NewInt(900000000000000),
142+
DelegatorShares: sdk.MustNewDecFromStr("10000000"),
143+
Description: stakingtypes.Description{
144+
Moniker: "Testnet Validator",
145+
},
146+
Commission: stakingtypes.Commission{
147+
CommissionRates: stakingtypes.CommissionRates{
148+
Rate: sdk.MustNewDecFromStr("0.05"),
149+
MaxRate: sdk.MustNewDecFromStr("0.1"),
150+
MaxChangeRate: sdk.MustNewDecFromStr("0.05"),
151+
},
152+
},
153+
MinSelfDelegation: sdk.OneInt(),
154+
}
155+
156+
// Add our validator to power and last validators store
157+
app.Keepers.Cosmos.Staking.SetValidator(ctx, newVal)
158+
err = app.Keepers.Cosmos.Staking.SetValidatorByConsAddr(ctx, newVal)
159+
if err != nil {
160+
return nil
161+
}
162+
163+
app.Keepers.Cosmos.Staking.SetValidatorByPowerIndex(ctx, newVal)
164+
165+
valAddr := newVal.GetOperator()
166+
app.Keepers.Cosmos.Staking.SetLastValidatorPower(ctx, valAddr, 0)
167+
168+
app.Keepers.Cosmos.Distr.Hooks().AfterValidatorCreated(ctx, valAddr)
169+
app.Keepers.Cosmos.Slashing.Hooks().AfterValidatorCreated(ctx, valAddr)
170+
171+
// DISTRIBUTION
172+
//
173+
174+
// Initialize records for this validator across all distribution stores
175+
app.Keepers.Cosmos.Distr.SetValidatorHistoricalRewards(ctx, valAddr, 0, distrtypes.NewValidatorHistoricalRewards(sdk.DecCoins{}, 1))
176+
app.Keepers.Cosmos.Distr.SetValidatorCurrentRewards(ctx, valAddr, distrtypes.NewValidatorCurrentRewards(sdk.DecCoins{}, 1))
177+
app.Keepers.Cosmos.Distr.SetValidatorAccumulatedCommission(ctx, valAddr, distrtypes.InitialValidatorAccumulatedCommission())
178+
app.Keepers.Cosmos.Distr.SetValidatorOutstandingRewards(ctx, valAddr, distrtypes.ValidatorOutstandingRewards{Rewards: sdk.DecCoins{}})
179+
180+
// SLASHING
181+
//
182+
183+
newConsAddr := val.ConsensusAddress
184+
185+
// Set validator signing info for our new validator.
186+
newValidatorSigningInfo := slashingtypes.ValidatorSigningInfo{
187+
Address: newConsAddr.String(),
188+
StartHeight: app.LastBlockHeight() - 1,
189+
Tombstoned: false,
190+
}
191+
192+
_, _ = app.Keepers.Cosmos.Staking.ApplyAndReturnValidatorSetUpdates(ctx)
193+
194+
app.Keepers.Cosmos.Slashing.SetValidatorSigningInfo(ctx, newConsAddr, newValidatorSigningInfo)
195+
}
196+
197+
//
198+
// Optional Changes:
199+
//
200+
201+
// GOV
202+
//
203+
204+
voteParams := app.Keepers.Cosmos.Gov.GetVotingParams(ctx)
205+
voteParams.VotingPeriod = tcfg.Gov.VotingParams.VotingPeriod.Duration
206+
app.Keepers.Cosmos.Gov.SetVotingParams(ctx, voteParams)
207+
208+
// BANK
209+
//
210+
211+
defaultCoins := sdk.NewCoins(
212+
sdk.NewInt64Coin("uakt", 1000000000000),
213+
sdk.NewInt64Coin("ibc/12C6A0C374171B595A0A9E18B83FA09D295FB1F2D8C6DAA3AC28683471752D84", 1000000000000), // axlUSDC
214+
)
215+
216+
for _, account := range tcfg.Accounts {
217+
err := app.Keepers.Cosmos.Bank.MintCoins(ctx, minttypes.ModuleName, defaultCoins)
218+
if err != nil {
219+
return nil
220+
}
221+
err = app.Keepers.Cosmos.Bank.SendCoinsFromModuleToAccount(ctx, minttypes.ModuleName, account, defaultCoins)
222+
if err != nil {
223+
return nil
224+
}
225+
}
226+
227+
// UPGRADE
228+
//
229+
if tcfg.Upgrade.Name != "" {
230+
upgradePlan := upgradetypes.Plan{
231+
Name: tcfg.Upgrade.Name,
232+
Height: app.LastBlockHeight() + 10,
233+
}
234+
235+
err = app.Keepers.Cosmos.Upgrade.ScheduleUpgrade(ctx, upgradePlan)
236+
if err != nil {
237+
panic(err)
238+
}
239+
240+
for name, fn := range utypes.GetUpgradesList() {
241+
upgrade, err := fn(app.Logger(), &app.App)
242+
if err != nil {
243+
panic(err)
244+
}
245+
246+
if tcfg.Upgrade.Name == name {
247+
app.Logger().Info(fmt.Sprintf("configuring upgrade `%s`", name))
248+
if storeUpgrades := upgrade.StoreLoader(); storeUpgrades != nil && tcfg.Upgrade.Name == name {
249+
app.Logger().Info(fmt.Sprintf("setting up store upgrades for `%s`", name))
250+
app.SetStoreLoader(upgradetypes.UpgradeStoreLoader(app.LastBlockHeight(), storeUpgrades))
251+
}
252+
}
253+
}
254+
}
255+
256+
return app
257+
}

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)