Skip to content

fix: improve search of utxo by full asset & fail on missing policy id#992

Merged
scarmuega merged 1 commit into
mainfrom
search-by-full-asset-u5c
May 14, 2026
Merged

fix: improve search of utxo by full asset & fail on missing policy id#992
scarmuega merged 1 commit into
mainfrom
search-by-full-asset-u5c

Conversation

@nicolasLuduena
Copy link
Copy Markdown
Member

@nicolasLuduena nicolasLuduena commented May 7, 2026

Summary by CodeRabbit

  • Bug Fixes
    • Updated asset query validation to require both policy ID and asset name when querying by asset. Asset name-only queries now return an error; policy-only queries are no longer supported.

@nicolasLuduena nicolasLuduena requested a review from scarmuega as a code owner May 7, 2026 18:54
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 7, 2026

Review Change Stack

📝 Walkthrough

Walkthrough

This PR updates the gRPC v1alpha and v1beta query implementations to unify how AssetPattern handles policy ID and asset name criteria. Instead of supporting independent queries, the logic now requires both fields together or neither. Combined queries concatenate bytes; asset-only queries reject with an invalid-argument error.

Changes

AssetPattern Query Index Logic

Layer / File(s) Summary
v1alpha Core Query Logic
src/serve/grpc/v1alpha/query.rs
IntoSet for AssetPattern now concatenates policy_id and asset_name bytes when both are provided, returns invalid_argument error when asset name is present without policy ID, and returns empty set when both absent.
v1beta Wiring and Core Logic
src/serve/grpc/v1beta/query.rs
Import order is adjusted; IntoSet implementation mirrors v1alpha logic for consistent policy/asset query handling across versions.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 A rabbit hops through query fields,
Where policy and asset yield—
Unite them both, or both release,
No lonely names for query peace.
Two versions sync, one hoppy beat! 🎉

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main changes: improving UTXO search by full asset and adding validation to fail when policy ID is missing.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch search-by-full-asset-u5c

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
src/serve/grpc/v1beta/query.rs (2)

170-178: 💤 Low value

Redundant intermediate wrappers in the combined-asset arm.

by_policy and by_asset are cloned into wrapper structs solely to enable the non-empty check via maybe_from, but in the (Some(_), Some(_)) arm both wrappers are discarded with _ and self.policy_id/self.asset_name are read again directly. Calling is_empty() directly avoids the allocations and makes the intent clearer.

