Skip to content

Commit

Permalink
test(e2e benchmark): introduces test manifest and its related utiliti…
Browse files Browse the repository at this point in the history
…es (#3391)

The first PR towards #3363 
Closes #3457

There will be an additional follow-up PR to further refactor the
`E2EThroughput`.

The `E2EThroughput` has been successfully tested (with the changes in
this PR) and is functioning properly.
You may run: 
```
go run ./test/e2e/benchmark  -v
```
  • Loading branch information
staheri14 authored May 13, 2024
1 parent 3930165 commit ef67d05
Show file tree
Hide file tree
Showing 9 changed files with 193 additions and 31 deletions.
60 changes: 47 additions & 13 deletions test/e2e/benchmark/throughput.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ import (
)

const (
seed = 42
txsimVersion = "a92de72"
seed = 42
)

func main() {
Expand All @@ -28,41 +27,76 @@ func E2EThroughput() error {

log.Println("=== RUN E2EThroughput", "version:", latestVersion)

manifest := testnet.Manifest{
ChainID: "test-e2e-throughput",
Validators: 2,
ValidatorResource: testnet.DefaultResources,
TxClientsResource: testnet.DefaultResources,
SelfDelegation: 10000000,
CelestiaAppVersion: latestVersion,
TxClientVersion: testnet.TxsimVersion,
BlobsPerSeq: 1,
BlobSequences: 1,
BlobSizes: "10000-10000",
PerPeerBandwidth: 5 * 1024 * 1024,
UpgradeHeight: 0,
TimeoutCommit: 1 * time.Second,
TimeoutPropose: 1 * time.Second,
Mempool: "v1",
BroadcastTxs: true,
Prometheus: true,
GovMaxSquareSize: appconsts.DefaultGovMaxSquareSize,
MaxBlockBytes: appconsts.DefaultMaxBytes,
TestDuration: 30 * time.Second,
TxClients: 2,
}
// create a new testnet
testNet, err := testnet.New("E2EThroughput", seed, testnet.GetGrafanaInfoFromEnvVar())
testNet, err := testnet.New("E2EThroughput", seed,
testnet.GetGrafanaInfoFromEnvVar(), manifest.ChainID,
manifest.GetGenesisModifiers()...)
testnet.NoError("failed to create testnet", err)

testNet.SetConsensusParams(manifest.GetConsensusParams())
defer func() {
log.Print("Cleaning up testnet")
testNet.Cleanup()
}()

// add 2 validators
testnet.NoError("failed to create genesis nodes", testNet.CreateGenesisNodes(2, latestVersion, 10000000, 0, testnet.DefaultResources))
testnet.NoError("failed to create genesis nodes",
testNet.CreateGenesisNodes(manifest.Validators,
manifest.CelestiaAppVersion, manifest.SelfDelegation,
manifest.UpgradeHeight, manifest.ValidatorResource))

// obtain the GRPC endpoints of the validators
gRPCEndpoints, err := testNet.RemoteGRPCEndpoints()
testnet.NoError("failed to get validators GRPC endpoints", err)
log.Println("validators GRPC endpoints", gRPCEndpoints)

// create txsim nodes and point them to the validators
log.Println("Creating txsim nodes")
// create tx clients and point them to the validators
log.Println("Creating tx clients")

err = testNet.CreateTxClients(txsimVersion, 1, "10000-10000", testnet.DefaultResources, gRPCEndpoints)
err = testNet.CreateTxClients(manifest.TxClientVersion, manifest.BlobSequences,
manifest.BlobSizes,
manifest.TxClientsResource, gRPCEndpoints[:manifest.TxClients])
testnet.NoError("failed to create tx clients", err)

// start the testnet
log.Println("Setting up testnet")
testnet.NoError("failed to setup testnet", testNet.Setup())
testnet.NoError("failed to setup testnet", testNet.Setup(
testnet.WithPerPeerBandwidth(manifest.PerPeerBandwidth),
testnet.WithTimeoutPropose(manifest.TimeoutPropose),
testnet.WithTimeoutCommit(manifest.TimeoutCommit),
testnet.WithPrometheus(manifest.Prometheus),
))
log.Println("Starting testnet")
testnet.NoError("failed to start testnet", testNet.Start())

// once the testnet is up, start the txsim
log.Println("Starting txsim nodes")
// once the testnet is up, start the tx clients
log.Println("Starting tx clients")
testnet.NoError("failed to start tx clients", testNet.StartTxClients())

// wait some time for the txsim to submit transactions
time.Sleep(1 * time.Minute)
// wait some time for the tx clients to submit transactions
time.Sleep(manifest.TestDuration)

log.Println("Reading blockchain")
blockchain, err := testnode.ReadBlockchain(context.Background(), testNet.Node(0).AddressRPC())
Expand Down
4 changes: 2 additions & 2 deletions test/e2e/check_upgrades.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func MinorVersionCompatibility(logger *log.Logger) error {
r := rand.New(rand.NewSource(seed))
logger.Println("Running minor version compatibility test", "versions", versions)

testNet, err := testnet.New("runMinorVersionCompatibility", seed, nil)
testNet, err := testnet.New("runMinorVersionCompatibility", seed, nil, "test")
testnet.NoError("failed to create testnet", err)

defer testNet.Cleanup()
Expand Down Expand Up @@ -142,7 +142,7 @@ func MajorUpgradeToV2(logger *log.Logger) error {
defer cancel()

logger.Println("Creating testnet")
testNet, err := testnet.New("runMajorUpgradeToV2", seed, nil)
testNet, err := testnet.New("runMajorUpgradeToV2", seed, nil, "test")
testnet.NoError("failed to create testnet", err)

defer testNet.Cleanup()
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/simple.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func E2ESimple(logger *log.Logger) error {

logger.Println("Running simple e2e test", "version", latestVersion)

testNet, err := testnet.New("E2ESimple", seed, nil)
testNet, err := testnet.New("E2ESimple", seed, nil, "test")
testnet.NoError("failed to create testnet", err)

defer testNet.Cleanup()
Expand Down
2 changes: 2 additions & 0 deletions test/e2e/testnet/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@ var DefaultResources = Resources{
CPU: "300m",
Volume: "1Gi",
}

const TxsimVersion = "a92de72"
79 changes: 79 additions & 0 deletions test/e2e/testnet/manifest.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package testnet

import (
"time"

"github.com/celestiaorg/celestia-app/v2/app"
"github.com/celestiaorg/celestia-app/v2/app/encoding"
"github.com/celestiaorg/celestia-app/v2/test/util/genesis"
blobtypes "github.com/celestiaorg/celestia-app/v2/x/blob/types"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
)

// Manifest defines the parameters for a testnet.
type Manifest struct {
ChainID string
TestDuration time.Duration
// Number of validators in the testnet
Validators int
// Number of tx clients (txsim for now) in the testnet; there will be 1 txclient per validator
// if TXClients is less than Validators, the remaining validators will not have any txclients
TxClients int
// Self-delegation amount for validators
SelfDelegation int64
// CelestiaAppVersion a specific version of the celestia-app container image within celestiaorg repository on GitHub's Container Registry i.e., https://github.com/celestiaorg/celestia-app/pkgs/container/celestia-app
CelestiaAppVersion string
// TxClientVersion a specific version of the txsim container image within celestiaorg repository on GitHub's Container Registry, i.e., https://github.com/celestiaorg/celestia-app/pkgs/container/txsim
TxClientVersion string
// Resource requirements for a validator node
ValidatorResource Resources
// Resource requirements for a tx client
TxClientsResource Resources

// tx client settings
// Number of blobs per sequence
BlobsPerSeq int
// Number of blob sequences
BlobSequences int
// Size of blobs in bytes, e.g., "10000" (exact size) or "10000-20000" (min-max format)
BlobSizes string

// p2p configs
// Bandwidth per peer in bytes per second
PerPeerBandwidth int64
// consensus configs
TimeoutCommit time.Duration
TimeoutPropose time.Duration

// Mempool configs
// Mempool version
Mempool string
BroadcastTxs bool

// prometheus configs
Prometheus bool

// consensus parameters
MaxBlockBytes int64

// other configs
UpgradeHeight int64
GovMaxSquareSize int64
}

func (m *Manifest) GetGenesisModifiers() []genesis.Modifier {
ecfg := encoding.MakeConfig(app.ModuleBasics)
var modifiers []genesis.Modifier

blobParams := blobtypes.DefaultParams()
blobParams.GovMaxSquareSize = uint64(m.GovMaxSquareSize)
modifiers = append(modifiers, genesis.SetBlobParams(ecfg.Codec, blobParams))

return modifiers
}

func (m *Manifest) GetConsensusParams() *tmproto.ConsensusParams {
cparams := app.DefaultConsensusParams()
cparams.Block.MaxBytes = m.MaxBlockBytes
return cparams
}
4 changes: 2 additions & 2 deletions test/e2e/testnet/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ func NewNode(
}, nil
}

func (n *Node) Init(genesis *types.GenesisDoc, peers []string) error {
func (n *Node) Init(genesis *types.GenesisDoc, peers []string, configOptions ...Option) error {
if len(peers) == 0 {
return fmt.Errorf("no peers provided")
}
Expand All @@ -154,7 +154,7 @@ func (n *Node) Init(genesis *types.GenesisDoc, peers []string) error {
}

// Create and write the config file
cfg, err := MakeConfig(n)
cfg, err := MakeConfig(n, configOptions...)
if err != nil {
return fmt.Errorf("making config: %w", err)
}
Expand Down
50 changes: 45 additions & 5 deletions test/e2e/testnet/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,60 @@ import (
"github.com/tendermint/tendermint/p2p/pex"
)

func MakeConfig(node *Node) (*config.Config, error) {
func MakeConfig(node *Node, opts ...Option) (*config.Config, error) {
cfg := config.DefaultConfig()
cfg.Moniker = node.Name
cfg.RPC.ListenAddress = "tcp://0.0.0.0:26657"
cfg.P2P.ExternalAddress = fmt.Sprintf("tcp://%v", node.AddressP2P(false))
cfg.P2P.PersistentPeers = strings.Join(node.InitialPeers, ",")
cfg.P2P.SendRate = 5 * 1024 * 1024 // 5MiB/s
cfg.P2P.RecvRate = 5 * 1024 * 1024 // 5MiB/s
cfg.Consensus.TimeoutPropose = 1 * time.Second
cfg.Consensus.TimeoutCommit = 1 * time.Second
cfg.Instrumentation.Prometheus = true

for _, opt := range opts {
opt(cfg)
}

return cfg, nil
}

type Option func(*config.Config)

func WithPerPeerBandwidth(bandwidth int64) Option {
return func(cfg *config.Config) {
cfg.P2P.SendRate = bandwidth
cfg.P2P.RecvRate = bandwidth
}
}

func WithTimeoutPropose(timeout time.Duration) Option {
return func(cfg *config.Config) {
cfg.Consensus.TimeoutPropose = timeout
}
}

func WithTimeoutCommit(timeout time.Duration) Option {
return func(cfg *config.Config) {
cfg.Consensus.TimeoutCommit = timeout
}
}

func WithPrometheus(prometheus bool) Option {
return func(cfg *config.Config) {
cfg.Instrumentation.Prometheus = prometheus
}
}

func WithMempool(mempool string) Option {
return func(cfg *config.Config) {
cfg.Mempool.Version = mempool
}
}

func WithBroadcastTxs(broadcast bool) Option {
return func(cfg *config.Config) {
cfg.Mempool.Broadcast = broadcast
}
}

func WriteAddressBook(peers []string, file string) error {
book := pex.NewAddrBook(file, false)
for _, peer := range peers {
Expand Down
19 changes: 13 additions & 6 deletions test/e2e/testnet/testnet.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@ func (t *Testnet) GetExecutor() (*knuu.Executor, error) {
return t.executor, nil
}

func New(name string, seed int64, grafana *GrafanaInfo) (*Testnet, error) {
func New(name string, seed int64, grafana *GrafanaInfo, chainID string,
genesisModifiers ...genesis.Modifier) (
*Testnet, error,
) {
identifier := fmt.Sprintf("%s_%s", name, time.Now().Format("20060102_150405"))
if err := knuu.InitializeWithScope(identifier); err != nil {
return nil, err
Expand All @@ -48,17 +51,21 @@ func New(name string, seed int64, grafana *GrafanaInfo) (*Testnet, error) {
return &Testnet{
seed: seed,
nodes: make([]*Node, 0),
executor: executor,
genesis: genesis.NewDefaultGenesis().WithChainID("test"),
genesis: genesis.NewDefaultGenesis().WithChainID(chainID).WithModifiers(genesisModifiers...),
keygen: newKeyGenerator(seed),
grafana: grafana,
executor: executor,
}, nil
}

func (t *Testnet) SetConsensusParams(params *tmproto.ConsensusParams) {
t.genesis.WithConsensusParams(params)
}

func (t *Testnet) SetConsensusMaxBlockSize(size int64) {
t.genesis.ConsensusParams.Block.MaxBytes = size
}

func (t *Testnet) CreateGenesisNode(version string, selfDelegation, upgradeHeight int64, resources Resources) error {
signerKey := t.keygen.Generate(ed25519Type)
networkKey := t.keygen.Generate(ed25519Type)
Expand Down Expand Up @@ -144,6 +151,7 @@ func (t *Testnet) CreateTxClient(name,
Msg("error creating txsim")
return err
}

// copy over the keyring directory to the txsim instance
err = txsim.Instance.AddFolder(txsimKeyringDir, txsimRootDir, "10001:10001")
if err != nil {
Expand All @@ -153,7 +161,6 @@ func (t *Testnet) CreateTxClient(name,
Msg("error adding keyring dir to txsim")
return err
}

err = txsim.Instance.Commit()
if err != nil {
log.Err(err).
Expand Down Expand Up @@ -235,7 +242,7 @@ func (t *Testnet) CreateNode(version string, startHeight, upgradeHeight int64, r
return nil
}

func (t *Testnet) Setup() error {
func (t *Testnet) Setup(configOpts ...Option) error {
genesis, err := t.genesis.Export()
if err != nil {
return err
Expand All @@ -251,7 +258,7 @@ func (t *Testnet) Setup() error {
}
}

err := node.Init(genesis, peers)
err := node.Init(genesis, peers, configOpts...)
if err != nil {
return err
}
Expand Down
4 changes: 2 additions & 2 deletions test/e2e/testnet/txsimNode.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,13 @@ func CreateTxClient(
log.Info().
Str("name", name).
Str("image", image).
Msg("setting image for txsim node")
Msg("setting image for tx client")
err = instance.SetImage(image)
if err != nil {
log.Err(err).
Str("name", name).
Str("image", image).
Msg("failed to set image for txsim node")
Msg("failed to set image for tx client")
return nil, err
}
err = instance.SetMemory(resources.MemoryRequest, resources.MemoryLimit)
Expand Down

0 comments on commit ef67d05

Please sign in to comment.