Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ go test -race ./package/...
- Wrap errors with context using `fmt.Errorf`
- Return errors early
- Use custom error types for domain-specific errors
- Never start an error message with "failed to"

### Logging

Expand Down
2 changes: 1 addition & 1 deletion apps/evm/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ require (
github.com/ipld/go-ipld-prime v0.21.0 // indirect
github.com/jackpal/go-nat-pmp v1.0.2 // indirect
github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect
github.com/klauspost/compress v1.18.0 // indirect
github.com/klauspost/compress v1.18.4 // indirect
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
github.com/koron/go-ssdp v0.0.6 // indirect
github.com/libp2p/go-buffer-pool v0.1.0 // indirect
Expand Down
4 changes: 2 additions & 2 deletions apps/evm/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -714,8 +714,8 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/asmfmt v1.3.2/go.mod h1:AG8TuvYojzulgDAMCnYn50l/5QV3Bs/tp6j0HLHbNSE=
github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
github.com/klauspost/compress v1.18.4 h1:RPhnKRAQ4Fh8zU2FY/6ZFDwTVTxgJ/EMydqSTzE9a2c=
github.com/klauspost/compress v1.18.4/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.3/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
Expand Down
2 changes: 1 addition & 1 deletion apps/grpc/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ require (
github.com/ipld/go-ipld-prime v0.21.0 // indirect
github.com/jackpal/go-nat-pmp v1.0.2 // indirect
github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect
github.com/klauspost/compress v1.18.0 // indirect
github.com/klauspost/compress v1.18.4 // indirect
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
github.com/koron/go-ssdp v0.0.6 // indirect
github.com/libp2p/go-buffer-pool v0.1.0 // indirect
Expand Down
4 changes: 2 additions & 2 deletions apps/grpc/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -646,8 +646,8 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/asmfmt v1.3.2/go.mod h1:AG8TuvYojzulgDAMCnYn50l/5QV3Bs/tp6j0HLHbNSE=
github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
github.com/klauspost/compress v1.18.4 h1:RPhnKRAQ4Fh8zU2FY/6ZFDwTVTxgJ/EMydqSTzE9a2c=
github.com/klauspost/compress v1.18.4/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.3/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
Expand Down
2 changes: 1 addition & 1 deletion apps/testapp/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ require (
github.com/ipld/go-ipld-prime v0.21.0 // indirect
github.com/jackpal/go-nat-pmp v1.0.2 // indirect
github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect
github.com/klauspost/compress v1.18.0 // indirect
github.com/klauspost/compress v1.18.4 // indirect
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
github.com/koron/go-ssdp v0.0.6 // indirect
github.com/libp2p/go-buffer-pool v0.1.0 // indirect
Expand Down
4 changes: 2 additions & 2 deletions apps/testapp/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -646,8 +646,8 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/asmfmt v1.3.2/go.mod h1:AG8TuvYojzulgDAMCnYn50l/5QV3Bs/tp6j0HLHbNSE=
github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
github.com/klauspost/compress v1.18.4 h1:RPhnKRAQ4Fh8zU2FY/6ZFDwTVTxgJ/EMydqSTzE9a2c=
github.com/klauspost/compress v1.18.4/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.3/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
Expand Down
64 changes: 56 additions & 8 deletions block/internal/da/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/rs/zerolog"

"github.com/evstack/ev-node/block/internal/common"
"github.com/evstack/ev-node/pkg/da"
blobrpc "github.com/evstack/ev-node/pkg/da/jsonrpc"
datypes "github.com/evstack/ev-node/pkg/da/types"
)
Expand Down Expand Up @@ -87,17 +88,44 @@ func (c *client) Submit(ctx context.Context, data [][]byte, _ float64, namespace
}
}

// Select compression level based on backlog pressure:
// large batch = high backlog = prioritize speed;
// small batch = low backlog = prioritize ratio.
compLevel := da.LevelBest
switch {
case len(data) > 10:
compLevel = da.LevelFastest
case len(data) > 3:
compLevel = da.LevelDefault
}

blobs := make([]*blobrpc.Blob, len(data))
for i, raw := range data {
if uint64(len(raw)) > common.DefaultMaxBlobSize {
compressed, compErr := da.Compress(raw, compLevel)
if compErr != nil {
return datypes.ResultSubmit{
BaseResult: datypes.BaseResult{
Code: datypes.StatusError,
Message: fmt.Sprintf("compress blob %d: %v", i, compErr),
},
}
}
c.logger.Debug().
Int("original_size", len(raw)).
Int("compressed_size", len(compressed)).
Float64("ratio", float64(len(compressed))/float64(max(len(raw), 1))).
Int("level", int(compLevel)).
Msg("compressed blob for DA submission")

if uint64(len(compressed)) > common.DefaultMaxBlobSize {
return datypes.ResultSubmit{
BaseResult: datypes.BaseResult{
Code: datypes.StatusTooBig,
Message: datypes.ErrBlobSizeOverLimit.Error(),
},
}
}
blobs[i], err = blobrpc.NewBlobV0(ns, raw)
blobs[i], err = blobrpc.NewBlobV0(ns, compressed)
if err != nil {
return datypes.ResultSubmit{
BaseResult: datypes.BaseResult{
Expand Down Expand Up @@ -278,12 +306,23 @@ func (c *client) Retrieve(ctx context.Context, height uint64, namespace []byte)
}
}

// Extract IDs and data from the blobs.
ids := make([]datypes.ID, len(blobs))
data := make([]datypes.Blob, len(blobs))
// Extract IDs and data from the blobs, decompressing if needed.
// Malicious or corrupt blobs that fail decompression are logged and skipped.
ids := make([]datypes.ID, 0, len(blobs))
data := make([]datypes.Blob, 0, len(blobs))
for i, b := range blobs {
ids[i] = blobrpc.MakeID(height, b.Commitment)
data[i] = b.Data()
decompressed, decompErr := da.Decompress(ctx, b.Data())
if decompErr != nil {
c.logger.Warn().
Err(decompErr).
Uint64("height", height).
Int("blob_index", i).
Int("blob_size", len(b.Data())).
Msg("skipping malicious or corrupt DA blob")
continue
}
Comment on lines +314 to +323
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Do not return success when decompression dropped all requested data.

Retrieve/Get currently swallow decompression errors and can return a “successful” empty/partial payload with no explicit failure signal. That can mask corruption and break caller assumptions on completeness.

💡 Proposed fix
  ids := make([]datypes.ID, 0, len(blobs))
  data := make([]datypes.Blob, 0, len(blobs))
+ failedDecompress := 0

  for i, b := range blobs {
    decompressed, decompErr := da.Decompress(ctx, b.Data())
    if decompErr != nil {
+     failedDecompress++
      c.logger.Warn().
        Err(decompErr).
        Uint64("height", height).
        Int("blob_index", i).
        Int("blob_size", len(b.Data())).
        Msg("skipping malicious or corrupt DA blob")
      continue
    }
    ids = append(ids, blobrpc.MakeID(height, b.Commitment))
    data = append(data, decompressed)
  }

+ if len(data) == 0 && len(blobs) > 0 {
+   return datypes.ResultRetrieve{
+     BaseResult: datypes.BaseResult{
+       Code:      datypes.StatusError,
+       Message:   fmt.Sprintf("all blobs failed decompression (%d/%d)", failedDecompress, len(blobs)),
+       Height:    height,
+       Timestamp: blockTime,
+     },
+   }
+ }

Apply the same principle in Get: if any requested ID fails decompression, return an error (or explicitly surface partial-result semantics).

As per coding guidelines, "Return errors early".

Also applies to: 330-338, 403-413

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@block/internal/da/client.go` around lines 314 - 323, In Retrieve/Get in
client.go, don't swallow decompression failures: when da.Decompress(ctx,
b.Data()) returns an error (the branch that currently logs via c.logger.Warn()
and continues), return an error immediately (or propagate a wrapped error)
instead of skipping that blob and returning a successful but incomplete payload;
update the code paths around da.Decompress, c.logger.Warn(), and the calling
functions Retrieve/Get to propagate the decompression error (or explicit
partial-result sentinel) so callers can detect corrupted/missing data.

ids = append(ids, blobrpc.MakeID(height, b.Commitment))
data = append(data, decompressed)
}

c.logger.Debug().Int("num_blobs", len(blobs)).Msg("retrieved blobs")
Expand Down Expand Up @@ -361,7 +400,16 @@ func (c *client) Get(ctx context.Context, ids []datypes.ID, namespace []byte) ([
if b == nil {
continue
}
res = append(res, b.Data())
decompressed, decompErr := da.Decompress(ctx, b.Data())
if decompErr != nil {
c.logger.Warn().
Err(decompErr).
Uint64("height", height).
Int("blob_size", len(b.Data())).
Msg("skipping malicious or corrupt DA blob")
continue
}
res = append(res, decompressed)
}

return res, nil
Expand Down
4 changes: 2 additions & 2 deletions execution/evm/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -186,8 +186,8 @@ github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7Bd
github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
github.com/jbenet/go-temp-err-catcher v0.1.0 h1:zpb3ZH6wIE8Shj2sKS+khgRvf7T7RABoLk/+KKHggpk=
github.com/jbenet/go-temp-err-catcher v0.1.0/go.mod h1:0kJRvmDZXNMIiJirNPEYfhpPwbGVtZVWC34vc5WLsDk=
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
github.com/klauspost/compress v1.18.4 h1:RPhnKRAQ4Fh8zU2FY/6ZFDwTVTxgJ/EMydqSTzE9a2c=
github.com/klauspost/compress v1.18.4/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
github.com/koron/go-ssdp v0.0.6 h1:Jb0h04599eq/CY7rB5YEqPS83HmRfHP2azkxMN2rFtU=
Expand Down
2 changes: 1 addition & 1 deletion execution/evm/test/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ require (
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/ipfs/go-cid v0.6.0 // indirect
github.com/jmhodges/levigo v1.0.0 // indirect
github.com/klauspost/compress v1.18.0 // indirect
github.com/klauspost/compress v1.18.4 // indirect
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/kr/text v0.2.0 // indirect
Expand Down
4 changes: 2 additions & 2 deletions execution/evm/test/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -404,8 +404,8 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
github.com/klauspost/compress v1.18.4 h1:RPhnKRAQ4Fh8zU2FY/6ZFDwTVTxgJ/EMydqSTzE9a2c=
github.com/klauspost/compress v1.18.4/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ require (
github.com/hashicorp/raft-boltdb v0.0.0-20251103221153-05f9dd7a5148
github.com/ipfs/go-datastore v0.9.1
github.com/ipfs/go-ds-badger4 v0.1.8
github.com/klauspost/compress v1.18.4
github.com/libp2p/go-libp2p v0.47.0
github.com/libp2p/go-libp2p-kad-dht v0.38.0
github.com/libp2p/go-libp2p-pubsub v0.15.0
Expand Down Expand Up @@ -89,7 +90,6 @@ require (
github.com/ipld/go-ipld-prime v0.21.0 // indirect
github.com/jackpal/go-nat-pmp v1.0.2 // indirect
github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect
github.com/klauspost/compress v1.18.0 // indirect
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
github.com/koron/go-ssdp v0.0.6 // indirect
github.com/libp2p/go-buffer-pool v0.1.0 // indirect
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -646,8 +646,8 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/asmfmt v1.3.2/go.mod h1:AG8TuvYojzulgDAMCnYn50l/5QV3Bs/tp6j0HLHbNSE=
github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
github.com/klauspost/compress v1.18.4 h1:RPhnKRAQ4Fh8zU2FY/6ZFDwTVTxgJ/EMydqSTzE9a2c=
github.com/klauspost/compress v1.18.4/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.3/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
Expand Down
20 changes: 5 additions & 15 deletions node/execution_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,22 +90,12 @@ func waitForNodeInitialization(node *FullNode) error {
func getExecutorFromNode(t *testing.T, node *FullNode) coreexecutor.Executor {
le := node.leaderElection
sle, ok := le.(*singleRoleElector)
if !ok {
t.Fatal("Leader election is not singleRoleElector")
}
require.True(t, ok, "Leader election is not singleRoleElector")
state := sle.state()
if state == nil {
t.Fatal("failoverState is nil")
}
bc := state.bc
if bc == nil {
t.Fatal("blockComponents is nil")
}
if bc.Executor != nil {
return bc.Executor.GetCoreExecutor()
}
t.Fatal("Executor not found in block components")
return nil
require.NotNil(t, state)
require.NotNil(t, state.bc)
require.NotNil(t, state.bc.Executor)
return state.bc.Executor.GetCoreExecutor()
}

func getTransactions(t *testing.T, executor coreexecutor.Executor, ctx context.Context) [][]byte {
Expand Down
Loading
Loading