Skip to content

rpc: Add getwalletstatus#367

Draft
str4d wants to merge 1 commit intomainfrom
316-wallet-status
Draft

rpc: Add getwalletstatus#367
str4d wants to merge 1 commit intomainfrom
316-wallet-status

Conversation

@str4d
Copy link
Collaborator

@str4d str4d commented Feb 4, 2026

Closes #316.
Closes COR-338.

@str4d str4d added the A-rpc-interface Area: RPC interface label Feb 4, 2026
#[rpc(server)]
pub(crate) trait Rpc {
/// Returns wallet status information.
#[method(name = "getwalletstatus")]
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I named it thusly because @oxarbitrage suggested walletstatus but get* fits better with existing naming. But is getwalletstatus both sufficiently clear vs getwalletinfo, and non-colliding with existing Bitcoin JSON-RPC names?

Copy link
Contributor

Choose a reason for hiding this comment

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

I think this is fine. There is no getwalletstatus in Bitcoin and i think the name is clear enough.

@str4d str4d requested a review from nuttycom February 4, 2026 01:49
@str4d str4d force-pushed the 316-wallet-status branch from eb16fc7 to 7838054 Compare February 4, 2026 02:02
Comment on lines +37 to +46
/// The height to which the wallet is fully synced.
///
/// The wallet only has a partial view of chain data above this height.
///
/// Omitted if the wallet does not have any accounts or birthday data and thus has
/// nowhere to sync from, or if the wallet birthday itself has not yet been synced.
/// The latter occurs when a recovered wallet first starts and is scanning the chain
/// tip region.
#[serde(skip_serializing_if = "Option::is_none")]
fully_synced_height: Option<u32>,
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Currently what happens is:

  • Accounts to recover are loaded into the wallet/
  • Wallet scans the chain tip region.
    • fully_synced_height = None because the wallet birthday height has not been scanned.
    • This takes quite a while.
  • Once the chain tip region is scanned, the next scan range is the birthday height.
    • fully_synced_height is now set.

Should instead fully_synced_height be non-optional and set to the last ignored height, or as a fallback the genesis block?

Copy link
Contributor

Choose a reason for hiding this comment

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

From an implementer’s perspective, optional fields are generally harder to work with, since the client needs to check for their presence before accessing them. They can also make responses more confusing in some cases.

In general, I tend to prefer having fields always present, but Zcash already uses this pattern in several places, so I think it’s fine as long as the behavior is clearly documented.

Copy link
Collaborator Author

@str4d str4d Feb 25, 2026

Choose a reason for hiding this comment

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

Having it be present-but-null vs not-present-if-null is a different question than the one I was asking.

My question was, should None be an allowable value here, or should we instead return something else?

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks for clarifying. I think returning the genesis block, the birthday block, or anything similar would also be confusing, so I prefer keeping None as you have it. Whatever we decide, I think it would be good to document this
behaviour in the field's description.

Comment on lines +69 to +72
// TODO: Replace these with accurate unscanned note counts, which we can determine
// because Zallet tracks the chain tip very closely.
progress_numerator: u64,
progress_denominator: u64,
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

These are temporary because it's all I have access to currently. Given that Zallet is intended to track the backing node's chain tip as closely as possible, once #237 is done we will always know the size of the note commitment trees, and thus it should always be possible to determine how many leaves within them have not yet been appended (and thus are unscanned).

@str4d str4d force-pushed the 316-wallet-status branch from 7838054 to 91ce9f5 Compare February 4, 2026 17:26
@oxarbitrage oxarbitrage self-requested a review February 9, 2026 20:50
@oxarbitrage
Copy link
Contributor

Hey, thanks for adding this, looking good.

I’ve been trying to integrate this into the Zebra QA framework so we can get rid of several anti-pattern sleeps. In particular, I was experimenting with using it in this test:

https://github.com/ZcashFoundation/zebra/blob/b46305a6437bea49d268aeb915b8e62ee4e63f0a/zebra-rpc/qa/rpc-tests/wallet.py

The test passes most of the time, but occasionally it gets stuck in scenarios like this:

{
  'node_tip': {
    'blockhash': '6058ceb2b07f544c586ad948b68a7ed49d6c3fdec8ac2f1b26779993f29f64fc',
    'height': 4
  },
  'wallet_tip': {
    'blockhash': 'd72879af1530f3c234c974e08bbf9f62c38e69245a7880b6947c10f299b2ab54',
    'height': 3
  },
  'fully_synced_height': 3
}

In this case, I’m waiting for the node tip and wallet tip to match before proceeding, but that never happens unless I mine a new block (which then triggers the Zallet scan to advance).

I’m not fully sure yet whether this is an issue in the test logic or something on the Zallet side. Any ideas or pointers would be very welcome. I’ll keep digging to find the root cause as well.

Happy to continue reviewing and approve once I can get this sorted out. Thanks!

Comment on lines +71 to +72
progress_numerator: u64,
progress_denominator: u64,
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
progress_numerator: u64,
progress_denominator: u64,
progress: (numerator: u64, denominator: u64),

Optional: These fields are closely related. Maybe consider grouping them into a tuple or a small type.

@linear
Copy link

linear bot commented Feb 23, 2026

@str4d
Copy link
Collaborator Author

str4d commented Feb 23, 2026

The test passes most of the time, but occasionally it gets stuck in scenarios like this:

{
  'node_tip': {
    'blockhash': '6058ceb2b07f544c586ad948b68a7ed49d6c3fdec8ac2f1b26779993f29f64fc',
    'height': 4
  },
  'wallet_tip': {
    'blockhash': 'd72879af1530f3c234c974e08bbf9f62c38e69245a7880b6947c10f299b2ab54',
    'height': 3
  },
  'fully_synced_height': 3
}

In this case, I’m waiting for the node tip and wallet tip to match before proceeding, but that never happens unless I mine a new block (which then triggers the Zallet scan to advance).

My guess is this will be fixed as part of #336. So I think we should get zcash/integration-tests#1 merged, then test applying this PR to its current state, and then test #336 after merging this PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-rpc-interface Area: RPC interface

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add a walletstatus RPC method

2 participants