Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion app/export.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,10 @@ func (app *AkashApp) prepForZeroHeightGenesis(ctx sdk.Context, jailAllowedAddrs

_ = iter.Close()

_, _ = app.Keepers.Cosmos.Staking.ApplyAndReturnValidatorSetUpdates(ctx)
_, err := app.Keepers.Cosmos.Staking.ApplyAndReturnValidatorSetUpdates(ctx)
if err != nil {
panic(err)
}

/* Handle slashing state. */

Expand Down
84 changes: 50 additions & 34 deletions app/testnet.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,11 @@ type TestnetValidator struct {
OperatorAddress sdk.ValAddress
ConsensusAddress sdk.ConsAddress
ConsensusPubKey *types.Any
Status stakingtypes.BondStatus
Moniker string
Commission stakingtypes.Commission
MinSelfDelegation sdk.Int
Delegations []TestnetDelegation
}

type TestnetUpgrade struct {
Expand All @@ -42,8 +44,18 @@ type TestnetGovConfig struct {
} `json:"voting_params,omitempty"`
}

type TestnetAccount struct {
Address sdk.AccAddress `json:"address"`
Balances []sdk.Coin `json:"balances"`
}
Comment on lines +47 to +50
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Use sdk.Coins for Balances to match bank APIs.

Bank.MintCoins/SendCoinsFromModuleToAccount accept sdk.Coins. Using []sdk.Coin here causes friction and type mismatches elsewhere.

 type TestnetAccount struct {
   Address  sdk.AccAddress `json:"address"`
-  Balances []sdk.Coin     `json:"balances"`
+  Balances sdk.Coins      `json:"balances"`
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
type TestnetAccount struct {
Address sdk.AccAddress `json:"address"`
Balances []sdk.Coin `json:"balances"`
}
type TestnetAccount struct {
Address sdk.AccAddress `json:"address"`
Balances sdk.Coins `json:"balances"`
}


type TestnetDelegation struct {
Address sdk.AccAddress `json:"address"`
Amount sdk.Coin `json:"amount"`
}

type TestnetConfig struct {
Accounts []sdk.AccAddress
Accounts []TestnetAccount
Validators []TestnetValidator
Gov TestnetGovConfig
Upgrade TestnetUpgrade
Expand Down Expand Up @@ -131,33 +143,41 @@ func InitAkashAppForTestnet(
panic(err)
}

// BANK
//

for _, account := range tcfg.Accounts {
err := app.Keepers.Cosmos.Bank.MintCoins(ctx, minttypes.ModuleName, account.Balances)
if err != nil {
panic(err)
}
err = app.Keepers.Cosmos.Bank.SendCoinsFromModuleToAccount(ctx, minttypes.ModuleName, account.Address, account.Balances)
if err != nil {
panic(err)
}
}

for _, val := range tcfg.Validators {
// Create Validator struct for our new validator.
newVal := stakingtypes.Validator{
OperatorAddress: val.OperatorAddress.String(),
ConsensusPubkey: val.ConsensusPubKey,
Jailed: false,
Status: stakingtypes.Bonded,
Tokens: sdk.NewInt(900000000000000),
DelegatorShares: sdk.MustNewDecFromStr("10000000"),
Status: val.Status,
Tokens: sdk.NewInt(0),
DelegatorShares: sdk.MustNewDecFromStr("0"),
Description: stakingtypes.Description{
Moniker: "Testnet Validator",
},
Commission: stakingtypes.Commission{
CommissionRates: stakingtypes.CommissionRates{
Rate: sdk.MustNewDecFromStr("0.05"),
MaxRate: sdk.MustNewDecFromStr("0.1"),
MaxChangeRate: sdk.MustNewDecFromStr("0.05"),
},
Moniker: val.Moniker,
},
MinSelfDelegation: sdk.OneInt(),
Commission: val.Commission,
MinSelfDelegation: val.MinSelfDelegation,
}

// Add our validator to power and last validators store
app.Keepers.Cosmos.Staking.SetValidator(ctx, newVal)
err = app.Keepers.Cosmos.Staking.SetValidatorByConsAddr(ctx, newVal)
if err != nil {
return nil
panic(err)
}

app.Keepers.Cosmos.Staking.SetValidatorByPowerIndex(ctx, newVal)
Expand Down Expand Up @@ -189,9 +209,24 @@ func InitAkashAppForTestnet(
Tombstoned: false,
}

_, _ = app.Keepers.Cosmos.Staking.ApplyAndReturnValidatorSetUpdates(ctx)
_, err = app.Keepers.Cosmos.Staking.ApplyAndReturnValidatorSetUpdates(ctx)
if err != nil {
panic(err)
}

app.Keepers.Cosmos.Slashing.SetValidatorSigningInfo(ctx, newConsAddr, newValidatorSigningInfo)

for _, del := range val.Delegations {
vl, found := app.Keepers.Cosmos.Staking.GetValidator(ctx, valAddr)
if !found {
panic("validator not found")
}

_, err = app.Keepers.Cosmos.Staking.Delegate(ctx, del.Address, del.Amount.Amount, stakingtypes.Unbonded, vl, true)
if err != nil {
panic(err)
}
}
}

//
Expand All @@ -205,25 +240,6 @@ func InitAkashAppForTestnet(
voteParams.VotingPeriod = tcfg.Gov.VotingParams.VotingPeriod.Duration
app.Keepers.Cosmos.Gov.SetVotingParams(ctx, voteParams)

// BANK
//

defaultCoins := sdk.NewCoins(
sdk.NewInt64Coin("uakt", 1000000000000),
sdk.NewInt64Coin("ibc/12C6A0C374171B595A0A9E18B83FA09D295FB1F2D8C6DAA3AC28683471752D84", 1000000000000), // axlUSDC
)

for _, account := range tcfg.Accounts {
err := app.Keepers.Cosmos.Bank.MintCoins(ctx, minttypes.ModuleName, defaultCoins)
if err != nil {
return nil
}
err = app.Keepers.Cosmos.Bank.SendCoinsFromModuleToAccount(ctx, minttypes.ModuleName, account, defaultCoins)
if err != nil {
return nil
}
}

// UPGRADE
//
if tcfg.Upgrade.Name != "" {
Expand Down
15 changes: 8 additions & 7 deletions cmd/akash/cmd/testnetify/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,13 @@ type ConsAddress struct {
}

type TestnetValidator struct {
Moniker string `json:"moniker"`
Operator AccAddress `json:"operator"`
Bonded bool `json:"bonded"`
Commission stakingtypes.Commission `json:"commission"`
MinSelfDelegation sdk.Int `json:"min_self_delegation"`
Home string `json:"home"`
Moniker string `json:"moniker"`
Operator AccAddress `json:"operator"`
Status stakingtypes.BondStatus `json:"status"`
Commission stakingtypes.Commission `json:"commission"`
MinSelfDelegation sdk.Int `json:"min_self_delegation"`
Home string `json:"home"`
Delegations []akash.TestnetDelegation `json:"delegations"`

privValidator *pvm.FilePV
pubKey crypto.PubKey
Expand All @@ -59,7 +60,7 @@ type TestnetValidators []TestnetValidator
type TestnetConfig struct {
ChainID string `json:"chain_id"`
Validators TestnetValidators `json:"validators"`
Accounts []sdk.AccAddress `json:"accounts"`
Accounts []akash.TestnetAccount `json:"accounts"`
Gov akash.TestnetGovConfig `json:"gov"`
Comment on lines +63 to 64
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Bech32 JSON parsing gap for Accounts/Delegations (sdk.AccAddress).

cfg.Accounts uses app.TestnetAccount, which has sdk.AccAddress. Without a custom UnmarshalJSON, JSON expects base64, not bech32. Same for Delegations’ Address field. This will confuse users and likely break config loading.

Two viable fixes (pick one):

  • Implement UnmarshalJSON on app.TestnetAccount and app.TestnetDelegation to parse bech32 addresses, or
  • Keep local testnetify JSON types that use your AccAddress/ValAddress wrappers, then convert to app types before building appConfig.

I can draft the UnmarshalJSON implementations in app/testnet.go if you prefer. Would you like that?

🤖 Prompt for AI Agents
In cmd/akash/cmd/testnetify/config.go around lines 63-64, cfg.Accounts and
related Delegations use app.TestnetAccount/TestnetDelegation which contain
sdk.AccAddress/sdk.ValAddress that JSON unmarshals as base64 by default; update
to support bech32 by either (A) adding UnmarshalJSON methods on
app.TestnetAccount and app.TestnetDelegation to accept bech32 strings and decode
them into AccAddress/ValAddress during JSON unmarshal, or (B) create local
testnetify JSON DTOs that use lightweight bech32 string wrappers (or
AccAddress/ValAddress wrapper types with custom UnmarshalJSON) to parse bech32,
then convert those DTOs into the app types before building appConfig — implement
one approach consistently for both Accounts and Delegations and add tests for
bech32 parsing and error cases.

upgrade akash.TestnetUpgrade
}
Expand Down
27 changes: 24 additions & 3 deletions cmd/akash/cmd/testnetify/testnetify.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package testnetify

import (
"bufio"
"encoding/hex"
"encoding/json"
"fmt"
"io"
Expand All @@ -13,6 +14,7 @@ import (

"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/spf13/cobra"
"github.com/tendermint/tendermint/crypto/tmhash"

Expand All @@ -29,6 +31,7 @@ import (
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
sdksrv "github.com/cosmos/cosmos-sdk/server"
"github.com/cosmos/cosmos-sdk/server/types"
sdktypes "github.com/cosmos/cosmos-sdk/types"

akash "github.com/akash-network/node/app"
)
Expand Down Expand Up @@ -114,6 +117,17 @@ you want to test the upgrade handler itself.
return err
}

for i, acc := range cfg.Accounts {
if len(acc.Balances) > 0 {
cfg.Accounts[i].Balances = sdk.NewCoins(acc.Balances...)
} else {
cfg.Accounts[i].Balances = sdk.NewCoins(
sdk.NewInt64Coin("uakt", 10000000000000),
sdk.NewInt64Coin("ibc/12C6A0C374171B595A0A9E18B83FA09D295FB1F2D8C6DAA3AC28683471752D84", 1000000000000), // axlUSDC
)
}
}

sctx.Logger.Info(fmt.Sprintf("loaded config from %s", cfgFilePath))

if name, _ := cmd.Flags().GetString(KeyTestnetTriggerUpgrade); name != "" {
Expand Down Expand Up @@ -296,7 +310,7 @@ func testnetify(sctx *sdksrv.Context, tcfg TestnetConfig, testnetAppCreator type
return nil, node.ErrSaveGenesisDocHash{Err: err}
}

state, stateStore, _, err := node.LoadStateFromDBOrGenesisDocProvider(stateDB, genDocProvider, "")
state, stateStore, _, err := node.LoadStateFromDBOrGenesisDocProvider(stateDB, genDocProvider, hex.EncodeToString(updatedChecksum))
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -346,6 +360,8 @@ func testnetify(sctx *sdksrv.Context, tcfg TestnetConfig, testnetAppCreator type
Moniker: val.Moniker,
Commission: val.Commission,
MinSelfDelegation: val.MinSelfDelegation,
Status: val.Status,
Delegations: val.Delegations,
})

tcfg.Validators[i].privValidator = privValidator
Expand Down Expand Up @@ -447,15 +463,20 @@ func testnetify(sctx *sdksrv.Context, tcfg TestnetConfig, testnetAppCreator type
Signature: voteProto.Signature,
})

var vp int64

for _, del := range val.Delegations {
vp += del.Amount.Amount.Quo(sdktypes.DefaultPowerReduction).Int64()
}
newValidators = append(newValidators, &cmttypes.Validator{
Address: val.validatorAddress,
PubKey: val.pubKey,
VotingPower: 900000000000000,
VotingPower: vp,
})
}

// Replace all valSets in state to be the valSet with just our validator.
// and set the very first validator as proposer
// and set the very first validator as a proposer
newValSet := &cmttypes.ValidatorSet{
Validators: newValidators,
Proposer: newValidators[0],
Expand Down
Loading