UtxoRpc server upgraded to 0.18.1 spec#813
Conversation
📝 WalkthroughWalkthroughUpdates gRPC handlers to process a single transaction per request, add timestamp population to BlockRef constructions across sync/watch flows and a BlockRef fallback for Apply events with no transactions, add Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant Server
participant Mapper
participant Domain
rect rgba(240,248,255,0.5)
Client->>Server: SubmitTx(tx: Raw)
Server->>Server: validate tx present & type
Server->>Mapper: map tx -> internal Tx
Server->>Domain: submit/persist tx
Server-->>Client: SubmitTxResponse(hash)
end
rect rgba(250,240,245,0.5)
Client->>Server: EvalTx(tx: Raw)
Server->>Mapper: map tx -> TxEval input
Server->>Domain: evaluate tx
Server-->>Client: EvalTxResponse(report: AnyChainEval)
end
sequenceDiagram
participant ChainSource
participant Mapper
participant Server
participant Client
rect rgba(240,255,240,0.5)
ChainSource->>Mapper: provide CBOR block (map_block_cbor)
Mapper->>Mapper: extract header, timestamp, txs
alt mapped block has txs
Mapper->>Server: Apply with serialized block & txs
Server-->>Client: FollowTipResponse { Apply + tip(with timestamp) }
else no txs
Mapper->>Server: Apply with serialized block (no txs)
Server-->>Client: FollowTipResponse { Idle + block_ref(with timestamp) }
end
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧹 Recent nitpick comments
📜 Recent review detailsConfiguration used: defaults Review profile: CHILL Plan: Pro ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (2)
🧰 Additional context used🧬 Code graph analysis (1)src/adapters.rs (1)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
🔇 Additional comments (1)
✏️ Tip: You can disable this entire section by setting Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 7
Fix all issues with AI Agents 🤖
In @src/serve/grpc/submit.rs:
- Around line 199-219: eval_tx currently treats request.into_inner().tx as a
single optional tx but the proto uses a Vec of txs and EvalTxResponse.report
expects a repeated list; update eval_tx to iterate over request.into_inner().tx
(the Vec), for each entry extract tx_raw like you do now, call
validate_tx(&self.domain, &chain, &tx_raw) and tx_eval_to_u5c, wrap each result
in an AnyChainEval with Chain::Cardano(result), collect those into a
Vec<AnyChainEval> and assign that collection to the response field (the repeated
report field on EvalTxResponse) instead of building a single
Option<AnyChainEval>.
- Line 92: The TxEval struct's fee field is being set to None but the current
pallas TxEval definition expects a concrete numeric type (not Option), causing a
type mismatch; update the assignment in the code that constructs TxEval (look
for the TxEval instantiation around submit.rs) to provide the correct numeric
value or zero (e.g., 0u64 or the exact integer type used by TxEval) instead of
None, or change the surrounding conversion to map an Option to the concrete type
(e.g., .unwrap_or(0) or a proper compute_fee() result) so the fee field matches
the TxEval fee type.
In @src/serve/grpc/sync.rs:
- Around line 54-61: The struct construction in point_to_blockref is setting a
non-existent timestamp field on u5c::sync::BlockRef; remove the timestamp:
timestamp, assignment from the BlockRef literal in point_to_blockref (or, if the
newer BlockRef in the dependency should include timestamp, update the dependency
and adjust imports accordingly) so the BlockRef is built only with existing
fields (e.g., hash and slot) and any timestamp handling is done separately.
- Around line 43-51: The BlockRef initialization is using fields not in the
UTxO-RPC spec; change the u5c::sync::BlockRef construction in the
mapper.map_block_cbor handling to only set index and hash (remove timestamp,
slot, and height assignments). Populate index from header.height and hash from
header.hash so the struct matches the spec exactly.
In @src/serve/grpc/watch.rs:
- Around line 193-210: The TipEvent::Apply arm uses
u5c::watch::watch_tx_response::Action::Idle which doesn't exist; remove that
variant and, when txs.is_empty(), return an empty vector instead of attempting
to emit Idle (i.e., replace the raw_to_blockref/Idle branch with vec![]), or
alternatively if you need to signal the block choose an existing variant (e.g.,
wrap the block ref into Action::Apply using the same WatchTxResponse shape) but
do not reference Action::Idle; update the TipEvent::Apply logic and calls to
raw_to_blockref accordingly.
🧹 Nitpick comments (3)
src/serve/grpc/watch.rs (2)
173-185: Inconsistency: Missingtimestampfield compared tosync.rsversion.The
raw_to_blockrefhelper insync.rs(lines 38-51) includes atimestampfield in itsBlockRefconstruction, but this version omits it. Ifu5c::watch::BlockRefsupports timestamp (as the sync version does), consider adding it for consistency.Some(u5c::watch::BlockRef { slot: header.slot, hash: header.hash, height: header.height, // timestamp: block.timestamp, // Add if supported by the spec })
211-218: Consider handlingTipEvent::Undowith empty transactions consistently.The
Applybranch now handles the case whenblock_to_txsreturns empty by emitting anIdleresponse (assuming the build issue is resolved). However, theUndobranch does not have similar handling—if an undo block has no matching transactions, it will emit an empty stream.Consider whether this asymmetry is intentional or if
Undoshould also emit an idle/status response when no transactions match the predicate.src/serve/grpc/sync.rs (1)
233-235: Timestamp lookup with silent fallback to 0.The
get_slot_timestampcall usesunwrap_or(0)as a fallback. While this prevents panics, returning timestamp0(Unix epoch) for missing slots could be misleading to clients. Consider:
- Logging when the fallback is used, or
- Returning an error if timestamp lookup fails for a known slot
This becomes moot if
timestampisn't a valid field yet, but worth noting for when it is.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
src/serve/grpc/query.rssrc/serve/grpc/submit.rssrc/serve/grpc/sync.rssrc/serve/grpc/watch.rs
🧰 Additional context used
🧬 Code graph analysis (3)
src/serve/grpc/watch.rs (1)
src/serve/grpc/sync.rs (1)
raw_to_blockref(39-52)
src/serve/grpc/submit.rs (2)
crates/core/src/facade.rs (7)
receive_tx(150-162)chain(22-22)chain(60-60)chain(64-64)chain(67-67)chain(70-70)validate_tx(136-148)crates/cardano/src/validate.rs (1)
validate_tx(12-92)
src/serve/grpc/sync.rs (3)
crates/core/src/lib.rs (1)
point(386-390)crates/core/src/batch.rs (1)
point(70-75)src/serve/grpc/watch.rs (1)
raw_to_blockref(173-185)
🪛 GitHub Actions: CI
src/serve/grpc/watch.rs
[error] 199-199: no variant or associated item named Idle found for enum pallas::interop::pallas_utxorpc::spec::watch::watch_tx_response::Action in the current scope
🪛 GitHub Check: Check Build
src/serve/grpc/query.rs
[failure] 219-219:
struct AnyUtxoData has no field named block_ref
src/serve/grpc/watch.rs
[failure] 199-199:
no variant or associated item named Idle found for enum pallas::interop::pallas_utxorpc::spec::watch::watch_tx_response::Action in the current scope
src/serve/grpc/submit.rs
[failure] 92-92:
mismatched types
[failure] 138-138:
the trait bound Vec<bytes::Bytes>: From<Vec<u8>> is not satisfied
[failure] 128-128:
no method named ok_or_else found for struct Vec<pallas::interop::pallas_utxorpc::spec::submit::AnyChainTx> in the current scope
[failure] 219-219:
mismatched types
[failure] 202-202:
no method named ok_or_else found for struct Vec<pallas::interop::pallas_utxorpc::spec::submit::AnyChainTx> in the current scope
src/serve/grpc/sync.rs
[failure] 58-58:
struct pallas::interop::pallas_utxorpc::spec::sync::BlockRef has no field named timestamp
[failure] 50-50:
struct pallas::interop::pallas_utxorpc::spec::sync::BlockRef has no field named timestamp
[failure] 74-74:
struct FollowTipResponse has no field named tip
🔇 Additional comments (1)
src/serve/grpc/query.rs (1)
212-220: No action needed. Theblock_reffield is already present and functional inu5c::query::AnyUtxoDataas used in pallas 1.0.0-alpha.3. The code at line 219 correctly setsblock_ref: None, and the field is also successfully used elsewhere in the codebase (line 399 withblock_ref: Some(...)). This review comment was based on incorrect static analysis.Likely an incorrect or invalid review comment.
| }) | ||
| .collect(), | ||
| fee: 0, // TODO | ||
| fee: None, // TODO |
There was a problem hiding this comment.
Build failure: Type mismatch for fee field.
Static analysis indicates a type mismatch on the fee field. The field likely expects a concrete numeric type rather than Option<_>. Verify the expected type in the current pallas spec version.
#!/bin/bash
# Search for TxEval struct definition to see expected fee type
ast-grep --pattern 'struct TxEval {
$$$
}'
rg -n "fee:" --type rust -C 3 | grep -i "txeval" -A 5 -B 5 | head -40🧰 Tools
🪛 GitHub Check: Check Build
[failure] 92-92:
mismatched types
🤖 Prompt for AI Agents
In @src/serve/grpc/submit.rs around line 92, The TxEval struct's fee field is
being set to None but the current pallas TxEval definition expects a concrete
numeric type (not Option), causing a type mismatch; update the assignment in the
code that constructs TxEval (look for the TxEval instantiation around submit.rs)
to provide the correct numeric value or zero (e.g., 0u64 or the exact integer
type used by TxEval) instead of None, or change the surrounding conversion to
map an Option to the concrete type (e.g., .unwrap_or(0) or a proper
compute_fee() result) so the fee field matches the TxEval fee type.
| let tx = message | ||
| .tx | ||
| .ok_or_else(|| Status::invalid_argument("missing tx"))?; | ||
| let tx_bytes = match tx.r#type { | ||
| Some(any_chain_tx::Type::Raw(bytes)) => bytes, | ||
| _ => return Err(Status::invalid_argument("missing or unsupported tx type")), | ||
| }; | ||
|
|
||
| Ok(Response::new(SubmitTxResponse { r#ref: hashes })) | ||
| let hash = receive_tx(&self.domain, &chain, tx_bytes.as_ref()) | ||
| .map_err(|e| Status::invalid_argument(format!("could not process tx: {e}")))?; | ||
|
|
||
| Ok(Response::new(SubmitTxResponse { | ||
| r#ref: hash.to_vec().into(), | ||
| })) |
There was a problem hiding this comment.
Build failure: API mismatch—message.tx is a Vec, not Option.
Static analysis shows that ok_or_else is not found for Vec<AnyChainTx>. This indicates that SubmitTxRequest.tx is still a Vec (multi-transaction) in the current pallas version, not a single optional field.
The code assumes a spec change to single-transaction requests that hasn't been reflected in the dependency yet. Either:
- Update the pallas dependency to one that matches the 0.18.1 spec with single-tx requests, or
- Revert to handling
message.txas aVecuntil the dependency is updated.
🔎 If reverting to Vec-based handling is needed
- let tx = message
- .tx
- .ok_or_else(|| Status::invalid_argument("missing tx"))?;
- let tx_bytes = match tx.r#type {
- Some(any_chain_tx::Type::Raw(bytes)) => bytes,
- _ => return Err(Status::invalid_argument("missing or unsupported tx type")),
- };
-
- let hash = receive_tx(&self.domain, &chain, tx_bytes.as_ref())
- .map_err(|e| Status::invalid_argument(format!("could not process tx: {e}")))?;
-
- Ok(Response::new(SubmitTxResponse {
- r#ref: hash.to_vec().into(),
- }))
+ let tx = message.tx.first()
+ .ok_or_else(|| Status::invalid_argument("missing tx"))?;
+ let tx_bytes = match &tx.r#type {
+ Some(any_chain_tx::Type::Raw(bytes)) => bytes.clone(),
+ _ => return Err(Status::invalid_argument("missing or unsupported tx type")),
+ };
+
+ let hash = receive_tx(&self.domain, &chain, tx_bytes.as_ref())
+ .map_err(|e| Status::invalid_argument(format!("could not process tx: {e}")))?;
+
+ Ok(Response::new(SubmitTxResponse {
+ r#ref: vec![hash.to_vec().into()],
+ }))Committable suggestion skipped: line range outside the PR's diff.
🧰 Tools
🪛 GitHub Check: Check Build
[failure] 138-138:
the trait bound Vec<bytes::Bytes>: From<Vec<u8>> is not satisfied
[failure] 128-128:
no method named ok_or_else found for struct Vec<pallas::interop::pallas_utxorpc::spec::submit::AnyChainTx> in the current scope
| let tx = request | ||
| .into_inner() | ||
| .tx | ||
| .into_iter() | ||
| .map(|tx| { | ||
| tx.r#type | ||
| .map(|tx_type| match tx_type { | ||
| any_chain_tx::Type::Raw(bytes) => bytes.to_vec(), | ||
| }) | ||
| .unwrap_or_default() | ||
| }) | ||
| .collect(); | ||
| .ok_or_else(|| Status::invalid_argument("missing tx"))?; | ||
|
|
||
| let tx_raw = match tx.r#type { | ||
| Some(any_chain_tx::Type::Raw(bytes)) => bytes.to_vec(), | ||
| _ => return Err(Status::invalid_argument("missing or unsupported tx type")), | ||
| }; | ||
|
|
||
| let chain = self.domain.read_chain().await; | ||
|
|
||
| let handle_eval = |tx_cbor: &[u8]| { | ||
| let result = validate_tx(&self.domain, &chain, tx_cbor); | ||
| let result = tx_eval_to_u5c(result); | ||
| let result = validate_tx(&self.domain, &chain, &tx_raw); | ||
| let result = tx_eval_to_u5c(result); | ||
|
|
||
| AnyChainEval { | ||
| chain: Some(Chain::Cardano(result)), | ||
| } | ||
| let report = AnyChainEval { | ||
| chain: Some(Chain::Cardano(result)), | ||
| }; | ||
|
|
||
| let eval_results: Vec<_> = txs_raw.iter().map(|x| handle_eval(x)).collect(); | ||
|
|
||
| Ok(Response::new(EvalTxResponse { | ||
| report: eval_results, | ||
| report: Some(report), |
There was a problem hiding this comment.
Build failure: Same API mismatch in eval_tx.
The eval_tx method has the same issue—request.tx is a Vec, and EvalTxResponse.report expects a different structure than a single Option<AnyChainEval>.
This needs to be aligned with the actual pallas spec version being used.
🧰 Tools
🪛 GitHub Check: Check Build
[failure] 219-219:
mismatched types
[failure] 202-202:
no method named ok_or_else found for struct Vec<pallas::interop::pallas_utxorpc::spec::submit::AnyChainTx> in the current scope
🤖 Prompt for AI Agents
In @src/serve/grpc/submit.rs around lines 199-219, eval_tx currently treats
request.into_inner().tx as a single optional tx but the proto uses a Vec of txs
and EvalTxResponse.report expects a repeated list; update eval_tx to iterate
over request.into_inner().tx (the Vec), for each entry extract tx_raw like you
do now, call validate_tx(&self.domain, &chain, &tx_raw) and tx_eval_to_u5c, wrap
each result in an AnyChainEval with Chain::Cardano(result), collect those into a
Vec<AnyChainEval> and assign that collection to the response field (the repeated
report field on EvalTxResponse) instead of building a single
Option<AnyChainEval>.
| let block = mapper.map_block_cbor(body); | ||
| let header = block.header?; | ||
|
|
||
| header.map(|h| u5c::sync::BlockRef { | ||
| slot: h.slot, | ||
| hash: h.hash, | ||
| height: h.height, | ||
| Some(u5c::sync::BlockRef { | ||
| slot: header.slot, | ||
| hash: header.hash, | ||
| height: header.height, | ||
| timestamp: block.timestamp, | ||
| }) |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, check the actual code at lines 43-51
cat -n src/serve/grpc/sync.rs | sed -n '40,55p'Repository: txpipe/dolos
Length of output: 585
🏁 Script executed:
# Search for BlockRef definition to verify field names
rg -n "struct BlockRef" --type rust -A 20 | head -80Repository: txpipe/dolos
Length of output: 38
🏁 Script executed:
# Also check for FollowTipResponse definition
rg -n "struct FollowTipResponse" --type rust -A 15 | head -60Repository: txpipe/dolos
Length of output: 38
🏁 Script executed:
# Check what version of pallas is being used
cat Cargo.toml | grep -A 5 -B 5 "pallas\|u5c"Repository: txpipe/dolos
Length of output: 780
🏁 Script executed:
# Search more broadly for BlockRef in the entire codebase
rg -n "BlockRef" --type rust | head -30Repository: txpipe/dolos
Length of output: 635
🏁 Script executed:
# Check if u5c is imported and where it comes from
rg -n "use.*u5c" --type rust | head -20Repository: txpipe/dolos
Length of output: 436
🏁 Script executed:
# Look for u5c in dependencies
rg -n "u5c" Cargo.tomlRepository: txpipe/dolos
Length of output: 38
🏁 Script executed:
# Check if this project uses cargo and try to see dependency tree
cd . && if [ -f Cargo.lock ]; then grep -A 5 "name = \"u5c\"" Cargo.lock 2>/dev/null || echo "u5c not in lock file"; fiRepository: txpipe/dolos
Length of output: 76
🏁 Script executed:
# Find where BlockRef is defined - check pallas interop module
find . -name "*.rs" -type f | xargs rg -l "sync::BlockRef" | head -10Repository: txpipe/dolos
Length of output: 80
🏁 Script executed:
# Check if there's a generated or proto file for BlockRef
find . -name "*.rs" -o -name "*.proto" | xargs rg -l "BlockRef" 2>/dev/null | head -15Repository: txpipe/dolos
Length of output: 106
🏁 Script executed:
# Look at the watch.rs file to see how BlockRef is used there
cat -n src/serve/grpc/watch.rs | sed -n '170,190p'Repository: txpipe/dolos
Length of output: 691
🏁 Script executed:
# Check if there's documentation or comments about BlockRef fields
rg -B 5 -A 10 "struct BlockRef|BlockRef {" --type rust | head -100Repository: txpipe/dolos
Length of output: 171
🏁 Script executed:
# Search for any compilation or build test output
if [ -f target/debug/dolos ] || [ -f target/release/dolos ]; then
echo "Binary exists";
else
echo "No compiled binary found";
fiRepository: txpipe/dolos
Length of output: 80
🏁 Script executed:
# Look at complete sync.rs file structure to understand the functions
cat -n src/serve/grpc/sync.rs | head -100Repository: txpipe/dolos
Length of output: 3713
🏁 Script executed:
# Check the exact point_to_blockref function
cat -n src/serve/grpc/sync.rs | sed -n '54,65p'Repository: txpipe/dolos
Length of output: 486
🏁 Script executed:
# Search for any TODO or FIXME comments near these lines
rg -n "TODO|FIXME|XXX" src/serve/grpc/sync.rsRepository: txpipe/dolos
Length of output: 222
🏁 Script executed:
# Try to find pallas version details and BlockRef definition
web_search pallas utxorpc BlockRef fields timestampRepository: txpipe/dolos
Length of output: 106
🌐 Web query:
pallas 1.0.0-alpha.3 BlockRef timestamp field utxorpc
💡 Result:
Short answer: The UTxO‑RPC spec's BlockRef does NOT include a timestamp field — it only defines index and hash — so pallas' utxorpc types follow the spec (no BlockRef.timestamp). See the UTxO‑RPC Sync/Watch spec and the pallas repo/release. [1][2]
Sources
- UTxO‑RPC Sync/Watch module — BlockRef fields (index, hash). [1]
- txpipe/pallas release / pallas-utxorpc crate (pallas implements UTxO‑RPC interop). [2]
🌐 Web query:
pallas interop utxorpc sync BlockRef struct definition
💡 Result:
BlockRef (UTxO RPC sync module) — fields:
- index: uint64 (height/slot)
- hash: bytes
Rust (pallas interop/utxorpc) equivalent (approx):
pub struct BlockRef {
pub index: u64,
pub hash: Bytes, // raw block hash bytes
}
Sources: UTxO RPC sync spec and pallas docs. [1][2]
References
[1] UTxO RPC — Sync module (BlockRef: index uint64, hash bytes).
[2] pallas crate — interop::utxorpc::spec::sync exposes BlockRef.
Remove timestamp, slot, and height fields from BlockRef assignments.
The UTxO-RPC spec defines BlockRef with only index and hash fields. Pallas implements the spec exactly, so assigning timestamp (line 50), slot, and height fields will fail compilation. Update the struct initialization to only include the fields defined in the spec.
🧰 Tools
🪛 GitHub Check: Check Build
[failure] 50-50:
struct pallas::interop::pallas_utxorpc::spec::sync::BlockRef has no field named timestamp
🤖 Prompt for AI Agents
In @src/serve/grpc/sync.rs around lines 43-51, The BlockRef initialization is
using fields not in the UTxO-RPC spec; change the u5c::sync::BlockRef
construction in the mapper.map_block_cbor handling to only set index and hash
(remove timestamp, slot, and height assignments). Populate index from
header.height and hash from header.hash so the struct matches the spec exactly.
| fn point_to_blockref(point: &ChainPoint, timestamp: u64) -> u5c::sync::BlockRef { | ||
| BlockRef { | ||
| hash: point.hash().map(|h| h.to_vec()).unwrap_or_default().into(), | ||
| slot: point.slot(), | ||
| timestamp, | ||
| ..Default::default() | ||
| } | ||
| } |
There was a problem hiding this comment.
Build failure: timestamp field assignment will fail.
The point_to_blockref function attempts to set a timestamp field that doesn't exist on BlockRef. This needs to be removed or the dependency updated.
🧰 Tools
🪛 GitHub Check: Check Build
[failure] 58-58:
struct pallas::interop::pallas_utxorpc::spec::sync::BlockRef has no field named timestamp
🤖 Prompt for AI Agents
In @src/serve/grpc/sync.rs around lines 54-61, The struct construction in
point_to_blockref is setting a non-existent timestamp field on
u5c::sync::BlockRef; remove the timestamp: timestamp, assignment from the
BlockRef literal in point_to_blockref (or, if the newer BlockRef in the
dependency should include timestamp, update the dependency and adjust imports
accordingly) so the BlockRef is built only with existing fields (e.g., hash and
slot) and any timestamp handling is done separately.
| match event { | ||
| TipEvent::Apply(_, block) => { | ||
| let block_ref = raw_to_blockref(mapper, block); | ||
| u5c::sync::FollowTipResponse { | ||
| action: Some(u5c::sync::follow_tip_response::Action::Apply( | ||
| raw_to_anychain(mapper, block), | ||
| )), | ||
| tip: block_ref, | ||
| } | ||
| } | ||
| TipEvent::Undo(_, block) => u5c::sync::FollowTipResponse { | ||
| action: Some(u5c::sync::follow_tip_response::Action::Undo( | ||
| raw_to_anychain(mapper, block), | ||
| )), | ||
| tip: None, // TODO: we don't have easy access to the new tip here | ||
| }, | ||
| TipEvent::Mark(x) => u5c::sync::FollowTipResponse { | ||
| action: Some(u5c::sync::follow_tip_response::Action::Reset( | ||
| point_to_blockref(x, 0), // TODO: we don't have the timestamp here | ||
| )), | ||
| tip: Some(point_to_blockref(x, 0)), | ||
| }, | ||
| } |
There was a problem hiding this comment.
Build failure: FollowTipResponse has no tip field.
Static analysis indicates that FollowTipResponse doesn't have a tip field in the current pallas version. The restructured response construction will fail to compile.
Additionally, note the TODO comments at lines 81 and 85 indicating incomplete timestamp handling:
- Line 81:
tip: None, // TODO: we don't have easy access to the new tip here - Line 85:
point_to_blockref(x, 0), // TODO: we don't have the timestamp here
These should be tracked for follow-up once the dependency is updated.
Would you like me to open an issue to track the TODO items for proper timestamp handling in Undo and Mark events?
🧰 Tools
🪛 GitHub Check: Check Build
[failure] 74-74:
struct FollowTipResponse has no field named tip
| TipEvent::Apply(_, block) => { | ||
| let txs = block_to_txs(block, mapper, request); | ||
| if txs.is_empty() { | ||
| let block_ref = raw_to_blockref(mapper, block); | ||
| if let Some(r) = block_ref { | ||
| vec![u5c::watch::WatchTxResponse { | ||
| action: Some(u5c::watch::watch_tx_response::Action::Idle(r)), | ||
| }] | ||
| } else { | ||
| vec![] | ||
| } | ||
| } else { | ||
| txs.into_iter() | ||
| .map(u5c::watch::watch_tx_response::Action::Apply) | ||
| .map(|x| u5c::watch::WatchTxResponse { action: Some(x) }) | ||
| .collect() | ||
| } | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, let's check the file in question
cat -n src/serve/grpc/watch.rs | sed -n '190,215p'Repository: txpipe/dolos
Length of output: 1353
🏁 Script executed:
# Check pallas version in Cargo.toml
rg -A2 -B2 "pallas" Cargo.tomlRepository: txpipe/dolos
Length of output: 485
🏁 Script executed:
# Search for Action enum definition and variants in the codebase
rg -n "enum Action" --type rust -A 10 | head -40Repository: txpipe/dolos
Length of output: 38
🏁 Script executed:
# Search for where Action is used with Idle
rg -n "Action::Idle" --type rustRepository: txpipe/dolos
Length of output: 169
🏁 Script executed:
# Check if there's a proto file that defines the watch service
fd -e proto | head -20Repository: txpipe/dolos
Length of output: 38
🏁 Script executed:
# Search for watch module or Action definition in the codebase
find . -type f -name "*.rs" | xargs grep -l "watch_tx_response" | head -10Repository: txpipe/dolos
Length of output: 81
🏁 Script executed:
# Look for the u5c module definition
fd -e rs | xargs grep -l "u5c::" | head -10Repository: txpipe/dolos
Length of output: 173
🏁 Script executed:
# Check if u5c is a generated proto module
find . -type f -name "*.rs" | xargs grep -l "mod u5c\|mod watch" | head -10Repository: txpipe/dolos
Length of output: 79
🏁 Script executed:
# Search for Action enum definition more broadly
rg -n "enum.*Action" --type rust -B2 -A10 | head -60Repository: txpipe/dolos
Length of output: 821
🏁 Script executed:
# Check the grpc/mod.rs file to see how u5c is defined
cat -n src/serve/grpc/mod.rsRepository: txpipe/dolos
Length of output: 4090
🏁 Script executed:
# Search for where u5c module is generated or imported
rg -n "u5c" src/serve/grpc/mod.rs -B3 -A3Repository: txpipe/dolos
Length of output: 1826
🏁 Script executed:
# Look for the proto or u5c module definition
find . -type f \( -name "*.proto" -o -name "*.rs" \) | xargs grep -l "watch_tx_response\|Action" | grep -v targetRepository: txpipe/dolos
Length of output: 319
🏁 Script executed:
# Search for all uses of Action enum in the watch.rs file
rg -n "Action::" src/serve/grpc/watch.rsRepository: txpipe/dolos
Length of output: 286
🏁 Script executed:
# Check if there's any documentation or comments about Action variants
rg -B5 -A5 "Action::Idle|Action::Apply|Action::Undo" src/serve/grpc/watch.rsRepository: txpipe/dolos
Length of output: 1105
🏁 Script executed:
# Search in pallas related documentation or comments about what variants exist
rg -n "Idle|Apply|Undo" --type rust | grep -i "action\|watch" | head -20Repository: txpipe/dolos
Length of output: 725
🏁 Script executed:
# Check if there are any build errors or TODO comments related to this
rg -n "TODO|FIXME|XXX|HACK" src/serve/grpc/watch.rs | head -20Repository: txpipe/dolos
Length of output: 165
🏁 Script executed:
# Look at the git history to see if Action::Idle was recently added
git log --oneline -20 -- src/serve/grpc/watch.rsRepository: txpipe/dolos
Length of output: 93
🏁 Script executed:
# Check if there's any configuration or feature flags that might affect this
cat Cargo.toml | grep -A20 "\[dependencies\]"Repository: txpipe/dolos
Length of output: 582
🏁 Script executed:
# Try to find any proto files or schema that would define the Action enum
find . -name "*.proto" -type fRepository: txpipe/dolos
Length of output: 38
🏁 Script executed:
# Search for pallas utxorpc documentation or comments
rg -n "utxorpc" --type rust -B3 -A3 | head -40Repository: txpipe/dolos
Length of output: 2494
🏁 Script executed:
# Check if there are any recent issues or comments about Action variants
rg -n "Idle\|Apply\|Undo" --type rust -B2 -A2 | grep -i "action\|watch_tx" | head -30Repository: txpipe/dolos
Length of output: 38
🏁 Script executed:
# Look for any test files or examples that might indicate which variants are valid
find . -name "*.rs" -type f | xargs grep -l "watch_tx_response" | xargs cat | head -100Repository: txpipe/dolos
Length of output: 3502
🏁 Script executed:
# Check the sync.rs file to see how it handles Action variants
cat -n src/serve/grpc/sync.rs | sed -n '65,85p'Repository: txpipe/dolos
Length of output: 1130
🏁 Script executed:
# Look for any build errors or compilation output
cat Cargo.toml | head -20Repository: txpipe/dolos
Length of output: 533
🏁 Script executed:
# Check if there's a .cargo or build directory with any cached build info
ls -la | grep -E "^d" | head -20Repository: txpipe/dolos
Length of output: 687
🏁 Script executed:
# Search for the pallas crate reference to understand what Action variants should exist
rg -n "watch_tx_response" --type rust -B5 -A5Repository: txpipe/dolos
Length of output: 1805
🏁 Script executed:
# Check if there's documentation about the watch_tx_response Action enum
rg -n "enum.*Action|type.*Action" --type rust -A15 | grep -A15 "watch"Repository: txpipe/dolos
Length of output: 38
🏁 Script executed:
# Let's check what pallas version 1.0.0-alpha.3 contains by looking at dependencies
rg -n "version.*1.0.0-alpha.3" Cargo.tomlRepository: txpipe/dolos
Length of output: 132
🌐 Web query:
pallas 1.0.0-alpha.3 watch_tx_response Action enum variants utxorpc
💡 Result:
The Action enum for watch_tx_response has two variants: Apply and Undo. [1][2]
Sources:
- pallas crate index (interop::utxorpc spec listing). [1]
- UTxO RPC Watch spec (WatchTxResponse: apply / undo). [2]
Remove or replace Action::Idle variant—it does not exist in pallas 1.0.0-alpha.3.
The code at line 199 attempts to use u5c::watch::watch_tx_response::Action::Idle, but the Action enum in the current pallas version only supports Apply and Undo variants. This will cause a compilation failure.
Either adjust the logic to use an existing variant or upgrade pallas to a version that includes the Idle variant.
🧰 Tools
🪛 GitHub Actions: CI
[error] 199-199: no variant or associated item named Idle found for enum pallas::interop::pallas_utxorpc::spec::watch::watch_tx_response::Action in the current scope
🪛 GitHub Check: Check Build
[failure] 199-199:
no variant or associated item named Idle found for enum pallas::interop::pallas_utxorpc::spec::watch::watch_tx_response::Action in the current scope
🤖 Prompt for AI Agents
In @src/serve/grpc/watch.rs around lines 193-210, The TipEvent::Apply arm uses
u5c::watch::watch_tx_response::Action::Idle which doesn't exist; remove that
variant and, when txs.is_empty(), return an empty vector instead of attempting
to emit Idle (i.e., replace the raw_to_blockref/Idle branch with vec![]), or
alternatively if you need to signal the block choose an existing variant (e.g.,
wrap the block ref into Action::Apply using the same WatchTxResponse shape) but
do not reference Action::Idle; update the TipEvent::Apply logic and calls to
raw_to_blockref accordingly.
There was a problem hiding this comment.
Actionable comments posted: 1
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/serve/grpc/sync.rs
🧰 Additional context used
🧬 Code graph analysis (1)
src/serve/grpc/sync.rs (1)
src/serve/grpc/watch.rs (1)
raw_to_blockref(173-185)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Check Build
🔇 Additional comments (1)
src/serve/grpc/sync.rs (1)
54-61: Compilation failure: Invalid fields inBlockRefconstruction.This issue was already flagged in previous reviews. The
sync::BlockRefstruct does not haveslotortimestampfields; onlyindexandhashare defined in the UTxO-RPC spec.Likely an incorrect or invalid review comment.
| let lookup = |br: &u5c::sync::BlockRef| -> Result<BlockBody, Status> { | ||
| if !br.hash.is_empty() { | ||
| if let Some(body) = store | ||
| .get_block_by_hash(&br.hash) | ||
| .map_err(|_| Status::internal("Failed to query chain service."))? | ||
| { | ||
| return Ok(body); | ||
| } | ||
| } | ||
|
|
||
| if br.height != 0 { | ||
| if let Some(body) = store | ||
| .get_block_by_number(&br.height) | ||
| .map_err(|_| Status::internal("Failed to query chain service."))? | ||
| { | ||
| return Ok(body); | ||
| } | ||
| } | ||
|
|
||
| if br.slot != 0 { | ||
| if let Some(body) = store | ||
| .get_block_by_slot(&br.slot) | ||
| .map_err(|_| Status::internal("Failed to query chain service."))? | ||
| { | ||
| return Ok(body); | ||
| } | ||
| } | ||
|
|
||
| Err(Status::not_found(format!("Failed to find block: {br:?}"))) | ||
| }; |
There was a problem hiding this comment.
Compilation failure: Invalid field access on BlockRef.
The lookup closure attempts to access br.height (line 146) and br.slot (line 155), but sync::BlockRef only has index and hash fields per the UTxO-RPC spec. This will cause compilation to fail.
Clarification needed
The spec defines index as a uint64, but it's unclear whether this represents slot or height in the Cardano context. You'll need to:
- Determine what
indexrepresents (slot, height, or block number) - Rewrite the lookup logic to use only
hashandindex - Decide on an appropriate fallback strategy if
indexdoesn't cover all lookup scenarios
Summary by CodeRabbit
Bug Fixes
Enhancements
New Features
Chores
✏️ Tip: You can customize this high-level summary in your review settings.