-
Notifications
You must be signed in to change notification settings - Fork 250
Comments
Conversation
Claude finished @julienrbrt's task in 2m 40s —— View job
Code Review: feat(pkg/da): support celestia-app
Tasks
- Gather context and understand the PR
- Review new
pkg/da/app/client.go(celestia-app client) - Review refactored
pkg/da/node/client.go(celestia-node client) - Review
pkg/da/types/types.go(BlobClient interface) - Review
pkg/da/factory/factory.go(DA factory) - Review
block/internal/da/changes - Review test coverage
- Summarize findings
Overview
This PR introduces a clean architectural refactoring by extracting a BlobClient interface and adding a new celestia-app client backed by CometBFT RPC. The direction is sound and the code is generally well-structured. However, there are a few critical functional gaps and subtle regressions that should be addressed before merging.
Critical Issues
1. pkg/da/app/client.go:76 — Submit is permanently unimplemented
The Submit method always returns StatusError for any valid input:
return datypes.ResultSubmit{ BaseResult: datypes.BaseResult{ Code: datypes.StatusError, Message: "Submit not implemented: requires transaction signing...", }, }
This means celestia-app is a read-only DA client. Nodes configured as aggregators (IsAggregator: true) are always redirected to the node client by the factory, but non-aggregator nodes can also call Submit indirectly (e.g., via forced inclusion). Any node that somehow ends up using the app client for submission will fail silently at the interface level.
The PR title says "support celestia-app" but submission — the core operation of a DA layer for a sequencer — is missing. This should either be implemented (requires signer integration) or the factory should hard-fail if an aggregator tries to force ClientTypeApp. Fix this →
2. pkg/da/node/client.go:62-65 — gasPrice and options are silently dropped
var opts SubmitOptions if len(options) > 0 { // Options would be parsed here if needed }
The gasPrice parameter is also discarded. SubmitOptions has a GasPrice field and IsGasPriceSet bool that were clearly designed to carry this value. Callers setting a gas price will get unexpected behavior with no error.
High Priority Issues
3. pkg/da/node/client.go:70-75 — Lost detailed error mapping from the old client
The previous jsonrpc/client.go mapped RPC errors to specific status codes (StatusTooBig, StatusAlreadyInMempool, StatusIncorrectAccountSequence, etc.). The new implementation returns a single generic StatusError for all Blob.Submit failures. This degrades the node's ability to react to specific DA conditions (e.g., correctly backing off vs. retrying on StatusAlreadyInMempool).
4. pkg/da/factory/factory.go:106-124 — Auto-detection silently falls back to node
// Default to node client if detection fails return ClientTypeNode
If the address is a valid celestia-app endpoint that's temporarily unreachable during startup, the factory silently falls back to creating a node client, which will then fail differently. This can make misconfiguration very hard to debug. Consider logging a warning, or when ForceType == ClientTypeAuto, returning an error on detection failure rather than a misleading default. Fix this →
5. pkg/da/factory/factory.go:259-264 — Timeout not propagated to app client
func createAppClient(cfg Config) datypes.BlobClient { return daapp.NewClient(daapp.Config{ RPCAddress: cfg.Address, Logger: cfg.Logger, DefaultTimeout: 0, // Use default ← intentionally drops the user's setting }) }
The configured timeout in factory.Config is never passed to the app client. This should forward cfg's timeout if one exists, or accept a DefaultTimeout field on the factory Config.
Medium Issues
6. pkg/da/app/client.go:160,173 — Fragile string-based error detection
if strings.Contains(err.Error(), "height") && strings.Contains(err.Error(), "future") { ... } if strings.Contains(err.Error(), "is not available, lowest height is") { ... }
CometBFT error messages are not part of its stable API. These patterns could break silently on CometBFT version upgrades, causing StatusHeightFromFuture errors to be returned as generic StatusError (or vice versa). Consider matching on rpcError.Code values (CometBFT uses numeric error codes) rather than message text.
7. pkg/da/app/client.go:209-213 — Base64 fallback logic is incorrect
txBytes, err := base64.StdEncoding.DecodeString(tx) if err != nil { // Try raw bytes if not base64 txBytes = []byte(tx) }
When tx is a string containing non-base64 data, []byte(tx) simply converts the UTF-8 string to bytes — it doesn't decode any binary format. This silently masks base64 decode errors and processes garbled data. If CometBFT always returns base64-encoded transactions, the fallback should be removed and the error should be logged.
8. pkg/da/node/client.go:155-158 — Silent nil commitment in Get
height, commitment := SplitID(id) if commitment == nil { continue // silently skips }
The local SplitID (in blob.go) returns nil commitment for malformed IDs, and the loop skips them silently. This could cause Get to return fewer results than IDs requested with no indication. The datypes.SplitID counterpart returns an explicit error; consider using that or logging the skip.
Low Priority / Nitpicks
9. pkg/da/app/client.go:57-61 — NewClient returns nil for empty address
if cfg.RPCAddress == "" { return nil }
Returning nil instead of an error makes it harder for callers to distinguish "intentionally no client" from a bug. The caller at factory.go:260 doesn't check for nil, so a blank address would propagate as a nil BlobClient and panic at first use.
10. pkg/da/app/client.go:195-200 — Shadowed err variable
blockTime := time.Now() if blockResult.Block.Header.Time != "" { if t, err := time.Parse(time.RFC3339Nano, blockResult.Block.Header.Time); err == nil {
The inner err shadows the outer one. This is syntactically valid but can be confusing. Using a distinct name like parseErr would be clearer.
11. pkg/da/factory/factory.go:127-185 — Double HTTP client per detection
Both isNodeEndpoint and isAppEndpoint create their own http.Client with a 5s timeout and add a context.WithTimeout. The HTTP client-level timeout is redundant when the context already has a deadline. Minor, but consider using a shared client or just relying on the context.
12. pkg/da/node/client_test.go — Limited high-level Submit/Retrieve test coverage
The test in client_test.go verifies RPC forwarding at the BlobAPI level but doesn't test the Submit/Retrieve/GetProofs/Validate methods of the Client struct (the BlobClient implementation). Edge cases like error status code translation are not covered.
What's Well Done
- The
BlobClientinterface is clean and well-scoped — it correctly separates blob operations from namespace wiring. - Compile-time interface assertions (
var _ datypes.BlobClient = (*Client)(nil)) in both clients. - The factory auto-detection pattern is a nice UX improvement; users don't need to know which client to configure.
- The
celestia-appclient is correct to return explicit errors forGetProofs/Validaterather than silently returning empty results. - Context propagation is consistent and correct throughout.
- The tracing layer (
block/internal/da/tracing.go) is properly extended forGetLatestDAHeight. pkg/da/app/client_test.gohas solid coverage for the new code paths.- The
RetrieveForcedInclusionwrapper inblock/internal/da/client.gocleanly handles the "namespace not configured" case.
|
The latest Buf updates on your PR. Results from workflow CI / buf-check (pull_request).
|
Summary of ChangesHello @julienrbrt, I'm Gemini Code Assist1 ! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request significantly enhances the Data Availability (DA) layer by introducing a new client for direct communication with Highlights
🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console. Changelog
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request introduces support for celestia-app as a Data Availability (DA) layer alongside the existing celestia-node support. It refactors the DA client logic to use a unified BlobClient interface, allowing for different underlying implementations. While the architectural direction is sound, the current implementation contains several critical regressions in the celestia-node (formerly jsonrpc) client, specifically regarding error mapping, result metadata, and placeholder implementations for proof verification. Additionally, the celestia-app client is missing blob submission functionality, which is a significant feature gap given the PR's objective.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The GetProofs method is currently a placeholder that returns empty byte slices for all proofs. This is a regression from the previous implementation which correctly fetched proofs from the blobAPI. This will break any logic relying on DA proof verification.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Validate method is currently a placeholder that passes a nil proof to the Included check. This is a regression and will cause validation to fail or behave incorrectly. The previous implementation correctly unmarshaled the proof before validation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new implementation of Submit in the node client has lost the detailed error mapping that existed in the previous version (e.g., mapping to StatusTooBig, StatusAlreadyInMempool, etc.). It now returns a generic StatusError for all failures, which reduces the ability of the node to react appropriately to specific DA layer conditions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the number of IDs and proofs do not match, the function returns nil, nil. This violates the interface expectation and may lead to nil pointer dereferences in callers. It should return an explicit error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The gasPrice and options parameters are currently ignored in the Submit implementation. This prevents callers from specifying transaction priority or other submission-specific configurations.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Submit method for celestia-app is not implemented and always returns an error. While the comment acknowledges this, it means the 'support' for celestia-app is currently read-only, which might not meet the expectations for this feature.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Error handling in Retrieve relies on string matching for 'height' and 'future'. This is fragile as CometBFT RPC error messages may change across versions. Consider using a more robust way to detect these specific error conditions if possible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Get implementation for celestia-app is inefficient as it calls Retrieve (which fetches the entire block) for every unique height in the requested IDs. While it groups by height, it still performs a full block fetch per height, which can be very heavy for large blocks.
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@ ## main #3095 +/- ## ========================================== - Coverage 60.92% 60.45% -0.48% ========================================== Files 113 115 +2 Lines 11617 11901 +284 ========================================== + Hits 7078 7195 +117 - Misses 3741 3913 +172 + Partials 798 793 -5
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Add direct support to celestia-app alongside celestia-node.