fix(grpc): convert ChainPoint/BlockRef timestamp from seconds to ms#1003
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (5)
✅ Files skipped from review due to trivial changes (1)
🚧 Files skipped from review as they are similar to previous changes (2)
📝 WalkthroughWalkthroughThis PR introduces a shared block reference helper ( ChangesMillisecond Timestamp Scaling Across gRPC Endpoints
Estimated code review effort🎯 2 (Simple) | ⏱️ ~8 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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 |
|
Actionable comments posted: 0 |
gonzalezzfelipe
left a comment
There was a problem hiding this comment.
This includes the changes already merged on #1000 , can you rebase for it to make it cleaner for review?
342ba2b to
e931df8
Compare
|
Actionable comments posted: 0 |
|
Tests fail but for un-related reasons (a newly added lint check). |
While integrating PR #1000 downstream into a Cardano application that consumes utxo-rpc through
pogun-chainfollower, we noticed the newblock_reffield onSearchUtxos/ReadUtxoscame back populated but with a 10-digit timestamp — a UNIX seconds value, not the milliseconds the utxorpc proto declares. Tracing it further, the same unit mismatch exists in four pre-existing sites in Dolos's gRPC layer (ReadTip,ReadTx, both on v1alpha and v1beta), all the way throughEraSummary::slot_timeand the pallasLedgerContextadapter.What the proto says
utxorpc/specdeclares the timestamp field as milliseconds in four places, consistently:proto/utxorpc/v1alpha/query/query.proto—ChainPoint.timestamp(// Block ms timestamp)proto/utxorpc/v1beta/query/query.proto—ChainPoint.timestamp(same)proto/utxorpc/v1alpha/sync/sync.proto—BlockRef.timestamp(same)proto/utxorpc/v1beta/sync/sync.proto—BlockRef.timestamp(same)What Dolos actually writes
The root is
EraSummary::slot_time(crates/cardano/src/eras.rs:23) which returns seconds. Three confirming signals in-tree:crates/cardano/src/eras.rs:38— the sibling helper names its arithmeticlet second_delta = slot_delta * self.slot_length;.crates/cardano/src/forks.rs:81— Byron's ms-typedslot_durationis divided by 1000 before being stored asslot_length.crates/cardano/src/forks.rs:106— Shelleysystem_startis stored aschrono::DateTime::timestamp() as u64, which is unix seconds.That seconds value flows directly into proto fields documented as ms at five sites:
QueryService.ReadTx(v1alpha)src/serve/grpc/v1alpha/query.rs:998mainQueryService.ReadTx(v1beta)src/serve/grpc/v1beta/query.rs:998mainSyncService.ReadTip(v1alpha)src/serve/grpc/v1alpha/sync.rs:277mainSyncService.ReadTip(v1beta)src/serve/grpc/v1beta/sync.rs:277mainQueryService.SearchUtxos&ReadUtxos(viablock_ref)src/serve/grpc/block_refs.rs:71The first four route through
LedgerContext::get_slot_timestamp(pallas trait, doc'd as seconds — correctly implemented by Dolos's adapter atsrc/adapters/mod.rs:208). The fifth bypasses the trait and callschain_summary.slot_time(slot)directly because PR #1000 hoists the era summary per request — also correct in isolation, but seconds.The fix
Convert at the boundary. Each gRPC site that writes into a
// Block ms timestampproto field multiplies the seconds-typed source value by 1000. Five surgical edits, total diff +21/−5.The pallas
LedgerContext::get_slot_timestamptrait is not changed — its contract is seconds and Dolos correctly implements it. The conversion belongs at the proto write boundary, not at the trait. The internalEraSummary::slot_timeis also unchanged for the same reason.Verification — built and probed a preprod snapshot
dolos bootstrap snapshot --variant fullon preprod,dolos daemon, thengrpcurlagainst each endpoint. Before this PR (PR #1000 alone), all five RPCs returned 10-digit timestamp values that decode to the correct date when read as seconds and to January 1970 when read as ms. After this PR, every endpoint returns the same value × 1000 — 13 digits, decoding correctly as ms:ReadTip(v1alpha + v1beta)1777953075(≈ 1970-01-21 as ms)1777979745000(2026-05-05 09:55:45 UTC)ReadTx(v1alpha + v1beta)17775670691777567069000(2026-04-30 16:37:49 UTC)ReadUtxos(v1alpha + v1beta)17775670691777567069000(2026-04-30 16:37:49 UTC)SearchUtxos(v1alpha + v1beta)17775751271777575127000(2026-04-30 18:52:07 UTC)Slot math sanity check: preprod's byron
startTime + byron_slots × 20s + shelley_slots × 1s = slot_time(slot)lines up to the second for every value above. The conversion isn't reinterpreting anything — it's just promoting units.Stacking
Based on
fix/u5c-block-ref-populate. The diff againstmainwill include PR #1000's changes plus this PR's five-site fix; the diff againstfix/u5c-block-ref-populateis just the five edits.Summary by CodeRabbit
New Features
Improvements