Compare commits

..

1 Commits

Author SHA1 Message Date
ad37ced82a Rebrand to cerc-io/tx-spammer 2022-12-20 16:56:12 -06:00
18 changed files with 933 additions and 593 deletions

View File

@ -17,9 +17,9 @@ jobs:
- name: Run docker build
run: make docker-build
- name: Tag docker image
run: docker tag cerc-io/tx-spammer git.vdb.to/cerc-io/tx-spammer/tx-spammer:${{steps.vars.outputs.sha}}
run: docker tag cerc-io/tx_spammer git.vdb.to/cerc-io/tx_spammer/tx_spammer:${{steps.vars.outputs.sha}}
- name: Docker Login
run: echo ${{ secrets.GITHUB_TOKEN }} | docker login https://git.vdb.to -u cerc-io --password-stdin
- name: Docker Push
run: docker push git.vdb.to/cerc-io/tx-spammer/tx-spammer:${{steps.vars.outputs.sha}}
run: docker push git.vdb.to/cerc-io/tx_spammer/tx_spammer:${{steps.vars.outputs.sha}}

View File

@ -15,11 +15,11 @@ jobs:
- name: Docker Login to Github Registry
run: echo ${{ secrets.GITHUB_TOKEN }} | docker login https://git.vdb.to -u vulcanize --password-stdin
- name: Docker Pull
run: docker pull git.vdb.to/cerc-io/tx-spammer/tx-spammer:${{steps.vars.outputs.sha}}
run: docker pull git.vdb.to/cerc-io/tx_spammer/tx_spammer:${{steps.vars.outputs.sha}}
- name: Docker Login to Docker Registry
run: echo ${{ secrets.VULCANIZEJENKINS_PAT }} | docker login -u vulcanizejenkins --password-stdin
- name: Tag docker image
run: docker tag git.vdb.to/cerc-io/tx-spammer/tx-spammer:${{steps.vars.outputs.sha}} cerc-io/tx-spammer:${{steps.vars.outputs.tag}}
run: docker tag git.vdb.to/cerc-io/tx_spammer/tx_spammer:${{steps.vars.outputs.sha}} cerc-io/tx_spammer:${{steps.vars.outputs.tag}}
- name: Docker Push to Docker Hub
run: docker push cerc-io/tx-spammer:${{steps.vars.outputs.tag}}
run: docker push cerc-io/tx_spammer:${{steps.vars.outputs.tag}}

View File

@ -1,17 +1,13 @@
FROM golang:1.21-alpine as builder
FROM golang:1.19-alpine as builder
RUN apk --update --no-cache add gcc libc-dev
RUN apk --update --no-cache add make git g++ linux-headers
# DEBUG
RUN apk add busybox-extras
# Get and build tx-spammer
ADD . /go/src/github.com/cerc-io/tx-spammer
WORKDIR /go/src/github.com/cerc-io/tx-spammer
ENV GO111MODULE=on
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -ldflags '-extldflags "-static"' -o tx-spammer .
RUN GO111MODULE=on GCO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -ldflags '-extldflags "-static"' -o tx-spammer .
# app container
FROM alpine

View File

