Browse Source

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

pull/7009/head
Callum Waters 3 years ago
committed by GitHub
parent
commit
60a6c6fb1a
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 127 additions and 17 deletions
  1. +2
    -0
      CHANGELOG_PENDING.md
  2. +1
    -1
      cmd/tendermint/commands/run_node.go
  3. +8
    -1
      internal/proxy/client.go
  4. +3
    -6
      test/e2e/Makefile
  5. +33
    -1
      test/e2e/README.md
  6. +51
    -2
      test/e2e/app/app.go
  7. +1
    -1
      test/e2e/app/snapshots.go
  8. +1
    -1
      test/e2e/app/state.go
  9. +1
    -1
      test/e2e/docker/Dockerfile
  10. +4
    -0
      test/e2e/node/built-in.toml
  11. +14
    -1
      test/e2e/node/config.go
  12. +3
    -2
      test/e2e/node/main.go
  13. +5
    -0
      test/e2e/node/socket.toml

+ 2
- 0
CHANGELOG_PENDING.md View File

@ -27,6 +27,8 @@ Friendly reminder: We have a [bug bounty program](https://hackerone.com/tendermi
### FEATURES ### FEATURES
- [\#6982](https://github.com/tendermint/tendermint/pull/6982) tendermint binary has built-in suppport for running the e2e application (with state sync support) (@cmwaters).
### IMPROVEMENTS ### IMPROVEMENTS
### BUG FIXES ### BUG FIXES


+ 1
- 1
cmd/tendermint/commands/run_node.go View File

@ -65,7 +65,7 @@ func AddNodeFlags(cmd *cobra.Command) {
"proxy-app", "proxy-app",
config.ProxyApp, config.ProxyApp,
"proxy app address, or one of: 'kvstore',"+ "proxy app address, or one of: 'kvstore',"+
" 'persistent_kvstore' or 'noop' for local testing.")
" 'persistent_kvstore', 'e2e' or 'noop' for local testing.")
cmd.Flags().String("abci", config.ABCI, "specify abci transport (socket | grpc)") cmd.Flags().String("abci", config.ABCI, "specify abci transport (socket | grpc)")
// rpc flags // rpc flags


+ 8
- 1
internal/proxy/client.go View File

@ -6,11 +6,12 @@ import (
abciclient "github.com/tendermint/tendermint/abci/client" abciclient "github.com/tendermint/tendermint/abci/client"
"github.com/tendermint/tendermint/abci/example/kvstore" "github.com/tendermint/tendermint/abci/example/kvstore"
"github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/abci/types"
e2e "github.com/tendermint/tendermint/test/e2e/app"
) )
// DefaultClientCreator returns a default ClientCreator, which will create a // DefaultClientCreator returns a default ClientCreator, which will create a
// local client if addr is one of: 'kvstore', // local client if addr is one of: 'kvstore',
// 'persistent_kvstore' or 'noop', otherwise - a remote client.
// 'persistent_kvstore', 'e2e', or 'noop', otherwise - a remote client.
// //
// The Closer is a noop except for persistent_kvstore applications, // The Closer is a noop except for persistent_kvstore applications,
// which will clean up the store. // which will clean up the store.
@ -21,6 +22,12 @@ func DefaultClientCreator(addr, transport, dbDir string) (abciclient.Creator, io
case "persistent_kvstore": case "persistent_kvstore":
app := kvstore.NewPersistentKVStoreApplication(dbDir) app := kvstore.NewPersistentKVStoreApplication(dbDir)
return abciclient.NewLocalCreator(app), app return abciclient.NewLocalCreator(app), app
case "e2e":
app, err := e2e.NewApplication(e2e.DefaultConfig(dbDir))
if err != nil {
panic(err)
}
return abciclient.NewLocalCreator(app), noopCloser{}
case "noop": case "noop":
return abciclient.NewLocalCreator(types.NewBaseApplication()), noopCloser{} return abciclient.NewLocalCreator(types.NewBaseApplication()), noopCloser{}
default: default:


+ 3
- 6
test/e2e/Makefile View File

@ -3,11 +3,8 @@ all: docker generator runner tests
docker: docker:
docker build --tag tendermint/e2e-node -f docker/Dockerfile ../.. docker build --tag tendermint/e2e-node -f docker/Dockerfile ../..
# 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
generator: generator:
go build -o build/generator ./generator go build -o build/generator ./generator
@ -18,4 +15,4 @@ runner:
tests: tests:
go test -o build/tests ./tests go test -o build/tests ./tests
.PHONY: all app docker generator runner tests
.PHONY: all docker generator runner tests node

+ 33
- 1
test/e2e/README.md View File

@ -142,10 +142,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: 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 - Average time to produce a block
- Standard deviation of producing a block - Standard deviation of producing a block
- Minimum and maximum time to produce 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
- 2
test/e2e/app/app.go View File

@ -1,4 +1,4 @@
package main
package app
import ( import (
"bytes" "bytes"
@ -27,6 +27,55 @@ type Application struct {
restoreChunks [][]byte 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. // NewApplication creates the application.
func NewApplication(cfg *Config) (*Application, error) { func NewApplication(cfg *Config) (*Application, error) {
state, err := NewState(filepath.Join(cfg.Dir, "state.json"), cfg.PersistInterval) state, err := NewState(filepath.Join(cfg.Dir, "state.json"), cfg.PersistInterval)
@ -134,7 +183,7 @@ func (app *Application) Commit() abci.ResponseCommit {
if err != nil { if err != nil {
panic(err) panic(err)
} }
logger.Info("Created state sync snapshot", "height", snapshot.Height)
app.logger.Info("Created state sync snapshot", "height", snapshot.Height)
} }
retainHeight := int64(0) retainHeight := int64(0)
if app.cfg.RetainBlocks > 0 { if app.cfg.RetainBlocks > 0 {


+ 1
- 1
test/e2e/app/snapshots.go View File

@ -1,5 +1,5 @@
// nolint: gosec // nolint: gosec
package main
package app
import ( import (
"encoding/json" "encoding/json"


+ 1
- 1
test/e2e/app/state.go View File

@ -1,5 +1,5 @@
//nolint: gosec //nolint: gosec
package main
package app
import ( import (
"crypto/sha256" "crypto/sha256"


+ 1
- 1
test/e2e/docker/Dockerfile View File

@ -19,7 +19,7 @@ COPY . .
RUN make build && cp build/tendermint /usr/bin/tendermint RUN make build && cp build/tendermint /usr/bin/tendermint
COPY test/e2e/docker/entrypoint* /usr/bin/ COPY test/e2e/docker/entrypoint* /usr/bin/
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 # 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. # e.g. leveldb and rocksdb which are already installed in the build image.


+ 4
- 0
test/e2e/node/built-in.toml View File

@ -0,0 +1,4 @@
snapshot_interval = 100
persist_interval = 1
chain_id = "test-chain"
protocol = "builtin"

test/e2e/app/config.go → test/e2e/node/config.go View File


test/e2e/app/main.go → test/e2e/node/main.go View File


+ 5
- 0
test/e2e/node/socket.toml View File

@ -0,0 +1,5 @@
snapshot_interval = 100
persist_interval = 1
chain_id = "test-chain"
protocol = "socket"
listen = "tcp://127.0.0.1:26658"

Loading…
Cancel
Save