main.go 4.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
package main

import (
	"context"
	"fmt"
	"log"
	"os"
	"time"

	"github.com/ethereum-optimism/optimism/op-node/cmd/batch_decoder/fetch"
11
	"github.com/ethereum-optimism/optimism/op-node/cmd/batch_decoder/reassemble"
12
	"github.com/ethereum-optimism/optimism/op-node/rollup/derive"
13 14
	"github.com/ethereum/go-ethereum/common"
	"github.com/ethereum/go-ethereum/ethclient"
15
	"github.com/urfave/cli/v2"
16 17 18 19 20 21
)

func main() {
	app := cli.NewApp()
	app.Name = "batch-decoder"
	app.Usage = "Optimism Batch Decoding Utility"
22
	app.Commands = []*cli.Command{
23 24 25 26
		{
			Name:  "fetch",
			Usage: "Fetches batches in the specified range",
			Flags: []cli.Flag{
27
				&cli.IntFlag{
28 29 30 31
					Name:     "start",
					Required: true,
					Usage:    "First block (inclusive) to fetch",
				},
32
				&cli.IntFlag{
33 34 35 36
					Name:     "end",
					Required: true,
					Usage:    "Last block (exclusive) to fetch",
				},
37
				&cli.StringFlag{
38 39 40 41
					Name:     "inbox",
					Required: true,
					Usage:    "Batch Inbox Address",
				},
42
				&cli.StringFlag{
43 44 45 46
					Name:     "sender",
					Required: true,
					Usage:    "Batch Sender Address",
				},
47
				&cli.StringFlag{
48 49 50 51
					Name:  "out",
					Value: "/tmp/batch_decoder/transactions_cache",
					Usage: "Cache directory for the found transactions",
				},
52
				&cli.StringFlag{
53 54 55
					Name:     "l1",
					Required: true,
					Usage:    "L1 RPC URL",
56
					EnvVars:  []string{"L1_RPC"},
57 58 59 60 61 62 63
				},
			},
			Action: func(cliCtx *cli.Context) error {
				client, err := ethclient.Dial(cliCtx.String("l1"))
				if err != nil {
					log.Fatal(err)
				}
64
				ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
				defer cancel()
				chainID, err := client.ChainID(ctx)
				if err != nil {
					log.Fatal(err)
				}
				config := fetch.Config{
					Start:   uint64(cliCtx.Int("start")),
					End:     uint64(cliCtx.Int("end")),
					ChainID: chainID,
					BatchSenders: map[common.Address]struct{}{
						common.HexToAddress(cliCtx.String("sender")): struct{}{},
					},
					BatchInbox:   common.HexToAddress(cliCtx.String("inbox")),
					OutDirectory: cliCtx.String("out"),
				}
				totalValid, totalInvalid := fetch.Batches(client, config)
				fmt.Printf("Fetched batches in range [%v,%v). Found %v valid & %v invalid batches\n", config.Start, config.End, totalValid, totalInvalid)
				fmt.Printf("Fetch Config: Chain ID: %v. Inbox Address: %v. Valid Senders: %v.\n", config.ChainID, config.BatchInbox, config.BatchSenders)
				fmt.Printf("Wrote transactions with batches to %v\n", config.OutDirectory)
				return nil
			},
		},
87 88 89 90
		{
			Name:  "reassemble",
			Usage: "Reassembles channels from fetched batches",
			Flags: []cli.Flag{
91
				&cli.StringFlag{
92 93 94 95
					Name:  "inbox",
					Value: "0xff00000000000000000000000000000000000420",
					Usage: "Batch Inbox Address",
				},
96
				&cli.StringFlag{
97 98 99 100
					Name:  "in",
					Value: "/tmp/batch_decoder/transactions_cache",
					Usage: "Cache directory for the found transactions",
				},
101
				&cli.StringFlag{
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
					Name:  "out",
					Value: "/tmp/batch_decoder/channel_cache",
					Usage: "Cache directory for the found channels",
				},
			},
			Action: func(cliCtx *cli.Context) error {
				config := reassemble.Config{
					BatchInbox:   common.HexToAddress(cliCtx.String("inbox")),
					InDirectory:  cliCtx.String("in"),
					OutDirectory: cliCtx.String("out"),
				}
				reassemble.Channels(config)
				return nil
			},
		},
117 118 119 120
		{
			Name:  "force-close",
			Usage: "Create the tx data which will force close a channel",
			Flags: []cli.Flag{
121
				&cli.StringFlag{
122 123 124 125
					Name:     "id",
					Required: true,
					Usage:    "ID of the channel to close",
				},
126
				&cli.StringFlag{
127 128 129 130
					Name:  "inbox",
					Value: "0x0000000000000000000000000000000000000000",
					Usage: "(Optional) Batch Inbox Address",
				},
131
				&cli.StringFlag{
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
					Name:  "in",
					Value: "/tmp/batch_decoder/transactions_cache",
					Usage: "Cache directory for the found transactions",
				},
			},
			Action: func(cliCtx *cli.Context) error {
				var id derive.ChannelID
				if err := (&id).UnmarshalText([]byte(cliCtx.String("id"))); err != nil {
					log.Fatal(err)
				}
				frames := reassemble.LoadFrames(cliCtx.String("in"), common.HexToAddress(cliCtx.String("inbox")))
				var filteredFrames []derive.Frame
				for _, frame := range frames {
					if frame.Frame.ID == id {
						filteredFrames = append(filteredFrames, frame.Frame)
					}
				}
				data, err := derive.ForceCloseTxData(filteredFrames)
				if err != nil {
					log.Fatal(err)
				}
				fmt.Printf("%x\n", data)
				return nil
			},
		},
157 158 159 160 161 162
	}

	if err := app.Run(os.Args); err != nil {
		log.Fatal(err)
	}
}