@ -21,8 +21,6 @@ import (
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/cerc-io/tx-spammer/pkg/auto"
)
@ -40,18 +38,11 @@ Support standard, optimism L2, optimism L1 to L2, and EIP1559 transactions`,
},
}
func init() {
autoSendCmd.PersistentFlags().Bool("stop-on-error", true,
"stop service when SendTransaction returns an error")
viper.BindPFlag(auto.SpammerStopOnError, autoSendCmd.PersistentFlags().Lookup("stop-on-error"))
}
func autoSend() {
config, err := auto.NewConfig()
if err != nil {
logWithCommand.Fatal(err)
}
logrus.WithFields(logrus.Fields{"config": config}).Debug("Loaded config")
txSpammer := auto.NewTxSpammer(config)
quitChan := make(chan bool)
doneChan, err := txSpammer.Loop(quitChan)
@ -70,4 +61,4 @@ func autoSend() {
func init() {
rootCmd.AddCommand(autoSendCmd)
}
}

View File

@ -45,7 +45,7 @@ func Execute() {
}
func initFuncs(cmd *cobra.Command, args []string) {
logfile := viper.GetString("log.file")
logfile := viper.GetString("logfile")
if logfile != "" {
file, err := os.OpenFile(logfile,
os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
@ -65,13 +65,13 @@ func initFuncs(cmd *cobra.Command, args []string) {
}
func logLevel() error {
viper.BindEnv("log.level", "LOG_LEVEL")
viper.BindEnv("log.level", "LOGRUS_LEVEL")
lvl, err := log.ParseLevel(viper.GetString("log.level"))
if err != nil {
return err
}
log.SetLevel(lvl)
if lvl > log.DebugLevel {
if lvl > log.InfoLevel {
log.SetReportCaller(true)
}
log.Info("Log level set to ", lvl.String())

View File

@ -28,13 +28,3 @@
gasLimit = 21000 # gasLimit to use for the eth transfer txs - env: $ETH_SEND_GAS_LIMIT
gasTipCap = "1000000000" # gasTipCap to use for the eth transfer txs - env: $ETH_SEND_GAS_TIP_CAP
gasFeeCap = "1000000007" # gasFeeCap to use for the eth transfer txs - env: $ETH_SEND_GAS_FEE_CAP
[blobSpammer]
frequency = 500 # how often to send a transaction (in milliseconds, -1 for no delay) - env: $ETH_SEND_FREQ
totalNumber = -1 # total number of transactions to send (per sender, -1 for unlimited) - env: $ETH_SEND_TOTAL_NUMBER
amount = "10000" # amount of wei (1x10^-18 ETH) to send in each tx (be mindful of the genesis allocations) - env: $ETH_SEND_AMOUNT
gasLimit = 21000 # gasLimit to use for the blob txs - env: $ETH_SEND_GAS_LIMIT
gasTipCap = "1000000000" # gasTipCap to use for the blob txs - env: $ETH_SEND_GAS_TIP_CAP
gasFeeCap = "1000000007" # gasFeeCap to use for the blob txs - env: $ETH_SEND_GAS_FEE_CAP
blobCount = 1 # number of blob sidecars to send with blob txs - env: $ETH_SEND_BLOB_LENGTH
blobFeeCap = "1000000" # blobFeeCap to use for the eth blob txs - env: $ETH_SEND_BLOB_FEE_CAP

116
go.mod
View File

@ -1,85 +1,57 @@
module github.com/cerc-io/tx-spammer
go 1.21
go 1.13
require (
github.com/ethereum/go-ethereum v1.14.5
github.com/holiman/uint256 v1.2.4
github.com/sirupsen/logrus v1.9.3
github.com/spf13/cobra v1.6.0
github.com/spf13/viper v1.13.0
)
require (
github.com/DataDog/zstd v1.5.2 // indirect
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/VictoriaMetrics/fastcache v1.12.2 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/bits-and-blooms/bitset v1.10.0 // indirect
github.com/Azure/azure-pipeline-go v0.2.2 // indirect
github.com/Azure/azure-storage-blob-go v0.7.0 // indirect
github.com/Azure/go-autorest/autorest/adal v0.8.0 // indirect
github.com/StackExchange/wmi v1.2.1 // indirect
github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847 // indirect
github.com/aws/aws-sdk-go v1.25.48 // indirect
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c // indirect
github.com/btcsuite/btcd v0.0.0-20171128150713-2e60448ffcc6 // indirect
github.com/btcsuite/btcd/btcec/v2 v2.2.1 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/cockroachdb/errors v1.11.1 // indirect
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect
github.com/cockroachdb/pebble v1.1.0 // indirect
github.com/cockroachdb/redact v1.1.5 // indirect
github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect
github.com/consensys/bavard v0.1.13 // indirect
github.com/consensys/gnark-crypto v0.12.1 // indirect
github.com/crate-crypto/go-ipa v0.0.0-20240223125850-b1e8a79f509c // indirect
github.com/crate-crypto/go-kzg-4844 v1.0.0 // indirect
github.com/deckarep/golang-set/v2 v2.6.0 // indirect
github.com/coreos/bbolt v1.3.2 // indirect
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e // indirect
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect
github.com/ethereum/c-kzg-4844 v1.0.0 // indirect
github.com/ethereum/go-verkle v0.1.1-0.20240306133620-7d920df305f0 // indirect
github.com/elastic/gosigar v0.8.1-0.20180330100440-37f05ff46ffa // indirect
github.com/ethereum/go-ethereum v1.10.25
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/getsentry/sentry-go v0.18.0 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect
github.com/gofrs/flock v0.8.1 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-stack/stack v1.8.1 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/holiman/bloomfilter/v2 v2.0.3 // indirect
github.com/inconshreveable/mousetrap v1.0.1 // indirect
github.com/klauspost/compress v1.15.15 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/magiconair/properties v1.8.6 // indirect
github.com/mattn/go-runewidth v0.0.13 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/mmcloughlin/addchain v0.4.0 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/pelletier/go-toml v1.9.5 // indirect
github.com/pelletier/go-toml/v2 v2.0.5 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/prometheus/client_golang v1.14.0 // indirect
github.com/prometheus/client_model v0.3.0 // indirect
github.com/prometheus/common v0.39.0 // indirect
github.com/prometheus/procfs v0.9.0 // indirect
github.com/rivo/uniseg v0.2.0 // indirect
github.com/rogpeppe/go-internal v1.9.0 // indirect
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0 // indirect
github.com/jmoiron/sqlx v1.2.0 // indirect
github.com/jonboulle/clockwork v0.1.0 // indirect
github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222 // indirect
github.com/robertkrimen/otto v0.0.0-20191219234010-c382bd3c16ff // indirect
github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521 // indirect
github.com/shirou/gopsutil v3.21.11+incompatible // indirect
github.com/sirupsen/logrus v1.9.0
github.com/soheilhy/cmux v0.1.4 // indirect
github.com/spf13/afero v1.9.2 // indirect
github.com/spf13/cast v1.5.0 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/subosito/gotenv v1.4.1 // indirect
github.com/supranational/blst v0.3.11 // indirect
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect
github.com/tklauser/go-sysconf v0.3.12 // indirect
github.com/tklauser/numcpus v0.6.1 // indirect
github.com/spf13/cobra v1.6.0
github.com/spf13/viper v1.13.0
github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 // indirect
github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3 // indirect
github.com/tklauser/go-sysconf v0.3.10 // indirect
github.com/tklauser/numcpus v0.5.0 // indirect
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 // indirect
github.com/urfave/cli v1.22.1 // indirect
github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208 // indirect
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect
github.com/yusufpapurcu/wmi v1.2.2 // indirect
golang.org/x/crypto v0.22.0 // indirect
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa // indirect
golang.org/x/sync v0.7.0 // indirect
golang.org/x/sys v0.20.0 // indirect
golang.org/x/text v0.14.0 // indirect
google.golang.org/protobuf v1.33.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
rsc.io/tmplfunc v0.0.3 // indirect
go.etcd.io/bbolt v1.3.2 // indirect
golang.org/x/crypto v0.0.0-20221012134737-56aed061732a // indirect
golang.org/x/sys v0.1.0 // indirect
golang.org/x/text v0.4.0 // indirect
gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200316214253-d7b0ff38cac9 // indirect
gopkg.in/resty.v1 v1.12.0 // indirect
gopkg.in/sourcemap.v1 v1.0.5 // indirect
gopkg.in/urfave/cli.v1 v1.20.0 // indirect
gotest.tools v2.2.0+incompatible // indirect
)
replace github.com/ethereum/go-ethereum v1.9.10 => github.com/vulcanize/go-ethereum v1.9.10-optimism-0.0.2

967
go.sum

File diff suppressed because it is too large Load Diff

View File

@ -21,6 +21,7 @@ import (
"context"
"crypto/ecdsa"
"fmt"
"github.com/ethereum/go-ethereum/ethclient"
"io/ioutil"
"math"
"math/big"
@ -28,16 +29,13 @@ import (
"strings"
"time"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/holiman/uint256"
"github.com/cerc-io/tx-spammer/pkg/shared"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/rpc"
"github.com/spf13/viper"
"github.com/cerc-io/tx-spammer/pkg/shared"
)
var (
@ -51,12 +49,10 @@ func init() {
// Config holds all the parameters for the auto tx spammer
type Config struct {
// Whether to stop service on any error from tx generation or sending
StopOnSendError bool
// HTTP client for sending transactions
RpcClient *rpc.Client
EthClient *ethclient.Client
ChainID *big.Int
// Key pairs for the accounts we will use to deploy contracts and send txs
SenderKeys []*ecdsa.PrivateKey
@ -73,9 +69,6 @@ type Config struct {
// Configuration for the eth transfer txs
SendConfig *SendConfig
// Configuration for the blob txs
BlobTxConfig *BlobTxConfig
}
// DeploymentConfig holds the parameters for the contract deployment contracts
@ -117,24 +110,7 @@ type SendConfig struct {
TotalNumber int
}
// SendConfig holds the parameters for the blob txs
type BlobTxConfig struct {
ChainID *big.Int
GasLimit uint64
GasFeeCap *big.Int
GasTipCap *big.Int
Amount *big.Int
BlobFeeCap *uint256.Int
BlobCount int
Frequency time.Duration
TotalNumber int
}
func NewConfig() (*Config, error) {
stopOnError := viper.GetBool(SpammerStopOnError)
// Initialize rpc client
httpPathStr := viper.GetString(ethHttpPath)
if httpPathStr == "" {
@ -204,15 +180,8 @@ func NewConfig() (*Config, error) {
return nil, err
}
// Load blob tx config
blobTxConfig, err := NewBlobTxConfig(chainID)
if err != nil {
return nil, err
}
// Assemble and return
return &Config{
StopOnSendError: stopOnError,
RpcClient: rpcClient,
EthClient: ethClient,
SenderKeys: keys,
@ -221,7 +190,6 @@ func NewConfig() (*Config, error) {
DeploymentConfig: deploymentConfig,
CallConfig: callConfig,
SendConfig: sendConfig,
BlobTxConfig: blobTxConfig,
}, nil
}
@ -323,37 +291,3 @@ func NewSendConfig(chainID *big.Int) (*SendConfig, error) {
TotalNumber: totalNumber,
}, nil
}
// NewBlobTxConfig constructs and returns a new SendConfig
func NewBlobTxConfig(chainID *big.Int) (*BlobTxConfig, error) {
amountStr := viper.GetString(ethBlobTxAmount)
amount, ok := new(big.Int).SetString(amountStr, 10)
if !ok {
return nil, fmt.Errorf("unable to convert amount string (%s) into big.Int", amountStr)
}
var frequency time.Duration
tmpFreq := viper.GetDuration(ethBlobTxFrequency)
if tmpFreq <= 0 {
frequency = time.Microsecond
} else {
frequency = tmpFreq * time.Millisecond
}
totalNumber := viper.GetInt(ethBlobTxTotalNumber)
if totalNumber < 0 {
totalNumber = math.MaxInt
}
return &BlobTxConfig{
ChainID: chainID,
Frequency: frequency,
Amount: amount,
GasLimit: viper.GetUint64(ethBlobTxGasLimit),
GasFeeCap: big.NewInt(viper.GetInt64(ethBlobTxGasFeeCap)),
GasTipCap: big.NewInt(viper.GetInt64(ethBlobTxGasTipCap)),
BlobFeeCap: uint256.MustFromBig(big.NewInt(viper.GetInt64(ethBlobTxBlobFeeCap))),
BlobCount: viper.GetInt(ethBlobTxBlobCount),
TotalNumber: totalNumber,
}, nil
}

View File

@ -18,13 +18,12 @@ package auto
import (
"crypto/ecdsa"
"github.com/sirupsen/logrus"
"time"
"github.com/sirupsen/logrus"
"github.com/cerc-io/tx-spammer/pkg/shared"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/rpc"
"github.com/cerc-io/tx-spammer/pkg/shared"
)
const (
@ -60,7 +59,7 @@ func (cp *ContractDeployer) Deploy() ([]common.Address, error) {
<-ticker.C
for i, key := range cp.senderKeys {
logrus.Debugf("Generating contract deployment for %s.", cp.senderAddrs[i].Hex())
signedTx, contractAddr, err := cp.txGenerator.createTx(&GenParams{
signedTx, contractAddr, err := cp.txGenerator.GenerateTx(&GenParams{
ChainID: cp.config.ChainID,
Sender: cp.senderAddrs[i],
SenderKey: key,

View File

@ -19,12 +19,9 @@ package auto
import "github.com/spf13/viper"
const (
SPAMMER_STOP_ON_ERROR = "SPAMMER_STOP_ON_ERROR"
// env variables
ETH_KEY_DIR_PATH = "ETH_KEY_DIR_PATH"
ETH_HTTP_PATH = "ETH_HTTP_PATH"
ETH_CONTRACT_ADDR_PATH = "ETH_CONTRACT_ADDR_PATH"
ETH_KEY_DIR_PATH = "ETH_KEY_DIR_PATH"
ETH_HTTP_PATH = "ETH_HTTP_PATH"
ETH_DEPLOYMENT_NUMBER = "ETH_DEPLOYMENT_NUMBER"
ETH_DEPLOYMENT_BIN_PATH = "ETH_DEPLOYMENT_BIN_PATH"
@ -47,21 +44,9 @@ const (
ETH_SEND_GAS_FEE_CAP = "ETH_SEND_GAS_FEE_CAP"
ETH_SEND_GAS_TIP_CAP = "ETH_SEND_GAS_TIP_CAP"
ETH_BLOBTX_FREQ = "ETH_BLOBTX_FREQ"
ETH_BLOBTX_TOTAL_NUMBER = "ETH_BLOBTX_TOTAL_NUMBER"
ETH_BLOBTX_AMOUNT = "ETH_BLOBTX_AMOUNT"
ETH_BLOBTX_GAS_LIMIT = "ETH_BLOBTX_GAS_LIMIT"
ETH_BLOBTX_GAS_FEE_CAP = "ETH_BLOBTX_GAS_FEE_CAP"
ETH_BLOBTX_GAS_TIP_CAP = "ETH_BLOBTX_GAS_TIP_CAP"
ETH_BLOBTX_BLOB_FEE_CAP = "ETH_BLOBTX_BLOB_FEE_CAP"
ETH_BLOBTX_BLOB_COUNT = "ETH_BLOBTX_BLOB_COUNT"
// toml bindings
SpammerStopOnError = "service.stopOnError"
ethKeyDirPath = "eth.keyDirPath"
ethHttpPath = "eth.httpPath"
ethContractAddrPath = "eth.contractAddrPath"
ethKeyDirPath = "eth.keyDirPath"
ethHttpPath = "eth.httpPath"
ethDeploymentBinPath = "deployment.binPath"
ethDeploymentNumber = "deployment.number"
@ -83,23 +68,11 @@ const (
ethSendGasLimit = "sendSpammer.gasLimit"
ethSendGasFeeCap = "sendSpammer.gasFeeCap"
ethSendGasTipCap = "sendSpammer.gasTipCap"
ethBlobTxFrequency = "blobSpammer.frequency"
ethBlobTxTotalNumber = "blobSpammer.totalNumber"
ethBlobTxAmount = "blobSpammer.amount"
ethBlobTxGasLimit = "blobSpammer.gasLimit"
ethBlobTxGasFeeCap = "blobSpammer.gasFeeCap"
ethBlobTxGasTipCap = "blobSpammer.gasTipCap"
ethBlobTxBlobFeeCap = "blobSpammer.blobFeeCap"
ethBlobTxBlobCount = "blobSpammer.blobCount"
)
func bindEnv() {
viper.BindEnv(SpammerStopOnError, SPAMMER_STOP_ON_ERROR)
viper.BindEnv(ethKeyDirPath, ETH_KEY_DIR_PATH)
viper.BindEnv(ethHttpPath, ETH_HTTP_PATH)
viper.BindEnv(ethContractAddrPath, ETH_CONTRACT_ADDR_PATH)
viper.BindEnv(ethDeploymentNumber, ETH_DEPLOYMENT_NUMBER)
viper.BindEnv(ethDeploymentBinPath, ETH_DEPLOYMENT_BIN_PATH)
@ -122,13 +95,4 @@ func bindEnv() {
viper.BindEnv(ethSendGasFeeCap, ETH_SEND_GAS_FEE_CAP)
viper.BindEnv(ethSendGasTipCap, ETH_SEND_GAS_TIP_CAP)
viper.BindEnv(ethSendGasLimit, ETH_CALL_GAS_LIMIT)
viper.BindEnv(ethBlobTxFrequency, ETH_BLOBTX_FREQ)
viper.BindEnv(ethBlobTxTotalNumber, ETH_BLOBTX_TOTAL_NUMBER)
viper.BindEnv(ethBlobTxAmount, ETH_BLOBTX_AMOUNT)
viper.BindEnv(ethBlobTxGasLimit, ETH_BLOBTX_GAS_LIMIT)
viper.BindEnv(ethBlobTxGasFeeCap, ETH_BLOBTX_GAS_FEE_CAP)
viper.BindEnv(ethBlobTxGasTipCap, ETH_BLOBTX_GAS_TIP_CAP)
viper.BindEnv(ethBlobTxBlobFeeCap, ETH_BLOBTX_BLOB_FEE_CAP)
viper.BindEnv(ethBlobTxBlobCount, ETH_BLOBTX_BLOB_COUNT)
}

View File

@ -17,12 +17,10 @@
package auto
import (
"fmt"
"github.com/cerc-io/tx-spammer/pkg/shared"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/rpc"
log "github.com/sirupsen/logrus"
"github.com/sirupsen/logrus"
"github.com/cerc-io/tx-spammer/pkg/shared"
)
// EthSender sends eth value transfer txs
@ -38,25 +36,24 @@ func NewEthSender(config *Config) *EthSender {
}
// Send awaits txs off the provided work queue and sends them
func (s *EthSender) Send(quitChan <-chan bool, txChan <-chan *types.Transaction, sentCh chan<- *types.Transaction) (<-chan bool, <-chan error) {
func (s *EthSender) Send(quitChan <-chan bool, txChan <-chan *types.Transaction, sentCh chan *types.Transaction) (<-chan bool, <-chan error) {
// err channel returned to calling context
errChan := make(chan error)
doneChan := make(chan bool)
go func() {
defer close(doneChan)
defer close(errChan)
counter := 0
for {
select {
case tx := <-txChan:
counter += 1
if err := shared.SendTransaction(s.client, tx); err != nil {
errChan <- fmt.Errorf("%w: tx = %s", err, tx.Hash())
errChan <- err
} else {
sentCh <- tx
}
case <-quitChan:
log.Infof("quitting Send loop (sent %d)", counter)
logrus.Infof("quitting Send loop (sent %d)", counter)
return
}
}

View File

@ -19,8 +19,8 @@ package auto
import (
"fmt"
"github.com/cerc-io/tx-spammer/pkg/shared"
"github.com/sirupsen/logrus"
"github.com/cerc-io/tx-spammer/pkg/shared"
)
// Spammer underlying struct type for spamming service
@ -58,35 +58,38 @@ func (s *Spammer) Loop(quitChan <-chan bool) (<-chan bool, error) {
sendDoneChan, sendErrChan := s.Sender.Send(senderQuit, txChan, watcher.PendingTxCh)
go func() {
<-genDoneChan
recoverClose(senderQuit)
<-sendDoneChan
recoverClose(watcher.quitCh)
close(doneChan)
}()
go func() {
for err := range genErrChan {
logrus.Errorf("tx generation error: %v", err)
recoverClose(genQuit)
}
}()
go func() {
for err := range sendErrChan {
logrus.Errorf("tx sending error: %v", err)
if s.config.StopOnSendError {
defer close(doneChan)
for {
select {
case err := <-genErrChan:
logrus.Errorf("tx generation error: %v", err)
recoverClose(genQuit)
<-genDoneChan
recoverClose(senderQuit)
<-sendDoneChan
recoverClose(watcher.quitCh)
case err := <-sendErrChan:
logrus.Errorf("tx sending error: %v", err)
recoverClose(genQuit)
<-genDoneChan
recoverClose(senderQuit)
<-sendDoneChan
recoverClose(watcher.quitCh)
case <-quitChan:
logrus.Info("shutting down tx spammer")
recoverClose(genQuit)
<-genDoneChan
recoverClose(senderQuit)
<-sendDoneChan
recoverClose(watcher.quitCh)
case <-sendDoneChan:
recoverClose(watcher.quitCh)
return
case <-genDoneChan:
recoverClose(senderQuit)
}
}
}()
go func() {
<-quitChan
logrus.Info("shutting down tx spammer")
recoverClose(genQuit)
}()
return doneChan, nil
}

View File

@ -19,20 +19,16 @@ package auto
import (
"context"
"crypto/ecdsa"
"errors"
"github.com/ethereum/go-ethereum/crypto"
log "github.com/sirupsen/logrus"
"math/big"
"math/rand"
"sync"
"time"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto/kzg4844"
"github.com/holiman/uint256"
log "github.com/sirupsen/logrus"
"github.com/cerc-io/tx-spammer/pkg/shared"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/cerc-io/tx-spammer/pkg/shared"
)
// TxGenerator generates and signs txs
@ -77,14 +73,6 @@ type GenParams struct {
To *common.Address
Amount *big.Int
Data []byte
BlobParams *BlobParams
}
type BlobParams struct {
BlobFeeCap *uint256.Int
BlobHashes []common.Hash
Sidecar *types.BlobTxSidecar
}
func (gen *TxGenerator) GenerateTxs(quitChan <-chan bool) (<-chan bool, <-chan *types.Transaction, <-chan error) {
@ -100,22 +88,10 @@ func (gen *TxGenerator) GenerateTxs(quitChan <-chan bool) (<-chan bool, <-chan *
wg.Add(1)
go gen.genCalls(wg, txChan, errChan, quitChan, sender, gen.config.SenderAddrs[i], gen.config.CallConfig)
}
if gen.config.BlobTxConfig.TotalNumber > 0 {
wg.Add(1)
go gen.genBlobTx(senderArgs{
wg: wg,
txChan: txChan,
errChan: errChan,
quitChan: quitChan,
senderKey: sender,
senderAddr: gen.config.SenderAddrs[i],
}, gen.config.BlobTxConfig)
}
}
doneChan := make(chan bool)
go func() {
wg.Wait()
close(errChan)
close(doneChan)
}()
return doneChan, txChan, errChan
@ -129,7 +105,7 @@ func (gen *TxGenerator) genSends(wg *sync.WaitGroup, txChan chan<- *types.Transa
case <-ticker.C:
dst := crypto.CreateAddress(receiverAddressSeed, uint64(i))
log.Debugf("Generating send from %s to %s.", senderAddr.Hex(), dst.Hex())
params := &GenParams{
rawTx, _, err := gen.GenerateTx(&GenParams{
ChainID: sendConfig.ChainID,
To: &dst,
Sender: senderAddr,
@ -138,8 +114,7 @@ func (gen *TxGenerator) genSends(wg *sync.WaitGroup, txChan chan<- *types.Transa
GasFeeCap: sendConfig.GasFeeCap,
GasTipCap: sendConfig.GasTipCap,
Amount: sendConfig.Amount,
}
rawTx, _, err := gen.createTx(params)
})
if err != nil {
errChan <- err
continue
@ -165,7 +140,7 @@ func (gen *TxGenerator) genCalls(wg *sync.WaitGroup, txChan chan<- *types.Transa
errChan <- err
continue
}
rawTx, _, err := gen.createTx(&GenParams{
rawTx, _, err := gen.GenerateTx(&GenParams{
Sender: senderAddr,
SenderKey: senderKey,
GasLimit: callConfig.GasLimit,
@ -186,71 +161,13 @@ func (gen *TxGenerator) genCalls(wg *sync.WaitGroup, txChan chan<- *types.Transa
log.Info("Done generating calls for ", senderAddr.Hex())
}
type senderArgs struct {
wg *sync.WaitGroup
txChan chan<- *types.Transaction
errChan chan<- error
quitChan <-chan bool
senderKey *ecdsa.PrivateKey
senderAddr common.Address
}
func (gen *TxGenerator) genBlobTx(args senderArgs, blobTxConfig *BlobTxConfig) {
defer args.wg.Done()
ticker := time.NewTicker(blobTxConfig.Frequency)
for i := 0; i < blobTxConfig.TotalNumber; i++ {
select {
case <-ticker.C:
dst := crypto.CreateAddress(receiverAddressSeed, uint64(i))
log.Debugf("Generating send from %s to %s.", args.senderAddr, dst)
params := &GenParams{
ChainID: blobTxConfig.ChainID,
To: &dst,
Sender: args.senderAddr,
SenderKey: args.senderKey,
GasLimit: blobTxConfig.GasLimit,
GasFeeCap: blobTxConfig.GasFeeCap,
GasTipCap: blobTxConfig.GasTipCap,
Amount: blobTxConfig.Amount,
}
blobdata := make([]byte, blobTxConfig.BlobCount)
for i := range blobdata {
blobdata[i] = byte(i + 1)
}
sidecar, err := makeSidecar(blobdata)
if err != nil {
args.errChan <- err
continue
}
params.BlobParams = &BlobParams{
BlobFeeCap: blobTxConfig.BlobFeeCap,
BlobHashes: sidecar.BlobHashes(),
Sidecar: sidecar,
}
rawTx, _, err := gen.createTx(params)
if err != nil {
args.errChan <- err
continue
}
args.txChan <- rawTx
case <-args.quitChan:
return
}
}
log.Info("Done generating sends for ", args.senderAddr)
}
// createTx generates tx from the provided params
func (gen *TxGenerator) createTx(params *GenParams) (*types.Transaction, common.Address, error) {
// GenerateTx generates tx from the provided params
func (gen *TxGenerator) GenerateTx(params *GenParams) (*types.Transaction, common.Address, error) {
nonce := gen.claimNonce(params.Sender)
tx := new(types.Transaction)
var contractAddr common.Address
var err error
if params.To == nil {
if params.BlobParams != nil {
return nil, common.Address{}, errors.New("BlobTx cannot be used for contract creation")
}
tx = types.NewTx(
&types.DynamicFeeTx{
ChainID: params.ChainID,
@ -266,7 +183,7 @@ func (gen *TxGenerator) createTx(params *GenParams) (*types.Transaction, common.
if err != nil {
return nil, common.Address{}, err
}
} else if params.BlobParams == nil {
} else {
tx = types.NewTx(
&types.DynamicFeeTx{
ChainID: params.ChainID,
@ -278,53 +195,10 @@ func (gen *TxGenerator) createTx(params *GenParams) (*types.Transaction, common.
Value: params.Amount,
Data: params.Data,
})
} else {
tx = types.NewTx(
&types.BlobTx{
ChainID: uint256.MustFromBig(params.ChainID),
Nonce: nonce,
Gas: params.GasLimit,
GasTipCap: uint256.MustFromBig(params.GasTipCap),
GasFeeCap: uint256.MustFromBig(params.GasFeeCap),
To: *params.To,
Value: uint256.MustFromBig(params.Amount),
Data: params.Data,
BlobFeeCap: params.BlobParams.BlobFeeCap,
BlobHashes: params.BlobParams.BlobHashes,
Sidecar: params.BlobParams.Sidecar,
})
}
signedTx, err := types.SignTx(tx, gen.config.Signer, params.SenderKey)
if err != nil {
return nil, common.Address{}, err
}
return signedTx, contractAddr, err
}
// From go-ethereum/cmd/devp2p/internal/ethtest/suite.go
func makeSidecar(data []byte) (*types.BlobTxSidecar, error) {
var (
blobs = make([]kzg4844.Blob, len(data))
commitments []kzg4844.Commitment
proofs []kzg4844.Proof
)
for i := range blobs {
blobs[i][0] = data[i]
c, err := kzg4844.BlobToCommitment(&blobs[i])
if err != nil {
return nil, err
}
p, err := kzg4844.ComputeBlobProof(&blobs[i], c)
if err != nil {
return nil, err
}
commitments = append(commitments, c)
proofs = append(proofs, p)
}
return &types.BlobTxSidecar{
Blobs: blobs,
Commitments: commitments,
Proofs: proofs,
}, nil
}

View File

@ -2,11 +2,10 @@ package auto
import (
"context"
"time"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/sirupsen/logrus"
"time"
)
type TxWatcher struct {
@ -45,8 +44,8 @@ func (tw *TxWatcher) Start() {
sleep *= 2
} else {
elapsed := time.Now().Sub(tw.startedAt)
logrus.Debugf("TxW: TX %s found in block %s after %v.", tx.Hash().Hex(),
receipt.BlockNumber.String(), time.Now().Sub(start))
logrus.Debugf("TxW: TX %s found in block %s after %dms.", tx.Hash().Hex(),
receipt.BlockNumber.String(), time.Now().Sub(start).Milliseconds())
logrus.Infof("TxW: %d in %.0f seconds (%.2f/sec, %d pending)",
tw.counter, elapsed.Seconds(), float64(tw.counter)/elapsed.Seconds(), len(tw.PendingTxCh))
}

View File

@ -17,8 +17,8 @@
package manual
import (
"github.com/cerc-io/tx-spammer/pkg/shared"
"github.com/sirupsen/logrus"
"github.com/cerc-io/tx-spammer/pkg/shared"
)
type Spammer struct {

View File

@ -19,10 +19,10 @@ package manual
import (
"sync/atomic"
"github.com/cerc-io/tx-spammer/pkg/shared"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/rlp"
"github.com/cerc-io/tx-spammer/pkg/shared"
)
// TxGenerator generates and signs txs

View File

@ -18,53 +18,37 @@ package shared
import (
"context"
"github.com/sirupsen/logrus"
"math/big"
"os"
"github.com/sirupsen/logrus"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
"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"
)
// TxSigner returns the Cancun signer at the provided block height
// ChainConfig returns the appropriate ethereum chain config for the provided chain id
func TxSigner(chainID *big.Int) types.Signer {
return types.NewCancunSigner(chainID)
return types.NewLondonSigner(chainID)
}
// SendTransaction sends a signed tx using the provided client
func SendTransaction(rpcClient *rpc.Client, tx *types.Transaction) error {
msg, err := core.TransactionToMessage(tx, TxSigner(tx.ChainId()), big.NewInt(1))
if err != nil {
return err
}
msg, _ := tx.AsMessage(TxSigner(tx.ChainId()), big.NewInt(1))
if nil == tx.To() {
logrus.WithFields(logrus.Fields{
"hash": tx.Hash(),
"from": msg.From,
"contract": crypto.CreateAddress(msg.From, tx.Nonce()),
}).Debug("Sending TX to create contract")
logrus.Debugf("TX %s to create contract %s (sender %s)",
tx.Hash().Hex(), crypto.CreateAddress(msg.From(), tx.Nonce()), msg.From().Hex())
} else if nil == tx.Data() || len(tx.Data()) == 0 {
logrus.Debugf("TX %s sending %s Wei to %s (sender %s)",
tx.Hash().Hex(), tx.Value().String(), msg.To().Hex(), msg.From().Hex())
} else {
fields := logrus.Fields{
"hash": tx.Hash(),
"from": msg.From,
"to": tx.To(),
"nonce": tx.Nonce(),
}
if numblobs := len(tx.BlobHashes()); numblobs > 0 {
fields["blobs"] = numblobs
}
if len(tx.Data()) == 0 {
fields["value"] = tx.Value()
logrus.WithFields(fields).Debug("Sending TX to transfer ETH")
} else {
logrus.WithFields(fields).Debug("Sending TX to call contract")
}
logrus.Debugf("TX %s calling contract %s (sender %s)",
tx.Hash().Hex(), msg.To().Hex(), msg.From().Hex())
}
data, err := tx.MarshalBinary()
if err != nil {
return err
@ -74,7 +58,7 @@ func SendTransaction(rpcClient *rpc.Client, tx *types.Transaction) error {
// SendRawTransaction sends a raw, signed tx using the provided client
func SendRawTransaction(rpcClient *rpc.Client, raw []byte) error {
logrus.Debugf("eth_sendRawTransaction: %x... (%d bytes)", raw[:min(10, len(raw))], len(raw))
logrus.Debug("eth_sendRawTransaction: ", hexutil.Encode(raw))
return rpcClient.CallContext(context.Background(), nil, "eth_sendRawTransaction", hexutil.Encode(raw))
}