Skip to content

Commit

Permalink
Add server
Browse files Browse the repository at this point in the history
  • Loading branch information
Ubuntu committed Aug 21, 2024
1 parent 313783d commit 6ea3f8b
Show file tree
Hide file tree
Showing 6 changed files with 261 additions and 138 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ require (
github.com/google/gopacket v1.1.19 // indirect
github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/gorilla/mux v1.8.1 // indirect
github.com/gorilla/websocket v1.5.1 // indirect
github.com/graph-gophers/graphql-go v1.3.0 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,8 @@ github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk
github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
Expand Down
154 changes: 16 additions & 138 deletions op-node/cmd/batch_decoder/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ import (

"github.com/ethereum-optimism/optimism/op-node/cmd/batch_decoder/fetch"
"github.com/ethereum-optimism/optimism/op-node/cmd/batch_decoder/reassemble"
"github.com/ethereum-optimism/optimism/op-node/cmd/batch_decoder/utils"
"github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum-optimism/optimism/op-node/rollup/derive"
"github.com/ethereum-optimism/optimism/op-service/client"
"github.com/ethereum-optimism/optimism/op-service/dial"
"github.com/ethereum-optimism/optimism/op-service/sources"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
Expand Down Expand Up @@ -264,98 +264,27 @@ func main() {
},
},
Action: func(cliCtx *cli.Context) error {
var (
L2GenesisTime uint64 = cliCtx.Uint64("l2-genesis-timestamp")
L2GenesisBlock uint64 = cliCtx.Uint64("l2-genesis-block")
L2BlockTime uint64 = cliCtx.Uint64("l2-block-time")
BatchInboxAddress common.Address = common.HexToAddress(cliCtx.String("inbox"))
StartBlock uint64 = cliCtx.Uint64("start")
EndBlock uint64 = cliCtx.Uint64("end")
)

// Get the L1 origin corresponding to the start block
// nextBlock is equal to the highest value in the `EndBlock` column of the db, plus 1
L2ChainID := new(big.Int).SetUint64(cliCtx.Uint64("l2-chain-id"))
rollupCfg, err := rollup.LoadOPStackRollupConfig(L2ChainID.Uint64())
if err == nil {
// prioritize superchain config
if L2GenesisTime != rollupCfg.Genesis.L2Time {
L2GenesisTime = rollupCfg.Genesis.L2Time
fmt.Printf("L2GenesisTime overridden: %v\n", L2GenesisTime)
}
if L2GenesisBlock != rollupCfg.Genesis.L2.Number {
L2GenesisBlock = rollupCfg.Genesis.L2.Number
fmt.Printf("L2GenesisBlock overridden: %v\n", L2GenesisBlock)
}
if L2BlockTime != rollupCfg.BlockTime {
L2BlockTime = rollupCfg.BlockTime
fmt.Printf("L2BlockTime overridden: %v\n", L2BlockTime)
}
if BatchInboxAddress != rollupCfg.BatchInboxAddress {
BatchInboxAddress = rollupCfg.BatchInboxAddress
fmt.Printf("BatchInboxAddress overridden: %v\n", BatchInboxAddress)
}
}
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

rollupClient, err := dial.DialRollupClientWithTimeout(ctx, dial.DefaultDialTimeout, nil, cliCtx.String("l2.node"))
if err != nil {
log.Fatal(err)
}

l1Origin, finalizedL1, err := getL1OriginAndFinalized(rollupClient, StartBlock)
if err != nil {
log.Fatal(err)
}

fetchConfig := fetch.Config{
Start: l1Origin,
End: finalizedL1,
ChainID: rollupCfg.L1ChainID,
BatchSenders: map[common.Address]struct{}{
common.HexToAddress(cliCtx.String("sender")): {},
},
BatchInbox: BatchInboxAddress,
OutDirectory: cliCtx.String("in"),
ConcurrentRequests: 10,
}

l1Client, err := ethclient.Dial(cliCtx.String("l1"))
if err != nil {
log.Fatal(err)
}
beaconAddr := cliCtx.String("l1.beacon")
var beacon *sources.L1BeaconClient
if beaconAddr != "" {
beaconClient := sources.NewBeaconHTTPClient(client.NewBasicHTTPClient(beaconAddr, nil))
beaconCfg := sources.L1BeaconClientConfig{FetchAllSidecars: false}
beacon = sources.NewL1BeaconClient(beaconClient, beaconCfg)
_, err := beacon.GetVersion(ctx)
if err != nil {
log.Fatal(fmt.Errorf("failed to check L1 Beacon API version: %w", err))
}
} else {
fmt.Println("L1 Beacon endpoint not set. Unable to fetch post-ecotone channel frames")
config := utils.BatchDecoderConfig{
L2GenesisTime: cliCtx.Uint64("l2-genesis-timestamp"),
L2GenesisBlock: cliCtx.Uint64("l2-genesis-block"),
L2BlockTime: cliCtx.Uint64("l2-block-time"),
BatchInboxAddress: common.HexToAddress(cliCtx.String("inbox")),
StartBlock: cliCtx.Uint64("start"),
EndBlock: cliCtx.Uint64("end"),
L2ChainID: new(big.Int).SetUint64(cliCtx.Uint64("l2-chain-id")),
L2Node: cliCtx.String("l2.node"),
L1RPC: cliCtx.String("l1"),
L1Beacon: cliCtx.String("l1.beacon"),
BatchSender: cliCtx.String("sender"),
// TODO: If this DataDir gets large, then we need to remove old data.
DataDir: cliCtx.String("in"),
}
totalValid, totalInvalid := fetch.Batches(l1Client, beacon, fetchConfig)
fmt.Printf("Fetched batches in range [%v,%v). Found %v valid & %v invalid batches\n", fetchConfig.Start, fetchConfig.End, totalValid, totalInvalid)

config := reassemble.Config{
BatchInbox: BatchInboxAddress,
InDirectory: cliCtx.String("in"),
OutDirectory: "",
L2ChainID: L2ChainID,
L2GenesisTime: L2GenesisTime,
L2BlockTime: L2BlockTime,
}

ranges, err := GetSpanBatchRanges(config, rollupCfg, StartBlock, EndBlock, 1000000)
ranges, err := utils.GetAllSpanBatchesInBlockRange(config)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Span batch ranges: %v\n", ranges)

return nil
},
},
Expand Down Expand Up @@ -405,54 +334,3 @@ func main() {
log.Fatal(err)
}
}

// Get a list of span batch ranges for a given L2 block range
func GetSpanBatchRanges(config reassemble.Config, rollupCfg *rollup.Config, startBlock uint64, endBlock uint64, maxSpanBatchDeviation uint64) ([]uint64, error) {
var ranges []uint64
ranges = append(ranges, startBlock)

start, end, err := reassemble.GetSpanBatchRange(config, rollupCfg, startBlock, 1000000)
currentStart := startBlock + 100
if err != nil {
fmt.Printf("Error getting span batch range: %v\n", err)
} else {
fmt.Printf("Span batch range: [%v,%v)\n", start, end)
currentStart = end
}

for currentStart < endBlock {
ranges = append(ranges, currentStart)
spanStart, spanEnd, err := reassemble.GetSpanBatchRange(config, rollupCfg, currentStart, 1000000)
if err != nil {
// If we hit an error, log it as a warning
fmt.Printf("Error getting span batch range: %v\n", err)
currentStart += 100
} else {
fmt.Printf("Span batch range: [%v,%v)\n", spanStart, spanEnd)
currentStart = spanEnd + 1
}
}
ranges = append(ranges, endBlock)
return ranges, nil
}

// Get the L1 origin corresponding to the given L2 block and the latest finalized L1 block.
func getL1OriginAndFinalized(rollupClient *sources.RollupClient, l2Block uint64) (uint64, uint64, error) {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

output, err := rollupClient.OutputAtBlock(ctx, l2Block)
if err != nil {
return 0, 0, err
}
l1Origin := output.BlockRef.L1Origin.Number

// get the latest finalized L1
status, err := rollupClient.SyncStatus(ctx)
if err != nil {
return 0, 0, err
}
finalizedL1 := status.FinalizedL1.Number

return l1Origin, finalizedL1, nil
}
1 change: 1 addition & 0 deletions op-node/cmd/batch_decoder/reassemble/reassemble.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ func Channels(config Config, rollupCfg *rollup.Config) {
}
}

// Loads the frames from the given directory and re-assembles the channel and searches for the given L2 block.
func GetSpanBatchRange(config Config, rollupCfg *rollup.Config, l2Block, maxSpanBatchDeviation uint64) (uint64, uint64, error) {
frames := LoadFrames(config.InDirectory, config.BatchInbox)
framesByChannel := make(map[derive.ChannelID][]FrameWithMetadata)
Expand Down
78 changes: 78 additions & 0 deletions op-node/cmd/batch_decoder/server/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package main

import (
"encoding/json"
"fmt"
"log"
"math/big"
"net/http"

"github.com/ethereum-optimism/optimism/op-node/cmd/batch_decoder/utils"

"github.com/gorilla/mux"
)

type SpanBatchRequest struct {
StartBlock uint64 `json:"startBlock"`
EndBlock uint64 `json:"endBlock"`
L2ChainID uint64 `json:"l2ChainID"`
L2Node string `json:"l2Node"`
L1RPC string `json:"l1RPC"`
L1Beacon string `json:"l1Beacon"`
BatchSender string `json:"batchSender"`
}

type SpanBatchRange struct {
Start uint64 `json:"start"`
End uint64 `json:"end"`
}

type SpanBatchResponse struct {
Ranges []SpanBatchRange `json:"ranges"`
}

func main() {
r := mux.NewRouter()
r.HandleFunc("/span-batch-ranges", handleSpanBatchRanges).Methods("POST")

fmt.Println("Server is running on :8080")
log.Fatal(http.ListenAndServe(":8080", r))
}

func handleSpanBatchRanges(w http.ResponseWriter, r *http.Request) {
var req SpanBatchRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}

config := utils.BatchDecoderConfig{
L2ChainID: new(big.Int).SetUint64(req.L2ChainID),
L2Node: req.L2Node,
L1RPC: req.L1RPC,
L1Beacon: req.L1Beacon,
BatchSender: req.BatchSender,
StartBlock: req.StartBlock,
EndBlock: req.EndBlock,
DataDir: "/tmp/batch_decoder/transactions_cache_new", // You might want to make this configurable
}

ranges, err := utils.GetAllSpanBatchesInBlockRange(config)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}

response := SpanBatchResponse{
Ranges: make([]SpanBatchRange, len(ranges)),
}
for i, r := range ranges {
response.Ranges[i] = SpanBatchRange{
Start: r[0],
End: r[1],
}
}

w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(response)
}
Loading

0 comments on commit 6ea3f8b

Please sign in to comment.