-
Notifications
You must be signed in to change notification settings - Fork 157
add warp tests for Coreth #1000
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
Merged
Merged
Changes from all commits
Commits
Show all changes
26 commits
Select commit
Hold shift + click to select a range
4ff9e2d
add warp tests for Coreth
ceyonur 9117f76
uncomment monitor
ceyonur f2bd399
fix linters
ceyonur 66a9571
exclude tests dir in UT
ceyonur 6c5f28e
use tmp dir
ceyonur 142e4ad
fix paths
ceyonur b86f5d7
fix comments
ceyonur 79afd95
use subnet-evm for warp tests
ceyonur cbc89b6
move subnet-evm to tmp
ceyonur b7bcb96
use different step to move
ceyonur 7d59339
remove tokens
ceyonur a68f0d5
remove extra key file
ceyonur 4279b23
remove subscriptions
ceyonur 3ada6b9
fix util function
ceyonur f0fa746
minimize subnet-evm diffs
ceyonur 69b01e0
Merge branch 'master' into add-warp-tests
ceyonur b56e3d2
fix linters
ceyonur 8f7b209
update monitor version
ceyonur 2191083
Merge branch 'master' into add-warp-tests
ceyonur 633b6fe
use bind.WaitMined
ceyonur 4e625ee
Merge branch 'add-warp-tests' of github.com:ava-labs/coreth into add-…
ceyonur 02cb3da
remove shellcheck
ceyonur ba18b7c
reviews
ceyonur 2542b0c
Merge branch 'master' into add-warp-tests
ceyonur e98468a
revert repo mv
ceyonur 1d86998
Merge branch 'add-warp-tests' of github.com:ava-labs/coreth into add-…
ceyonur File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -50,3 +50,6 @@ build/ | |
avalanchego | ||
|
||
.direnv | ||
|
||
cmd/simulator/.simulator/* | ||
cmd/simulator/simulator |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
#!/usr/bin/env bash | ||
|
||
set -euo pipefail | ||
|
||
# Ensure the go command is run from the root of the repository so that its go.mod file is used | ||
REPO_ROOT=$( | ||
cd "$(dirname "${BASH_SOURCE[0]}")" | ||
cd .. && pwd | ||
) | ||
cd "${REPO_ROOT}" | ||
|
||
# If an explicit version is not specified, go run uses the ginkgo version from go.mod | ||
go run github.com/onsi/ginkgo/v2/ginkgo "${@}" |
1 change: 1 addition & 0 deletions
1
cmd/simulator/.simulator/keys/0x8db97C7cEcE249c2b98bDC0226Cc4C2A57BF52FC
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
56289e99c94b6912bfc12adc093c9b51124f0dc54ac7a766b2bc5ccf558d8027 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
# Load Simulator | ||
|
||
When building developing your own blockchain using `coreth`, you may want to analyze how your fee parameterization behaves and/or how many resources your VM uses under different load patterns. For this reason, we developed `cmd/simulator`. `cmd/simulator` lets you drive arbitrary load across any number of [endpoints] with a user-specified `keys` directory (insecure) `timeout`, `workers`, `max-fee-cap`, and `max-tip-cap`. | ||
|
||
## Building the Load Simulator | ||
|
||
To build the load simulator, navigate to the base of the simulator directory: | ||
|
||
```bash | ||
cd $GOPATH/src/github.com/ava-labs/coreth/cmd/simulator | ||
``` | ||
|
||
Build the simulator: | ||
|
||
```bash | ||
go build -o ./simulator main/*.go | ||
``` | ||
|
||
To confirm that you built successfully, run the simulator and print the version: | ||
|
||
```bash | ||
./simulator --version | ||
``` | ||
|
||
This should give the following output: | ||
|
||
``` | ||
v0.1.0 | ||
``` | ||
|
||
To run the load simulator, you must first start an EVM based network. The load simulator works on both the C-Chain and Subnet-EVM, so we will start a single node network and run the load simulator on the C-Chain. | ||
|
||
To start a single node network, follow the instructions from the AvalancheGo [README](https://github.com/ava-labs/avalanchego#building-avalanchego) to build from source. | ||
|
||
Once you've built AvalancheGo, open the AvalancheGo directory in a separate terminal window and run a single node non-staking network with the following command: | ||
|
||
```bash | ||
./build/avalanchego --sybil-protection-enabled=false --network-id=local | ||
``` | ||
|
||
WARNING: | ||
|
||
The `--sybil-protection-enabled=false` flag is only suitable for local testing. Disabling staking serves two functions explicitly for testing purposes: | ||
|
||
1. Ignore stake weight on the P-Chain and count each connected peer as having a stake weight of 1 | ||
2. Automatically opts in to validate every Subnet | ||
|
||
Once you have AvalancheGo running locally, it will be running an HTTP Server on the default port `9650`. This means that the RPC Endpoint for the C-Chain will be http://127.0.0.1:9650/ext/bc/C/rpc and ws://127.0.0.1:9650/ext/bc/C/ws for WebSocket connections. | ||
|
||
Now, we can run the simulator command to simulate some load on the local C-Chain for 30s: | ||
|
||
```bash | ||
./simulator --timeout=1m --workers=1 --max-fee-cap=300 --max-tip-cap=10 --txs-per-worker=50 | ||
``` | ||
|
||
## Command Line Flags | ||
|
||
To see all of the command line flag options, run | ||
|
||
```bash | ||
./simulator --help | ||
``` |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
// Copyright (C) 2019-2025, Ava Labs, Inc. All rights reserved. | ||
// See the file LICENSE for licensing terms. | ||
|
||
package config | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"strings" | ||
"time" | ||
|
||
"github.com/spf13/pflag" | ||
"github.com/spf13/viper" | ||
) | ||
|
||
const Version = "v0.1.1" | ||
|
||
const ( | ||
ConfigFilePathKey = "config-file" | ||
LogLevelKey = "log-level" | ||
EndpointsKey = "endpoints" | ||
MaxFeeCapKey = "max-fee-cap" | ||
MaxTipCapKey = "max-tip-cap" | ||
WorkersKey = "workers" | ||
TxsPerWorkerKey = "txs-per-worker" | ||
KeyDirKey = "key-dir" | ||
VersionKey = "version" | ||
TimeoutKey = "timeout" | ||
BatchSizeKey = "batch-size" | ||
MetricsPortKey = "metrics-port" | ||
MetricsOutputKey = "metrics-output" | ||
) | ||
|
||
var ( | ||
ErrNoEndpoints = errors.New("must specify at least one endpoint") | ||
ErrNoWorkers = errors.New("must specify non-zero number of workers") | ||
ErrNoTxs = errors.New("must specify non-zero number of txs-per-worker") | ||
) | ||
|
||
type Config struct { | ||
Endpoints []string `json:"endpoints"` | ||
MaxFeeCap int64 `json:"max-fee-cap"` | ||
MaxTipCap int64 `json:"max-tip-cap"` | ||
Workers int `json:"workers"` | ||
TxsPerWorker uint64 `json:"txs-per-worker"` | ||
KeyDir string `json:"key-dir"` | ||
Timeout time.Duration `json:"timeout"` | ||
BatchSize uint64 `json:"batch-size"` | ||
MetricsPort uint64 `json:"metrics-port"` | ||
MetricsOutput string `json:"metrics-output"` | ||
} | ||
|
||
func BuildConfig(v *viper.Viper) (Config, error) { | ||
c := Config{ | ||
Endpoints: v.GetStringSlice(EndpointsKey), | ||
MaxFeeCap: v.GetInt64(MaxFeeCapKey), | ||
MaxTipCap: v.GetInt64(MaxTipCapKey), | ||
Workers: v.GetInt(WorkersKey), | ||
TxsPerWorker: v.GetUint64(TxsPerWorkerKey), | ||
KeyDir: v.GetString(KeyDirKey), | ||
Timeout: v.GetDuration(TimeoutKey), | ||
BatchSize: v.GetUint64(BatchSizeKey), | ||
MetricsPort: v.GetUint64(MetricsPortKey), | ||
MetricsOutput: v.GetString(MetricsOutputKey), | ||
} | ||
if len(c.Endpoints) == 0 { | ||
return c, ErrNoEndpoints | ||
} | ||
if c.Workers == 0 { | ||
return c, ErrNoWorkers | ||
} | ||
if c.TxsPerWorker == 0 { | ||
return c, ErrNoTxs | ||
} | ||
// Note: it's technically valid for the fee/tip cap to be 0, but cannot | ||
// be less than 0. | ||
if c.MaxFeeCap < 0 { | ||
return c, fmt.Errorf("invalid max fee cap %d < 0", c.MaxFeeCap) | ||
} | ||
if c.MaxTipCap < 0 { | ||
return c, fmt.Errorf("invalid max tip cap %d <= 0", c.MaxTipCap) | ||
} | ||
return c, nil | ||
} | ||
|
||
func BuildViper(fs *pflag.FlagSet, args []string) (*viper.Viper, error) { | ||
if err := fs.Parse(args); err != nil { | ||
return nil, err | ||
} | ||
|
||
v := viper.New() | ||
v.AutomaticEnv() | ||
v.SetEnvKeyReplacer(strings.NewReplacer("-", "_")) | ||
v.SetEnvPrefix("evm_simulator") | ||
if err := v.BindPFlags(fs); err != nil { | ||
return nil, err | ||
} | ||
|
||
if v.IsSet(ConfigFilePathKey) { | ||
v.SetConfigFile(v.GetString(ConfigFilePathKey)) | ||
if err := v.ReadInConfig(); err != nil { | ||
return nil, err | ||
} | ||
} | ||
return v, nil | ||
} | ||
|
||
// BuildFlagSet returns a complete set of flags for simulator | ||
func BuildFlagSet() *pflag.FlagSet { | ||
fs := pflag.NewFlagSet("simulator", pflag.ContinueOnError) | ||
addSimulatorFlags(fs) | ||
return fs | ||
} | ||
|
||
func addSimulatorFlags(fs *pflag.FlagSet) { | ||
fs.Bool(VersionKey, false, "Print the version and exit") | ||
fs.String(ConfigFilePathKey, "", "Specify the config path to use to load a YAML config for the simulator") | ||
fs.StringSlice(EndpointsKey, []string{"ws://127.0.0.1:9650/ext/bc/C/ws"}, "Specify a comma separated list of RPC Websocket Endpoints (minimum of 1 endpoint)") | ||
fs.Int64(MaxFeeCapKey, 50, "Specify the maximum fee cap to use for transactions denominated in GWei (must be > 0)") | ||
fs.Int64(MaxTipCapKey, 1, "Specify the max tip cap for transactions denominated in GWei (must be >= 0)") | ||
fs.Uint64(TxsPerWorkerKey, 100, "Specify the number of transactions to create per worker (must be > 0)") | ||
fs.Int(WorkersKey, 1, "Specify the number of workers to create for the simulator (must be > 0)") | ||
fs.String(KeyDirKey, ".simulator/keys", "Specify the directory to save private keys in (INSECURE: only use for testing)") | ||
fs.Duration(TimeoutKey, 5*time.Minute, "Specify the timeout for the simulator to complete (0 indicates no timeout)") | ||
fs.String(LogLevelKey, "info", "Specify the log level to use in the simulator") | ||
fs.Uint64(BatchSizeKey, 100, "Specify the batchsize for the worker to issue and confirm txs") | ||
fs.Uint64(MetricsPortKey, 8082, "Specify the port to use for the metrics server") | ||
fs.String(MetricsOutputKey, "", "Specify the file to write metrics in json format, or empty to write to stdout (defaults to stdout)") | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
// Copyright (C) 2019-2025, Ava Labs, Inc. All rights reserved. | ||
// See the file LICENSE for licensing terms. | ||
|
||
package key | ||
|
||
import ( | ||
"context" | ||
"crypto/ecdsa" | ||
"fmt" | ||
"os" | ||
"path/filepath" | ||
|
||
"github.com/ava-labs/libevm/common" | ||
ethcrypto "github.com/ava-labs/libevm/crypto" | ||
) | ||
|
||
type Key struct { | ||
PrivKey *ecdsa.PrivateKey | ||
Address common.Address | ||
} | ||
|
||
func CreateKey(pk *ecdsa.PrivateKey) *Key { | ||
return &Key{pk, ethcrypto.PubkeyToAddress(pk.PublicKey)} | ||
} | ||
|
||
// Load attempts to open a [Key] stored at [file]. | ||
func Load(file string) (*Key, error) { | ||
pk, err := ethcrypto.LoadECDSA(file) | ||
if err != nil { | ||
return nil, fmt.Errorf("problem loading private key from %s: %w", file, err) | ||
} | ||
return CreateKey(pk), nil | ||
} | ||
|
||
// LoadAll loads all keys in [dir]. | ||
func LoadAll(ctx context.Context, dir string) ([]*Key, error) { | ||
if _, err := os.Stat(dir); os.IsNotExist(err) { | ||
if err := os.MkdirAll(dir, 0o755); err != nil { | ||
return nil, fmt.Errorf("unable to create %s: %w", dir, err) | ||
} | ||
|
||
return nil, nil | ||
} | ||
|
||
var files []string | ||
|
||
err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { | ||
if path == dir { | ||
return nil | ||
} | ||
|
||
files = append(files, path) | ||
return nil | ||
}) | ||
if err != nil { | ||
return nil, fmt.Errorf("could not walk %s: %w", dir, err) | ||
} | ||
|
||
ks := make([]*Key, len(files)) | ||
for i, file := range files { | ||
k, err := Load(file) | ||
if err != nil { | ||
return nil, fmt.Errorf("could not load key at %s: %w", file, err) | ||
} | ||
|
||
ks[i] = k | ||
} | ||
return ks, nil | ||
} | ||
|
||
// Save persists a [Key] to [dir] (where the filename is the hex-encoded | ||
// address). | ||
func (k *Key) Save(dir string) error { | ||
fp := filepath.Join(dir, k.Address.Hex()) | ||
return ethcrypto.SaveECDSA(fp, k.PrivKey) | ||
} | ||
|
||
// Generate creates a new [Key] and returns it. | ||
func Generate() (*Key, error) { | ||
pk, err := ethcrypto.GenerateKey() | ||
if err != nil { | ||
return nil, fmt.Errorf("%w: cannot generate key", err) | ||
} | ||
return CreateKey(pk), nil | ||
} |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.