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

add get_confirmations() RPC and add to dashboard #56

Merged
merged 8 commits into from
Oct 14, 2023

Conversation

dan-da
Copy link
Collaborator

@dan-da dan-da commented Sep 26, 2023

Addresses #6. (partial)

The major objective of this PR is adding the get_confirmations RPC. A secondary objective is displaying the confirmations field in overview screen of the Dashboard. Other changes are ancillary.

Server:

  • implement get_confirmations RPC
  • return confirmations field in get_dashboard_overview_data RPC
  • add wallet_state::get_latest_balance_height()
  • add block_height to tuple returned from wallet_state::get_balance_history

Dashboard:

  • display confirmations in overview screens
  • change confirmations field from usize to u64

Notes:

  • The get_confirmations() RPC function has been simplified and made more efficient than the prototype here.
  • get_latest_balance_height() will need to be modified to take into account unsynced/abandoned utxo. There is already Balance history does not agree with balance #28 for this, so I think it is best to do in a follow-up PR. Also, I'm not yet certain of the correct fix, as I did try to simply filter out by utxo.is_abandoned in get_balance_history() and that did not solve the balance/history sync issue. suggestions welcome.
  • I considered returning additional fields from get_latest_balance_height() and just calling it get_latest_balance(). However the amount field requires an additional call+loop and since there is no present need, I decided to keep it as simple/fast as possible.
  • As a first pass at optimizing I had added block_height field to values returned from wallet_state::get_balance_history(). That fn is no longer called from get_confirmations() however I left the block_height field in place because I think it would be useful to callers of the get_history() RPC. I think it would be useful to display the height in Dashboard history, but decided to leave that change for a follow-up PR. Anyway, this note explains that diff.
  • I'm a bit uncertain yet about the correct type(s) for block heights (and counts). There is the BlockHeight type which the compiler treats as i128. But it doesn't really make sense for a height to be signed. Also, i128 and u128 both seem like overkill... how many blocks are we anticipating? Is u64 not enough? The dashboard was previously using usize for confirmations field, which seems a bit loose as it could be u32 on some platform, so I changed it to u64 and also my reasoning is less data over the wire vs u128. But I would rather just be consistent with a single type (based on u64?) used everywhere to represent block heights. Perhaps the RPC and Dashboard should all be using the BlockHeight for confirmations field rather than a primitive type. thoughts?

Testing:

  • Restarted server and Dashboard, then verified that confirmations are displayed in the overview screen to the right of synced balance
  • Verified that confirmations field is zero when a new block is mined to my wallet, and increases by 1 for each subsequent block.
  • Compared the synced balance with top-most balance in History screen. The history screen balance is higher than synced balance. This is wrong but expected until Balance history does not agree with balance #28 is fixed.

I wanted to create a unit test for get_confirmations RPC however it is unclear to me how to do so. There are a few unit tests in rpc_server.rs, but afaict none of them setup a wallet with a non-zero balance which would be a requirement for my test(s). If someone could provide such a setup fn, I would happily make use of it.

Addresses Neptune-Crypto#6.  (partial)

Server:
* implement get_confirmations RPC
* return confirmations field in get_dashboard_overview_data RPC
* add wallet_state::get_latest_balance_height()
* add block_height to tuple returned from
   wallet_state::get_balance_history

Dashboard:
* display confirmations in overview screens
* change confirmations field from usize to u64
@Sword-Smith
Copy link
Member

Sword-Smith commented Sep 27, 2023

I'm afraid Alan and I gave you some wrong information. The description in #6 says " The number of blocks (=confirmations) since the most recent balance update". If the last balance update is a outgoing transaction (UTXOs being spent), then any of the wallet's monitored UTXOs could have been spent, not just the last one. The monitored UTXOs are ordered by the blockheight at which they were received, and this ordering does not change. The get_balance_height does actually return the relevant information that get_latest_balance_height needs, as the returned list from get_balance_height can be ordered by BlockHeight and then the last element in that ordered list should contain the latest update. Sorry that we didn't catch that when you showed you suggestion in #6.

