complex chain generator
This commit is contained in:
parent
6d3943cf6f
commit
3cff19fc83
61
cmd/autoSend.go
Normal file
61
cmd/autoSend.go
Normal file
@ -0,0 +1,61 @@
|
||||
// Copyright © 2020 Vulcanize, Inc
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/signal"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/vulcanize/tx_spammer/pkg/auto"
|
||||
)
|
||||
|
||||
// autoSendCmd represents the autoSend command
|
||||
var autoSendCmd = &cobra.Command{
|
||||
Use: "autoSend",
|
||||
Short: "Send large volumes of different tx types to different nodes for testing purposes",
|
||||
Long: `Loads tx configuration from .toml config file
|
||||
Generates txs from configuration and provided private keys and sends them to designated node according to set frequency and number
|
||||
Support standard, optimism L2, optimism L1 to L2, and EIP1559 transactions`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
subCommand = cmd.CalledAs()
|
||||
logWithCommand = *logrus.WithField("SubCommand", subCommand)
|
||||
autoSend()
|
||||
},
|
||||
}
|
||||
|
||||
func autoSend() {
|
||||
config, err := auto.NewConfig()
|
||||
if err != nil {
|
||||
logWithCommand.Fatal(err)
|
||||
}
|
||||
txSpammer := auto.NewTxSpammer(config)
|
||||
quitChan := make(chan bool)
|
||||
doneChan := txSpammer.Loop(quitChan)
|
||||
|
||||
go func() {
|
||||
shutdown := make(chan os.Signal)
|
||||
signal.Notify(shutdown, os.Interrupt)
|
||||
<-shutdown
|
||||
close(quitChan)
|
||||
}()
|
||||
<-doneChan
|
||||
|
||||
}
|
||||
func init() {
|
||||
rootCmd.AddCommand(autoSendCmd)
|
||||
}
|
@ -18,7 +18,6 @@ package cmd
|
||||
import (
|
||||
"os"
|
||||
"os/signal"
|
||||
"sync"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
@ -46,9 +45,8 @@ func sendTxs() {
|
||||
logWithCommand.Fatal(err)
|
||||
}
|
||||
txSpammer := manual.NewTxSpammer(params)
|
||||
wg := new(sync.WaitGroup)
|
||||
quitChan := make(chan bool)
|
||||
txSpammer.Loop(wg, quitChan)
|
||||
doneChan := txSpammer.Loop(quitChan)
|
||||
|
||||
go func() {
|
||||
shutdown := make(chan os.Signal)
|
||||
@ -56,7 +54,7 @@ func sendTxs() {
|
||||
<-shutdown
|
||||
close(quitChan)
|
||||
}()
|
||||
wg.Wait()
|
||||
<-doneChan
|
||||
|
||||
}
|
||||
func init() {
|
||||
|
@ -48,7 +48,7 @@ type Config struct {
|
||||
Client *rpc.Client
|
||||
|
||||
// Key pairs for the accounts we will use to deploy contracts and send txs
|
||||
SenderKeys []*ecdsa.PrivateKey
|
||||
SenderKeys []*ecdsa.PrivateKey
|
||||
SenderAddrs []common.Address
|
||||
|
||||
// Type of the txs we are working with
|
||||
@ -92,8 +92,8 @@ type DeploymentConfig struct {
|
||||
|
||||
// CallConfig holds the parameters for the contract calling txs
|
||||
type CallConfig struct {
|
||||
GasLimit uint64
|
||||
GasPrice *big.Int
|
||||
GasLimit uint64
|
||||
GasPrice *big.Int
|
||||
|
||||
MethodName string
|
||||
ABI abi.ABI
|
||||
@ -112,13 +112,12 @@ type SendConfig struct {
|
||||
Amount *big.Int
|
||||
|
||||
DestinationAddresses []common.Address
|
||||
Frequency time.Duration
|
||||
Number uint64
|
||||
Frequency time.Duration
|
||||
Number uint64
|
||||
}
|
||||
|
||||
// todo: EIP1559Config
|
||||
type EIP1559Config struct {
|
||||
|
||||
}
|
||||
|
||||
func NewConfig() (*Config, error) {
|
||||
@ -217,7 +216,7 @@ func NewConfig() (*Config, error) {
|
||||
}
|
||||
|
||||
// NewOptimismConfig constructs and returns a new OptimismConfig
|
||||
func NewOptimismConfig() *OptimismConfig{
|
||||
func NewOptimismConfig() *OptimismConfig {
|
||||
l1SenderStr := viper.GetString(ethOptimismL1Sender)
|
||||
var l1Sender *common.Address
|
||||
if l1SenderStr != "" {
|
||||
@ -306,11 +305,11 @@ func NewSendConfig(destinationAddrs []common.Address) (*SendConfig, error) {
|
||||
}
|
||||
return &SendConfig{
|
||||
DestinationAddresses: destinationAddrs,
|
||||
Frequency: viper.GetDuration(ethSendFrequency),
|
||||
Number: viper.GetUint64(ethSendTotalNumber),
|
||||
Amount: amount,
|
||||
GasPrice: gasPrice,
|
||||
GasLimit: viper.GetUint64(ethSendGasLimit),
|
||||
Frequency: viper.GetDuration(ethSendFrequency),
|
||||
Number: viper.GetUint64(ethSendTotalNumber),
|
||||
Amount: amount,
|
||||
GasPrice: gasPrice,
|
||||
GasLimit: viper.GetUint64(ethSendGasLimit),
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
36
pkg/auto/deployer.go
Normal file
36
pkg/auto/deployer.go
Normal file
@ -0,0 +1,36 @@
|
||||
// VulcanizeDB
|
||||
// Copyright © 2020 Vulcanize
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package auto
|
||||
|
||||
import "crypto/ecdsa"
|
||||
|
||||
type ContractDeployer struct {
|
||||
SenderKeys []*ecdsa.PrivateKey
|
||||
Config *DeploymentConfig
|
||||
}
|
||||
|
||||
func NewContractDeployer(config *Config) *ContractDeployer {
|
||||
return &ContractDeployer{
|
||||
Config: config.DeploymentConfig,
|
||||
SenderKeys: config.SenderKeys,
|
||||
}
|
||||
}
|
||||
|
||||
func (cp *ContractDeployer) Deploy() error {
|
||||
|
||||
return nil
|
||||
}
|
@ -118,4 +118,4 @@ func bindEnv() {
|
||||
viper.BindEnv(ethSendAmount, ETH_SEND_AMOUNT)
|
||||
viper.BindEnv(ethSendGasLimit, ETH_SEND_GAS_LIMIT)
|
||||
viper.BindEnv(ethSendGasPrice, ETH_SEND_GAS_PRICE)
|
||||
}
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ func (s *EthSender) Send(quitChan <-chan bool, txRlpChan <-chan []byte) (<-chan
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case tx := <- txRlpChan:
|
||||
case tx := <-txRlpChan:
|
||||
if err := shared.SendRawTransaction(s.client, tx); err != nil {
|
||||
errChan <- err
|
||||
}
|
||||
|
56
pkg/auto/service.go
Normal file
56
pkg/auto/service.go
Normal file
@ -0,0 +1,56 @@
|
||||
// VulcanizeDB
|
||||
// Copyright © 2020 Vulcanize
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package auto
|
||||
|
||||
import (
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/vulcanize/tx_spammer/pkg/shared"
|
||||
)
|
||||
|
||||
// Spammer underlying struct type for spamming service
|
||||
type Spammer struct {
|
||||
Deployer *ContractDeployer
|
||||
Caller *ContractCaller
|
||||
Sender *EthSender
|
||||
}
|
||||
|
||||
// NewTxSpammer creates a new tx spamming service
|
||||
func NewTxSpammer(config *Config) shared.Service {
|
||||
return &Spammer{
|
||||
Deployer: NewContractDeployer(config),
|
||||
Caller: NewContractCaller(config),
|
||||
Sender: NewEthSender(config),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Spammer) Loop(quitChan <-chan bool) <-chan bool {
|
||||
forwardQuit := make(chan bool)
|
||||
doneChan, errChan := s.Sender.Send(forwardQuit)
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case err := <-errChan:
|
||||
logrus.Error(err)
|
||||
case forwardQuit <- <-quitChan:
|
||||
return
|
||||
case <-doneChan:
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
return doneChan
|
||||
}
|
120
pkg/auto/tx_generator.go
Normal file
120
pkg/auto/tx_generator.go
Normal file
@ -0,0 +1,120 @@
|
||||
// VulcanizeDB
|
||||
// Copyright © 2020 Vulcanize
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package auto
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/vulcanize/tx_spammer/pkg/shared"
|
||||
)
|
||||
|
||||
// TxGenerator generates and signs txs
|
||||
type TxGenerator struct {
|
||||
signer types.Signer
|
||||
optimismConfig *OptimismConfig
|
||||
eip1559Config *EIP1559Config
|
||||
// keep track of account nonces locally so we aren't spamming to determine the nonce
|
||||
// this assumes these accounts are not sending txs outside this process
|
||||
nonces map[common.Address]*uint64
|
||||
}
|
||||
|
||||
// NewTxGenerator creates a new tx generator
|
||||
func NewTxGenerator(config Config) *TxGenerator {
|
||||
nonces := make(map[common.Address]*uint64)
|
||||
for _, addr := range config.SenderAddrs {
|
||||
startingNonce := uint64(0)
|
||||
nonces[addr] = &startingNonce
|
||||
}
|
||||
return &TxGenerator{
|
||||
signer: config.Signer,
|
||||
nonces: nonces,
|
||||
optimismConfig: config.OptimismConfig,
|
||||
eip1559Config: config.EIP1559Config,
|
||||
}
|
||||
}
|
||||
|
||||
// GenParams params for GenerateTx method calls
|
||||
type GenParams struct {
|
||||
Signer types.Signer
|
||||
Sender common.Address
|
||||
SenderKey *ecdsa.PrivateKey
|
||||
To *common.Address
|
||||
Amount *big.Int
|
||||
GasLimit uint64
|
||||
GasPrice *big.Int
|
||||
Data []byte
|
||||
}
|
||||
|
||||
func (tg TxGenerator) GenerateTxs(quitChan <-chan bool) (<-chan bool, <-chan []byte, <-chan error) {
|
||||
|
||||
}
|
||||
|
||||
// GenerateTx generates tx from the provided params
|
||||
func (tg TxGenerator) GenerateTx(ty shared.TxType, params *GenParams) ([]byte, error) {
|
||||
tx := make([]byte, 0)
|
||||
switch ty {
|
||||
case shared.OptimismL2:
|
||||
return tg.genL2(params, tg.optimismConfig)
|
||||
case shared.Standard:
|
||||
return tg.gen(params)
|
||||
case shared.EIP1559:
|
||||
return tg.gen1559(params, tg.eip1559Config)
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported tx type: %s", ty.String())
|
||||
}
|
||||
return tx, nil
|
||||
}
|
||||
|
||||
func (gen TxGenerator) genL2(params *GenParams, op *OptimismConfig) ([]byte, error) {
|
||||
nonce := atomic.AddUint64(gen.nonces[params.Sender], 1)
|
||||
tx := new(types.Transaction)
|
||||
if params.To == nil {
|
||||
tx = types.NewContractCreation(nonce, params.Amount, params.GasLimit, params.GasPrice, params.Data, op.L1SenderAddr, op.L1RollupTxId, op.QueueOrigin)
|
||||
if err := shared.WriteContractAddr(shared.DefaultDeploymentAddrLogPathPrefix, params.Sender, nonce); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
} else {
|
||||
tx = types.NewTransaction(nonce, *params.To, params.Amount, params.GasLimit, params.GasPrice, params.Data, op.L1SenderAddr, op.L1RollupTxId, op.QueueOrigin, op.SigHashType)
|
||||
}
|
||||
signedTx, err := types.SignTx(tx, params.Signer, params.SenderKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
txRlp, err := rlp.EncodeToBytes(signedTx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return txRlp, nil
|
||||
}
|
||||
|
||||
func (gen TxGenerator) gen(params *GenParams) ([]byte, error) {
|
||||
// TODO: support standard geth
|
||||
return nil, errors.New("L1 support not yet available")
|
||||
}
|
||||
|
||||
func (gen TxGenerator) gen1559(params *GenParams, eip1559Config *EIP1559Config) ([]byte, error) {
|
||||
// TODO: support EIP1559
|
||||
return nil, errors.New("1559 support not yet available")
|
||||
}
|
@ -19,12 +19,13 @@ package manual
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"fmt"
|
||||
"github.com/vulcanize/tx_spammer/pkg/shared"
|
||||
"math/big"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/vulcanize/tx_spammer/pkg/shared"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
|
@ -54,4 +54,4 @@ const (
|
||||
func bindEnv() {
|
||||
viper.BindEnv("eth.txs", ETH_TX_LIST)
|
||||
viper.BindEnv("eth.addrLogPath", ETH_ADDR_LOG)
|
||||
}
|
||||
}
|
||||
|
@ -18,10 +18,11 @@ package manual
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/sirupsen/logrus"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/vulcanize/tx_spammer/pkg/shared"
|
||||
)
|
||||
|
||||
@ -86,4 +87,4 @@ func (s *TxSender) genAndSend(p TxParams) error {
|
||||
}
|
||||
logrus.Infof("sending tx %s", p.Name)
|
||||
return shared.SendRawTransaction(p.Client, tx)
|
||||
}
|
||||
}
|
||||
|
@ -18,4 +18,4 @@ package shared
|
||||
|
||||
const (
|
||||
DefaultDeploymentAddrLogPathPrefix = "./accounts/addresses/"
|
||||
)
|
||||
)
|
||||
|
@ -19,4 +19,4 @@ package shared
|
||||
// Service looping interface
|
||||
type Service interface {
|
||||
Loop(quitChan <-chan bool) (doneChan <-chan bool)
|
||||
}
|
||||
}
|
||||
|
@ -19,14 +19,15 @@ package shared
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"math/big"
|
||||
"os"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
"github.com/ethereum/temp/common/hexutil"
|
||||
)
|
||||
|
||||
// ChainConfig returns the appropriate ethereum chain config for the provided chain id
|
||||
@ -60,4 +61,4 @@ func WriteContractAddr(filePath string, senderAddr common.Address, nonce uint64)
|
||||
return err
|
||||
}
|
||||
return f.Close()
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user