Skip to content

Commit

Permalink
livefuzzer: improve cli (#14)
Browse files Browse the repository at this point in the history
* livefuzzer: improve cli

* happy linter, happy life

* README: updated instructions
  • Loading branch information
MariusVanDerWijden authored Dec 22, 2022
1 parent b18d186 commit 88aa362
Show file tree
Hide file tree
Showing 4 changed files with 166 additions and 52 deletions.
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,9 @@ Tx-fuzz allows for an optional seed parameter to get reproducible fuzz transacti
You can optionally specify a seed parameter or a secret key to use as a faucet

```
./livefuzzer spam <seed> [no-al] <SK>
./livefuzzer spam --seed <seed> --sk <SK>
```

You can set the RPC to use with `--rpc <RPC>`.

Some nodes (besu) don't have the `eth_createAccessList` RPC call, in this case it makes sense to disable accesslist creation with `--no-al`.
209 changes: 158 additions & 51 deletions cmd/livefuzzer/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,88 +22,142 @@ import (
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
"github.com/urfave/cli/v2"
)

var (
address = "http://127.0.0.1:8545"
txPerAccount = 1000
airdropValue = new(big.Int).Mul(big.NewInt(int64(txPerAccount*100000)), big.NewInt(params.GWei))
corpus [][]byte
)

func main() {
// eth.sendTransaction({from:personal.listAccounts[0], to:"0xb02A2EdA1b317FBd16760128836B0Ac59B560e9D", value: "100000000000000"})
if len(os.Args) < 2 {
panic("invalid amount of args, need 2")
seedFlag = &cli.Int64Flag{
Name: "seed",
Usage: "Seed for the RNG, (Default = RandomSeed)",
Value: 0,
}

var (
accesslist = true
seed *int64
)
skFlag = &cli.StringFlag{
Name: "sk",
Usage: "Secret key",
Value: "0xcdfbe6f7602f67a97602e3e9fc24cde1cdffa88acd47745c0b84c5ff55891e1b",
}

var offset int
if len(os.Args) >= 3 {
a := common.LeftPadBytes(common.FromHex(os.Args[2]), 8)
s := int64(binary.BigEndian.Uint64(a))
seed = &s
offset += 1
corpusFlag = &cli.StringFlag{
Name: "corpus",
Usage: "Use additional Corpus",
}

if len(os.Args) > 3+offset && os.Args[3+offset] == "no-al" {
accesslist = false
offset += 1
noALFlag = &cli.BoolFlag{
Name: "no-al",
Usage: "Disable accesslist creation",
Value: false,
}

if len(os.Args) > 3+offset {
txfuzz.SK = os.Args[3+offset]
sk := crypto.ToECDSAUnsafe(common.FromHex(txfuzz.SK))
txfuzz.ADDR = crypto.PubkeyToAddress(sk.PublicKey).Hex()
countFlag = &cli.IntFlag{
Name: "count",
Usage: "Count of addresses to create",
Value: 100,
}

switch os.Args[1] {
case "airdrop":
airdrop(airdropValue)
case "spam":
for {
airdrop(airdropValue)
SpamTransactions(uint64(txPerAccount), false, accesslist, seed)
time.Sleep(10 * time.Second)
}
case "corpus":
cp, err := readCorpusElements(os.Args[2])
if err != nil {
panic(err)
}
corpus = cp
SpamTransactions(uint64(txPerAccount), true, accesslist, seed)
case "unstuck":
unstuckTransactions()
case "send":
send()
case "create":
createAddresses(100)
default:
fmt.Println("unrecognized option")
rpcFlag = &cli.StringFlag{
Name: "rpc",
Usage: "RPC provider",
Value: "http://127.0.0.1:8545",
}
)

var airdropCommand = &cli.Command{
Name: "airdrop",
Usage: "Airdrops to a list of accounts",
Action: runAirdrop,
Flags: []cli.Flag{
skFlag,
rpcFlag,
},
}

var spamCommand = &cli.Command{
Name: "spam",
Usage: "Send spam transactions",
Action: runSpam,
Flags: []cli.Flag{
skFlag,
seedFlag,
noALFlag,
corpusFlag,
rpcFlag,
},
}

var unstuckCommand = &cli.Command{
Name: "unstuck",
Usage: "Tries to unstuck an account",
Action: runUnstuck,
Flags: []cli.Flag{
skFlag,
rpcFlag,
},
}
var sendCommand = &cli.Command{
Name: "send",
Usage: "Sends a single transaction",
Action: runSend,
Flags: []cli.Flag{
skFlag,
rpcFlag,
},
}
var createCommand = &cli.Command{
Name: "create",
Usage: "Create ephemeral accounts",
Action: runCreate,
Flags: []cli.Flag{
countFlag,
rpcFlag,
},
}

func initApp() *cli.App {
app := cli.NewApp()
app.Name = "tx-fuzz"
app.Usage = "Fuzzer for sending spam transactions"
app.Commands = []*cli.Command{
airdropCommand,
spamCommand,
unstuckCommand,
sendCommand,
createCommand,
}
return app
}

var app = initApp()

func main() {
// eth.sendTransaction({from:personal.listAccounts[0], to:"0xb02A2EdA1b317FBd16760128836B0Ac59B560e9D", value: "100000000000000"})
if err := app.Run(os.Args); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}

func SpamTransactions(N uint64, fromCorpus bool, accessList bool, seed *int64) {
func SpamTransactions(N uint64, fromCorpus bool, accessList bool, seed int64) {
backend, _, err := getRealBackend()
if err != nil {
log.Warn("Could not get backend", "error", err)
return
}
var src rand.Rand
if seed == nil {
if seed == 0 {
fmt.Println("No seed provided, creating one")
rnd := make([]byte, 8)
crand.Read(rnd)
s := int64(binary.BigEndian.Uint64(rnd))
seed = &s
seed = s
}
src = *rand.New(rand.NewSource(*seed))
fmt.Printf("Spamming transactions with seed: 0x%x\n", *seed)
src = *rand.New(rand.NewSource(seed))
fmt.Printf("Spamming transactions with seed: 0x%x\n", seed)
// Now let everyone spam baikal transactions
var wg sync.WaitGroup
wg.Add(len(keys))
Expand Down Expand Up @@ -206,3 +260,56 @@ func send() {
value := new(big.Int).Mul(big.NewInt(100000), big.NewInt(params.Ether))
sendTx(sk, client, to, value)
}

func runAirdrop(c *cli.Context) error {
setupDefaults(c)
airdrop(airdropValue)
return nil
}

func runSpam(c *cli.Context) error {
setupDefaults(c)
noAL := c.Bool(noALFlag.Name)
seed := c.Int64(seedFlag.Name)
// Setup corpus if needed
if corpusFile := c.String(corpusFlag.Name); corpusFile != "" {
cp, err := readCorpusElements(corpusFile)
if err != nil {
panic(err)
}
corpus = cp
}

for {
airdrop(airdropValue)
SpamTransactions(uint64(txPerAccount), false, !noAL, seed)
time.Sleep(10 * time.Second)
}
}

func runUnstuck(c *cli.Context) error {
setupDefaults(c)
unstuckTransactions()
return nil
}

func runSend(c *cli.Context) error {
setupDefaults(c)
send()
return nil
}

func runCreate(c *cli.Context) error {
setupDefaults(c)
createAddresses(100)
return nil
}

func setupDefaults(c *cli.Context) {
if sk := c.String(skFlag.Name); sk != "" {
txfuzz.SK = c.String(sk)
sk := crypto.ToECDSAUnsafe(common.FromHex(txfuzz.SK))
txfuzz.ADDR = crypto.PubkeyToAddress(sk.PublicKey).Hex()
}
address = c.String(rpcFlag.Name)
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ require (
github.com/MariusVanDerWijden/FuzzyVM v0.0.0-20221202121132-bd37e8fb1d0d
github.com/ethereum/go-ethereum v1.10.26
github.com/holiman/goevmlab v0.0.0-20221207202144-89074274e1b7
github.com/urfave/cli/v2 v2.23.7 // indirect
)
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,8 @@ github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/X
github.com/urfave/cli/v2 v2.10.2/go.mod h1:f8iq5LtQ/bLxafbdBSLPPNsgaW0l/2fYYEHhAyPlwvo=
github.com/urfave/cli/v2 v2.23.5 h1:xbrU7tAYviSpqeR3X4nEFWUdB/uDZ6DE+HxmRU7Xtyw=
github.com/urfave/cli/v2 v2.23.5/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc=
github.com/urfave/cli/v2 v2.23.7 h1:YHDQ46s3VghFHFf1DdF+Sh7H4RqhcM+t0TmZRJx4oJY=
github.com/urfave/cli/v2 v2.23.7/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
Expand Down

0 comments on commit 88aa362

Please sign in to comment.