I would suggest:

  1. Fix logic to return BlockHeight of latest balance update -- not latest incoming transaction as this PR's code does.
  2. Write a test demonstrating correct behavior, or find an existing test that sets up the relevant states and add a call to get_latest_balance_height in that.
  3. Verify that the block in question belongs to the canonical chain. You can use block_belongs_to_canonical_chain in archival_state.rs for this. If it does not, then find the next-most recent balance update etc. This point can also be addressed later, as you suggest, if you prefer that

u64 for blockheight should be more than enough. But why not just use the existing BlockHeight struct that is a wrapped BFieldElement which is a data structure that goes up to almost u64::MAX ($2^{64} - 2^{32} + 1$ to be precise.)

@Sword-Smith Sword-Smith mentioned this pull request Sep 27, 2023
17 tasks
@Sword-Smith Sword-Smith self-requested a review September 27, 2023 11:29
Copy link
Member

@Sword-Smith Sword-Smith left a comment

Choose a reason for hiding this comment

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

Please see previous comment

dan-da added a commit to dan-da/neptune-core that referenced this pull request Sep 28, 2023
Addresses Neptune-Crypto#56 (comment)

1. rewrite get_latest_balance_height() to find latest spent utxo
   anywhere in list of monitored_utxos.
2. change type of Confirmations field from u64 to BlockHeight
   in server and Dashboard.
@dan-da
Copy link
Collaborator Author

dan-da commented Sep 28, 2023

Fix logic to return BlockHeight of latest balance update -- not latest incoming transaction as this PR's code does.

Done. I think. Please review. ;-)

duh, whoops! nice catch on that. Now that you point it out, of course the list must be traversed to find latest spent utxo. I do wonder though if it could be possible to store the latest spent in the wallet to make this lookup o(1). Anyway I still tried to make the fn as efficient as possible given that it is called by the Dashboard overview. Maybe premature optimization, I dunno.

Write a test demonstrating correct behavior, or find an existing test that sets up the relevant states and add a call to get_latest_balance_height in that.

I didn't see such a test in wallet_state.rs. Perhaps I need to look elsewhere, or maybe you can point me to one. Anyway, I've run out of time tonight, so will look at that next coding session. We can keep the PR open.

Verify that the block in question belongs to the canonical chain

haven't looked into this yet. I will take a look and if it seems simple/clear and it works I will do it, else leave for a followup PR.

why not just use the existing BlockHeight struct

yes! That was my initial instinct, but I was a bit confused because the Dashboard was initially written to accept a u64 and BlockHeight::sub() returns i128. And I wasn't sure how pedantic we are being about BlockHeight vs say BlockCount. ie, a strict interpretation could say that a Height is only to be used in context of a count from block 0. Anyway, with your blessing I changed it to use BlockHeight everywhere in latest commit.

extra: I added an impl Display for Sign that just prints "-" if sign is negative. This helped me debug print a list of utxo's with amount and I figure it may be worth keeping, but happy to remove if you don't like it.

Addresses Neptune-Crypto#56 (comment)

1. rewrite get_latest_balance_height() to find latest spent utxo
   anywhere in list of monitored_utxos.
2. change type of Confirmations field from u64 to BlockHeight
   in server and Dashboard.
We can shoehorn a test of this function into an existing test by adding
a few asserts and verifying ensuring that also the light state is
updated correctly in the test.

This test can be used for test-driven development of (what I believe is)
a correct implementation of the method `get_latest_balance_height`.
Notice, though, that this test assumes that this method is a method on the
`GlobalState` struct and not, as previously, on wallet state.

Cf. Neptune-Crypto#56.
Copy link
Member

@Sword-Smith Sword-Smith left a comment

