Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

e2e: allow running of single node using the e2e app (backport) #7024

Merged
merged 2 commits into from
Sep 29, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG_PENDING.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ Friendly reminder, we have a [bug bounty program](https://hackerone.com/tendermi

### FEATURES

- [\#6982](https://github.com/tendermint/tendermint/pull/6982) tendermint binary has built-in suppport for running the end to end application (with state sync support) (@cmwaters).

### IMPROVEMENTS

### BUG FIXES
4 changes: 1 addition & 3 deletions cmd/tendermint/commands/run_node.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,7 @@ func AddNodeFlags(cmd *cobra.Command) {
"proxy_app",
config.ProxyApp,
"proxy app address, or one of: 'kvstore',"+
" 'persistent_kvstore',"+
" 'counter',"+
" 'counter_serial' or 'noop' for local testing.")
" 'persistent_kvstore', 'counter', 'e2e' or 'noop' for local testing.")
cmd.Flags().String("abci", config.ABCI, "specify abci transport (socket | grpc)")

// rpc flags
Expand Down
7 changes: 7 additions & 0 deletions proxy/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/tendermint/tendermint/abci/example/kvstore"
"github.com/tendermint/tendermint/abci/types"
tmsync "github.com/tendermint/tendermint/libs/sync"
e2e "github.com/tendermint/tendermint/test/e2e/app"
)

