github.com/ethereum-optimism/optimism@v1.7.2/op-node/cmd/batch_decoder/main.go (about)

     1  package main
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"log"
     7  	"math/big"
     8  	"os"
     9  	"time"
    10  
    11  	"github.com/ethereum-optimism/optimism/op-node/cmd/batch_decoder/fetch"
    12  	"github.com/ethereum-optimism/optimism/op-node/cmd/batch_decoder/reassemble"
    13  	"github.com/ethereum-optimism/optimism/op-node/rollup"
    14  	"github.com/ethereum-optimism/optimism/op-node/rollup/derive"
    15  	"github.com/ethereum/go-ethereum/common"
    16  	"github.com/ethereum/go-ethereum/ethclient"
    17  	"github.com/urfave/cli/v2"
    18  )
    19  
    20  func main() {
    21  	app := cli.NewApp()
    22  	app.Name = "batch-decoder"
    23  	app.Usage = "Optimism Batch Decoding Utility"
    24  	app.Commands = []*cli.Command{
    25  		{
    26  			Name:  "fetch",
    27  			Usage: "Fetches batches in the specified range",
    28  			Flags: []cli.Flag{
    29  				&cli.IntFlag{
    30  					Name:     "start",
    31  					Required: true,
    32  					Usage:    "First block (inclusive) to fetch",
    33  				},
    34  				&cli.IntFlag{
    35  					Name:     "end",
    36  					Required: true,
    37  					Usage:    "Last block (exclusive) to fetch",
    38  				},
    39  				&cli.StringFlag{
    40  					Name:     "inbox",
    41  					Required: true,
    42  					Usage:    "Batch Inbox Address",
    43  				},
    44  				&cli.StringFlag{
    45  					Name:     "sender",
    46  					Required: true,
    47  					Usage:    "Batch Sender Address",
    48  				},
    49  				&cli.StringFlag{
    50  					Name:  "out",
    51  					Value: "/tmp/batch_decoder/transactions_cache",
    52  					Usage: "Cache directory for the found transactions",
    53  				},
    54  				&cli.StringFlag{
    55  					Name:     "l1",
    56  					Required: true,
    57  					Usage:    "L1 RPC URL",
    58  					EnvVars:  []string{"L1_RPC"},
    59  				},
    60  				&cli.IntFlag{
    61  					Name:  "concurrent-requests",
    62  					Value: 10,
    63  					Usage: "Concurrency level when fetching L1",
    64  				},
    65  			},
    66  			Action: func(cliCtx *cli.Context) error {
    67  				client, err := ethclient.Dial(cliCtx.String("l1"))
    68  				if err != nil {
    69  					log.Fatal(err)
    70  				}
    71  				ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
    72  				defer cancel()
    73  				chainID, err := client.ChainID(ctx)
    74  				if err != nil {
    75  					log.Fatal(err)
    76  				}
    77  				config := fetch.Config{
    78  					Start:   uint64(cliCtx.Int("start")),
    79  					End:     uint64(cliCtx.Int("end")),
    80  					ChainID: chainID,
    81  					BatchSenders: map[common.Address]struct{}{
    82  						common.HexToAddress(cliCtx.String("sender")): {},
    83  					},
    84  					BatchInbox:         common.HexToAddress(cliCtx.String("inbox")),
    85  					OutDirectory:       cliCtx.String("out"),
    86  					ConcurrentRequests: uint64(cliCtx.Int("concurrent-requests")),
    87  				}
    88  				totalValid, totalInvalid := fetch.Batches(client, config)
    89  				fmt.Printf("Fetched batches in range [%v,%v). Found %v valid & %v invalid batches\n", config.Start, config.End, totalValid, totalInvalid)
    90  				fmt.Printf("Fetch Config: Chain ID: %v. Inbox Address: %v. Valid Senders: %v.\n", config.ChainID, config.BatchInbox, config.BatchSenders)
    91  				fmt.Printf("Wrote transactions with batches to %v\n", config.OutDirectory)
    92  				return nil
    93  			},
    94  		},
    95  		{
    96  			Name:  "reassemble",
    97  			Usage: "Reassembles channels from fetched batch transactions and decode batches",
    98  			Flags: []cli.Flag{
    99  				&cli.StringFlag{
   100  					Name:  "in",
   101  					Value: "/tmp/batch_decoder/transactions_cache",
   102  					Usage: "Cache directory for the found transactions",
   103  				},
   104  				&cli.StringFlag{
   105  					Name:  "out",
   106  					Value: "/tmp/batch_decoder/channel_cache",
   107  					Usage: "Cache directory for the found channels",
   108  				},
   109  				&cli.Uint64Flag{
   110  					Name:  "l2-chain-id",
   111  					Value: 10,
   112  					Usage: "L2 chain id for span batch derivation. Default value from op-mainnet.",
   113  				},
   114  				&cli.Uint64Flag{
   115  					Name:  "l2-genesis-timestamp",
   116  					Value: 1686068903,
   117  					Usage: "L2 genesis time for span batch derivation. Default value from op-mainnet. " +
   118  						"Superchain-registry prioritized when given value is inconsistent.",
   119  				},
   120  				&cli.Uint64Flag{
   121  					Name:  "l2-block-time",
   122  					Value: 2,
   123  					Usage: "L2 block time for span batch derivation. Default value from op-mainnet. " +
   124  						"Superchain-registry prioritized when given value is inconsistent.",
   125  				},
   126  				&cli.StringFlag{
   127  					Name:  "inbox",
   128  					Value: "0xFF00000000000000000000000000000000000010",
   129  					Usage: "Batch Inbox Address. Default value from op-mainnet. " +
   130  						"Superchain-registry prioritized when given value is inconsistent.",
   131  				},
   132  			},
   133  			Action: func(cliCtx *cli.Context) error {
   134  				var (
   135  					L2GenesisTime     uint64         = cliCtx.Uint64("l2-genesis-timestamp")
   136  					L2BlockTime       uint64         = cliCtx.Uint64("l2-block-time")
   137  					BatchInboxAddress common.Address = common.HexToAddress(cliCtx.String("inbox"))
   138  				)
   139  				L2ChainID := new(big.Int).SetUint64(cliCtx.Uint64("l2-chain-id"))
   140  				rollupCfg, err := rollup.LoadOPStackRollupConfig(L2ChainID.Uint64())
   141  				if err == nil {
   142  					// prioritize superchain config
   143  					if L2GenesisTime != rollupCfg.Genesis.L2Time {
   144  						L2GenesisTime = rollupCfg.Genesis.L2Time
   145  						fmt.Printf("L2GenesisTime overridden: %v\n", L2GenesisTime)
   146  					}
   147  					if L2BlockTime != rollupCfg.BlockTime {
   148  						L2BlockTime = rollupCfg.BlockTime
   149  						fmt.Printf("L2BlockTime overridden: %v\n", L2BlockTime)
   150  					}
   151  					if BatchInboxAddress != rollupCfg.BatchInboxAddress {
   152  						BatchInboxAddress = rollupCfg.BatchInboxAddress
   153  						fmt.Printf("BatchInboxAddress overridden: %v\n", BatchInboxAddress)
   154  					}
   155  				}
   156  				config := reassemble.Config{
   157  					BatchInbox:    BatchInboxAddress,
   158  					InDirectory:   cliCtx.String("in"),
   159  					OutDirectory:  cliCtx.String("out"),
   160  					L2ChainID:     L2ChainID,
   161  					L2GenesisTime: L2GenesisTime,
   162  					L2BlockTime:   L2BlockTime,
   163  				}
   164  				reassemble.Channels(config)
   165  				return nil
   166  			},
   167  		},
   168  		{
   169  			Name:  "force-close",
   170  			Usage: "Create the tx data which will force close a channel",
   171  			Flags: []cli.Flag{
   172  				&cli.StringFlag{
   173  					Name:     "id",
   174  					Required: true,
   175  					Usage:    "ID of the channel to close",
   176  				},
   177  				&cli.StringFlag{
   178  					Name:  "inbox",
   179  					Value: "0x0000000000000000000000000000000000000000",
   180  					Usage: "(Optional) Batch Inbox Address",
   181  				},
   182  				&cli.StringFlag{
   183  					Name:  "in",
   184  					Value: "/tmp/batch_decoder/transactions_cache",
   185  					Usage: "Cache directory for the found transactions",
   186  				},
   187  			},
   188  			Action: func(cliCtx *cli.Context) error {
   189  				var id derive.ChannelID
   190  				if err := (&id).UnmarshalText([]byte(cliCtx.String("id"))); err != nil {
   191  					log.Fatal(err)
   192  				}
   193  				frames := reassemble.LoadFrames(cliCtx.String("in"), common.HexToAddress(cliCtx.String("inbox")))
   194  				var filteredFrames []derive.Frame
   195  				for _, frame := range frames {
   196  					if frame.Frame.ID == id {
   197  						filteredFrames = append(filteredFrames, frame.Frame)
   198  					}
   199  				}
   200  				data, err := derive.ForceCloseTxData(filteredFrames)
   201  				if err != nil {
   202  					log.Fatal(err)
   203  				}
   204  				fmt.Printf("%x\n", data)
   205  				return nil
   206  			},
   207  		},
   208  	}
   209  
   210  	if err := app.Run(os.Args); err != nil {
   211  		log.Fatal(err)
   212  	}
   213  }