Choose a reason for hiding this comment

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

With respect to the testing, you can shoehorn tests of the get_latest_balance_height into the existing test wallet_state_prune_abandoned_mutxos. It's a bit intricate because the test previously didn't update all parts of the state as it would under real execution, so I modified the test to verify what I consider correct behavior for this new function. If you want to do test-driven development of this new function, feel free to cherry-pick this commit :)

Note that this modified test also checks for the correct behavior of property "3" in my above comment.

Verify that the block in question belongs to the canonical chain.

Also note that this modified test requires you to move the method get_latest_balance_height from wallet_state.rs to the file containing GlobalState.

2bc4858

Sorry about our confusion of types for BlockHeight, block count etc. The data structures are not set in stone, and neither is what we store in the database. So if you want to add anything there, feel free to suggest such changes. But maybe for now, you just want to get this functionality working and then we can revisit e.g. the wallet DB when you have a better overview?

Tip: Inspect the MonitoredUtxo data model and see what methods it has available. You can use existing methods to solve property "3".

src/models/blockchain/transaction/amount.rs Show resolved Hide resolved
src/bin/dashboard_src/overview_screen.rs Show resolved Hide resolved
src/rpc_server.rs Show resolved Hide resolved
src/models/state/wallet/wallet_state.rs Outdated Show resolved Hide resolved
@dan-da
Copy link
Collaborator Author

dan-da commented Sep 28, 2023

thx! super helpful comments. I'm away today, but will continue on it over the weekend.

Addresses Neptune-Crypto#6 and Neptune-Crypto#28

block_height.rs:
  * display BlockHeight as u64 to get rid of ugly leading zeros.

wallet_state.rs:
  * add block height to missing membership_proof warning message
  * remove get_balance_history()  (moved to wallet/mod.rs)

wallet/mod.rs:
  * log time taken in get_latest_balance_height().
  * rework get_latest_balance_height to find max(confirmed_in_block)
    ignoring any utxo not on current tip.
  * add get_balance_history() and rework to ignore any utxo not on
    current tip.  (issue Neptune-Crypto#28)

lib.rs:
  * add 2 fn to time any fn call:
      time_fn_call() and time_fn_call_async()

rpc_server.rs:
  * call ::get_balance_history() on global state, not wallet_state.
@dan-da
Copy link
Collaborator Author

dan-da commented Oct 6, 2023

I think this is ready for another review. See commit messages for summary of changes.

Copy link
Member

@Sword-Smith Sword-Smith left a comment

Choose a reason for hiding this comment

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

Looks very good.

src/models/state/mod.rs Outdated Show resolved Hide resolved
Addresses:
  Neptune-Crypto#56 (comment)

Changes:
 1. remove test environment detection in ::get_latest_balance_height()
 2. decorate wallet_state_prune_abandoned_mutxos() with #[traced_test]

The net effect is that:
 1. The decorated test case will display debug!() log output.
 2. Any other test cases will not.
@dan-da dan-da mentioned this pull request Oct 7, 2023
@Sword-Smith Sword-Smith merged commit 3fd5fc7 into Neptune-Crypto:master Oct 14, 2023
3 checks passed
Sword-Smith pushed a commit that referenced this pull request Oct 14, 2023
Addresses #56 (comment)

1. rewrite get_latest_balance_height() to find latest spent utxo
   anywhere in list of monitored_utxos.
2. change type of Confirmations field from u64 to BlockHeight
   in server and Dashboard.
Sword-Smith added a commit that referenced this pull request Oct 14, 2023
We can shoehorn a test of this function into an existing test by adding
a few asserts and verifying ensuring that also the light state is
updated correctly in the test.

This test can be used for test-driven development of (what I believe is)
a correct implementation of the method `get_latest_balance_height`.
Notice, though, that this test assumes that this method is a method on the
`GlobalState` struct and not, as previously, on wallet state.

Cf. #56.
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