♻️ Proposed refactor
 impl IntoSet for u5c::cardano::AssetPattern {
     fn into_set<S: CardanoIndexExt>(self, indexes: &S) -> Result<HashSet<TxoRef>, Status> {
-        let by_policy = ByPolicyQuery::maybe_from(self.policy_id.clone());
-        let by_asset = ByAssetQuery::maybe_from(self.asset_name.clone());
-
-        match (by_policy, by_asset) {
-            (Some(_), Some(_)) => {
-                let mut subject = self.policy_id.to_vec();
-                subject.extend_from_slice(&self.asset_name);
-                ByAssetQuery(bytes::Bytes::from(subject)).into_set(indexes)
-            }
-            (Some(x), None) => x.into_set(indexes),
-            (None, Some(_)) => Err(Status::invalid_argument(
-                "asset name query requires a policy_id",
-            )),
-            (None, None) => Ok(HashSet::default()),
+        match (!self.policy_id.is_empty(), !self.asset_name.is_empty()) {
+            (true, true) => {
+                let mut subject = self.policy_id.to_vec();
+                subject.extend_from_slice(&self.asset_name);
+                ByAssetQuery(bytes::Bytes::from(subject)).into_set(indexes)
+            }
+            (true, false) => ByPolicyQuery(self.policy_id).into_set(indexes),
+            (false, true) => Err(Status::invalid_argument(
+                "asset name query requires a policy_id",
+            )),
+            (false, false) => Ok(HashSet::default()),
         }
     }
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/serve/grpc/v1beta/query.rs` around lines 170 - 178, The current code
constructs ByPolicyQuery::maybe_from and ByAssetQuery::maybe_from only to check
non-emptiness and then ignores those wrappers in the (Some(_), Some(_)) arm;
instead, avoid allocations by checking the raw fields directly (use
self.policy_id.is_empty() and self.asset_name.is_empty()) and only build the
combined subject if both are non-empty, then create the bytes vector and call
ByAssetQuery(bytes::Bytes::from(subject)).into_set(indexes); remove the initial
ByPolicyQuery/ByAssetQuery wrapper variables and their maybe_from calls (refer
to ByPolicyQuery, ByAssetQuery, maybe_from, self.policy_id, self.asset_name, and
the final ByAssetQuery(...).into_set(indexes)).

168-186: ⚡ Quick win

No unit tests cover the two new AssetPattern code paths.

The (Some(_), Some(_)) combined-query arm and the (None, Some(_)) error arm both lack test coverage. Given that this is the primary functional change in the PR, tests for these paths would prevent regressions.

Suggested cases:

  • policy_id non-empty + asset_name non-empty → utxos_by_asset is called with the concatenated subject.
  • policy_id empty + asset_name non-empty → Status::invalid_argument("asset name query requires a policy_id").
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/serve/grpc/v1beta/query.rs` around lines 168 - 186, Add unit tests for
the IntoSet impl for u5c::cardano::AssetPattern covering the two missing
branches: create a test that constructs an AssetPattern with non-empty policy_id
and non-empty asset_name and assert that ByAssetQuery is invoked (i.e., the
resulting utxo set equals the expected result from ByAssetQuery when called with
the concatenated subject) and another test that constructs an AssetPattern with
empty policy_id and non-empty asset_name and asserts the function returns
Err(Status::invalid_argument("asset name query requires a policy_id")). Locate
the IntoSet implementation for u5c::cardano::AssetPattern and write tests that
exercise AssetPattern.into_set<S: CardanoIndexExt>(indexes) using a mock or test
implementation of CardanoIndexExt that lets you verify
ByAssetQuery(bytes::Bytes::from(subject)).into_set(indexes) was used and that
the error arm is returned for the empty-policy case.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/serve/grpc/v1beta/query.rs`:
- Around line 170-178: The current code constructs ByPolicyQuery::maybe_from and
ByAssetQuery::maybe_from only to check non-emptiness and then ignores those
wrappers in the (Some(_), Some(_)) arm; instead, avoid allocations by checking
the raw fields directly (use self.policy_id.is_empty() and
self.asset_name.is_empty()) and only build the combined subject if both are
non-empty, then create the bytes vector and call
ByAssetQuery(bytes::Bytes::from(subject)).into_set(indexes); remove the initial
ByPolicyQuery/ByAssetQuery wrapper variables and their maybe_from calls (refer
to ByPolicyQuery, ByAssetQuery, maybe_from, self.policy_id, self.asset_name, and
the final ByAssetQuery(...).into_set(indexes)).
- Around line 168-186: Add unit tests for the IntoSet impl for
u5c::cardano::AssetPattern covering the two missing branches: create a test that
constructs an AssetPattern with non-empty policy_id and non-empty asset_name and
assert that ByAssetQuery is invoked (i.e., the resulting utxo set equals the
expected result from ByAssetQuery when called with the concatenated subject) and
another test that constructs an AssetPattern with empty policy_id and non-empty
asset_name and asserts the function returns Err(Status::invalid_argument("asset
name query requires a policy_id")). Locate the IntoSet implementation for
u5c::cardano::AssetPattern and write tests that exercise
AssetPattern.into_set<S: CardanoIndexExt>(indexes) using a mock or test
implementation of CardanoIndexExt that lets you verify
ByAssetQuery(bytes::Bytes::from(subject)).into_set(indexes) was used and that
the error arm is returned for the empty-policy case.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7db97c6e-619b-4fba-bd05-24b2d8b18031

📥 Commits

Reviewing files that changed from the base of the PR and between d1d2f35 and d94b454.

📒 Files selected for processing (2)
  • src/serve/grpc/v1alpha/query.rs
  • src/serve/grpc/v1beta/query.rs

@scarmuega scarmuega merged commit f6bbcde into main May 14, 2026
12 checks passed
@scarmuega scarmuega deleted the search-by-full-asset-u5c branch May 14, 2026 15:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants