55 "fmt"
66 coreda "github.com/evstack/ev-node/core/da"
77 "golang.org/x/sync/errgroup"
8- "math/big"
98 "net/http"
109 "os"
1110 "time"
@@ -14,7 +13,6 @@ import (
1413 "github.com/01builders/da-monitor/internal/evm"
1514 "github.com/01builders/da-monitor/internal/evnode"
1615 "github.com/01builders/da-monitor/internal/metrics"
17- "github.com/ethereum/go-ethereum/core/types"
1816 "github.com/prometheus/client_golang/prometheus/promhttp"
1917 "github.com/rs/zerolog"
2018 "github.com/spf13/cobra"
@@ -29,7 +27,6 @@ const (
2927 flagDataNS = "data-namespace"
3028 flagDuration = "duration"
3129 flagVerbose = "verbose"
32- flagBlockHeight = "block-height"
3330 flagPort = "port"
3431 flagChain = "chain-id"
3532 flagEnableMetrics = "enable-metrics"
@@ -48,7 +45,6 @@ type flagValues struct {
4845 dataNS string
4946 duration int
5047 verbose bool
51- blockHeight int64
5248 port int
5349 chainID string
5450 enableMetrics bool
@@ -72,8 +68,7 @@ func NewMonitorCmd() *cobra.Command {
7268 cmd .Flags ().StringVar (& flags .celestiaAuthToken , flagCelestiaAuthToken , "" , "Celestia authentication token (optional)" )
7369 cmd .Flags ().StringVar (& flags .headerNS , flagHeaderNS , "" , "Header namespace (my_app_header_namespace)" )
7470 cmd .Flags ().StringVar (& flags .dataNS , flagDataNS , "" , "Data namespace (my_app_data_namespace)" )
75- cmd .Flags ().Int64Var (& flags .blockHeight , flagBlockHeight , 0 , "Specific block height to verify" )
76- cmd .Flags ().IntVar (& flags .duration , flagDuration , 0 , "Duration in seconds to stream (0 = infinite, ignored if block-height is set)" )
71+ cmd .Flags ().IntVar (& flags .duration , flagDuration , 0 , "Duration in seconds to stream (0 = infinite)" )
7772 cmd .Flags ().BoolVar (& flags .verbose , flagVerbose , false , "Enable verbose logging" )
7873 cmd .Flags ().BoolVar (& flags .enableMetrics , flagEnableMetrics , false , "Enable Prometheus metrics HTTP server" )
7974 cmd .Flags ().IntVar (& flags .port , flagPort , 2112 , "HTTP server port for metrics (only used if --enable-metrics is set)" )
@@ -183,18 +178,6 @@ func monitorAndVerifyDataAndHeaders(cmd *cobra.Command, args []string) error {
183178 logger .Info ().Msg ("Prometheus metrics server disabled (use --enable-metrics to enable)" )
184179 }
185180
186- // If specific block height is provided, query it directly
187- if flags .blockHeight > 0 {
188- // Get header from EVM client
189- header , err := cfg .EvmClient .HeaderByNumber (ctx , big .NewInt (flags .blockHeight ))
190- if err != nil {
191- return fmt .Errorf ("failed to get header: %w" , err )
192- }
193-
194- verifyBlock (ctx , cfg .EVNodeClient , cfg .CelestiaClient , header , cfg .HeaderNS , cfg .DataNS , logger )
195- return nil
196- }
197-
198181 // Setup timeout if specified
199182 streamCtx := ctx
200183 if flags .duration > 0 {
@@ -232,68 +215,3 @@ func monitorAndVerifyDataAndHeaders(cmd *cobra.Command, args []string) error {
232215
233216 return g .Wait ()
234217}
235-
236- func verifyBlock (ctx context.Context , evnodeClient * evnode.Client , celestiaClient * celestia.Client , header * types.Header , headerNS , dataNS []byte , logger zerolog.Logger ) {
237- blockHeight := header .Number .Uint64 ()
238-
239- // check if block has transactions by comparing tx root to EmptyRootHash
240- // EmptyRootHash is the Keccak256 hash of the RLP encoding of an empty list
241- // this is a deterministic constant value that will always be the same for blocks with no transactions
242- hasTransactions := header .TxHash != types .EmptyRootHash
243-
244- logger .Info ().
245- Uint64 ("block_height" , blockHeight ).
246- Str ("hash" , header .Hash ().Hex ()).
247- Time ("time" , time .Unix (int64 (header .Time ), 0 )).
248- Uint64 ("gas_used" , header .GasUsed ).
249- Bool ("has_transactions" , hasTransactions ).
250- Msg ("processing block" )
251-
252- // Get block with blob data from ev-node
253- blockResult , err := evnodeClient .GetBlockWithBlobs (ctx , blockHeight )
254- if err != nil {
255- logger .Error ().Err (err ).Uint64 ("block_height" , blockHeight ).Msg ("failed to get block with blobs from ev-node" )
256- return
257- }
258-
259- logger .Info ().
260- Uint64 ("header_da_height" , blockResult .HeaderDaHeight ).
261- Uint64 ("data_da_height" , blockResult .DataDaHeight ).
262- Int ("header_blob_size" , len (blockResult .HeaderBlob )).
263- Int ("data_blob_size" , len (blockResult .DataBlob )).
264- Msg ("retrieved block data from ev-node" )
265-
266- // Verify header blob exists on Celestia
267- logger .Debug ().Msg ("verifying header blob with commitment..." )
268- headerExists , err := celestiaClient .VerifyBlobAtHeight (ctx , blockResult .HeaderBlob , blockResult .HeaderDaHeight , headerNS )
269- if err != nil {
270- logger .Error ().Err (err ).Uint64 ("da_height" , blockResult .HeaderDaHeight ).Msg ("failed to verify header blob" )
271- } else if ! headerExists {
272- logger .Error ().
273- Uint64 ("da_height" , blockResult .HeaderDaHeight ).
274- Msg ("ALERT: header blob NOT FOUND on Celestia - commitment does not match any blob at this height" )
275- } else {
276- logger .Info ().
277- Uint64 ("da_height" , blockResult .HeaderDaHeight ).
278- Msg ("✓ header blob VERIFIED on Celestia - commitment matches" )
279- }
280-
281- // only verify data blob if block has transactions
282- if hasTransactions {
283- logger .Info ().Msg ("verifying data blob (accounting for SignedData wrapper)..." )
284- dataExists , err := celestiaClient .VerifyDataBlobAtHeight (ctx , blockResult .DataBlob , blockResult .DataDaHeight , dataNS )
285- if err != nil {
286- logger .Error ().Err (err ).Uint64 ("da_height" , blockResult .DataDaHeight ).Msg ("failed to verify data blob" )
287- } else if ! dataExists {
288- logger .Error ().
289- Uint64 ("da_height" , blockResult .DataDaHeight ).
290- Msg ("data blob NOT FOUND on Celestia" )
291- } else {
292- logger .Info ().
293- Uint64 ("da_height" , blockResult .DataDaHeight ).
294- Msg ("data blob VERIFIED on Celestia" )
295- }
296- } else {
297- logger .Debug ().Msg ("skipped data verification for empty block" )
298- }
299- }
0 commit comments