Compare commits

...

7 Commits

Author SHA1 Message Date
8f7e737896 Support sending Blob transactions (#23)
Reviewed-on: #23
2024-07-01 13:52:21 +00:00
Ian Norden
24f7fd5e97
Merge pull request #20 from cerc-io/ian_dev
update workflows with fixed name
2023-04-07 22:32:49 -05:00
i-norden
01cb9fb46c update workflows with fixed name 2023-04-07 14:37:05 -05:00
Ian Norden
18518e7cb5
Merge pull request #19 from cerc-io/ian_dev
update to get v1.11.5
2023-04-03 00:00:52 -05:00
i-norden
d1455a9cbd use core.TransactionToMessage 2023-04-02 23:37:04 -05:00
i-norden
b699663536 update dep 2023-03-31 08:57:31 -05:00
e09975d0c8
Rebrand to cerc-io/tx-spammer (#15) 2022-12-21 09:59:07 -06:00
26 changed files with 668 additions and 1053 deletions

View File

@ -17,9 +17,9 @@ jobs:
- name: Run docker build
run: make docker-build
- name: Tag docker image
run: docker tag vulcanize/tx_spammer docker.pkg.github.com/vulcanize/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://docker.pkg.github.com -u vulcanize --password-stdin
run: echo ${{ secrets.GITHUB_TOKEN }} | docker login https://git.vdb.to -u cerc-io --password-stdin
- name: Docker Push
run: docker push docker.pkg.github.com/vulcanize/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

@ -13,13 +13,13 @@ jobs:
echo ::set-output name=sha::$(echo ${GITHUB_SHA:0:7})
echo ::set-output name=tag::$(echo ${GITHUB_REF#refs/tags/})
- name: Docker Login to Github Registry
run: echo ${{ secrets.GITHUB_TOKEN }} | docker login https://docker.pkg.github.com -u vulcanize --password-stdin
run: echo ${{ secrets.GITHUB_TOKEN }} | docker login https://git.vdb.to -u vulcanize --password-stdin
- name: Docker Pull
run: docker pull docker.pkg.github.com/vulcanize/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 docker.pkg.github.com/vulcanize/tx_spammer/tx_spammer:${{steps.vars.outputs.sha}} vulcanize/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 vulcanize/tx_spammer:${{steps.vars.outputs.tag}}
run: docker push cerc-io/tx-spammer:${{steps.vars.outputs.tag}}

2
.gitignore vendored
View File

@ -14,4 +14,4 @@
# Dependency directories (remove the comment below to include it)
# vendor/
.idea/
tx_spammer
tx-spammer

View File

@ -1,13 +1,17 @@
FROM golang:1.19-alpine as builder
FROM golang:1.21-alpine as builder
RUN apk --update --no-cache add make git g++ linux-headers
RUN apk --update --no-cache add gcc libc-dev
# DEBUG
RUN apk add busybox-extras
# Get and build tx_spammer
ADD . /go/src/github.com/vulcanize/tx_spammer
WORKDIR /go/src/github.com/vulcanize/tx_spammer
RUN GO111MODULE=on GCO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -ldflags '-extldflags "-static"' -o tx_spammer .
# Get and build 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 .
# app container
FROM alpine
@ -22,11 +26,12 @@ USER $USER
# chown first so dir is writable
# note: using $USER is merged, but not in the stable release yet
COPY --chown=5000:5000 --from=builder /go/src/github.com/vulcanize/tx_spammer/$CONFIG_FILE config.toml
COPY --chown=5000:5000 --from=builder /go/src/github.com/vulcanize/tx_spammer/startup_script.sh .
COPY --chown=5000:5000 --from=builder /go/src/github.com/cerc-io/tx-spammer/$CONFIG_FILE config.toml
COPY --chown=5000:5000 --from=builder /go/src/github.com/cerc-io/tx-spammer/startup_script.sh .
# keep binaries immutable
COPY --from=builder /go/src/github.com/vulcanize/tx_spammer/tx_spammer tx_spammer
COPY --from=builder /go/src/github.com/vulcanize/tx_spammer/environments environments
COPY --from=builder /go/src/github.com/cerc-io/tx-spammer/tx-spammer tx-spammer
COPY --from=builder /go/src/github.com/cerc-io/tx-spammer/environments environments
COPY --from=builder /go/src/github.com/cerc-io/tx-spammer/sol sol
ENTRYPOINT ["/app/startup_script.sh"]

View File

@ -1,11 +1,11 @@
## Build docker image
.PHONY: docker-build
docker-build:
docker build -t vulcanize/tx_spammer -f Dockerfile .
docker build -t cerc/tx-spammer -f Dockerfile .
.PHONY: build
build:
GO111MODULE=on go build -o tx_spammer .
GO111MODULE=on go build -o tx-spammer .
.PHONY: contract
contract:

View File

@ -1,9 +1,9 @@
# tx_spammer
# tx-spammer
Tools to enable the semi-reproducible growth of a large and complex chain over RPC, for testing and benchmarking purposes
Usage:
`./tx_spammer autoSend --config=./environments/gen.toml`
`./tx-spammer autoSend --config=./environments/gen.toml`
The `autoSend` command takes as input a .toml config of the below format, the fields can be overridden with the env variables in the comments.
It uses the provided key pairs and configuraiton parameters to generate and deploy a number of contracts with a simple interface for `Put`ing to a dynamic data structure.

View File

@ -21,7 +21,9 @@ import (
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/vulcanize/tx_spammer/pkg/auto"
"github.com/spf13/viper"
"github.com/cerc-io/tx-spammer/pkg/auto"
)
// autoSendCmd represents the autoSend command
@ -38,11 +40,18 @@ 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)
@ -61,4 +70,4 @@ func autoSend() {
func init() {
rootCmd.AddCommand(autoSendCmd)
}
}

View File

@ -33,7 +33,7 @@ var (
)
var rootCmd = &cobra.Command{
Use: "tx_spammer",
Use: "tx-spammer",
PersistentPreRun: initFuncs,
}
@ -45,7 +45,7 @@ func Execute() {
}
func initFuncs(cmd *cobra.Command, args []string) {
logfile := viper.GetString("logfile")
logfile := viper.GetString("log.file")
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", "LOGRUS_LEVEL")
viper.BindEnv("log.level", "LOG_LEVEL")
lvl, err := log.ParseLevel(viper.GetString("log.level"))
if err != nil {
return err
}
log.SetLevel(lvl)
if lvl > log.InfoLevel {
if lvl > log.DebugLevel {
log.SetReportCaller(true)
}
log.Info("Log level set to ", lvl.String())

View File

@ -22,7 +22,7 @@ import (
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/vulcanize/tx_spammer/pkg/manual"
"github.com/cerc-io/tx-spammer/pkg/manual"
)
// sendTxsCmd represents the sendTxs command

View File

@ -1,65 +1,40 @@
[eth]
txs = ["L2ContractDeployment", "L2ContractPutCall", "L2ContractGetCall"] # $ETH_TX_LIST
addrLogPath = "" # ETH_ADDR_LOG
keyDirPath = "./keys/" # path to the directory with all of the key pairs to use - env: $ETH_KEY_DIR_PATH
httpPath = "http://localhost:8545" # http url for the node we wish to send all our transactions to - env: $ETH_HTTP_PATH
[L2ContractDeployment]
type = "L2"
httpPath = ""
chainID = 420
to = ""
amount = "0"
gasLimit = 0
gasPrice = "0"
data = ""
senderKeyPath = ""
writeSenderPath = ""
writeDeploymentAddrPath = ""
frequency = 1
totalNumber = 1
delay = 0
l1Sender = ""
l1RollupTxId = 0
sigHashType = 0
queueOrigin = 0
[deployment]
number = 1 # number of contracts we will deploy for each key at keyPath - env: $ETH_DEPLOYMENT_NUMBER
binPath = "sol/build/Test.bin" # hex data for the contracts we will deploy - env: $ETH_DEPLOYMENT_BIN_PATH
gasLimit = 100000 # gasLimit to use for the deployment txs - env: $ETH_DEPLOYMENT_GAS_LIMIT
gasTipCap = "1000000000" # gasTipCap to use for the deployment txs - env: $ETH_DEPLOYMENT_GAS_TIP_CAP
gasFeeCap = "1000000007" # gasFeeCap to use for the deployment txs - env: $ETH_DEPLOYMENT_GAS_FEE_CAP
[L2ContractPutCall]
type = "L2"
httpPath = ""
chainID = 420
to = ""
amount = "0"
gasLimit = 0
gasPrice = "0"
data = ""
senderKeyPath = ""
writeSenderPath = ""
frequency = 15
totalNumber = 1
delay = 60
l1Sender = ""
l1RollupTxId = 0
sigHashType = 0
queueOrigin = 0
[contractSpammer]
frequency = -1 # how often to send a transaction (in milliseconds, -1 for no delay) - env: $ETH_CALL_FREQ
totalNumber = -1 # total number of transactions to send (per sender, -1 for unlimited) - env: $ETH_CALL_TOTAL_NUMBER
abiPath = "sol/build/Test.abi" # path to the abi file for the contract we are calling - env: $ETH_CALL_ABI_PATH
# NOTE: we expect to be calling a method such as Put(address addr, uint256 val) where the first argument is an
# integer than we can increment to store values at new locations in the contract trie (to grow it) and
# the second argument is an integer value that we store at these positions
methodName = "Put" # the method name we are calling - env: $ETH_CALL_METHOD_NAME
gasLimit = 42000 # gasLimit to use for the eth call txs - env: $ETH_CALL_GAS_LIMIT
gasTipCap = "1000000000" # gasTipCap to use for the eth call txs - env: $ETH_CALL_GAS_TIP_CAP
gasFeeCap = "1000000007" # gasFeeCap to use for the eth call txs - env: $ETH_CALL_GAS_FEE_CAP
[L2ContractGetCall]
type = "L2"
httpPath = ""
chainID = 420
to = ""
amount = "0"
gasLimit = 0
gasPrice = "0"
data = ""
senderKeyPath = ""
writeSenderPath = ""
frequency = 60
totalNumber = 2
delay = 30
l1Sender = ""
l1RollupTxId = 0
sigHashType = 0
queueOrigin = 0
[sendSpammer]
frequency = -1 # 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 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
[log]
level = "info"
file = ""
[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

View File

@ -1,30 +0,0 @@
[eth]
keyDirPath = "./keys/" # path to the directory with all of the key pairs to use - env: $ETH_KEY_DIR_PATH
httpPath = "http://localhost:8545" # http url for the node we wish to send all our transactions to - env: $ETH_HTTP_PATH
[deployment]
number = 1 # number of contracts we will deploy for each key at keyPath - env: $ETH_DEPLOYMENT_NUMBER
binPath = "sol/build/Test.bin" # hex data for the contracts we will deploy - env: $ETH_DEPLOYMENT_BIN_PATH
gasLimit = 100000 # gasLimit to use for the deployment txs - env: $ETH_DEPLOYMENT_GAS_LIMIT
gasTipCap = "1000000000" # gasTipCap to use for the deployment txs - env: $ETH_DEPLOYMENT_GAS_TIP_CAP
gasFeeCap = "1000000007" # gasFeeCap to use for the deployment txs - env: $ETH_DEPLOYMENT_GAS_FEE_CAP
[contractSpammer]
frequency = -1 # how often to send a transaction (in milliseconds, -1 for no delay) - env: $ETH_CALL_FREQ
totalNumber = -1 # total number of transactions to send (per sender, -1 for unlimited) - env: $ETH_CALL_TOTAL_NUMBER
abiPath = "sol/build/Test.abi" # path to the abi file for the contract we are calling - env: $ETH_CALL_ABI_PATH
# NOTE: we expect to be calling a method such as Put(address addr, uint256 val) where the first argument is an
# integer than we can increment to store values at new locations in the contract trie (to grow it) and
# the second argument is an integer value that we store at these positions
methodName = "Put" # the method name we are calling - env: $ETH_CALL_METHOD_NAME
gasLimit = 42000 # gasLimit to use for the eth call txs - env: $ETH_CALL_GAS_LIMIT
gasTipCap = "1000000000" # gasTipCap to use for the eth call txs - env: $ETH_CALL_GAS_TIP_CAP
gasFeeCap = "1000000007" # gasFeeCap to use for the eth call txs - env: $ETH_CALL_GAS_FEE_CAP
[sendSpammer]
frequency = -1 # 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 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

128
go.mod
View File

@ -1,57 +1,85 @@
module github.com/vulcanize/tx_spammer
module github.com/cerc-io/tx-spammer
go 1.13
go 1.21
require (
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/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/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/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/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/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
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
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
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/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/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/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/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/shirou/gopsutil v3.21.11+incompatible // 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/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
)

967
go.sum

File diff suppressed because it is too large Load Diff

View File

@ -15,7 +15,7 @@
package main
import "github.com/vulcanize/tx_spammer/cmd"
import "github.com/cerc-io/tx-spammer/cmd"
func main() {
cmd.Execute()

View File

@ -21,7 +21,6 @@ import (
"context"
"crypto/ecdsa"
"fmt"
"github.com/ethereum/go-ethereum/ethclient"
"io/ioutil"
"math"
"math/big"
@ -29,13 +28,16 @@ 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/vulcanize/tx_spammer/pkg/shared"
)
var (
@ -49,10 +51,12 @@ 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
@ -69,6 +73,9 @@ 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
@ -110,7 +117,24 @@ 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 == "" {
@ -180,8 +204,15 @@ 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,
@ -190,6 +221,7 @@ func NewConfig() (*Config, error) {
DeploymentConfig: deploymentConfig,
CallConfig: callConfig,
SendConfig: sendConfig,
BlobTxConfig: blobTxConfig,
}, nil
}
@ -291,3 +323,37 @@ 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,12 +18,13 @@ 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/vulcanize/tx_spammer/pkg/shared"
)
const (
@ -59,7 +60,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.GenerateTx(&GenParams{
signedTx, contractAddr, err := cp.txGenerator.createTx(&GenParams{
ChainID: cp.config.ChainID,
Sender: cp.senderAddrs[i],
SenderKey: key,

View File

@ -19,9 +19,12 @@ 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_KEY_DIR_PATH = "ETH_KEY_DIR_PATH"
ETH_HTTP_PATH = "ETH_HTTP_PATH"
ETH_CONTRACT_ADDR_PATH = "ETH_CONTRACT_ADDR_PATH"
ETH_DEPLOYMENT_NUMBER = "ETH_DEPLOYMENT_NUMBER"
ETH_DEPLOYMENT_BIN_PATH = "ETH_DEPLOYMENT_BIN_PATH"
@ -44,9 +47,21 @@ 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
ethKeyDirPath = "eth.keyDirPath"
ethHttpPath = "eth.httpPath"
SpammerStopOnError = "service.stopOnError"
ethKeyDirPath = "eth.keyDirPath"
ethHttpPath = "eth.httpPath"
ethContractAddrPath = "eth.contractAddrPath"
ethDeploymentBinPath = "deployment.binPath"
ethDeploymentNumber = "deployment.number"
@ -68,11 +83,23 @@ 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)
@ -95,4 +122,13 @@ 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,10 +17,12 @@
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"
"github.com/sirupsen/logrus"
"github.com/vulcanize/tx_spammer/pkg/shared"
log "github.com/sirupsen/logrus"
)
// EthSender sends eth value transfer txs
@ -36,24 +38,25 @@ 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 <- err
errChan <- fmt.Errorf("%w: tx = %s", err, tx.Hash())
} else {
sentCh <- tx
}
case <-quitChan:
logrus.Infof("quitting Send loop (sent %d)", counter)
log.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/vulcanize/tx_spammer/pkg/shared"
)
// Spammer underlying struct type for spamming service
@ -58,38 +58,35 @@ func (s *Spammer) Loop(quitChan <-chan bool) (<-chan bool, error) {
sendDoneChan, sendErrChan := s.Sender.Send(senderQuit, txChan, watcher.PendingTxCh)
go func() {
defer close(doneChan)
for {
select {
case err := <-genErrChan:
logrus.Errorf("tx generation error: %v", err)
<-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 {
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,16 +19,20 @@ package auto
import (
"context"
"crypto/ecdsa"
"github.com/ethereum/go-ethereum/crypto"
log "github.com/sirupsen/logrus"
"errors"
"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/vulcanize/tx_spammer/pkg/shared"
)
// TxGenerator generates and signs txs
@ -73,6 +77,14 @@ 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) {
@ -88,10 +100,22 @@ 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
@ -105,7 +129,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())
rawTx, _, err := gen.GenerateTx(&GenParams{
params := &GenParams{
ChainID: sendConfig.ChainID,
To: &dst,
Sender: senderAddr,
@ -114,7 +138,8 @@ 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
@ -140,7 +165,7 @@ func (gen *TxGenerator) genCalls(wg *sync.WaitGroup, txChan chan<- *types.Transa
errChan <- err
continue
}
rawTx, _, err := gen.GenerateTx(&GenParams{
rawTx, _, err := gen.createTx(&GenParams{
Sender: senderAddr,
SenderKey: senderKey,
GasLimit: callConfig.GasLimit,
@ -161,13 +186,71 @@ func (gen *TxGenerator) genCalls(wg *sync.WaitGroup, txChan chan<- *types.Transa
log.Info("Done generating calls for ", senderAddr.Hex())
}
// GenerateTx generates tx from the provided params
func (gen *TxGenerator) GenerateTx(params *GenParams) (*types.Transaction, common.Address, error) {
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) {
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,
@ -183,7 +266,7 @@ func (gen *TxGenerator) GenerateTx(params *GenParams) (*types.Transaction, commo
if err != nil {
return nil, common.Address{}, err
}
} else {
} else if params.BlobParams == nil {
tx = types.NewTx(
&types.DynamicFeeTx{
ChainID: params.ChainID,
@ -195,10 +278,53 @@ func (gen *TxGenerator) GenerateTx(params *GenParams) (*types.Transaction, commo
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,10 +2,11 @@ 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 {
@ -44,8 +45,8 @@ func (tw *TxWatcher) Start() {
sleep *= 2
} else {
elapsed := time.Now().Sub(tw.startedAt)
logrus.Debugf("TxW: TX %s found in block %s after %dms.", tx.Hash().Hex(),
receipt.BlockNumber.String(), time.Now().Sub(start).Milliseconds())
logrus.Debugf("TxW: TX %s found in block %s after %v.", tx.Hash().Hex(),
receipt.BlockNumber.String(), time.Now().Sub(start))
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

@ -23,7 +23,7 @@ import (
"github.com/sirupsen/logrus"
"github.com/vulcanize/tx_spammer/pkg/shared"
"github.com/cerc-io/tx-spammer/pkg/shared"
)
// TxSender type for

View File

@ -17,8 +17,8 @@
package manual
import (
"github.com/cerc-io/tx-spammer/pkg/shared"
"github.com/sirupsen/logrus"
"github.com/vulcanize/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/vulcanize/tx_spammer/pkg/shared"
)
// TxGenerator generates and signs txs

View File

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

29
startup_script.sh Normal file → Executable file
View File

@ -1,16 +1,35 @@
#!/bin/sh
set -e
set +x
test $SPAMMER_COMMAND
set +e
if [ -z "$SPAMMER_COMMAND" ]; then
echo "SPAMMER_COMMAND env value is required!"
exit 2
fi
if [ -z "$LOG_LEVEL" ]; then
LOG_LEVEL="debug"
fi
if [ ! -z "$ACCOUNTS_CSV_URL" ] && [ ! -d "keys" ]; then
mkdir keys
wget -O accounts.csv $ACCOUNTS_CSV_URL
i=0
for line in `cat accounts.csv`; do
echo $line | cut -d',' -f3 | sed 's/^0x//' > keys/$i.key
i=$((i + 1))
done
fi
if [ ! -d "accounts/addresses" ]; then
mkdir -p "accounts/addresses"
fi
echo "Running tx spammer"
./tx_spammer ${SPAMMER_COMMAND} --config=config.toml --log-file=${LOG_FILE} --log-level=${LOG_LEVEL}
./tx-spammer ${SPAMMER_COMMAND} --config=config.toml --log-level=${LOG_LEVEL}
if [ $? -eq 0 ]; then
echo "tx spammer ran successfully"
else
echo "tx spammer ran with error. Is the config file correct?"
exit 1
fi
fi