From 337f90e7b63eb5abd390737bfb23466a24f5b507 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0lker=20G=C3=B6ktu=C4=9F=20=C3=96ZT=C3=9CRK?= Date: Mon, 4 Jan 2021 16:21:06 +0300 Subject: [PATCH 1/5] init cmdchainrunner pkg --- starport/pkg/chaincmd/chaincmd.go | 18 +++- starport/pkg/chaincmd/runner/account.go | 90 +++++++++++++++++++ starport/pkg/chaincmd/runner/chain.go | 41 +++++++++ starport/pkg/chaincmd/runner/runner.go | 98 +++++++++++++++++++++ starport/services/chain/plugin-launchpad.go | 2 +- starport/services/chain/plugin-stargate.go | 2 +- 6 files changed, 246 insertions(+), 5 deletions(-) create mode 100644 starport/pkg/chaincmd/runner/account.go create mode 100644 starport/pkg/chaincmd/runner/chain.go create mode 100644 starport/pkg/chaincmd/runner/runner.go diff --git a/starport/pkg/chaincmd/chaincmd.go b/starport/pkg/chaincmd/chaincmd.go index 30dc75d6e0..7b3c734e06 100644 --- a/starport/pkg/chaincmd/chaincmd.go +++ b/starport/pkg/chaincmd/chaincmd.go @@ -79,8 +79,8 @@ func WithChainID(chainID string) Option { } } -// WithKeyrinBackend provides a specific keyring backend for the commands that accept this option -func WithKeyrinBackend(keyringBackend KeyringBackend) Option { +// WithKeyringBackend provides a specific keyring backend for the commands that accept this option +func WithKeyringBackend(keyringBackend KeyringBackend) Option { return func(c *ChainCmd) { c.keyringBackend = keyringBackend } @@ -152,6 +152,18 @@ func (c ChainCmd) ShowKeyAddressCommand(accountName string) step.Option { return c.cliCommand(command) } +// ListKeysCommand returns the command to print the list of a keys in the chain keyring +func (c ChainCmd) ListKeysCommand() step.Option { + command := []string{ + commandKeys, + "list", + optionOutput, + constJSON, + } + command = c.attachKeyringBackend(command) + return step.Exec(c.appCmd, c.attachHome(command)...) +} + // AddGenesisAccountCommand returns the command to add a new account in the genesis file of the chain func (c ChainCmd) AddGenesisAccountCommand(address string, coins string) step.Option { command := []string{ @@ -162,7 +174,7 @@ func (c ChainCmd) AddGenesisAccountCommand(address string, coins string) step.Op return c.daemonCommand(command) } -// Options for the GentxCommand +// GentxOption for the GentxCommand type GentxOption func([]string) []string // GentxWithMoniker provides moniker option for the gentx command diff --git a/starport/pkg/chaincmd/runner/account.go b/starport/pkg/chaincmd/runner/account.go new file mode 100644 index 0000000000..5d544bb391 --- /dev/null +++ b/starport/pkg/chaincmd/runner/account.go @@ -0,0 +1,90 @@ +package chaincmdrunner + +import ( + "bytes" + "context" + "encoding/json" + "errors" + "strings" + + "github.com/tendermint/starport/starport/pkg/cmdrunner/step" +) + +// AddAccount creates a new account or imports an account when mnemonic is provided. +// returns with an error if the operation went unsuccessful or an account with the provided name +// already exists. +func (r Runner) AddAccount(ctx context.Context, name, mnemonic string) (Account, error) { + b := &bytes.Buffer{} + + // check if account already exists. + var accounts []Account + if err := r.run(ctx, runOptions{stdout: b}, r.cc.ListKeysCommand()); err != nil { + return Account{}, err + } + if err := json.NewDecoder(b).Decode(&accounts); err != nil { + return Account{}, err + } + for _, account := range accounts { + if account.Name == name { + return Account{}, errors.New("account already exists") + } + } + b.Reset() + + account := Account{ + Name: name, + Mnemonic: mnemonic, + } + + // import the account when mnemonic is provided, otherwise create a new one. + if mnemonic != "" { + if err := r.run( + ctx, + runOptions{}, + r.cc.ImportKeyCommand(name), + step.Write([]byte(mnemonic+"\n")), + ); err != nil { + return Account{}, err + } + } else { + if err := r.run(ctx, runOptions{stdout: b}, r.cc.AddKeyCommand(name)); err != nil { + return Account{}, err + } + if err := json.NewDecoder(b).Decode(&account); err != nil { + return Account{}, err + } + b.Reset() + } + + // get full details of the account. + if err := r.run(ctx, runOptions{stdout: b}, r.cc.ShowKeyAddressCommand(name)); err != nil { + return Account{}, err + } + account.Address = strings.TrimSpace(b.String()) + + return account, nil +} + +// Account represents a user account. +type Account struct { + Name string `json:"name"` + Address string `json:"address"` + Mnemonic string `json:"mnemonic,omitempty"` +} + +// ShowAccount shows details of an account. +func (r Runner) ShowAccount(ctx context.Context, name string) (Account, error) { + b := &bytes.Buffer{} + if err := r.run(ctx, runOptions{stdout: b}, r.cc.ShowKeyAddressCommand(name)); err != nil { + return Account{}, err + } + return Account{ + Name: name, + Address: strings.TrimSpace(b.String()), + }, nil +} + +// AddGenesisAccount adds account to genesis by its address. +func (r Runner) AddGenesisAccount(ctx context.Context, address, coins string) error { + return r.run(ctx, runOptions{}, r.cc.AddGenesisAccountCommand(address, coins)) +} diff --git a/starport/pkg/chaincmd/runner/chain.go b/starport/pkg/chaincmd/runner/chain.go new file mode 100644 index 0000000000..56335e89ca --- /dev/null +++ b/starport/pkg/chaincmd/runner/chain.go @@ -0,0 +1,41 @@ +package chaincmdrunner + +import ( + "bytes" + "context" + "strings" + + "github.com/tendermint/starport/starport/pkg/chaincmd" +) + +// Start starts the blockchain. +func (r Runner) Start(ctx context.Context, args []string) error { + return r.run(ctx, runOptions{longRunning: true}, r.cc.StartCommand(args...)) +} + +// Init inits the blockchain. +func (r Runner) Init(ctx context.Context, moniker string) error { + return r.run(ctx, runOptions{}, r.cc.InitCommand(moniker)) +} + +// Gentx generates a genesis tx carrying a self delegation. +func (r Runner) Gentx(ctx context.Context, validatorName, selfDelegation string, options ...chaincmd.GentxOption) error { + return r.run(ctx, runOptions{}, r.cc.GentxCommand(validatorName, selfDelegation, options...)) +} + +// CollectGentxs collects gentxs. +func (r Runner) CollectGentxs(ctx context.Context) error { + return r.run(ctx, runOptions{}, r.cc.CollectGentxsCommand()) +} + +// ValidateGenesis validates genesis. +func (r Runner) ValidateGenesis(ctx context.Context) error { + return r.run(ctx, runOptions{}, r.cc.ValidateGenesisCommand()) +} + +// ShowNodeID shows node id. +func (r Runner) ShowNodeID(ctx context.Context) (nodeID string, err error) { + b := &bytes.Buffer{} + err = r.run(ctx, runOptions{stdout: b}, r.cc.ShowNodeIDCommand()) + return strings.TrimSpace(b.String()), err +} diff --git a/starport/pkg/chaincmd/runner/runner.go b/starport/pkg/chaincmd/runner/runner.go new file mode 100644 index 0000000000..2809709022 --- /dev/null +++ b/starport/pkg/chaincmd/runner/runner.go @@ -0,0 +1,98 @@ +// Package chaincmdrunner provides a high level access to a blockchain's commands. +package chaincmdrunner + +import ( + "bytes" + "context" + "io" + "io/ioutil" + + "github.com/pkg/errors" + "github.com/tendermint/starport/starport/pkg/chaincmd" + "github.com/tendermint/starport/starport/pkg/cmdrunner" + "github.com/tendermint/starport/starport/pkg/cmdrunner/step" +) + +// Runner provides a high level access to a blockchain's commands. +type Runner struct { + cc chaincmd.ChainCmd + stdout, stderr io.Writer + workdir string +} + +// Option configures Runner. +type Option func(r *Runner) + +// Stdout sets stdout for executed commands. +func Stdout(w io.Writer) Option { + return func(r *Runner) { + r.stdout = w + } +} + +// Stderr sets stderr for executed commands. +func Stderr(w io.Writer) Option { + return func(r *Runner) { + r.stderr = w + } +} + +// Workdir sets current working directory. +func Workdir(path string) Option { + return func(r *Runner) { + r.workdir = path + } +} + +// New creates a new Runner with cc and options. +func New(cc chaincmd.ChainCmd, options ...Option) Runner { + r := Runner{ + cc: cc, + stdout: ioutil.Discard, + stderr: ioutil.Discard, + } + + // apply options. + for _, apply := range options { + apply(&r) + } + + return r +} + +type runOptions struct { + // longRunning indicates that command expected to run for a long period of time. + longRunning bool + + // stdout and stderr used to collect a copy of command's outputs. + stdout, stderr io.Writer +} + +// run executes a command. +func (r Runner) run(ctx context.Context, roptions runOptions, soptions ...step.Option) error { + errb := &bytes.Buffer{} + stdout := r.stdout + stderr := r.stderr + + if roptions.stdout != nil { + stdout = io.MultiWriter(stdout, roptions.stdout) + } + if roptions.stderr != nil { + stderr = io.MultiWriter(stderr, roptions.stderr) + } + + if !roptions.longRunning { + stderr = io.MultiWriter(r.stderr, errb) + } + + rnoptions := []cmdrunner.Option{ + cmdrunner.DefaultStdout(stdout), + cmdrunner.DefaultStderr(stderr), + } + + err := cmdrunner. + New(rnoptions...). + Run(ctx, step.New(soptions...)) + + return errors.Wrap(err, errb.String()) +} diff --git a/starport/services/chain/plugin-launchpad.go b/starport/services/chain/plugin-launchpad.go index c953febdb9..208e5c1a34 100644 --- a/starport/services/chain/plugin-launchpad.go +++ b/starport/services/chain/plugin-launchpad.go @@ -25,7 +25,7 @@ func newLaunchpadPlugin(app App) *launchpadPlugin { // initialize the chain command with keyring backend test cmd := chaincmd.New( app.D(), - chaincmd.WithKeyrinBackend(chaincmd.KeyringBackendTest), + chaincmd.WithKeyringBackend(chaincmd.KeyringBackendTest), chaincmd.WithLaunchpad(app.CLI()), ) diff --git a/starport/services/chain/plugin-stargate.go b/starport/services/chain/plugin-stargate.go index 0a912b306f..3f820a1663 100644 --- a/starport/services/chain/plugin-stargate.go +++ b/starport/services/chain/plugin-stargate.go @@ -30,7 +30,7 @@ func newStargatePlugin(app App, chain *Chain) (*stargatePlugin, error) { // initialize the chain command with keyring backend test cmd := chaincmd.New( app.D(), - chaincmd.WithKeyrinBackend(chaincmd.KeyringBackendTest), + chaincmd.WithKeyringBackend(chaincmd.KeyringBackendTest), chaincmd.WithChainID(id), ) From 89adb3d900fdad0533a146f763f2cf0bd8361b21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0lker=20G=C3=B6ktu=C4=9F=20=C3=96ZT=C3=9CRK?= Date: Wed, 6 Jan 2021 18:00:59 +0300 Subject: [PATCH 2/5] start using chaincmdrunner in chain and networkbuilder services --- go.mod | 2 +- go.sum | 4 +- starport/pkg/chaincmd/chaincmd.go | 3 +- starport/pkg/chaincmd/runner/account.go | 4 +- starport/pkg/chaincmd/runner/chain.go | 45 ++- starport/pkg/chaincmd/runner/runner.go | 52 +++- starport/services/chain/chain.go | 33 +- starport/services/chain/init.go | 281 ++++-------------- starport/services/chain/log.go | 12 +- starport/services/chain/plugin-launchpad.go | 82 +++-- starport/services/chain/plugin-stargate.go | 47 +-- starport/services/chain/plugin.go | 18 +- starport/services/chain/serve.go | 78 ++--- .../services/networkbuilder/blockchain.go | 27 +- .../services/networkbuilder/networkbuilder.go | 17 +- .../services/networkbuilder/simulation.go | 41 +-- 16 files changed, 300 insertions(+), 446 deletions(-) diff --git a/go.mod b/go.mod index 62f41fc4fb..9e33fcd0da 100644 --- a/go.mod +++ b/go.mod @@ -49,7 +49,7 @@ require ( golang.org/x/mod v0.4.0 golang.org/x/net v0.0.0-20201021035429-f5854403a974 // indirect golang.org/x/sync v0.0.0-20201207232520-09787c993a3a - golang.org/x/sys v0.0.0-20201223074533-0d417f636930 // indirect + golang.org/x/sys v0.0.0-20210105210732-16f7687f5001 // indirect golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf // indirect google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154 // indirect google.golang.org/grpc v1.33.0 diff --git a/go.sum b/go.sum index 332abbe5ec..8a9c14c8a8 100644 --- a/go.sum +++ b/go.sum @@ -928,8 +928,8 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201223074533-0d417f636930 h1:vRgIt+nup/B/BwIS0g2oC0haq0iqbV3ZA+u6+0TlNCo= -golang.org/x/sys v0.0.0-20201223074533-0d417f636930/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210105210732-16f7687f5001 h1:/dSxr6gT0FNI1MO5WLJo8mTmItROeOKTkDn+7OwWBos= +golang.org/x/sys v0.0.0-20210105210732-16f7687f5001/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf h1:MZ2shdL+ZM/XzY3ZGOnh4Nlpnxz5GSOhOmtHo3iPU6M= golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= diff --git a/starport/pkg/chaincmd/chaincmd.go b/starport/pkg/chaincmd/chaincmd.go index 7b3c734e06..fcf95affde 100644 --- a/starport/pkg/chaincmd/chaincmd.go +++ b/starport/pkg/chaincmd/chaincmd.go @@ -161,7 +161,8 @@ func (c ChainCmd) ListKeysCommand() step.Option { constJSON, } command = c.attachKeyringBackend(command) - return step.Exec(c.appCmd, c.attachHome(command)...) + + return c.cliCommand(command) } // AddGenesisAccountCommand returns the command to add a new account in the genesis file of the chain diff --git a/starport/pkg/chaincmd/runner/account.go b/starport/pkg/chaincmd/runner/account.go index 5d544bb391..75c6399d75 100644 --- a/starport/pkg/chaincmd/runner/account.go +++ b/starport/pkg/chaincmd/runner/account.go @@ -47,12 +47,14 @@ func (r Runner) AddAccount(ctx context.Context, name, mnemonic string) (Account, return Account{}, err } } else { - if err := r.run(ctx, runOptions{stdout: b}, r.cc.AddKeyCommand(name)); err != nil { + // note that, launchpad prints account output from stderr. + if err := r.run(ctx, runOptions{stdout: b, stderr: b}, r.cc.AddKeyCommand(name)); err != nil { return Account{}, err } if err := json.NewDecoder(b).Decode(&account); err != nil { return Account{}, err } + b.Reset() } diff --git a/starport/pkg/chaincmd/runner/chain.go b/starport/pkg/chaincmd/runner/chain.go index 56335e89ca..e6e73e5be7 100644 --- a/starport/pkg/chaincmd/runner/chain.go +++ b/starport/pkg/chaincmd/runner/chain.go @@ -3,24 +3,60 @@ package chaincmdrunner import ( "bytes" "context" + "regexp" "strings" "github.com/tendermint/starport/starport/pkg/chaincmd" ) // Start starts the blockchain. -func (r Runner) Start(ctx context.Context, args []string) error { +func (r Runner) Start(ctx context.Context, args ...string) error { return r.run(ctx, runOptions{longRunning: true}, r.cc.StartCommand(args...)) } +// LaunchpadStartRestServer start launchpad rest server. +func (r Runner) LaunchpadStartRestServer(ctx context.Context, apiAddress, rpcAddress string) error { + return r.run(ctx, runOptions{longRunning: true}, r.cc.LaunchpadRestServerCommand(apiAddress, rpcAddress)) +} + // Init inits the blockchain. func (r Runner) Init(ctx context.Context, moniker string) error { return r.run(ctx, runOptions{}, r.cc.InitCommand(moniker)) } +// KeyValue holds a key, value pair. +type KeyValue struct { + key string + value string +} + +// KV returns a new key, value pair. +func KV(key, value string) KeyValue { + return KeyValue{key, value} +} + +// LaunchpadSetConfigs updates configurations for a launchpad app. +func (r Runner) LaunchpadSetConfigs(ctx context.Context, kvs ...KeyValue) error { + for _, kv := range kvs { + if err := r.run(ctx, runOptions{}, r.cc.LaunchpadSetConfigCommand(kv.key, kv.value)); err != nil { + return err + } + } + return nil +} + +var gentxRe = regexp.MustCompile(`(?m)"(.+?)"`) + // Gentx generates a genesis tx carrying a self delegation. -func (r Runner) Gentx(ctx context.Context, validatorName, selfDelegation string, options ...chaincmd.GentxOption) error { - return r.run(ctx, runOptions{}, r.cc.GentxCommand(validatorName, selfDelegation, options...)) +func (r Runner) Gentx(ctx context.Context, validatorName, selfDelegation string, options ...chaincmd.GentxOption) (gentxPath string, err error) { + b := &bytes.Buffer{} + + // note: launchpad outputs from stderr. + if err := r.run(ctx, runOptions{stdout: b, stderr: b}, r.cc.GentxCommand(validatorName, selfDelegation, options...)); err != nil { + return "", err + } + + return gentxRe.FindStringSubmatch(b.String())[1], nil } // CollectGentxs collects gentxs. @@ -37,5 +73,6 @@ func (r Runner) ValidateGenesis(ctx context.Context) error { func (r Runner) ShowNodeID(ctx context.Context) (nodeID string, err error) { b := &bytes.Buffer{} err = r.run(ctx, runOptions{stdout: b}, r.cc.ShowNodeIDCommand()) - return strings.TrimSpace(b.String()), err + nodeID = strings.TrimSpace(b.String()) + return } diff --git a/starport/pkg/chaincmd/runner/runner.go b/starport/pkg/chaincmd/runner/runner.go index 2809709022..d18aaa0b95 100644 --- a/starport/pkg/chaincmd/runner/runner.go +++ b/starport/pkg/chaincmd/runner/runner.go @@ -11,13 +11,14 @@ import ( "github.com/tendermint/starport/starport/pkg/chaincmd" "github.com/tendermint/starport/starport/pkg/cmdrunner" "github.com/tendermint/starport/starport/pkg/cmdrunner/step" + "github.com/tendermint/starport/starport/pkg/lineprefixer" ) // Runner provides a high level access to a blockchain's commands. type Runner struct { - cc chaincmd.ChainCmd - stdout, stderr io.Writer - workdir string + cc chaincmd.ChainCmd + stdout, stderr io.Writer + daemonLogPrefix, cliLogPrefix string } // Option configures Runner. @@ -30,17 +31,24 @@ func Stdout(w io.Writer) Option { } } -// Stderr sets stderr for executed commands. -func Stderr(w io.Writer) Option { +// DaemonLogPrefix is a prefix added to app's daemon logs. +func DaemonLogPrefix(prefix string) Option { return func(r *Runner) { - r.stderr = w + r.daemonLogPrefix = prefix } } -// Workdir sets current working directory. -func Workdir(path string) Option { +// CLILogPrefix is a prefix added to app's cli logs. +func CLILogPrefix(prefix string) Option { + return func(r *Runner) { + r.cliLogPrefix = prefix + } +} + +// Stderr sets stderr for executed commands. +func Stderr(w io.Writer) Option { return func(r *Runner) { - r.workdir = path + r.stderr = w } } @@ -52,10 +60,20 @@ func New(cc chaincmd.ChainCmd, options ...Option) Runner { stderr: ioutil.Discard, } - // apply options. + applyOptions(&r, options) + + return r +} + +func applyOptions(r *Runner, options []Option) { for _, apply := range options { - apply(&r) + apply(r) } +} + +// Copy makes a copy of runner by overwriting its options with given options. +func (r Runner) Copy(options ...Option) Runner { + applyOptions(&r, options) return r } @@ -70,9 +88,13 @@ type runOptions struct { // run executes a command. func (r Runner) run(ctx context.Context, roptions runOptions, soptions ...step.Option) error { - errb := &bytes.Buffer{} - stdout := r.stdout - stderr := r.stderr + var ( + errb = &bytes.Buffer{} + + // add optional prefixes to output streams. + stdout io.Writer = lineprefixer.NewWriter(r.stdout, func() string { return r.daemonLogPrefix }) + stderr io.Writer = lineprefixer.NewWriter(r.stderr, func() string { return r.cliLogPrefix }) + ) if roptions.stdout != nil { stdout = io.MultiWriter(stdout, roptions.stdout) @@ -82,7 +104,7 @@ func (r Runner) run(ctx context.Context, roptions runOptions, soptions ...step.O } if !roptions.longRunning { - stderr = io.MultiWriter(r.stderr, errb) + stderr = io.MultiWriter(stderr, errb) } rnoptions := []cmdrunner.Option{ diff --git a/starport/services/chain/chain.go b/starport/services/chain/chain.go index 51032c45fd..8fa9bc0b6d 100644 --- a/starport/services/chain/chain.go +++ b/starport/services/chain/chain.go @@ -9,6 +9,7 @@ import ( "strings" "github.com/tendermint/starport/starport/pkg/chaincmd" + chaincmdrunner "github.com/tendermint/starport/starport/pkg/chaincmd/runner" "github.com/go-git/go-git/v5" "github.com/gookit/color" @@ -51,7 +52,7 @@ type Chain struct { plugin Plugin version version logLevel LogLevel - cmd chaincmd.ChainCmd + cmd chaincmdrunner.Runner serveCancel context.CancelFunc serveRefresher chan struct{} stdout, stderr io.Writer @@ -94,11 +95,31 @@ func New(app App, noCheck bool, logLevel LogLevel) (*Chain, error) { if err != nil { return nil, err } - c.cmd = chaincmd.New( - app.D(), + + ccoptions := []chaincmd.Option{ chaincmd.WithChainID(id), chaincmd.WithHome(c.Home()), - ) + chaincmd.WithKeyringBackend(chaincmd.KeyringBackendTest), + } + if c.plugin.Version() == cosmosver.Launchpad { + ccoptions = append(ccoptions, + chaincmd.WithLaunchpad(app.CLI()), + //chaincmd.WithLaunchpadCLIHome(), + ) + } + + cc := chaincmd.New(app.D(), ccoptions...) + + ccroptions := []chaincmdrunner.Option{} + if c.logLevel == LogVerbose { + ccroptions = append(ccroptions, + chaincmdrunner.Stdout(os.Stdout), + chaincmdrunner.Stderr(os.Stderr), + chaincmdrunner.DaemonLogPrefix(c.genPrefix(logAppd)), + chaincmdrunner.CLILogPrefix(c.genPrefix(logAppcli)), + ) + } + c.cmd = chaincmdrunner.New(cc, ccroptions...) return c, nil } @@ -202,7 +223,7 @@ func (c *Chain) ConfigTOMLPath() string { return fmt.Sprintf("%s/config/config.toml", c.Home()) } -// Commands returns the chaincmd object to perform command with the chain binary -func (c *Chain) Commands() chaincmd.ChainCmd { +// Commands returns the runner execute commands on the chain's binary +func (c *Chain) Commands() chaincmdrunner.Runner { return c.cmd } diff --git a/starport/services/chain/init.go b/starport/services/chain/init.go index 242159d16a..f1532c44ab 100644 --- a/starport/services/chain/init.go +++ b/starport/services/chain/init.go @@ -1,19 +1,11 @@ package chain import ( - "bytes" "context" - "encoding/json" "fmt" - "io" "os" - "regexp" - "strings" "github.com/imdario/mergo" - "github.com/pkg/errors" - "github.com/tendermint/starport/starport/pkg/cmdrunner" - "github.com/tendermint/starport/starport/pkg/cmdrunner/step" "github.com/tendermint/starport/starport/pkg/confile" "github.com/tendermint/starport/starport/pkg/xos" ) @@ -34,171 +26,79 @@ func (c *Chain) Init(ctx context.Context) error { return err } - var steps step.Steps - var errb bytes.Buffer - // cleanup persistent data from previous `serve`. - steps.Add(step.New( - step.PreExec(func() error { - for _, path := range c.plugin.StoragePaths() { - if err := os.RemoveAll(path); err != nil { - return err - } - } - return nil - }), - )) + for _, path := range c.plugin.StoragePaths() { + if err := os.RemoveAll(path); err != nil { + return err + } + } // init node. - steps.Add(step.New( - c.cmd.InitCommand(moniker), - // overwrite configuration changes from Starport's config.yml to - // over app's sdk configs. - step.PostExec(func(err error) error { - if err != nil { - return err - } - - // make sure that chain id given during chain.New() has the most priority. - if conf.Genesis != nil { - conf.Genesis["chain_id"] = chainID - } - - appconfigs := []struct { - ec confile.EncodingCreator - path string - changes map[string]interface{} - }{ - {confile.DefaultJSONEncodingCreator, c.GenesisPath(), conf.Genesis}, - {confile.DefaultTOMLEncodingCreator, c.AppTOMLPath(), conf.Init.App}, - {confile.DefaultTOMLEncodingCreator, c.ConfigTOMLPath(), conf.Init.Config}, - } + if err := c.cmd.Init(ctx, moniker); err != nil { + return err + } - for _, ac := range appconfigs { - cf := confile.New(ac.ec, ac.path) - var conf map[string]interface{} - if err := cf.Load(&conf); err != nil { - return err - } - if err := mergo.Merge(&conf, ac.changes, mergo.WithOverride); err != nil { - return err - } - if err := cf.Save(conf); err != nil { - return err - } - } - return nil - }), - step.PostExec(func(err error) error { - if err != nil { - return err - } - return c.plugin.PostInit(conf) - }), - step.Stderr(io.MultiWriter(c.stdLog(logAppd).err, &errb)), - step.Stdout(c.stdLog(logAppd).out), - )) + // overwrite configuration changes from Starport's config.yml to + // over app's sdk configs. - err = cmdrunner.New(c.cmdOptions()...).Run(ctx, steps...) - return errors.Wrap(err, errb.String()) -} + // make sure that chain id given during chain.New() has the most priority. + if conf.Genesis != nil { + conf.Genesis["chain_id"] = chainID + } -func (c *Chain) setupSteps() (steps step.Steps, err error) { - if err := c.checkIBCRelayerSupport(); err == nil { - steps.Add(step.New( - step.PreExec(func() error { - if err := xos.RemoveAllUnderHome(".relayer"); err != nil { - return err - } - info, err := c.RelayerInfo() - if err != nil { - return err - } - fmt.Fprintf(c.stdLog(logStarport).out, "✨ Relayer info: %s\n", info) - return nil - }), - )) + appconfigs := []struct { + ec confile.EncodingCreator + path string + changes map[string]interface{} + }{ + {confile.DefaultJSONEncodingCreator, c.GenesisPath(), conf.Genesis}, + {confile.DefaultTOMLEncodingCreator, c.AppTOMLPath(), conf.Init.App}, + {confile.DefaultTOMLEncodingCreator, c.ConfigTOMLPath(), conf.Init.Config}, } - chainID, err := c.ID() - if err != nil { - return nil, err + for _, ac := range appconfigs { + cf := confile.New(ac.ec, ac.path) + var conf map[string]interface{} + if err := cf.Load(&conf); err != nil { + return err + } + if err := mergo.Merge(&conf, ac.changes, mergo.WithOverride); err != nil { + return err + } + if err := cf.Save(conf); err != nil { + return err + } } - for _, execOption := range c.plugin.ConfigCommands(chainID) { - execOption := execOption - steps.Add(step.New(step.NewOptions(). - Add(execOption). - Add(c.stdSteps(logAppcli)...)..., - )) + // run post init handler + if err := c.plugin.PostInit(conf); err != nil { + return err } - return steps, nil + return nil } -// CreateAccount creates an account on chain. -// cmnemonic is returned when account is created but not restored. -func (c *Chain) CreateAccount(ctx context.Context, name, mnemonic string, isSilent bool) (Account, error) { - acc := Account{ - Name: name, +func (c *Chain) configure(ctx context.Context) error { + // setup IBC Relayer. + if err := c.checkIBCRelayerSupport(); err == nil { + if err := xos.RemoveAllUnderHome(".relayer"); err != nil { + return err + } + info, err := c.RelayerInfo() + if err != nil { + return err + } + fmt.Fprintf(c.stdLog(logStarport).out, "✨ Relayer info: %s\n", info) + return nil } - var ( - steps step.Steps - key = &bytes.Buffer{} - errb = &bytes.Buffer{} - ) - - if mnemonic != "" { - steps.Add( - step.New(step.NewOptions(). - Add(c.plugin.ImportUserCommand(name, mnemonic)...). - Add(step.Stderr(errb))..., - ), - ) - } else { - generatedMnemonic := &bytes.Buffer{} - steps.Add( - step.New(step.NewOptions(). - Add(c.plugin.AddUserCommand(name)...). - Add( - step.PostExec(func(exitErr error) error { - if exitErr != nil { - return errors.Wrapf(exitErr, "cannot create %s account", name) - } - if err := json.NewDecoder(generatedMnemonic).Decode(&acc); err != nil { - return errors.Wrap(err, "cannot decode mnemonic") - } - if !isSilent { - fmt.Fprintf(c.stdLog(logStarport).out, "šŸ™‚ Created an account. Password (mnemonic): %[1]v\n", acc.Mnemonic) - } - return nil - }), - ). - Add(c.stdSteps(logAppcli)...). - // Stargate pipes from stdout, Launchpad pipes from stderr. - Add(step.Stderr(generatedMnemonic), step.Stdout(generatedMnemonic))..., - ), - ) + // configure blockchain. + chainID, err := c.ID() + if err != nil { + return err } - steps.Add( - step.New( - c.plugin.ShowAccountCommand(name), - step.PostExec(func(err error) error { - if err != nil { - return err - } - acc.Address = strings.TrimSpace(key.String()) - return nil - }), - step.Stderr(io.MultiWriter(c.stdLog(logAppcli).err, errb)), - step.Stdout(key), - ), - ) - - err := cmdrunner.New(c.cmdOptions()...).Run(ctx, steps...) - return acc, errors.Wrap(err, errb.String()) + return c.plugin.Configure(ctx, chainID) } type Validator struct { @@ -212,28 +112,6 @@ type Validator struct { GasPrices string } -var gentxRe = regexp.MustCompile(`(?m)"(.+?)"`) - -// Gentx generates a gentx for v. -func (c *Chain) Gentx(ctx context.Context, v Validator) (gentxPath string, err error) { - var ( - gentxPathMessage = &bytes.Buffer{} - errb = &bytes.Buffer{} - ) - - if err := cmdrunner. - New(c.cmdOptions()...). - Run(ctx, step.New( - c.plugin.GentxCommand(v), - step.Stderr(io.MultiWriter(gentxPathMessage, c.stdLog(logAppd).err, errb)), - step.Stdout(io.MultiWriter(gentxPathMessage, c.stdLog(logAppd).out)), - )); err != nil { - return "", errors.Wrap(err, errb.String()) - } - - return gentxRe.FindStringSubmatch(gentxPathMessage.String())[1], nil -} - // Account represents an account in the chain. type Account struct { Name string @@ -241,52 +119,3 @@ type Account struct { Mnemonic string `json:"mnemonic"` Coins string } - -// AddGenesisAccount add a genesis account in the chain. -func (c *Chain) AddGenesisAccount(ctx context.Context, account Account) error { - errb := &bytes.Buffer{} - - err := cmdrunner. - New(c.cmdOptions()...). - Run(ctx, step.New( - c.cmd.AddGenesisAccountCommand(account.Address, account.Coins), - step.Stderr(errb), - )) - return errors.Wrap(err, errb.String()) -} - -// CollectGentx collects gentxs on chain. -func (c *Chain) CollectGentx(ctx context.Context) error { - errb := &bytes.Buffer{} - - err := cmdrunner. - New(c.cmdOptions()...). - Run(ctx, step.New( - c.cmd.CollectGentxsCommand(), - step.Stderr(io.MultiWriter(c.stdLog(logAppd).err, errb)), - step.Stdout(c.stdLog(logAppd).out), - )) - return errors.Wrap(err, errb.String()) -} - -// ShowNodeID shows node's id. -func (c *Chain) ShowNodeID(ctx context.Context) (string, error) { - var ( - key = &bytes.Buffer{} - errb = &bytes.Buffer{} - ) - - if err := cmdrunner. - New(c.cmdOptions()...). - Run(ctx, - step.New( - c.cmd.ShowNodeIDCommand(), - step.Stdout(key), - step.Stderr(errb), - ), - ); err != nil { - return "", errors.Wrap(err, errb.String()) - } - - return strings.TrimSpace(key.String()), nil -} diff --git a/starport/services/chain/log.go b/starport/services/chain/log.go index c4b1c534b1..78ea90dac1 100644 --- a/starport/services/chain/log.go +++ b/starport/services/chain/log.go @@ -17,8 +17,8 @@ var prefixes = map[logType]struct { }{ logStarport: {"starport", 202}, logBuild: {"build", 203}, - logAppd: {"%sd", 204}, - logAppcli: {"%scli", 205}, + logAppd: {"%s daemon", 204}, + logAppcli: {"%s cli", 205}, logRelayer: {"relayer", 206}, } @@ -75,3 +75,11 @@ func (c *Chain) stdLog(logType logType) std { err: stderr, } } + +func (c *Chain) genPrefix(logType logType) string { + prefix := prefixes[logType] + + return prefixgen. + New(prefix.Name, prefixgen.Common(prefixgen.Color(prefix.Color))...). + Gen(c.app.Name) +} diff --git a/starport/services/chain/plugin-launchpad.go b/starport/services/chain/plugin-launchpad.go index 208e5c1a34..97b3afc242 100644 --- a/starport/services/chain/plugin-launchpad.go +++ b/starport/services/chain/plugin-launchpad.go @@ -6,9 +6,11 @@ import ( "path/filepath" "github.com/tendermint/starport/starport/pkg/chaincmd" + "golang.org/x/sync/errgroup" "github.com/pelletier/go-toml" "github.com/pkg/errors" + chaincmdrunner "github.com/tendermint/starport/starport/pkg/chaincmd/runner" "github.com/tendermint/starport/starport/pkg/cmdrunner" "github.com/tendermint/starport/starport/pkg/cmdrunner/step" "github.com/tendermint/starport/starport/pkg/cosmosver" @@ -17,11 +19,12 @@ import ( ) type launchpadPlugin struct { - app App - cmd chaincmd.ChainCmd + app App + chain *Chain + cmd chaincmd.ChainCmd } -func newLaunchpadPlugin(app App) *launchpadPlugin { +func newLaunchpadPlugin(app App, chain *Chain) *launchpadPlugin { // initialize the chain command with keyring backend test cmd := chaincmd.New( app.D(), @@ -30,8 +33,9 @@ func newLaunchpadPlugin(app App) *launchpadPlugin { ) return &launchpadPlugin{ - app: app, - cmd: cmd, + app: app, + chain: chain, + cmd: cmd, } } @@ -65,34 +69,19 @@ func (p *launchpadPlugin) Binaries() []string { } } -func (p *launchpadPlugin) AddUserCommand(accountName string) step.Options { - return step.NewOptions().Add(p.cmd.AddKeyCommand(accountName)) -} - -func (p *launchpadPlugin) ImportUserCommand(name, mnemonic string) step.Options { - return step.NewOptions(). - Add( - p.cmd.ImportKeyCommand(name), - step.Write([]byte(mnemonic+"\n")), - ) -} - -func (p *launchpadPlugin) ShowAccountCommand(accountName string) step.Option { - return p.cmd.ShowKeyAddressCommand(accountName) -} - -func (p *launchpadPlugin) ConfigCommands(chainID string) []step.Option { - return []step.Option{ - p.cmd.LaunchpadSetConfigCommand("keyring-backend", "test"), - p.cmd.LaunchpadSetConfigCommand("chain-id", chainID), - p.cmd.LaunchpadSetConfigCommand("output", "json"), - p.cmd.LaunchpadSetConfigCommand("indent", "true"), - p.cmd.LaunchpadSetConfigCommand("trust-node", "true"), - } +func (p *launchpadPlugin) Configure(ctx context.Context, chainID string) error { + return p.chain.Commands().LaunchpadSetConfigs(ctx, + chaincmdrunner.KV("keyring-backend", "test"), + chaincmdrunner.KV("chain-id", chainID), + chaincmdrunner.KV("output", "json"), + chaincmdrunner.KV("indent", "true"), + chaincmdrunner.KV("trust-node", "true"), + ) } -func (p *launchpadPlugin) GentxCommand(v Validator) step.Option { - return p.cmd.GentxCommand( +func (p *launchpadPlugin) Gentx(ctx context.Context, v Validator) (path string, err error) { + return p.chain.Commands().Gentx( + ctx, v.Name, v.StakingAmount, chaincmd.GentxWithMoniker(v.Moniker), @@ -132,23 +121,20 @@ func (p *launchpadPlugin) configtoml(conf starportconf.Config) error { return err } -func (p *launchpadPlugin) StartCommands(conf starportconf.Config) [][]step.Option { - return [][]step.Option{ - step.NewOptions(). - Add( - p.cmd.StartCommand(), - step.PostExec(func(exitErr error) error { - return errors.Wrapf(exitErr, "cannot run %[1]vd start", p.app.Name) - }), - ), - step.NewOptions(). - Add( - p.cmd.LaunchpadRestServerCommand(xurl.TCP(conf.Servers.APIAddr), xurl.TCP(conf.Servers.RPCAddr)), - step.PostExec(func(exitErr error) error { - return errors.Wrapf(exitErr, "cannot run %[1]vcli rest-server", p.app.Name) - }), - ), - } +func (p *launchpadPlugin) Start(ctx context.Context, conf starportconf.Config) error { + g, ctx := errgroup.WithContext(ctx) + + g.Go(func() error { + err := p.chain.Commands().Start(ctx) + return errors.Wrapf(err, "cannot run %[1]vd start", p.app.Name) + }) + + g.Go(func() error { + err := p.chain.Commands().LaunchpadStartRestServer(ctx, xurl.TCP(conf.Servers.APIAddr), xurl.TCP(conf.Servers.RPCAddr)) + return errors.Wrapf(err, "cannot run %[1]vcli rest-server", p.app.Name) + }) + + return g.Wait() } func (p *launchpadPlugin) StoragePaths() []string { diff --git a/starport/services/chain/plugin-stargate.go b/starport/services/chain/plugin-stargate.go index 3f820a1663..b71dc8b7dc 100644 --- a/starport/services/chain/plugin-stargate.go +++ b/starport/services/chain/plugin-stargate.go @@ -9,7 +9,6 @@ import ( "github.com/pelletier/go-toml" "github.com/pkg/errors" - "github.com/tendermint/starport/starport/pkg/cmdrunner/step" "github.com/tendermint/starport/starport/pkg/cosmosver" "github.com/tendermint/starport/starport/pkg/xurl" starportconf "github.com/tendermint/starport/starport/services/chain/conf" @@ -55,28 +54,13 @@ func (p *stargatePlugin) Binaries() []string { } } -func (p *stargatePlugin) AddUserCommand(accountName string) step.Options { - return step.NewOptions().Add(p.cmd.AddKeyCommand(accountName)) -} - -func (p *stargatePlugin) ImportUserCommand(name, mnemonic string) step.Options { - return step.NewOptions(). - Add( - p.cmd.ImportKeyCommand(name), - step.Write([]byte(mnemonic+"\n")), - ) -} - -func (p *stargatePlugin) ShowAccountCommand(accountName string) step.Option { - return p.cmd.ShowKeyAddressCommand(accountName) -} - -func (p *stargatePlugin) ConfigCommands(_ string) []step.Option { +func (p *stargatePlugin) Configure(_ context.Context, _ string) error { return nil } -func (p *stargatePlugin) GentxCommand(v Validator) step.Option { - return p.cmd.GentxCommand( +func (p *stargatePlugin) Gentx(ctx context.Context, v Validator) (path string, err error) { + return p.chain.Commands().Gentx( + ctx, v.Name, v.StakingAmount, chaincmd.GentxWithMoniker(v.Moniker), @@ -138,21 +122,14 @@ func (p *stargatePlugin) configtoml(conf starportconf.Config) error { return err } -func (p *stargatePlugin) StartCommands(conf starportconf.Config) [][]step.Option { - return [][]step.Option{ - step.NewOptions(). - Add( - p.cmd.StartCommand( - "--pruning", - "nothing", - "--grpc.address", - conf.Servers.GRPCAddr, - ), - step.PostExec(func(exitErr error) error { - return errors.Wrapf(exitErr, "cannot run %[1]vd start", p.app.Name) - }), - ), - } +func (p *stargatePlugin) Start(ctx context.Context, conf starportconf.Config) error { + err := p.chain.Commands().Start(ctx, + "--pruning", + "nothing", + "--grpc.address", + conf.Servers.GRPCAddr, + ) + return errors.Wrapf(err, "cannot run %[1]vd start", p.app.Name) } func (p *stargatePlugin) StoragePaths() []string { diff --git a/starport/services/chain/plugin.go b/starport/services/chain/plugin.go index e38034e794..1efaaa7042 100644 --- a/starport/services/chain/plugin.go +++ b/starport/services/chain/plugin.go @@ -3,7 +3,6 @@ package chain import ( "context" - "github.com/tendermint/starport/starport/pkg/cmdrunner/step" "github.com/tendermint/starport/starport/pkg/cosmosver" starportconf "github.com/tendermint/starport/starport/services/chain/conf" ) @@ -20,26 +19,17 @@ type Plugin interface { // Binaries returns a list of binaries that will be compiled for the app. Binaries() []string - // AddUserCommand returns step.Exec configuration to add users. - AddUserCommand(name string) step.Options - - // ImportUserCommand returns step.Exec configuration to import users. - ImportUserCommand(namem, mnemonic string) step.Options - - // ShowAccountCommand returns step.Exec configuration to run show account. - ShowAccountCommand(accountName string) step.Option - // ConfigCommands returns step.Exec configuration for config commands. - ConfigCommands(chainID string) []step.Option + Configure(ctx context.Context, chainID string) error // GentxCommand returns step.Exec configuration for gentx command. - GentxCommand(v Validator) step.Option + Gentx(context.Context, Validator) (path string, err error) // PostInit hook. PostInit(starportconf.Config) error // StartCommands returns step.Exec configuration to start servers. - StartCommands(starportconf.Config) [][]step.Option + Start(context.Context, starportconf.Config) error // StoragePaths returns a list of where persistent data kept. StoragePaths() []string @@ -65,7 +55,7 @@ func (c *Chain) pickPlugin() (Plugin, error) { } switch version { case cosmosver.Launchpad: - return newLaunchpadPlugin(c.app), nil + return newLaunchpadPlugin(c.app, c), nil case cosmosver.Stargate: return newStargatePlugin(c.app, c) } diff --git a/starport/services/chain/serve.go b/starport/services/chain/serve.go index 27c0fe1f55..306f3ec7a8 100644 --- a/starport/services/chain/serve.go +++ b/starport/services/chain/serve.go @@ -12,7 +12,6 @@ import ( "path" "path/filepath" "strings" - "sync" "time" "github.com/pkg/errors" @@ -183,90 +182,65 @@ func (c *Chain) serve(ctx context.Context) error { } for _, account := range conf.Accounts { - acc, err := c.CreateAccount(ctx, account.Name, "", false) + acc, err := c.Commands().AddAccount(ctx, account.Name, "") if err != nil { return err } - acc.Coins = strings.Join(account.Coins, ",") - if err := c.AddGenesisAccount(ctx, acc); err != nil { + coins := strings.Join(account.Coins, ",") + if err := c.Commands().AddGenesisAccount(ctx, acc.Address, coins); err != nil { return err } + + fmt.Fprintf(c.stdLog(logStarport).out, "šŸ™‚ Created an account. Password (mnemonic): %[1]v\n", acc.Mnemonic) } + for _, account := range sconf.Accounts { - acc, err := c.CreateAccount(ctx, account.Name, account.Mnemonic, false) + acc, err := c.Commands().AddAccount(ctx, account.Name, account.Mnemonic) if err != nil { return err } - acc.Coins = strings.Join(account.Coins, ",") - if err := c.AddGenesisAccount(ctx, acc); err != nil { + coins := strings.Join(account.Coins, ",") + if err := c.Commands().AddGenesisAccount(ctx, acc.Address, coins); err != nil { return err } } - setupSteps, err := c.setupSteps() - if err != nil { - return err - } - if err := cmdrunner. - New(c.cmdOptions()...). - Run(ctx, setupSteps...); err != nil { + if err := c.configure(ctx); err != nil { return err } - if _, err := c.Gentx(ctx, Validator{ + + if _, err := c.plugin.Gentx(ctx, Validator{ Name: conf.Validator.Name, StakingAmount: conf.Validator.Staked, }); err != nil { return err } - if err := c.CollectGentx(ctx); err != nil { + + if err := c.Commands().CollectGentxs(ctx); err != nil { return err } - wr := sync.WaitGroup{} - wr.Add(1) + return c.start(ctx, conf) +} + +func (c *Chain) start(ctx context.Context, conf conf.Config) error { + g, ctx := errgroup.WithContext(ctx) + + g.Go(func() error { return c.plugin.Start(ctx, conf) }) + + fmt.Fprintf(c.stdLog(logStarport).out, "šŸŒ Running a Cosmos '%[1]v' app with Tendermint at %s.\n", c.app.Name, xurl.HTTP(conf.Servers.RPCAddr)) + fmt.Fprintf(c.stdLog(logStarport).out, "šŸŒ Running a server at %s (LCD)\n", xurl.HTTP(conf.Servers.APIAddr)) + fmt.Fprintf(c.stdLog(logStarport).out, "\nšŸš€ Get started: %s\n\n", xurl.HTTP(conf.Servers.DevUIAddr)) go func() { - wr.Wait() if err := c.initRelayer(ctx, conf); err != nil && ctx.Err() == nil { fmt.Fprintf(c.stdLog(logStarport).err, "could not init relayer: %s", err) } }() - return cmdrunner. - New(append(c.cmdOptions(), cmdrunner.RunParallel())...). - Run(ctx, c.serverSteps(ctx, &wr, conf)...) -} - -func (c *Chain) serverSteps(_ context.Context, wr *sync.WaitGroup, conf conf.Config) (steps step.Steps) { - var wg sync.WaitGroup - wg.Add(len(c.plugin.StartCommands(conf))) - go func() { - wg.Wait() - fmt.Fprintf(c.stdLog(logStarport).out, "šŸŒ Running a Cosmos '%[1]v' app with Tendermint at %s.\n", c.app.Name, xurl.HTTP(conf.Servers.RPCAddr)) - fmt.Fprintf(c.stdLog(logStarport).out, "šŸŒ Running a server at %s (LCD)\n", xurl.HTTP(conf.Servers.APIAddr)) - fmt.Fprintf(c.stdLog(logStarport).out, "\nšŸš€ Get started: %s\n\n", xurl.HTTP(conf.Servers.DevUIAddr)) - wr.Done() - }() - - for _, exec := range c.plugin.StartCommands(conf) { - steps.Add( - step.New( - step.NewOptions(). - Add(exec...). - Add( - step.InExec(func() error { - wg.Done() - return nil - }), - ). - Add(c.stdSteps(logAppd)...)..., - ), - ) - } - - return + return g.Wait() } func (c *Chain) watchAppFrontend(ctx context.Context) error { diff --git a/starport/services/networkbuilder/blockchain.go b/starport/services/networkbuilder/blockchain.go index ba8982b24b..57feb15007 100644 --- a/starport/services/networkbuilder/blockchain.go +++ b/starport/services/networkbuilder/blockchain.go @@ -8,6 +8,7 @@ import ( "os" "github.com/cosmos/cosmos-sdk/types" + "github.com/tendermint/starport/starport/pkg/chaincmd" "github.com/tendermint/starport/starport/pkg/cosmosver" "github.com/tendermint/starport/starport/pkg/events" "github.com/tendermint/starport/starport/pkg/gomodulepath" @@ -166,16 +167,34 @@ type Account struct { } func (b *Blockchain) CreateAccount(ctx context.Context, account chain.Account) (chain.Account, error) { - return b.chain.CreateAccount(ctx, account.Name, account.Mnemonic, false) + acc, err := b.chain.Commands().AddAccount(ctx, account.Name, account.Mnemonic) + if err != nil { + return chain.Account{}, err + } + return chain.Account{ + Name: acc.Name, + Address: acc.Address, + Mnemonic: acc.Mnemonic, + }, nil } // IssueGentx creates a Genesis transaction for account with proposal. func (b *Blockchain) IssueGentx(ctx context.Context, account chain.Account, proposal Proposal) (gentx jsondoc.Doc, err error) { proposal.Validator.Name = account.Name - if err := b.chain.AddGenesisAccount(ctx, account); err != nil { + if err := b.chain.Commands().AddGenesisAccount(ctx, account.Address, account.Coins); err != nil { return nil, err } - gentxPath, err := b.chain.Gentx(ctx, proposal.Validator) + gentxPath, err := b.chain.Commands().Gentx( + ctx, + account.Name, + proposal.Validator.StakingAmount, + chaincmd.GentxWithMoniker(proposal.Validator.Moniker), + chaincmd.GentxWithCommissionRate(proposal.Validator.CommissionRate), + chaincmd.GentxWithCommissionMaxRate(proposal.Validator.CommissionMaxRate), + chaincmd.GentxWithCommissionMaxChangeRate(proposal.Validator.CommissionMaxChangeRate), + chaincmd.GentxWithMinSelfDelegation(proposal.Validator.MinSelfDelegation), + chaincmd.GentxWithGasPrices(proposal.Validator.GasPrices), + ) if err != nil { return nil, err } @@ -187,7 +206,7 @@ func (b *Blockchain) IssueGentx(ctx context.Context, account chain.Account, prop // address is the ip+port combination of a p2p address of a node (does not include id). // https://docs.tendermint.com/master/spec/p2p/config.html. func (b *Blockchain) Join(ctx context.Context, accountAddress, publicAddress string, coins types.Coins, gentx []byte, selfDelegation types.Coin) error { - key, err := b.chain.ShowNodeID(ctx) + key, err := b.chain.Commands().ShowNodeID(ctx) if err != nil { return err } diff --git a/starport/services/networkbuilder/networkbuilder.go b/starport/services/networkbuilder/networkbuilder.go index 517d114527..6599128253 100644 --- a/starport/services/networkbuilder/networkbuilder.go +++ b/starport/services/networkbuilder/networkbuilder.go @@ -21,8 +21,7 @@ import ( "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/plumbing" "github.com/tendermint/starport/starport/pkg/availableport" - "github.com/tendermint/starport/starport/pkg/cmdrunner" - "github.com/tendermint/starport/starport/pkg/cmdrunner/step" + chaincmdrunner "github.com/tendermint/starport/starport/pkg/chaincmd/runner" "github.com/tendermint/starport/starport/pkg/confile" "github.com/tendermint/starport/starport/pkg/cosmosver" "github.com/tendermint/starport/starport/pkg/ctxticker" @@ -358,11 +357,11 @@ func (b *Builder) StartChain(ctx context.Context, chainID string, flags []string // run the start command of the chain. g.Go(func() error { - return cmdrunner.New().Run(ctx, step.New( - chainHandler.Commands().StartCommand(flags...), - step.Stdout(os.Stdout), - step.Stderr(os.Stderr), - )) + return chainHandler.Commands(). + Copy( + chaincmdrunner.Stdout(os.Stdout), + chaincmdrunner.Stderr(os.Stderr)). + Start(ctx, flags...) }) // log connected peers info. @@ -427,7 +426,7 @@ func generateGenesis(ctx context.Context, chainInfo spn.Chain, launchInfo spn.La Coins: account.Coins.String(), } - if err := chainHandler.AddGenesisAccount(ctx, genesisAccount); err != nil { + if err := chainHandler.Commands().AddGenesisAccount(ctx, genesisAccount.Address, genesisAccount.Coins); err != nil { return err } } @@ -455,7 +454,7 @@ func generateGenesis(ctx context.Context, chainInfo spn.Chain, launchInfo spn.La } } if len(launchInfo.GenTxs) > 0 { - if err = chainHandler.CollectGentx(ctx); err != nil { + if err = chainHandler.Commands().CollectGentxs(ctx); err != nil { return err } } diff --git a/starport/services/networkbuilder/simulation.go b/starport/services/networkbuilder/simulation.go index b17c264c30..8becb289fd 100644 --- a/starport/services/networkbuilder/simulation.go +++ b/starport/services/networkbuilder/simulation.go @@ -1,7 +1,6 @@ package networkbuilder import ( - "bytes" "context" "errors" "fmt" @@ -18,8 +17,7 @@ import ( "github.com/otiai10/copy" "github.com/pelletier/go-toml" "github.com/tendermint/starport/starport/pkg/availableport" - "github.com/tendermint/starport/starport/pkg/cmdrunner" - "github.com/tendermint/starport/starport/pkg/cmdrunner/step" + chaincmdrunner "github.com/tendermint/starport/starport/pkg/chaincmd/runner" "github.com/tendermint/starport/starport/pkg/cosmosver" "github.com/tendermint/starport/starport/pkg/events" "github.com/tendermint/starport/starport/pkg/gomodulepath" @@ -91,14 +89,15 @@ func (b *Builder) VerifyProposals(ctx context.Context, chainID string, proposals return false, err } + runner := chainHandler.Commands(). + Copy( + chaincmdrunner.Stderr(commandOut), // This is the error of the verifying command, therefore this is the same as stdout + chaincmdrunner.Stdout(commandOut), + ) + // run validate-genesis command on the generated genesis b.ev.Send(events.New(events.StatusOngoing, "validating genesis format")) - err = cmdrunner.New().Run(ctx, step.New( - chainHandler.Commands().ValidateGenesisCommand(), - step.Stderr(commandOut), // This is the error of the verifying command, therefore this is the same as stdout - step.Stdout(commandOut), - )) - if err != nil { + if runner.ValidateGenesis(ctx); err != nil { return false, nil } b.ev.Send(events.New(events.StatusDone, "genesis correctly formatted")) @@ -116,23 +115,13 @@ func (b *Builder) VerifyProposals(ctx context.Context, chainID string, proposals // Go routine to start the app b.ev.Send(events.New(events.StatusOngoing, "starting chain")) go func() { - errBytes := &bytes.Buffer{} - err := cmdrunner.New().Run(ctx, step.New( - chainHandler.Commands().StartCommand(), - step.PostExec(func(exitErr error) error { - // If the error is validator set is nil, it means the genesis didn't get broken after a proposal - // The genesis was correctly generated but we don't have the necessary proposals to have a validator set - // after the execution of gentxs - if strings.Contains(errBytes.String(), ValidatorSetNilErrorMessage) { - return nil - } - - // We interpret any other error as if the genesis is broken - return exitErr - }), - step.Stderr(io.MultiWriter(commandOut, errBytes)), - step.Stdout(commandOut), - )) + err := runner.Start(ctx) + // If the error is validator set is nil, it means the genesis didn't get broken after a proposal + // The genesis was correctly generated but we don't have the necessary proposals to have a validator set + // after the execution of gentxs + if strings.Contains(err.Error(), ValidatorSetNilErrorMessage) { + err = nil + } exit <- err }() From e7b3711b7138e068039eee20586aa4c95379bec6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0lker=20G=C3=B6ktu=C4=9F=20=C3=96ZT=C3=9CRK?= Date: Thu, 7 Jan 2021 12:36:36 +0300 Subject: [PATCH 3/5] cleanup --- starport/services/chain/init.go | 6 +----- starport/services/chain/plugin-launchpad.go | 9 --------- starport/services/chain/plugin-stargate.go | 14 -------------- 3 files changed, 1 insertion(+), 28 deletions(-) diff --git a/starport/services/chain/init.go b/starport/services/chain/init.go index f1532c44ab..b948803f46 100644 --- a/starport/services/chain/init.go +++ b/starport/services/chain/init.go @@ -71,11 +71,7 @@ func (c *Chain) Init(ctx context.Context) error { } // run post init handler - if err := c.plugin.PostInit(conf); err != nil { - return err - } - - return nil + return c.plugin.PostInit(conf) } func (c *Chain) configure(ctx context.Context) error { diff --git a/starport/services/chain/plugin-launchpad.go b/starport/services/chain/plugin-launchpad.go index 97b3afc242..f2c60840f3 100644 --- a/starport/services/chain/plugin-launchpad.go +++ b/starport/services/chain/plugin-launchpad.go @@ -21,21 +21,12 @@ import ( type launchpadPlugin struct { app App chain *Chain - cmd chaincmd.ChainCmd } func newLaunchpadPlugin(app App, chain *Chain) *launchpadPlugin { - // initialize the chain command with keyring backend test - cmd := chaincmd.New( - app.D(), - chaincmd.WithKeyringBackend(chaincmd.KeyringBackendTest), - chaincmd.WithLaunchpad(app.CLI()), - ) - return &launchpadPlugin{ app: app, chain: chain, - cmd: cmd, } } diff --git a/starport/services/chain/plugin-stargate.go b/starport/services/chain/plugin-stargate.go index b71dc8b7dc..9100419462 100644 --- a/starport/services/chain/plugin-stargate.go +++ b/starport/services/chain/plugin-stargate.go @@ -17,26 +17,12 @@ import ( type stargatePlugin struct { app App chain *Chain - cmd chaincmd.ChainCmd } func newStargatePlugin(app App, chain *Chain) (*stargatePlugin, error) { - id, err := chain.ID() - if err != nil { - return nil, err - } - - // initialize the chain command with keyring backend test - cmd := chaincmd.New( - app.D(), - chaincmd.WithKeyringBackend(chaincmd.KeyringBackendTest), - chaincmd.WithChainID(id), - ) - return &stargatePlugin{ app: app, chain: chain, - cmd: cmd, }, nil } From ff8f3f932d42b36384386088a3e5faf4a745a22f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0lker=20G=C3=B6ktu=C4=9F=20=C3=96ZT=C3=9CRK?= Date: Thu, 7 Jan 2021 12:47:43 +0300 Subject: [PATCH 4/5] fix linter --- starport/services/chain/plugin-stargate.go | 4 ++-- starport/services/chain/plugin.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/starport/services/chain/plugin-stargate.go b/starport/services/chain/plugin-stargate.go index 9100419462..0aae059f8c 100644 --- a/starport/services/chain/plugin-stargate.go +++ b/starport/services/chain/plugin-stargate.go @@ -19,11 +19,11 @@ type stargatePlugin struct { chain *Chain } -func newStargatePlugin(app App, chain *Chain) (*stargatePlugin, error) { +func newStargatePlugin(app App, chain *Chain) *stargatePlugin { return &stargatePlugin{ app: app, chain: chain, - }, nil + } } func (p *stargatePlugin) Name() string { diff --git a/starport/services/chain/plugin.go b/starport/services/chain/plugin.go index 1efaaa7042..dcb812b4a0 100644 --- a/starport/services/chain/plugin.go +++ b/starport/services/chain/plugin.go @@ -57,7 +57,7 @@ func (c *Chain) pickPlugin() (Plugin, error) { case cosmosver.Launchpad: return newLaunchpadPlugin(c.app, c), nil case cosmosver.Stargate: - return newStargatePlugin(c.app, c) + return newStargatePlugin(c.app, c), nil } panic("unknown cosmos version") } From 758403469bb27eea81c09bb62056b9b519fcf79f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0lker=20G=C3=B6ktu=C4=9F=20=C3=96ZT=C3=9CRK?= Date: Thu, 7 Jan 2021 15:58:15 +0300 Subject: [PATCH 5/5] cosmetics --- starport/pkg/chaincmd/runner/chain.go | 12 ++++++------ starport/services/chain/plugin-launchpad.go | 10 +++++----- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/starport/pkg/chaincmd/runner/chain.go b/starport/pkg/chaincmd/runner/chain.go index e6e73e5be7..fd0f232aa0 100644 --- a/starport/pkg/chaincmd/runner/chain.go +++ b/starport/pkg/chaincmd/runner/chain.go @@ -24,19 +24,19 @@ func (r Runner) Init(ctx context.Context, moniker string) error { return r.run(ctx, runOptions{}, r.cc.InitCommand(moniker)) } -// KeyValue holds a key, value pair. -type KeyValue struct { +// KV holds a key, value pair. +type KV struct { key string value string } -// KV returns a new key, value pair. -func KV(key, value string) KeyValue { - return KeyValue{key, value} +// NewKV returns a new key, value pair. +func NewKV(key, value string) KV { + return KV{key, value} } // LaunchpadSetConfigs updates configurations for a launchpad app. -func (r Runner) LaunchpadSetConfigs(ctx context.Context, kvs ...KeyValue) error { +func (r Runner) LaunchpadSetConfigs(ctx context.Context, kvs ...KV) error { for _, kv := range kvs { if err := r.run(ctx, runOptions{}, r.cc.LaunchpadSetConfigCommand(kv.key, kv.value)); err != nil { return err diff --git a/starport/services/chain/plugin-launchpad.go b/starport/services/chain/plugin-launchpad.go index f2c60840f3..5b9151faf2 100644 --- a/starport/services/chain/plugin-launchpad.go +++ b/starport/services/chain/plugin-launchpad.go @@ -62,11 +62,11 @@ func (p *launchpadPlugin) Binaries() []string { func (p *launchpadPlugin) Configure(ctx context.Context, chainID string) error { return p.chain.Commands().LaunchpadSetConfigs(ctx, - chaincmdrunner.KV("keyring-backend", "test"), - chaincmdrunner.KV("chain-id", chainID), - chaincmdrunner.KV("output", "json"), - chaincmdrunner.KV("indent", "true"), - chaincmdrunner.KV("trust-node", "true"), + chaincmdrunner.NewKV("keyring-backend", "test"), + chaincmdrunner.NewKV("chain-id", chainID), + chaincmdrunner.NewKV("output", "json"), + chaincmdrunner.NewKV("indent", "true"), + chaincmdrunner.NewKV("trust-node", "true"), ) }