-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' into f_two_convienence_methods
- Loading branch information
Showing
7 changed files
with
679 additions
and
43 deletions.
There are no files selected for viewing
This file contains 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,47 @@ | ||
## Running multi-key load test with Seth and WASP | ||
To effectively simulate transaction workloads from multiple keys, you can utilize a "rotating wallet." Refer to the [example](client_wasp_test.go) code provided for guidance. | ||
|
||
There are 2 modes: Ephemeral and a static keyfile mode | ||
|
||
### Ephemeral mode | ||
We generate 60 ephemeral keys and run the test, set `ephemeral_addresses_number` in `seth.toml` | ||
|
||
This mode **should never be used on testnets or mainnets** in order not to lose funds. Please use it to test with simulated networks, like private `Geth` or `Anvil` | ||
|
||
```toml | ||
ephemeral_addresses_number = 60 | ||
``` | ||
Then start the Geth and run the test | ||
|
||
``` | ||
nix develop | ||
make GethSync | ||
// another terminal, from examples_wasp dir | ||
export SETH_LOG_LEVEL=debug | ||
export SETH_CONFIG_PATH=seth.toml | ||
export NETWORK=Geth | ||
export ROOT_PRIVATE_KEY=ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 | ||
export LOKI_TENANT_ID=promtail | ||
export LOKI_URL=... | ||
go test -v -run TestWithWasp | ||
``` | ||
See both [generator](client_wasp_test.go) and [test](client_wasp_test.go) implementation example | ||
|
||
Check your results [here](https://grafana.ops.prod.cldev.sh/d/WaspDebug/waspdebug?orgId=1&from=now-5m&to=now) | ||
|
||
If you see `key sync timeout`, just increase `ephemeral_addresses_number` to have more load | ||
|
||
You can also change default `key_sync` values | ||
```toml | ||
[nonce_manager] | ||
# 20 req/s limit for key syncing | ||
key_sync_rate_limit_per_sec = 20 | ||
# key synchronization timeout, if it's more than N sec you'll see an error, raise amount of keys or increase the timeout | ||
key_sync_timeout = "30s" | ||
# key sync retry delay, each N seconds we'll updage each key nonce | ||
key_sync_retry_delay = "1s" | ||
# total number of retries until we throw an error | ||
key_sync_retries = 30 | ||
``` |
This file contains 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 @@ | ||
package examples_wasp | ||
|
||
import ( | ||
"os" | ||
"testing" | ||
|
||
"github.com/ethereum/go-ethereum/accounts/abi/bind" | ||
"github.com/ethereum/go-ethereum/common" | ||
"github.com/pkg/errors" | ||
"github.com/smartcontractkit/seth" | ||
network_debug_contract "github.com/smartcontractkit/seth/contracts/bind/debug" | ||
link_token "github.com/smartcontractkit/seth/contracts/bind/link" | ||
network_sub_contract "github.com/smartcontractkit/seth/contracts/bind/sub" | ||
) | ||
|
||
func init() { | ||
_ = os.Setenv("SETH_CONFIG_PATH", "seth.toml") | ||
} | ||
|
||
var ( | ||
TestEnv TestEnvironment | ||
) | ||
|
||
type TestEnvironment struct { | ||
Client *seth.Client | ||
DebugContract *network_debug_contract.NetworkDebugContract | ||
DebugSubContract *network_sub_contract.NetworkDebugSubContract | ||
LinkTokenContract *link_token.LinkToken | ||
DebugContractAddress common.Address | ||
DebugSubContractAddress common.Address | ||
DebugContractRaw *bind.BoundContract | ||
ContractMap seth.ContractMap | ||
} | ||
|
||
func NewDebugContractSetup() ( | ||
*seth.Client, | ||
*network_debug_contract.NetworkDebugContract, | ||
common.Address, | ||
common.Address, | ||
*bind.BoundContract, | ||
error, | ||
) { | ||
cfg, err := seth.ReadConfig() | ||
if err != nil { | ||
return nil, nil, common.Address{}, common.Address{}, nil, err | ||
} | ||
cs, err := seth.NewContractStore(cfg.ABIDir, cfg.BINDir) | ||
if err != nil { | ||
return nil, nil, common.Address{}, common.Address{}, nil, err | ||
} | ||
addrs, pkeys, err := cfg.ParseKeys() | ||
if err != nil { | ||
return nil, nil, common.Address{}, common.Address{}, nil, err | ||
} | ||
contractMap := seth.NewEmptyContractMap() | ||
|
||
abiFinder := seth.NewABIFinder(contractMap, cs) | ||
tracer, err := seth.NewTracer(cfg.Network.URLs[0], cs, &abiFinder, cfg, contractMap, addrs) | ||
if err != nil { | ||
return nil, nil, common.Address{}, common.Address{}, nil, err | ||
} | ||
|
||
nm, err := seth.NewNonceManager(cfg, addrs, pkeys) | ||
if err != nil { | ||
return nil, nil, common.Address{}, common.Address{}, nil, errors.Wrap(err, seth.ErrCreateNonceManager) | ||
} | ||
|
||
c, err := seth.NewClientRaw(cfg, addrs, pkeys, seth.WithContractStore(cs), seth.WithTracer(tracer), seth.WithNonceManager(nm)) | ||
if err != nil { | ||
return nil, nil, common.Address{}, common.Address{}, nil, err | ||
} | ||
subData, err := c.DeployContractFromContractStore(c.NewTXOpts(), "NetworkDebugSubContract.abi") | ||
if err != nil { | ||
return nil, nil, common.Address{}, common.Address{}, nil, err | ||
} | ||
data, err := c.DeployContractFromContractStore(c.NewTXOpts(), "NetworkDebugContract.abi", subData.Address) | ||
if err != nil { | ||
return nil, nil, common.Address{}, common.Address{}, nil, err | ||
} | ||
contract, err := network_debug_contract.NewNetworkDebugContract(data.Address, c.Client) | ||
if err != nil { | ||
return nil, nil, common.Address{}, common.Address{}, nil, err | ||
} | ||
return c, contract, data.Address, subData.Address, data.BoundContract, nil | ||
} | ||
|
||
func TestMain(m *testing.M) { | ||
var err error | ||
client, debugContract, debugContractAddress, debugSubContractAddress, debugContractRaw, err := NewDebugContractSetup() | ||
if err != nil { | ||
panic(err) | ||
} | ||
|
||
linkTokenAbi, err := link_token.LinkTokenMetaData.GetAbi() | ||
if err != nil { | ||
panic(err) | ||
} | ||
linkDeploymentData, err := client.DeployContract(client.NewTXOpts(), "LinkToken", *linkTokenAbi, common.FromHex(link_token.LinkTokenMetaData.Bin)) | ||
if err != nil { | ||
panic(err) | ||
} | ||
linkToken, err := link_token.NewLinkToken(linkDeploymentData.Address, client.Client) | ||
if err != nil { | ||
panic(err) | ||
} | ||
linkAbi, err := link_token.LinkTokenMetaData.GetAbi() | ||
if err != nil { | ||
panic(err) | ||
} | ||
client.ContractStore.AddABI("LinkToken", *linkAbi) | ||
|
||
contractMap := seth.NewEmptyContractMap() | ||
for k, v := range client.ContractAddressToNameMap.GetContractMap() { | ||
contractMap.AddContract(k, v) | ||
} | ||
|
||
TestEnv = TestEnvironment{ | ||
Client: client, | ||
DebugContract: debugContract, | ||
LinkTokenContract: linkToken, | ||
DebugContractAddress: debugContractAddress, | ||
DebugSubContractAddress: debugSubContractAddress, | ||
DebugContractRaw: debugContractRaw, | ||
ContractMap: contractMap, | ||
} | ||
|
||
exitVal := m.Run() | ||
os.Exit(exitVal) | ||
} |
This file contains 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 @@ | ||
package examples_wasp | ||
|
||
import ( | ||
"errors" | ||
"github.com/smartcontractkit/seth" | ||
"github.com/smartcontractkit/wasp" | ||
"github.com/stretchr/testify/require" | ||
"math/big" | ||
"testing" | ||
"time" | ||
) | ||
|
||
type ExampleGun struct { | ||
client *seth.Client | ||
Data []string | ||
} | ||
|
||
func NewExampleHTTPGun(client *seth.Client) *ExampleGun { | ||
return &ExampleGun{ | ||
client: client, | ||
Data: make([]string, 0), | ||
} | ||
} | ||
|
||
func (m *ExampleGun) Call(l *wasp.Generator) *wasp.Response { | ||
_, err := m.client.Decode( | ||
TestEnv.DebugContract.AddCounter(m.client.NewTXKeyOpts(m.client.AnySyncedKey()), big.NewInt(0), big.NewInt(1)), | ||
) | ||
if err != nil { | ||
return &wasp.Response{Error: errors.Join(err).Error()} | ||
} | ||
return &wasp.Response{} | ||
} | ||
|
||
func TestWithWasp(t *testing.T) { | ||
t.Setenv("ROOT_PRIVATE_KEY", "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80") | ||
t.Setenv("SETH_CONFIG_PATH", "seth.toml") | ||
cfg, err := seth.ReadConfig() | ||
require.NoError(t, err, "failed to read config") | ||
c, err := seth.NewClientWithConfig(cfg) | ||
require.NoError(t, err, "failed to initalise seth") | ||
labels := map[string]string{ | ||
"go_test_name": "TestWithWasp", | ||
"gen_name": "TestWithWasp", | ||
"branch": "TestWithWasp", | ||
"commit": "TestWithWasp", | ||
} | ||
gen, err := wasp.NewGenerator(&wasp.Config{ | ||
LoadType: wasp.RPS, | ||
Schedule: wasp.CombineAndRepeat( | ||
2, | ||
wasp.Plain(2, 30*time.Second), | ||
wasp.Plain(10, 30*time.Second), | ||
wasp.Plain(2, 30*time.Second), | ||
), | ||
Gun: NewExampleHTTPGun(c), | ||
Labels: labels, | ||
LokiConfig: wasp.NewEnvLokiConfig(), | ||
}) | ||
require.NoError(t, err) | ||
gen.Run(true) | ||
} |
Oops, something went wrong.