// ClientCreator creates new ABCI clients.
Expand Down Expand Up @@ -79,6 +80,12 @@ func DefaultClientCreator(addr, transport, dbDir string) ClientCreator {
return NewLocalClientCreator(kvstore.NewApplication())
case "persistent_kvstore":
return NewLocalClientCreator(kvstore.NewPersistentKVStoreApplication(dbDir))
case "e2e":
app, err := e2e.NewApplication(e2e.DefaultConfig(dbDir))
if err != nil {
panic(err)
}
return NewLocalClientCreator(app)
case "noop":
return NewLocalClientCreator(types.NewBaseApplication())
default:
Expand Down
6 changes: 3 additions & 3 deletions test/e2e/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ docker:
# We need to build support for database backends into the app in
# order to build a binary with a Tendermint node in it (for built-in
# ABCI testing).
app:
go build -o build/app -tags badgerdb,boltdb,cleveldb,rocksdb ./app
node:
go build -o build/node -tags badgerdb,boltdb,cleveldb,rocksdb ./node

# To be used primarily by the e2e docker instance. If you want to produce this binary
# elsewhere, then run go build in the maverick directory.
Expand All @@ -20,4 +20,4 @@ generator:
runner:
go build -o build/runner ./runner

.PHONY: all app docker generator maverick runner
.PHONY: all node docker generator maverick runner
34 changes: 33 additions & 1 deletion test/e2e/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,42 @@ Docker does not enable IPv6 by default. To do so, enter the following in
}
```

## Benchmarking testnets
## Benchmarking Testnets

It is also possible to run a simple benchmark on a testnet. This is done through the `benchmark` command. This manages the entire process: setting up the environment, starting the test net, waiting for a considerable amount of blocks to be used (currently 100), and then returning the following metrics from the sample of the blockchain:

- Average time to produce a block
- Standard deviation of producing a block
- Minimum and maximum time to produce a block

## Running Individual Nodes

The E2E test harness is designed to run several nodes of varying configurations within docker. It is also possible to run a single node in the case of running larger, geographically-dispersed testnets. To run a single node you can either run:

**Built-in**

```bash
make node
tendermint init validator
TMHOME=$HOME/.tendermint ./build/node ./node/built-in.toml
```

To make things simpler the e2e application can also be run in the tendermint binary
by running

```bash
tendermint start --proxy-app e2e
```

However this won't offer the same level of configurability of the application.

**Socket**

```bash
make node
tendermint init validator
tendermint start
./build/node ./node.socket.toml
```

Check `node/config.go` to see how the settings of the test application can be tweaked.
51 changes: 50 additions & 1 deletion test/e2e/app/app.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package main
package app

import (
"bytes"
Expand Down Expand Up @@ -28,6 +28,55 @@ type Application struct {
restoreChunks [][]byte
}

// Config allows for the setting of high level parameters for running the e2e Application
// KeyType and ValidatorUpdates must be the same for all nodes running the same application.
type Config struct {
// The directory with which state.json will be persisted in. Usually $HOME/.tendermint/data
Dir string `toml:"dir"`

// SnapshotInterval specifies the height interval at which the application
// will take state sync snapshots. Defaults to 0 (disabled).
SnapshotInterval uint64 `toml:"snapshot_interval"`

// RetainBlocks specifies the number of recent blocks to retain. Defaults to
// 0, which retains all blocks. Must be greater that PersistInterval,
// SnapshotInterval and EvidenceAgeHeight.
RetainBlocks uint64 `toml:"retain_blocks"`

// KeyType sets the curve that will be used by validators.
// Options are ed25519 & secp256k1
KeyType string `toml:"key_type"`

// PersistInterval specifies the height interval at which the application
// will persist state to disk. Defaults to 1 (every height), setting this to
// 0 disables state persistence.
PersistInterval uint64 `toml:"persist_interval"`

// ValidatorUpdates is a map of heights to validator names and their power,
// and will be returned by the ABCI application. For example, the following
// changes the power of validator01 and validator02 at height 1000:
//
// [validator_update.1000]
// validator01 = 20
// validator02 = 10
//
// Specifying height 0 returns the validator update during InitChain. The
// application returns the validator updates as-is, i.e. removing a
// validator must be done by returning it with power 0, and any validators
// not specified are not changed.
//
// height <-> pubkey <-> voting power
ValidatorUpdates map[string]map[string]uint8 `toml:"validator_update"`
}

func DefaultConfig(dir string) *Config {
return &Config{
PersistInterval: 1,
SnapshotInterval: 100,
Dir: dir,
}
}

// NewApplication creates the application.
func NewApplication(cfg *Config) (*Application, error) {
state, err := NewState(filepath.Join(cfg.Dir, "state.json"), cfg.PersistInterval)
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/app/snapshots.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// nolint: gosec
package main
package app

import (
"encoding/json"
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/app/state.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//nolint: gosec
package main
package app

import (
"crypto/sha256"
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ COPY . .
RUN make build && cp build/tendermint /usr/bin/tendermint
COPY test/e2e/docker/entrypoint* /usr/bin/
RUN cd test/e2e && make maverick && cp build/maverick /usr/bin/maverick
RUN cd test/e2e && make app && cp build/app /usr/bin/app
RUN cd test/e2e && make node && cp build/node /usr/bin/app

# Set up runtime directory. We don't use a separate runtime image since we need
# e.g. leveldb and rocksdb which are already installed in the build image.
Expand Down
4 changes: 4 additions & 0 deletions test/e2e/node/built-in.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
snapshot_interval = 100
persist_interval = 1
chain_id = "test-chain"
protocol = "builtin"
14 changes: 14 additions & 0 deletions test/e2e/app/config.go → test/e2e/node/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (
"fmt"

"github.com/BurntSushi/toml"

"github.com/tendermint/tendermint/test/e2e/app"
)

// Config is the application configuration.
Expand All @@ -26,6 +28,18 @@ type Config struct {
KeyType string `toml:"key_type"`
}

// App extracts out the application specific configuration parameters
func (cfg *Config) App() *app.Config {
return &app.Config{
Dir: cfg.Dir,
SnapshotInterval: cfg.SnapshotInterval,
RetainBlocks: cfg.RetainBlocks,
KeyType: cfg.KeyType,
ValidatorUpdates: cfg.ValidatorUpdates,
PersistInterval: cfg.PersistInterval,
}
}

// LoadConfig loads the configuration from disk.
func LoadConfig(file string) (*Config, error) {
cfg := &Config{
Expand Down
7 changes: 4 additions & 3 deletions test/e2e/app/main.go → test/e2e/node/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
"github.com/tendermint/tendermint/privval"
"github.com/tendermint/tendermint/proxy"
rpcserver "github.com/tendermint/tendermint/rpc/jsonrpc/server"
"github.com/tendermint/tendermint/test/e2e/app"
e2e "github.com/tendermint/tendermint/test/e2e/pkg"
mcs "github.com/tendermint/tendermint/test/maverick/consensus"
maverick "github.com/tendermint/tendermint/test/maverick/node"
Expand Down Expand Up @@ -98,7 +99,7 @@ func run(configFile string) error {

// startApp starts the application server, listening for connections from Tendermint.
func startApp(cfg *Config) error {
app, err := NewApplication(cfg)
app, err := app.NewApplication(cfg.App())
if err != nil {
return err
}
Expand All @@ -119,7 +120,7 @@ func startApp(cfg *Config) error {
//
// FIXME There is no way to simply load the configuration from a file, so we need to pull in Viper.
func startNode(cfg *Config) error {
app, err := NewApplication(cfg)
app, err := app.NewApplication(cfg.App())
if err != nil {
return err
}
Expand Down Expand Up @@ -205,7 +206,7 @@ func startLightClient(cfg *Config) error {
// startMaverick starts a Maverick node that runs the application directly. It assumes the Tendermint
// configuration is in $TMHOME/config/tendermint.toml.
func startMaverick(cfg *Config) error {
app, err := NewApplication(cfg)
app, err := app.NewApplication(cfg.App())
if err != nil {
return err
}
Expand Down
5 changes: 5 additions & 0 deletions test/e2e/node/socket.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
snapshot_interval = 100
persist_interval = 1
chain_id = "test-chain"
protocol = "socket"
listen = "tcp://127.0.0.1:26658"