rpc: expose VTXO expiry info - #758
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces a new GetVTXOExpiryInfo RPC endpoint to the daemon service, allowing clients to query the expiry posture of a VTXO identified by outpoint or pkScript. It includes the corresponding protobuf definitions, server-side implementation, SDK client updates, and comprehensive unit tests. A critical issue was identified in the implementation where the ChainDepth field is omitted during the construction of the dummy vtxo.Descriptor in expiryInfoFromTiming, which leads to incorrect threshold calculations for VTXOs with out-of-round ancestry. A code suggestion has been provided to resolve this bug.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| desc := &vtxo.Descriptor{ | ||
| BatchExpiry: batchExpiry, | ||
| RelativeExpiry: relativeExpiry, | ||
| Ancestry: []vtxo.Ancestry{{ | ||
| TreeDepth: maxTreeDepth, | ||
| }}, | ||
| } |
There was a problem hiding this comment.
The ChainDepth field is omitted when constructing the dummy vtxo.Descriptor inside expiryInfoFromTiming. Since ChainDepth (the number of OOR checkpoint hops) is a critical input for calculating the unilateral exit delay, omitting it will cause CalculateCriticalThreshold and CalculateRefreshThreshold to return incorrect thresholds for any VTXO with OOR ancestry (where chainDepth > 0).
Please populate the ChainDepth field on the descriptor. Note that depending on the exact type of vtxo.Descriptor.ChainDepth (e.g., int, int32, or uint32), you may need to cast chainDepth accordingly (e.g., int(chainDepth)).
Additionally, once this is fixed, the test TestExpiryInfoFromDescriptorUsesDefaultThresholds in darepod/rpc_vtxo_expiry_test.go (which sets ChainDepth: 2 but asserts thresholds calculated with ChainDepth: 0) will fail. You will need to update the test assertions to reflect the correct thresholds for ChainDepth: 2, or change the test's ChainDepth to 0.
| desc := &vtxo.Descriptor{ | |
| BatchExpiry: batchExpiry, | |
| RelativeExpiry: relativeExpiry, | |
| Ancestry: []vtxo.Ancestry{{ | |
| TreeDepth: maxTreeDepth, | |
| }}, | |
| } | |
| desc := &vtxo.Descriptor{ | |
| BatchExpiry: batchExpiry, | |
| RelativeExpiry: relativeExpiry, | |
| ChainDepth: int(chainDepth), | |
| Ancestry: []vtxo.Ancestry{{ | |
| TreeDepth: maxTreeDepth, | |
| }}, | |
| } |
|
@bhandras, remember to re-request review from reviewers when ready |
Summary
Adds a daemon RPC surface for querying the wallet/VTXO layer's expiry posture for a VTXO by local outpoint or indexed pkScript.
This gives higher-level swap code an authoritative answer for refresh safety decisions instead of duplicating threshold math outside darepo-client.
What changed
GetVTXOExpiryInfotoDaemonService, including grpc-gateway and mailbox/generated bindings.VTXOExpiryStatusandVTXOExpiryInfoto the daemon proto, plus an optionalexpiry_infofield onVTXO.vtxo.DefaultExpiryConfig().sdk/arkand the REST client.Validation
make rpcgit diff --checkgo test ./...