-
Notifications
You must be signed in to change notification settings - Fork 117
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add chain-initiator tool to use mainnet snapshot in localnet
- Loading branch information
Showing
16 changed files
with
795 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
package main | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
) | ||
|
||
func (a *Account) UnmarshalJSON(data []byte) error { | ||
var raw map[string]interface{} | ||
if err := json.Unmarshal(data, &raw); err != nil { | ||
return err | ||
} | ||
|
||
// Set the Type field from the raw data | ||
typeStr, ok := raw["@type"].(string) | ||
if !ok { | ||
return fmt.Errorf("type field is missing or invalid") | ||
} | ||
a.Type = typeStr | ||
|
||
switch a.Type { | ||
case "/cosmos.auth.v1beta1.BaseAccount": | ||
var ba BaseAccount | ||
if err := json.Unmarshal(data, &ba); err != nil { | ||
return err | ||
} | ||
a.BaseAccount = &ba | ||
case "/cosmos.auth.v1beta1.ModuleAccount": | ||
var ma ModuleAccount | ||
if err := json.Unmarshal(data, &ma); err != nil { | ||
return err | ||
} | ||
a.ModuleAccount = &ma | ||
default: | ||
return fmt.Errorf("unknown account type: %s", a.Type) | ||
} | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package main | ||
|
||
import ( | ||
"log" | ||
"os/exec" | ||
) | ||
|
||
func addGenesisAccount(cmdPath, address, balance, homePath string) { | ||
// Command and arguments | ||
args := []string{"add-genesis-account", address, balance + "rowan", "--home", homePath} | ||
|
||
// Execute the command | ||
if err := exec.Command(cmdPath, args...).Run(); err != nil { | ||
log.Fatalf("Command execution failed: %v", err) | ||
} | ||
|
||
// If execution reaches here, the command was successful | ||
log.Printf("add genesis account with address %s, balance: %s and home path %s successfully", address, balance, homePath) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package main | ||
|
||
import ( | ||
"encoding/json" | ||
"log" | ||
"os/exec" | ||
) | ||
|
||
func addKey(cmdPath, name, homePath, keyringBackend string) string { | ||
// Command and arguments | ||
args := []string{"keys", "add", name, "--home", homePath, "--keyring-backend", keyringBackend, "--output", "json"} | ||
|
||
// Execute the command | ||
output, err := exec.Command(cmdPath, args...).CombinedOutput() | ||
if err != nil { | ||
log.Fatalf("Command execution failed: %v", err) | ||
} | ||
|
||
// Unmarshal the JSON output | ||
var keyOutput KeyOutput | ||
if err := json.Unmarshal(output, &keyOutput); err != nil { | ||
log.Fatalf("Failed to unmarshal JSON output: %v", err) | ||
} | ||
|
||
// Log the address | ||
log.Printf("add key with name %s, home path: %s, keyring backend %s and address %s successfully", name, homePath, keyringBackend, keyOutput.Address) | ||
|
||
return keyOutput.Address | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package main | ||
|
||
import ( | ||
"log" | ||
"os/exec" | ||
) | ||
|
||
func collectGentxs(cmdPath, homePath string) { | ||
// Command and arguments | ||
args := []string{"collect-gentxs", "--home", homePath} | ||
|
||
// Execute the command | ||
if err := exec.Command(cmdPath, args...).Run(); err != nil { | ||
log.Fatalf("Command execution failed: %v", err) | ||
} | ||
|
||
// If execution reaches here, the command was successful | ||
log.Printf("collect gen txs with home path %s successfully", homePath) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package main | ||
|
||
func filterAccounts(accounts []Account, filterAddresses []string) []Account { | ||
filterMap := make(map[string]struct{}) | ||
for _, addr := range filterAddresses { | ||
filterMap[addr] = struct{}{} | ||
} | ||
|
||
var newAccounts []Account | ||
for _, account := range accounts { | ||
if shouldFilterAccount(account, filterMap) { | ||
continue | ||
} | ||
newAccounts = append(newAccounts, account) | ||
} | ||
return newAccounts | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package main | ||
|
||
import ( | ||
sdk "github.com/cosmos/cosmos-sdk/types" | ||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" | ||
) | ||
|
||
func filterBalances(balances []banktypes.Balance, filterAddresses []string) ([]banktypes.Balance, sdk.Coins) { | ||
filterMap := make(map[string]struct{}) | ||
for _, addr := range filterAddresses { | ||
filterMap[addr] = struct{}{} | ||
} | ||
|
||
var newBalances []banktypes.Balance | ||
var coinsToRemove sdk.Coins | ||
for _, balance := range balances { | ||
if _, exists := filterMap[balance.Address]; exists { | ||
coinsToRemove = coinsToRemove.Add(balance.Coins...) | ||
continue | ||
} | ||
newBalances = append(newBalances, balance) | ||
} | ||
return newBalances, coinsToRemove | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package main | ||
|
||
import ( | ||
"log" | ||
"os/exec" | ||
) | ||
|
||
func genTx(cmdPath, name, balance, chainId, homePath, keyringBackend string) { | ||
// Command and arguments | ||
args := []string{"gentx", name, balance + "rowan", "--chain-id", chainId, "--home", homePath, "--keyring-backend", keyringBackend} | ||
|
||
// Execute the command | ||
if err := exec.Command(cmdPath, args...).Run(); err != nil { | ||
log.Fatalf("Command execution failed: %v", err) | ||
} | ||
|
||
// If execution reaches here, the command was successful | ||
log.Printf("gen tx with name %s, balance: %s, chain id %s, home path %s and keyring backend %s successfully", name, balance, chainId, homePath, keyringBackend) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package main | ||
|
||
import ( | ||
"log" | ||
"os/exec" | ||
) | ||
|
||
func initChain(cmdPath, moniker, chainId, homePath string) { | ||
// Command and arguments | ||
args := []string{"init", moniker, "--chain-id", chainId, "--home", homePath} | ||
|
||
// Execute the command | ||
if err := exec.Command(cmdPath, args...).Run(); err != nil { | ||
log.Fatalf("Command execution failed: %v", err) | ||
} | ||
|
||
// If execution reaches here, the command was successful | ||
log.Printf("init chain with moniker %s, chain id %s and home path: %s successfully", moniker, chainId, homePath) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
package main | ||
|
||
import ( | ||
"log" | ||
|
||
app "github.com/Sifchain/sifnode/app" | ||
sdk "github.com/cosmos/cosmos-sdk/types" | ||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
const ( | ||
moniker = "node" | ||
chainId = "sifchain-1" | ||
keyringBackend = "test" | ||
validatorKeyName = "validator" | ||
validatorBalance = "4000000000000000000000000000" | ||
) | ||
|
||
func main() { | ||
var rootCmd = &cobra.Command{ | ||
Use: "initiator [cmd_path] [home_path] [genesis_file_path]", | ||
Short: "Chain Initiator is a tool for modifying genesis files", | ||
Long: `A tool for performing various operations on genesis files of a blockchain setup.`, | ||
Args: cobra.ExactArgs(3), // Expect exactly two arguments | ||
Run: func(cmd *cobra.Command, args []string) { | ||
cmdPath := args[0] // sifnoded | ||
homePath := args[1] // /tmp/node | ||
genesisFilePath := args[2] // /tmp/genesis.json | ||
|
||
// set address prefix | ||
app.SetConfig(false) | ||
|
||
// remove home path | ||
removeHome(homePath) | ||
|
||
// init chain | ||
initChain(cmdPath, moniker, chainId, homePath) | ||
|
||
// add validator key | ||
validatorAddress := addKey(cmdPath, validatorKeyName, homePath, keyringBackend) | ||
|
||
// add genesis account | ||
addGenesisAccount(cmdPath, validatorAddress, validatorBalance, homePath) | ||
|
||
// generate genesis tx | ||
genTx(cmdPath, validatorKeyName, validatorBalance, chainId, homePath, keyringBackend) | ||
|
||
// collect genesis txs | ||
collectGentxs(cmdPath, homePath) | ||
|
||
// validate genesis | ||
validateGenesis(cmdPath, homePath) | ||
|
||
genesis, err := readGenesisFile(genesisFilePath) | ||
if err != nil { | ||
log.Fatalf("Error reading genesis file: %v", err) | ||
} | ||
|
||
genesisInitFilePath := homePath + "/config/genesis.json" | ||
genesisInit, err := readGenesisFile(genesisInitFilePath) | ||
if err != nil { | ||
log.Fatalf("Error reading initial genesis file: %v", err) | ||
} | ||
|
||
filterAccountAddresses := []string{ | ||
"sif1harggtyrlukcfrtmpgjzptsnaedcdh38qqknp2", // multisig account with missing pubkeys | ||
} | ||
filterBalanceAddresses := []string{ | ||
"sif1harggtyrlukcfrtmpgjzptsnaedcdh38qqknp2", | ||
authtypes.NewModuleAddress("distribution").String(), | ||
authtypes.NewModuleAddress("bonded_tokens_pool").String(), | ||
authtypes.NewModuleAddress("not_bonded_tokens_pool").String(), | ||
} | ||
|
||
var coinsToRemove sdk.Coins | ||
|
||
genesis.AppState.Auth.Accounts = filterAccounts(genesis.AppState.Auth.Accounts, filterAccountAddresses) | ||
genesis.AppState.Bank.Balances, coinsToRemove = filterBalances(genesis.AppState.Bank.Balances, filterBalanceAddresses) | ||
|
||
newValidatorBalance, ok := sdk.NewIntFromString("4000000000000000000000000000") | ||
if !ok { | ||
panic("invalid number") | ||
} | ||
newValidatorBalanceCoin := sdk.NewCoin("rowan", newValidatorBalance) | ||
|
||
// update supply | ||
genesis.AppState.Bank.Supply = genesis.AppState.Bank.Supply.Sub(coinsToRemove).Add(newValidatorBalanceCoin) | ||
|
||
// Add new validator account and balance | ||
genesis.AppState.Auth.Accounts = append(genesis.AppState.Auth.Accounts, genesisInit.AppState.Auth.Accounts[0]) | ||
genesis.AppState.Bank.Balances = append(genesis.AppState.Bank.Balances, genesisInit.AppState.Bank.Balances[0]) | ||
|
||
// reset staking data | ||
stakingParams := genesis.AppState.Staking.Params | ||
genesis.AppState.Staking = genesisInit.AppState.Staking | ||
genesis.AppState.Staking.Params = stakingParams | ||
|
||
// reset slashing data | ||
genesis.AppState.Slashing = genesisInit.AppState.Slashing | ||
|
||
// reset distribution data | ||
genesis.AppState.Distribution = genesisInit.AppState.Distribution | ||
|
||
// set genutil from genesisInit | ||
genesis.AppState.Genutil = genesisInit.AppState.Genutil | ||
|
||
outputFilePath := homePath + "/config/genesis.json" | ||
if err := writeGenesisFile(outputFilePath, genesis); err != nil { | ||
log.Fatalf("Error writing genesis file: %v", err) | ||
} | ||
|
||
// start chain | ||
start(cmdPath, homePath) | ||
}, | ||
} | ||
|
||
if err := rootCmd.Execute(); err != nil { | ||
log.Fatalf("Error executing command: %v", err) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package main | ||
|
||
import ( | ||
"bufio" | ||
"encoding/json" | ||
"fmt" | ||
"os" | ||
) | ||
|
||
func readGenesisFile(filePath string) (Genesis, error) { | ||
var genesis Genesis | ||
file, err := os.Open(filePath) | ||
if err != nil { | ||
return genesis, fmt.Errorf("error opening file: %w", err) | ||
} | ||
defer file.Close() | ||
|
||
if err := json.NewDecoder(bufio.NewReader(file)).Decode(&genesis); err != nil { | ||
return genesis, fmt.Errorf("error decoding JSON: %w", err) | ||
} | ||
|
||
return genesis, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package main | ||
|
||
import ( | ||
"log" | ||
"os/exec" | ||
) | ||
|
||
func removeHome(homePath string) { | ||
// Command and arguments | ||
args := []string{"-rf", homePath} | ||
|
||
// Execute the command | ||
if err := exec.Command("rm", args...).Run(); err != nil { | ||
log.Fatalf("Command execution failed: %v", err) | ||
} | ||
|
||
// If execution reaches here, the command was successful | ||
log.Printf("removed home path %s successfully", homePath) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package main | ||
|
||
func shouldFilterAccount(account Account, filterAddresses map[string]struct{}) bool { | ||
if account.BaseAccount != nil { | ||
if _, exists := filterAddresses[account.BaseAccount.Address]; exists { | ||
return true | ||
} | ||
} | ||
if account.ModuleAccount != nil { | ||
if _, exists := filterAddresses[account.ModuleAccount.BaseAccount.Address]; exists { | ||
return true | ||
} | ||
} | ||
return false | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package main | ||
|
||
import ( | ||
"log" | ||
"os" | ||
"os/exec" | ||
) | ||
|
||
func start(cmdPath, homePath string) { | ||
// Command and arguments | ||
args := []string{"start", "--home", homePath} | ||
|
||
// Set up the command | ||
cmd := exec.Command(cmdPath, args...) | ||
|
||
// Attach command's stdout and stderr to os.Stdout and os.Stderr | ||
cmd.Stdout = os.Stdout | ||
cmd.Stderr = os.Stderr | ||
|
||
// Execute the command and stream the output | ||
if err := cmd.Run(); err != nil { | ||
log.Fatalf("Command execution failed: %v", err) | ||
} | ||
} |
Oops, something went wrong.