Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

change(rpc): Update getaddressbalance RPC to return received field #9295

Draft
wants to merge 10 commits into
base: db-format-upgrade-trait
Choose a base branch
from

Conversation

arya2
Copy link
Contributor

@arya2 arya2 commented Feb 24, 2025

Motivation

Updates the getaddressbalance RPC to accept either a single address string or a list of them to match zcashd, and adds the received field on the method's response.

This PR is still a draft as it will need an acceptance test.

Depends-On: #9263

Will close #8452.

Solution

  • Bumps db format version for address balances to include a received field, and adds an in-place format upgrade,
  • Parses single address strings passed to RPC methods accepting AddressStrings as a Vec with one item, and
  • Adds the received field to the getaddressbalance RPC output.

Tests

This PR still needs an acceptance test for the db format upgrade.
The changes to the RPC should be covered by existing snapshot tests.

PR Checklist

  • The PR name is suitable for the release notes.
  • The solution is tested.
  • The documentation is up to date.
  • The PR has a priority label.
  • If the PR shouldn't be in the release notes, it has the
    C-exclude-from-changelog label.

Sorry, something went wrong.

@arya2 arya2 added S-blocked Status: Blocked on other tasks A-rpc Area: Remote Procedure Call interfaces A-state Area: State / database changes P-Medium ⚡ labels Feb 24, 2025
@arya2 arya2 self-assigned this Feb 24, 2025
Copy link
Contributor

mergify bot commented Feb 24, 2025

Merge Protections

Your pull request matches the following merge protections and will not be merged until they are valid.

🔴 ⛓️ Depends-On Requirements

This rule is failing.

Requirement based on the presence of Depends-On in the body of the pull request

Sorry, something went wrong.

@mpguerra mpguerra linked an issue Feb 25, 2025 that may be closed by this pull request
…uct, `PruneTrees`, and moves the logic for tree deduplication to the trait impl
- Avoids duplicate validation of format upgrades at startup when db is already upgraded,
- Minor refactors
- Doc fixes and cleanups
@arya2 arya2 force-pushed the db-format-upgrade-trait branch from 55b3602 to deff106 Compare February 25, 2025 19:25
- Adds received balances to non-finalized state, and
- Applies the partial chain received balance change to the finalized received balance when reading address balances.
Comment on lines +41 to +45
// Return early if there are no blocks in the state and the database is empty.
// Note: The caller should (and as of this writing, does) return early if the database is empty anyway.
if initial_tip_height.is_min() {
return Ok(());
}
Copy link
Contributor Author

@arya2 arya2 Feb 26, 2025

Choose a reason for hiding this comment

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

This condition is checking if the state contains only the genesis block, not if it's entirely empty.

Suggested change
// Return early if there are no blocks in the state and the database is empty.
// Note: The caller should (and as of this writing, does) return early if the database is empty anyway.
if initial_tip_height.is_min() {
return Ok(());
}

@mpguerra mpguerra removed this from the Zebra Ready for zcashd Deprecation milestone Feb 26, 2025
Comment on lines +151 to +157
// Read the address balance from disk.
let mut balance = db
.address_balance_location(address)
.expect("should have address balances in finalized state");

// Update the address balance with the tallied received balance.
*balance.received_mut() = received;
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm not fully convinced of the correctness of the flow here.

What if:

  • An AddressBalanceReceived (ABR) is read, and its received is updated in memory
  • A block is comitted, and another field of the same ABR is updated (e.g. balance)
  • The in-memory ABR is written to the DB, overwriting the updated balance
  • Below, it is noticed that a block is committed, and the loop continues, but it won't restore the correct balance AFAICT?

I feel like we can't avoid reading and writing to the same field unless it's inside the same database commit.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This explains the values in the failed test logs, I'm thinking I'll add a mechanism for pausing block commits before writing to disk from an in-place upgrade.

Alternatives:

  • add a mechanism for blocking the state service initialization at startup on the completion of certain format upgrades
  • remove the in-place upgrade and make it a major format upgrade

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yes, it seems a blocking format upgrade might be useful here, though a bit annoying for operators.

Another alternative would be to use a new column, but that would add redundancy.

Another option: https://github.com/facebook/rocksdb/wiki/Merge-Operator ?

@arya2 arya2 force-pushed the db-format-upgrade-trait branch from deff106 to a9a17e2 Compare March 15, 2025 00:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-rpc Area: Remote Procedure Call interfaces A-state Area: State / database changes P-Medium ⚡ S-blocked Status: Blocked on other tasks
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Update getaddressbalance RPC method for block explorer usage
3 participants