Merge pull request #230 from CosmWasm/remove-wasmgovd-binary
Remove wasmgovd binary
This commit is contained in:
@@ -40,7 +40,6 @@ RUN LEDGER_ENABLED=false BUILD_TAGS=muslc make build-gaiaflex
|
||||
FROM alpine:3.12
|
||||
|
||||
COPY --from=go-builder /code/build/wasmd /usr/bin/wasmd
|
||||
COPY --from=go-builder /code/build/wasmgovd /usr/bin/wasmgovd
|
||||
COPY --from=go-builder /code/build/wasmcli /usr/bin/wasmcli
|
||||
|
||||
# testnet
|
||||
|
||||
1
Makefile
1
Makefile
@@ -101,7 +101,6 @@ ifeq ($(OS),Windows_NT)
|
||||
go build -mod=readonly $(BUILD_FLAGS) -o build/wasmcli.exe ./cmd/wasmcli
|
||||
else
|
||||
go build -mod=readonly $(BUILD_FLAGS) -o build/wasmd ./cmd/wasmd
|
||||
go build -mod=readonly $(BUILD_FLAGS) -o build/wasmgovd ./cmd/wasmgovd
|
||||
go build -mod=readonly $(BUILD_FLAGS) -o build/wasmcli ./cmd/wasmcli
|
||||
endif
|
||||
|
||||
|
||||
31
README.md
31
README.md
@@ -129,6 +129,37 @@ docker run --rm -it \
|
||||
cosmwasm/wasmd:latest ./logs.sh
|
||||
```
|
||||
|
||||
## Runtime flags
|
||||
|
||||
We provide a number of variables in `app/app.go` that are intended to be set via `-ldflags -X ...`
|
||||
compile-time flags. This enables us to avoid copying a new binary directory over for each small change
|
||||
to the configuration.
|
||||
|
||||
Available flags:
|
||||
|
||||
* `-X github.com/CosmWasm/wasmd/app.CLIDir=.coral` - set the config directory for the cli (default `~/.wasmcli`)
|
||||
* `-X github.com/CosmWasm/wasmd/app.NodeDir=.corald` - set the config/data directory for the node (default `~/.wasmd`)
|
||||
* `-X github.com/CosmWasm/wasmd/app.Bech32Prefix=coral` - set the bech32 prefix for all accounts (default `cosmos`)
|
||||
* `-X github.com/CosmWasm/wasmd/app.ProposalsEnabled=true` - enable all x/wasm governance proposals (default `false`)
|
||||
* `-X github.com/CosmWasm/wasmd/app.EnableSpecificProposals=MigrateContract,UpdateAdmin,ClearAdmin` -
|
||||
enable a subset of the x/wasm governance proposal types (overrides `ProposalsEnabled`)
|
||||
|
||||
Examples:
|
||||
|
||||
* [`wasmd`](./Makefile#L50-L55) is a generic, permissionless version using the `cosmos` bech32 prefix
|
||||
* [`gaiaflex`](./Makefile#L78-L87) is a generic, *permissioned* version using the `cosmos` bech32 prefix
|
||||
* [`coral`](./Makefile#L63-L71) is a permissionless version designed for a specific testnet, with a `coral` bech32 prefix
|
||||
|
||||
## Genesis Configuration
|
||||
|
||||
@alpe we should document all the genesis config for x/wasm even more.
|
||||
|
||||
Tip: if you want to lock this down to a permisisoned network, the following script can edit the genesis file
|
||||
to only allow permissioned use of code upload or instantiating. (Make sure you set `app.ProposalsEnabled=true`
|
||||
in this binary):
|
||||
|
||||
`sed -i 's/permission": "Everybody"/permission": "Nobody"/' .../config/genesis.json`
|
||||
|
||||
## Contributors
|
||||
|
||||
Much thanks to all who have contributed to this project, from this app, to the `cosmwasm` framework, to example contracts and documentation.
|
||||
|
||||
@@ -1,153 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
|
||||
"github.com/tendermint/tendermint/libs/cli"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys"
|
||||
"github.com/cosmos/cosmos-sdk/server"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
authexported "github.com/cosmos/cosmos-sdk/x/auth/exported"
|
||||
authvesting "github.com/cosmos/cosmos-sdk/x/auth/vesting"
|
||||
"github.com/cosmos/cosmos-sdk/x/genutil"
|
||||
)
|
||||
|
||||
const (
|
||||
flagClientHome = "home-client"
|
||||
flagVestingStart = "vesting-start-time"
|
||||
flagVestingEnd = "vesting-end-time"
|
||||
flagVestingAmt = "vesting-amount"
|
||||
)
|
||||
|
||||
// AddGenesisAccountCmd returns add-genesis-account cobra Command.
|
||||
func AddGenesisAccountCmd(
|
||||
ctx *server.Context, cdc *codec.Codec, defaultNodeHome, defaultClientHome string,
|
||||
) *cobra.Command {
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "add-genesis-account [address_or_key_name] [coin][,[coin]]",
|
||||
Short: "Add a genesis account to genesis.json",
|
||||
Long: `Add a genesis account to genesis.json. The provided account must specify
|
||||
the account address or key name and a list of initial coins. If a key name is given,
|
||||
the address will be looked up in the local Keybase. The list of initial tokens must
|
||||
contain valid denominations. Accounts may optionally be supplied with vesting parameters.
|
||||
`,
|
||||
Args: cobra.ExactArgs(2),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
config := ctx.Config
|
||||
config.SetRoot(viper.GetString(cli.HomeFlag))
|
||||
|
||||
addr, err := sdk.AccAddressFromBech32(args[0])
|
||||
inBuf := bufio.NewReader(cmd.InOrStdin())
|
||||
if err != nil {
|
||||
// attempt to lookup address from Keybase if no address was provided
|
||||
kb, err := keys.NewKeyring(
|
||||
sdk.KeyringServiceName(),
|
||||
viper.GetString(flags.FlagKeyringBackend),
|
||||
viper.GetString(flagClientHome),
|
||||
inBuf,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
info, err := kb.Get(args[0])
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get address from Keybase: %w", err)
|
||||
}
|
||||
|
||||
addr = info.GetAddress()
|
||||
}
|
||||
|
||||
coins, err := sdk.ParseCoins(args[1])
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse coins: %w", err)
|
||||
}
|
||||
|
||||
vestingStart := viper.GetInt64(flagVestingStart)
|
||||
vestingEnd := viper.GetInt64(flagVestingEnd)
|
||||
vestingAmt, err := sdk.ParseCoins(viper.GetString(flagVestingAmt))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse vesting amount: %w", err)
|
||||
}
|
||||
|
||||
// create concrete account type based on input parameters
|
||||
var genAccount authexported.GenesisAccount
|
||||
|
||||
baseAccount := auth.NewBaseAccount(addr, coins.Sort(), nil, 0, 0)
|
||||
if !vestingAmt.IsZero() {
|
||||
baseVestingAccount, err := authvesting.NewBaseVestingAccount(baseAccount, vestingAmt.Sort(), vestingEnd)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create base vesting account: %w", err)
|
||||
}
|
||||
|
||||
switch {
|
||||
case vestingStart != 0 && vestingEnd != 0:
|
||||
genAccount = authvesting.NewContinuousVestingAccountRaw(baseVestingAccount, vestingStart)
|
||||
|
||||
case vestingEnd != 0:
|
||||
genAccount = authvesting.NewDelayedVestingAccountRaw(baseVestingAccount)
|
||||
|
||||
default:
|
||||
return errors.New("invalid vesting parameters; must supply start and end time or end time")
|
||||
}
|
||||
} else {
|
||||
genAccount = baseAccount
|
||||
}
|
||||
|
||||
if err := genAccount.Validate(); err != nil {
|
||||
return fmt.Errorf("failed to validate new genesis account: %w", err)
|
||||
}
|
||||
|
||||
genFile := config.GenesisFile()
|
||||
appState, genDoc, err := genutil.GenesisStateFromGenFile(cdc, genFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to unmarshal genesis state: %w", err)
|
||||
}
|
||||
|
||||
authGenState := auth.GetGenesisStateFromAppState(cdc, appState)
|
||||
|
||||
if authGenState.Accounts.Contains(addr) {
|
||||
return fmt.Errorf("cannot add account at existing address %s", addr)
|
||||
}
|
||||
|
||||
// Add the new account to the set of genesis accounts and sanitize the
|
||||
// accounts afterwards.
|
||||
authGenState.Accounts = append(authGenState.Accounts, genAccount)
|
||||
authGenState.Accounts = auth.SanitizeGenesisAccounts(authGenState.Accounts)
|
||||
|
||||
authGenStateBz, err := cdc.MarshalJSON(authGenState)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshal auth genesis state: %w", err)
|
||||
}
|
||||
|
||||
appState[auth.ModuleName] = authGenStateBz
|
||||
|
||||
appStateJSON, err := cdc.MarshalJSON(appState)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshal application genesis state: %w", err)
|
||||
}
|
||||
|
||||
genDoc.AppState = appStateJSON
|
||||
return genutil.ExportGenesisFile(genDoc, genFile)
|
||||
},
|
||||
}
|
||||
|
||||
cmd.Flags().String(cli.HomeFlag, defaultNodeHome, "node's home directory")
|
||||
cmd.Flags().String(flags.FlagKeyringBackend, flags.DefaultKeyringBackend, "Select keyring's backend (os|file|test)")
|
||||
cmd.Flags().String(flagClientHome, defaultClientHome, "client's home directory")
|
||||
cmd.Flags().String(flagVestingAmt, "", "amount of coins for vesting accounts")
|
||||
cmd.Flags().Uint64(flagVestingStart, 0, "schedule start time (unix epoch) for vesting accounts")
|
||||
cmd.Flags().Uint64(flagVestingEnd, 0, "schedule end time (unix epoch) for vesting accounts")
|
||||
|
||||
return cmd
|
||||
}
|
||||
@@ -1,117 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/CosmWasm/wasmd/app"
|
||||
"github.com/CosmWasm/wasmd/x/wasm"
|
||||
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||
"github.com/cosmos/cosmos-sdk/client/debug"
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/server"
|
||||
"github.com/cosmos/cosmos-sdk/store"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
genutilcli "github.com/cosmos/cosmos-sdk/x/genutil/client/cli"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
"github.com/tendermint/tendermint/libs/cli"
|
||||
"github.com/tendermint/tendermint/libs/log"
|
||||
tmtypes "github.com/tendermint/tendermint/types"
|
||||
dbm "github.com/tendermint/tm-db"
|
||||
)
|
||||
|
||||
const flagInvCheckPeriod = "inv-check-period"
|
||||
|
||||
var invCheckPeriod uint
|
||||
|
||||
func main() {
|
||||
cdc := app.MakeCodec()
|
||||
|
||||
config := sdk.GetConfig()
|
||||
config.SetBech32PrefixForAccount(sdk.Bech32PrefixAccAddr, sdk.Bech32PrefixAccPub)
|
||||
config.SetBech32PrefixForValidator(sdk.Bech32PrefixValAddr, sdk.Bech32PrefixValPub)
|
||||
config.SetBech32PrefixForConsensusNode(sdk.Bech32PrefixConsAddr, sdk.Bech32PrefixConsPub)
|
||||
config.Seal()
|
||||
|
||||
homeDir := os.ExpandEnv("$HOME/.wasmgovd")
|
||||
|
||||
ctx := server.NewDefaultContext()
|
||||
cobra.EnableCommandSorting = false
|
||||
rootCmd := &cobra.Command{
|
||||
Use: "wasmgovd",
|
||||
Short: "Wasm Daemon (server) with wasm gov proposals enabled\",",
|
||||
PersistentPreRunE: server.PersistentPreRunEFn(ctx),
|
||||
}
|
||||
rootCmd.AddCommand(genutilcli.InitCmd(ctx, cdc, app.ModuleBasics, homeDir))
|
||||
rootCmd.AddCommand(genutilcli.CollectGenTxsCmd(ctx, cdc, auth.GenesisAccountIterator{}, homeDir))
|
||||
rootCmd.AddCommand(genutilcli.MigrateGenesisCmd(ctx, cdc))
|
||||
rootCmd.AddCommand(
|
||||
genutilcli.GenTxCmd(
|
||||
ctx, cdc, app.ModuleBasics, staking.AppModuleBasic{},
|
||||
auth.GenesisAccountIterator{}, homeDir, app.DefaultCLIHome,
|
||||
),
|
||||
)
|
||||
rootCmd.AddCommand(genutilcli.ValidateGenesisCmd(ctx, cdc, app.ModuleBasics))
|
||||
rootCmd.AddCommand(AddGenesisAccountCmd(ctx, cdc, homeDir, app.DefaultCLIHome))
|
||||
rootCmd.AddCommand(flags.NewCompletionCmd(rootCmd, true))
|
||||
// rootCmd.AddCommand(testnetCmd(ctx, cdc, app.ModuleBasics, auth.GenesisAccountIterator{}))
|
||||
rootCmd.AddCommand(replayCmd())
|
||||
rootCmd.AddCommand(debug.Cmd(cdc))
|
||||
|
||||
server.AddCommands(ctx, cdc, rootCmd, newApp, exportAppStateAndTMValidators)
|
||||
|
||||
// prepare and add flags
|
||||
executor := cli.PrepareBaseCmd(rootCmd, "WM", homeDir)
|
||||
rootCmd.PersistentFlags().UintVar(&invCheckPeriod, flagInvCheckPeriod,
|
||||
0, "Assert registered invariants every N blocks")
|
||||
err := executor.Execute()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func newApp(logger log.Logger, db dbm.DB, traceStore io.Writer) abci.Application {
|
||||
var cache sdk.MultiStorePersistentCache
|
||||
|
||||
if viper.GetBool(server.FlagInterBlockCache) {
|
||||
cache = store.NewCommitKVStoreCacheManager()
|
||||
}
|
||||
pruningOpts, err := server.GetPruningOptionsFromFlags()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
skipUpgradeHeights := make(map[int64]bool)
|
||||
for _, h := range viper.GetIntSlice(server.FlagUnsafeSkipUpgrades) {
|
||||
skipUpgradeHeights[int64(h)] = true
|
||||
}
|
||||
|
||||
return app.NewWasmApp(logger, db, traceStore, true, invCheckPeriod,
|
||||
wasm.EnableAllProposals, skipUpgradeHeights,
|
||||
baseapp.SetPruning(pruningOpts),
|
||||
baseapp.SetMinGasPrices(viper.GetString(server.FlagMinGasPrices)),
|
||||
baseapp.SetHaltHeight(viper.GetUint64(server.FlagHaltHeight)),
|
||||
baseapp.SetHaltTime(viper.GetUint64(server.FlagHaltTime)),
|
||||
baseapp.SetInterBlockCache(cache))
|
||||
}
|
||||
|
||||
func exportAppStateAndTMValidators(
|
||||
logger log.Logger, db dbm.DB, traceStore io.Writer, height int64, forZeroHeight bool, jailWhiteList []string,
|
||||
) (json.RawMessage, []tmtypes.GenesisValidator, error) {
|
||||
|
||||
if height != -1 {
|
||||
gapp := app.NewWasmApp(logger, db, traceStore, false, uint(1), wasm.EnableAllProposals, nil)
|
||||
err := gapp.LoadHeight(height)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return gapp.ExportAppStateAndValidators(forZeroHeight, jailWhiteList)
|
||||
}
|
||||
|
||||
gapp := app.NewWasmApp(logger, db, traceStore, true, uint(1), wasm.EnableAllProposals, nil)
|
||||
return gapp.ExportAppStateAndValidators(forZeroHeight, jailWhiteList)
|
||||
}
|
||||
@@ -1,191 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/CosmWasm/wasmd/app"
|
||||
"github.com/CosmWasm/wasmd/x/wasm"
|
||||
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||
"github.com/cosmos/cosmos-sdk/server"
|
||||
storetypes "github.com/cosmos/cosmos-sdk/store/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
cpm "github.com/otiai10/copy"
|
||||
"github.com/spf13/cobra"
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
tmos "github.com/tendermint/tendermint/libs/os"
|
||||
"github.com/tendermint/tendermint/proxy"
|
||||
tmsm "github.com/tendermint/tendermint/state"
|
||||
tmstore "github.com/tendermint/tendermint/store"
|
||||
tm "github.com/tendermint/tendermint/types"
|
||||
)
|
||||
|
||||
func replayCmd() *cobra.Command {
|
||||
return &cobra.Command{
|
||||
Use: "replay <root-dir>",
|
||||
Short: "Replay gaia transactions",
|
||||
RunE: func(_ *cobra.Command, args []string) error {
|
||||
return replayTxs(args[0])
|
||||
},
|
||||
Args: cobra.ExactArgs(1),
|
||||
}
|
||||
}
|
||||
|
||||
func replayTxs(rootDir string) error {
|
||||
|
||||
if false {
|
||||
// Copy the rootDir to a new directory, to preserve the old one.
|
||||
fmt.Fprintln(os.Stderr, "Copying rootdir over")
|
||||
oldRootDir := rootDir
|
||||
rootDir = oldRootDir + "_replay"
|
||||
if tmos.FileExists(rootDir) {
|
||||
tmos.Exit(fmt.Sprintf("temporary copy dir %v already exists", rootDir))
|
||||
}
|
||||
if err := cpm.Copy(oldRootDir, rootDir); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
configDir := filepath.Join(rootDir, "config")
|
||||
dataDir := filepath.Join(rootDir, "data")
|
||||
ctx := server.NewDefaultContext()
|
||||
|
||||
// App DB
|
||||
// appDB := dbm.NewMemDB()
|
||||
fmt.Fprintln(os.Stderr, "Opening app database")
|
||||
appDB, err := sdk.NewLevelDB("application", dataDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// TM DB
|
||||
// tmDB := dbm.NewMemDB()
|
||||
fmt.Fprintln(os.Stderr, "Opening tendermint state database")
|
||||
tmDB, err := sdk.NewLevelDB("state", dataDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Blockchain DB
|
||||
fmt.Fprintln(os.Stderr, "Opening blockstore database")
|
||||
bcDB, err := sdk.NewLevelDB("blockstore", dataDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// TraceStore
|
||||
var traceStoreWriter io.Writer
|
||||
var traceStoreDir = filepath.Join(dataDir, "trace.log")
|
||||
traceStoreWriter, err = os.OpenFile(
|
||||
traceStoreDir,
|
||||
os.O_WRONLY|os.O_APPEND|os.O_CREATE,
|
||||
0666,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Application
|
||||
fmt.Fprintln(os.Stderr, "Creating application")
|
||||
gapp := app.NewWasmApp(
|
||||
// TODO: do we want to set skipUpgradeHieghts here?
|
||||
ctx.Logger, appDB, traceStoreWriter, true, uint(1), wasm.EnableAllProposals, nil,
|
||||
baseapp.SetPruning(storetypes.PruneEverything))
|
||||
|
||||
// Genesis
|
||||
var genDocPath = filepath.Join(configDir, "genesis.json")
|
||||
genDoc, err := tm.GenesisDocFromFile(genDocPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
genState, err := tmsm.MakeGenesisState(genDoc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// tmsm.SaveState(tmDB, genState)
|
||||
|
||||
cc := proxy.NewLocalClientCreator(gapp)
|
||||
proxyApp := proxy.NewAppConns(cc)
|
||||
err = proxyApp.Start()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
err = proxyApp.Stop()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}()
|
||||
|
||||
state := tmsm.LoadState(tmDB)
|
||||
if state.LastBlockHeight == 0 {
|
||||
// Send InitChain msg
|
||||
fmt.Fprintln(os.Stderr, "Sending InitChain msg")
|
||||
validators := tm.TM2PB.ValidatorUpdates(genState.Validators)
|
||||
csParams := tm.TM2PB.ConsensusParams(genDoc.ConsensusParams)
|
||||
req := abci.RequestInitChain{
|
||||
Time: genDoc.GenesisTime,
|
||||
ChainId: genDoc.ChainID,
|
||||
ConsensusParams: csParams,
|
||||
Validators: validators,
|
||||
AppStateBytes: genDoc.AppState,
|
||||
}
|
||||
res, err := proxyApp.Consensus().InitChainSync(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
newValidatorz, err := tm.PB2TM.ValidatorUpdates(res.Validators)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
newValidators := tm.NewValidatorSet(newValidatorz)
|
||||
|
||||
// Take the genesis state.
|
||||
state = genState
|
||||
state.Validators = newValidators
|
||||
state.NextValidators = newValidators
|
||||
}
|
||||
|
||||
// Create executor
|
||||
fmt.Fprintln(os.Stderr, "Creating block executor")
|
||||
blockExec := tmsm.NewBlockExecutor(tmDB, ctx.Logger, proxyApp.Consensus(), nil, tmsm.MockEvidencePool{})
|
||||
|
||||
// Create block store
|
||||
fmt.Fprintln(os.Stderr, "Creating block store")
|
||||
blockStore := tmstore.NewBlockStore(bcDB)
|
||||
|
||||
tz := []time.Duration{0, 0, 0}
|
||||
for i := int(state.LastBlockHeight) + 1; ; i++ {
|
||||
fmt.Fprintln(os.Stderr, "Running block ", i)
|
||||
t1 := time.Now()
|
||||
|
||||
// Apply block
|
||||
fmt.Printf("loading and applying block %d\n", i)
|
||||
blockmeta := blockStore.LoadBlockMeta(int64(i))
|
||||
if blockmeta == nil {
|
||||
fmt.Printf("Couldn't find block meta %d... done?\n", i)
|
||||
return nil
|
||||
}
|
||||
block := blockStore.LoadBlock(int64(i))
|
||||
if block == nil {
|
||||
return fmt.Errorf("couldn't find block %d", i)
|
||||
}
|
||||
|
||||
t2 := time.Now()
|
||||
|
||||
state, _, err = blockExec.ApplyBlock(state, blockmeta.BlockID, block)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
t3 := time.Now()
|
||||
tz[0] += t2.Sub(t1)
|
||||
tz[1] += t3.Sub(t2)
|
||||
|
||||
fmt.Fprintf(os.Stderr, "new app hash: %X\n", state.AppHash)
|
||||
fmt.Fprintln(os.Stderr, tz)
|
||||
}
|
||||
}
|
||||
@@ -1,374 +0,0 @@
|
||||
package main
|
||||
|
||||
// DONTCOVER
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
tmconfig "github.com/tendermint/tendermint/config"
|
||||
"github.com/tendermint/tendermint/crypto"
|
||||
tmos "github.com/tendermint/tendermint/libs/os"
|
||||
tmrand "github.com/tendermint/tendermint/libs/rand"
|
||||
"github.com/tendermint/tendermint/types"
|
||||
tmtime "github.com/tendermint/tendermint/types/time"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
clientkeys "github.com/cosmos/cosmos-sdk/client/keys"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys"
|
||||
"github.com/cosmos/cosmos-sdk/server"
|
||||
srvconfig "github.com/cosmos/cosmos-sdk/server/config"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/types/module"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
authexported "github.com/cosmos/cosmos-sdk/x/auth/exported"
|
||||
"github.com/cosmos/cosmos-sdk/x/genutil"
|
||||
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking"
|
||||
)
|
||||
|
||||
var (
|
||||
flagNodeDirPrefix = "node-dir-prefix"
|
||||
flagNumValidators = "v"
|
||||
flagOutputDir = "output-dir"
|
||||
flagNodeDaemonHome = "node-daemon-home"
|
||||
flagNodeCLIHome = "node-cli-home"
|
||||
flagStartingIPAddress = "starting-ip-address"
|
||||
)
|
||||
|
||||
// get cmd to initialize all files for tendermint testnet and application
|
||||
func testnetCmd(ctx *server.Context, cdc *codec.Codec,
|
||||
mbm module.BasicManager, genAccIterator genutiltypes.GenesisAccountsIterator,
|
||||
) *cobra.Command {
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "testnet",
|
||||
Short: "Initialize files for a Wasmd testnet",
|
||||
Long: `testnet will create "v" number of directories and populate each with
|
||||
necessary files (private validator, genesis, config, etc.).
|
||||
|
||||
Note, strict routability for addresses is turned off in the config file.
|
||||
|
||||
Example:
|
||||
wasmd testnet --v 4 --output-dir ./output --starting-ip-address 192.168.10.2
|
||||
`,
|
||||
RunE: func(cmd *cobra.Command, _ []string) error {
|
||||
config := ctx.Config
|
||||
|
||||
outputDir := viper.GetString(flagOutputDir)
|
||||
chainID := viper.GetString(flags.FlagChainID)
|
||||
minGasPrices := viper.GetString(server.FlagMinGasPrices)
|
||||
nodeDirPrefix := viper.GetString(flagNodeDirPrefix)
|
||||
nodeDaemonHome := viper.GetString(flagNodeDaemonHome)
|
||||
nodeCLIHome := viper.GetString(flagNodeCLIHome)
|
||||
startingIPAddress := viper.GetString(flagStartingIPAddress)
|
||||
numValidators := viper.GetInt(flagNumValidators)
|
||||
|
||||
return InitTestnet(cmd, config, cdc, mbm, genAccIterator, outputDir, chainID,
|
||||
minGasPrices, nodeDirPrefix, nodeDaemonHome, nodeCLIHome, startingIPAddress, numValidators)
|
||||
},
|
||||
}
|
||||
|
||||
cmd.Flags().Int(flagNumValidators, 4,
|
||||
"Number of validators to initialize the testnet with")
|
||||
cmd.Flags().StringP(flagOutputDir, "o", "./mytestnet",
|
||||
"Directory to store initialization data for the testnet")
|
||||
cmd.Flags().String(flagNodeDirPrefix, "node",
|
||||
"Prefix the directory name for each node with (node results in node0, node1, ...)")
|
||||
cmd.Flags().String(flagNodeDaemonHome, "wasmd",
|
||||
"Home directory of the node's daemon configuration")
|
||||
cmd.Flags().String(flagNodeCLIHome, "wasmcli",
|
||||
"Home directory of the node's cli configuration")
|
||||
cmd.Flags().String(flagStartingIPAddress, "192.168.0.1",
|
||||
"Starting IP address (192.168.0.1 results in persistent peers list ID0@192.168.0.1:46656, ID1@192.168.0.2:46656, ...)")
|
||||
cmd.Flags().String(
|
||||
flags.FlagChainID, "", "genesis file chain-id, if left blank will be randomly created")
|
||||
cmd.Flags().String(
|
||||
server.FlagMinGasPrices, fmt.Sprintf("0.000006%s", sdk.DefaultBondDenom),
|
||||
"Minimum gas prices to accept for transactions; All fees in a tx must meet this minimum (e.g. 0.01photino,0.001stake)")
|
||||
cmd.Flags().String(flags.FlagKeyringBackend, flags.DefaultKeyringBackend, "Select keyring's backend (os|file|test)")
|
||||
return cmd
|
||||
}
|
||||
|
||||
const nodeDirPerm = 0755
|
||||
|
||||
// Initialize the testnet
|
||||
func InitTestnet(cmd *cobra.Command, config *tmconfig.Config, cdc *codec.Codec,
|
||||
mbm module.BasicManager, genAccIterator genutiltypes.GenesisAccountsIterator,
|
||||
outputDir, chainID, minGasPrices, nodeDirPrefix, nodeDaemonHome,
|
||||
nodeCLIHome, startingIPAddress string, numValidators int) error {
|
||||
|
||||
if chainID == "" {
|
||||
chainID = "chain-" + tmrand.Str(6)
|
||||
}
|
||||
|
||||
monikers := make([]string, numValidators)
|
||||
nodeIDs := make([]string, numValidators)
|
||||
valPubKeys := make([]crypto.PubKey, numValidators)
|
||||
|
||||
wasmConfig := srvconfig.DefaultConfig()
|
||||
wasmConfig.MinGasPrices = minGasPrices
|
||||
|
||||
//nolint:prealloc
|
||||
var (
|
||||
genAccounts []authexported.GenesisAccount
|
||||
genFiles []string
|
||||
)
|
||||
|
||||
inBuf := bufio.NewReader(cmd.InOrStdin())
|
||||
// generate private keys, node IDs, and initial transactions
|
||||
for i := 0; i < numValidators; i++ {
|
||||
nodeDirName := fmt.Sprintf("%s%d", nodeDirPrefix, i)
|
||||
nodeDir := filepath.Join(outputDir, nodeDirName, nodeDaemonHome)
|
||||
clientDir := filepath.Join(outputDir, nodeDirName, nodeCLIHome)
|
||||
gentxsDir := filepath.Join(outputDir, "gentxs")
|
||||
|
||||
config.SetRoot(nodeDir)
|
||||
config.RPC.ListenAddress = "tcp://0.0.0.0:26657"
|
||||
|
||||
if err := os.MkdirAll(filepath.Join(nodeDir, "config"), nodeDirPerm); err != nil {
|
||||
_ = os.RemoveAll(outputDir)
|
||||
return err
|
||||
}
|
||||
|
||||
if err := os.MkdirAll(clientDir, nodeDirPerm); err != nil {
|
||||
_ = os.RemoveAll(outputDir)
|
||||
return err
|
||||
}
|
||||
|
||||
monikers = append(monikers, nodeDirName)
|
||||
config.Moniker = nodeDirName
|
||||
|
||||
ip, err := getIP(i, startingIPAddress)
|
||||
if err != nil {
|
||||
_ = os.RemoveAll(outputDir)
|
||||
return err
|
||||
}
|
||||
|
||||
nodeIDs[i], valPubKeys[i], err = genutil.InitializeNodeValidatorFiles(config)
|
||||
if err != nil {
|
||||
_ = os.RemoveAll(outputDir)
|
||||
return err
|
||||
}
|
||||
|
||||
memo := fmt.Sprintf("%s@%s:26656", nodeIDs[i], ip)
|
||||
genFiles = append(genFiles, config.GenesisFile())
|
||||
|
||||
kb, err := keys.NewKeyring(
|
||||
sdk.KeyringServiceName(),
|
||||
viper.GetString(flags.FlagKeyringBackend),
|
||||
viper.GetString(flagClientHome),
|
||||
inBuf,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
keyPass := clientkeys.DefaultKeyPass
|
||||
addr, secret, err := server.GenerateSaveCoinKey(kb, nodeDirName, keyPass, true)
|
||||
if err != nil {
|
||||
_ = os.RemoveAll(outputDir)
|
||||
return err
|
||||
}
|
||||
|
||||
info := map[string]string{"secret": secret}
|
||||
|
||||
cliPrint, err := json.Marshal(info)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// save private key seed words
|
||||
if err := writeFile(fmt.Sprintf("%v.json", "key_seed"), clientDir, cliPrint); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
accTokens := sdk.TokensFromConsensusPower(1000)
|
||||
accStakingTokens := sdk.TokensFromConsensusPower(500)
|
||||
coins := sdk.Coins{
|
||||
sdk.NewCoin(fmt.Sprintf("%stoken", nodeDirName), accTokens),
|
||||
sdk.NewCoin(sdk.DefaultBondDenom, accStakingTokens),
|
||||
}
|
||||
genAccounts = append(genAccounts, auth.NewBaseAccount(addr, coins.Sort(), nil, 0, 0))
|
||||
|
||||
valTokens := sdk.TokensFromConsensusPower(100)
|
||||
msg := staking.NewMsgCreateValidator(
|
||||
sdk.ValAddress(addr),
|
||||
valPubKeys[i],
|
||||
sdk.NewCoin(sdk.DefaultBondDenom, valTokens),
|
||||
staking.NewDescription(nodeDirName, "", "", "", ""),
|
||||
staking.NewCommissionRates(sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec()),
|
||||
sdk.OneInt(),
|
||||
)
|
||||
|
||||
tx := auth.NewStdTx([]sdk.Msg{msg}, auth.StdFee{}, []auth.StdSignature{}, memo)
|
||||
txBldr := auth.NewTxBuilderFromCLI(inBuf).WithChainID(chainID).WithMemo(memo).WithKeybase(kb)
|
||||
|
||||
signedTx, err := txBldr.SignStdTx(nodeDirName, clientkeys.DefaultKeyPass, tx, false)
|
||||
if err != nil {
|
||||
_ = os.RemoveAll(outputDir)
|
||||
return err
|
||||
}
|
||||
|
||||
txBytes, err := cdc.MarshalJSON(signedTx)
|
||||
if err != nil {
|
||||
_ = os.RemoveAll(outputDir)
|
||||
return err
|
||||
}
|
||||
|
||||
// gather gentxs folder
|
||||
if err := writeFile(fmt.Sprintf("%v.json", nodeDirName), gentxsDir, txBytes); err != nil {
|
||||
_ = os.RemoveAll(outputDir)
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO: Rename config file to server.toml as it's not particular to Gaia
|
||||
// (REF: https://github.com/cosmos/cosmos-sdk/issues/4125).
|
||||
wasmConfigFilePath := filepath.Join(nodeDir, "config/wasmd.toml")
|
||||
srvconfig.WriteConfigFile(wasmConfigFilePath, wasmConfig)
|
||||
}
|
||||
|
||||
if err := initGenFiles(cdc, mbm, chainID, genAccounts, genFiles, numValidators); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err := collectGenFiles(
|
||||
cdc, config, chainID, monikers, nodeIDs, valPubKeys, numValidators,
|
||||
outputDir, nodeDirPrefix, nodeDaemonHome, genAccIterator,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cmd.PrintErrf("Successfully initialized %d node directories\n", numValidators)
|
||||
return nil
|
||||
}
|
||||
|
||||
func initGenFiles(
|
||||
cdc *codec.Codec, mbm module.BasicManager, chainID string,
|
||||
genAccounts []authexported.GenesisAccount, genFiles []string, numValidators int,
|
||||
) error {
|
||||
|
||||
appGenState := mbm.DefaultGenesis()
|
||||
|
||||
// set the accounts in the genesis state
|
||||
authDataBz := appGenState[auth.ModuleName]
|
||||
var authGenState auth.GenesisState
|
||||
cdc.MustUnmarshalJSON(authDataBz, &authGenState)
|
||||
authGenState.Accounts = genAccounts
|
||||
appGenState[auth.ModuleName] = cdc.MustMarshalJSON(authGenState)
|
||||
|
||||
appGenStateJSON, err := codec.MarshalJSONIndent(cdc, appGenState)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
genDoc := types.GenesisDoc{
|
||||
ChainID: chainID,
|
||||
AppState: appGenStateJSON,
|
||||
Validators: nil,
|
||||
}
|
||||
|
||||
// generate empty genesis files for each validator and save
|
||||
for i := 0; i < numValidators; i++ {
|
||||
if err := genDoc.SaveAs(genFiles[i]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func collectGenFiles(
|
||||
cdc *codec.Codec, config *tmconfig.Config, chainID string,
|
||||
monikers, nodeIDs []string, valPubKeys []crypto.PubKey,
|
||||
numValidators int, outputDir, nodeDirPrefix, nodeDaemonHome string,
|
||||
genAccIterator genutiltypes.GenesisAccountsIterator) error {
|
||||
|
||||
var appState json.RawMessage
|
||||
genTime := tmtime.Now()
|
||||
|
||||
for i := 0; i < numValidators; i++ {
|
||||
nodeDirName := fmt.Sprintf("%s%d", nodeDirPrefix, i)
|
||||
nodeDir := filepath.Join(outputDir, nodeDirName, nodeDaemonHome)
|
||||
gentxsDir := filepath.Join(outputDir, "gentxs")
|
||||
moniker := monikers[i]
|
||||
config.Moniker = nodeDirName
|
||||
|
||||
config.SetRoot(nodeDir)
|
||||
|
||||
nodeID, valPubKey := nodeIDs[i], valPubKeys[i]
|
||||
initCfg := genutil.NewInitConfig(chainID, gentxsDir, moniker, nodeID, valPubKey)
|
||||
|
||||
genDoc, err := types.GenesisDocFromFile(config.GenesisFile())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
nodeAppState, err := genutil.GenAppStateFromConfig(cdc, config, initCfg, *genDoc, genAccIterator)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if appState == nil {
|
||||
// set the canonical application state (they should not differ)
|
||||
appState = nodeAppState
|
||||
}
|
||||
|
||||
genFile := config.GenesisFile()
|
||||
|
||||
// overwrite each validator's genesis file to have a canonical genesis time
|
||||
if err := genutil.ExportGenesisFileWithTime(genFile, chainID, nil, appState, genTime); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func getIP(i int, startingIPAddr string) (ip string, err error) {
|
||||
if len(startingIPAddr) == 0 {
|
||||
ip, err = server.ExternalIP()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return ip, nil
|
||||
}
|
||||
return calculateIP(startingIPAddr, i)
|
||||
}
|
||||
|
||||
func calculateIP(ip string, i int) (string, error) {
|
||||
ipv4 := net.ParseIP(ip).To4()
|
||||
if ipv4 == nil {
|
||||
return "", fmt.Errorf("%v: non ipv4 address", ip)
|
||||
}
|
||||
|
||||
for j := 0; j < i; j++ {
|
||||
ipv4[3]++
|
||||
}
|
||||
|
||||
return ipv4.String(), nil
|
||||
}
|
||||
|
||||
func writeFile(name string, dir string, contents []byte) error {
|
||||
writePath := filepath.Join(dir)
|
||||
file := filepath.Join(writePath, name)
|
||||
|
||||
err := tmos.EnsureDir(writePath, 0700)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = tmos.WriteFile(file, contents, 0600)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
if test -n "$1"; then
|
||||
# need -R not -r to copy hidden files
|
||||
cp -R "$1/.wasmd" /root
|
||||
cp -R "$1/.wasmcli" /root
|
||||
fi
|
||||
|
||||
mkdir -p /root/log
|
||||
wasmgovd start --rpc.laddr tcp://0.0.0.0:26657 --trace
|
||||
@@ -1,24 +0,0 @@
|
||||
#!/bin/sh
|
||||
#set -o errexit -o nounset -o pipefail
|
||||
|
||||
PASSWORD=${PASSWORD:-1234567890}
|
||||
STAKE=${STAKE_TOKEN:-ustake}
|
||||
FEE=${FEE_TOKEN:-ucosm}
|
||||
|
||||
wasmgovd init --chain-id=testing testing
|
||||
sed -i 's/permission": "Everybody"/permission": "Nobody"/' "$HOME"/.wasmgovd/config/genesis.json
|
||||
# staking/governance token is hardcoded in config, change this
|
||||
sed -i "s/\"stake\"/\"$STAKE\"/" "$HOME"/.wasmgovd/config/genesis.json
|
||||
if ! wasmcli keys show validator; then
|
||||
(echo "$PASSWORD"; echo "$PASSWORD") | wasmcli keys add validator
|
||||
fi
|
||||
# hardcode the validator account for this instance
|
||||
echo "$PASSWORD" | wasmgovd add-genesis-account validator "1000000000$STAKE,1000000000$FEE"
|
||||
# (optionally) add a few more genesis accounts
|
||||
for addr in "$@"; do
|
||||
echo $addr
|
||||
wasmgovd add-genesis-account "$addr" "1000000000$STAKE,1000000000$FEE"
|
||||
done
|
||||
# submit a genesis validator tx
|
||||
(echo "$PASSWORD"; echo "$PASSWORD"; echo "$PASSWORD") | wasmgovd gentx --name validator --amount "250000000$STAKE"
|
||||
wasmgovd collect-gentxs
|
||||
Reference in New Issue
Block a user