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

Bump to BDK alpha 10 #526

Merged
merged 3 commits into from
May 8, 2024

Conversation

thunderbiscuit
Copy link
Member

@thunderbiscuit thunderbiscuit commented May 3, 2024

This PR brings in the alpha 10 version of BDK.

New wallet method for fetching new addresses, the fantastic new full_scan and sync methods on the Esplora client, and no more generic on the Wallet type.

Changelog

Added
  - Update bdk_wallet to alpha 10 [#526]
  - Wallet.reveal_next_address() method [#526]
  - EsploraClient.sync() method [#526]
  - Wallet.start_full_scan() method [#526]
  - Wallet.start_sync_with_revealed_spks() method [#526]
  - Wallet.commit() [#526]

Removed
  - AddressIndex type [#526]
  - Wallet.try_get_internal_address() method [#526]

[#526]: https://github.com/bitcoindevkit/bdk-ffi/pull/526

Copy link

coderabbitai bot commented May 3, 2024

Walkthrough

The updates across the bdk-ffi library and its bindings in various languages focus on enhancing wallet functionalities, error handling, and test scenarios. Key changes include the introduction of FullScanRequest and SyncRequest to streamline wallet scanning processes, updating error handling mechanisms, and refining method signatures for better clarity and efficiency. These modifications aim to improve the developer experience, code organization, and robustness of the library.

Changes

Files Change Summary
bdk-ffi/src/bdk.udl, bdk-ffi/src/error.rs, bdk-ffi/src/lib.rs, bdk-ffi/src/types.rs, bdk-ffi/src/wallet.rs Modified method signatures, added FullScanRequest and SyncRequest, and improved error handling.
bdk-ffi/src/esplora.rs Refactored full_scan and sync methods, updated request types usage for enhanced functionality.
bdk-jvm/lib/src/test/kotlin/org/bitcoindevkit/*.kt, bdk-python/tests/*.py, bdk-swift/Tests/.../*.swift, bdk-android/lib/src/.../*.kt Adapted test code to utilize new FullScanRequest and method changes, enhancing clarity and separation of concerns in test scenarios.

Recent Review Details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits Files that changed from the base of the PR and between 72b5bfd and e9a7628.
Files selected for processing (10)
  • bdk-android/lib/src/androidTest/kotlin/org/bitcoindevkit/LiveTxBuilderTest.kt (2 hunks)
  • bdk-android/lib/src/androidTest/kotlin/org/bitcoindevkit/LiveWalletTest.kt (2 hunks)
  • bdk-ffi/src/bdk.udl (8 hunks)
  • bdk-ffi/src/wallet.rs (5 hunks)
  • bdk-jvm/lib/src/test/kotlin/org/bitcoindevkit/LiveTxBuilderTest.kt (2 hunks)
  • bdk-jvm/lib/src/test/kotlin/org/bitcoindevkit/LiveWalletTest.kt (2 hunks)
  • bdk-python/tests/test_live_tx_builder.py (2 hunks)
  • bdk-python/tests/test_live_wallet.py (3 hunks)
  • bdk-swift/Tests/BitcoinDevKitTests/LiveTxBuilderTests.swift (2 hunks)
  • bdk-swift/Tests/BitcoinDevKitTests/LiveWalletTests.swift (2 hunks)
Files skipped from review as they are similar to previous changes (10)
  • bdk-android/lib/src/androidTest/kotlin/org/bitcoindevkit/LiveTxBuilderTest.kt
  • bdk-android/lib/src/androidTest/kotlin/org/bitcoindevkit/LiveWalletTest.kt
  • bdk-ffi/src/bdk.udl
  • bdk-ffi/src/wallet.rs
  • bdk-jvm/lib/src/test/kotlin/org/bitcoindevkit/LiveTxBuilderTest.kt
  • bdk-jvm/lib/src/test/kotlin/org/bitcoindevkit/LiveWalletTest.kt
  • bdk-python/tests/test_live_tx_builder.py
  • bdk-python/tests/test_live_wallet.py
  • bdk-swift/Tests/BitcoinDevKitTests/LiveTxBuilderTests.swift
  • bdk-swift/Tests/BitcoinDevKitTests/LiveWalletTests.swift

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

Share
Tips

Chat

There are 3 ways to chat with CodeRabbit:

Note: Auto-reply has been disabled for this repository by the repository owner. The CodeRabbit bot will not respond to your replies unless it is explicitly tagged.

  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai generate interesting stats about this repository and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (invoked as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger a review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai help to get help.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Configration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@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.

Actionable comments posted: 4

use crate::types::AddressInfo;
use crate::types::Balance;
use crate::types::CanonicalTx;
use crate::types::ChainPosition;
use crate::types::FullScanRequest;
Copy link

Choose a reason for hiding this comment

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

Tip

Codebase Verification

The import of FullScanRequest in bdk-ffi/src/lib.rs does not appear to be used within the module. This could indicate that the import is unnecessary unless there are hidden usages not captured by the search. It is recommended to review the necessity of this import to maintain clean and efficient code.

  • File: bdk-ffi/src/lib.rs
    • Import statement on line 43 might be unnecessary as no usage was found in the module.
Analysis chain

Ensure that FullScanRequest is used within this module since it's being imported.

Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Verify usage of `FullScanRequest` in the current module.

# Test: Search for the usage of `FullScanRequest`. Expect: At least one occurrence.
rg --type rust $'FullScanRequest' src/lib.rs

Length of output: 94



Script:

#!/bin/bash
# Description: Check if the file src/lib.rs exists in the repository.

# Test: Search for the file src/lib.rs using fd to ensure the file path is correct.
fd 'lib.rs' --type file

Length of output: 42



Script:

#!/bin/bash
# Description: Verify usage of `FullScanRequest` in the correct module file.

# Test: Search for the usage of `FullScanRequest` in bdk-ffi/src/lib.rs. Expect: At least one occurrence.
rg --type rust $'FullScanRequest' bdk-ffi/src/lib.rs

Length of output: 86

Comment on lines 28 to 47
request: Arc<FullScanRequest>,
stop_gap: u64,
parallel_requests: u64,
) -> Result<Arc<Update>, EsploraError> {
let wallet = wallet.get_wallet();

let previous_tip = wallet.latest_checkpoint();
let keychain_spks = wallet.all_unbounded_spk_iters().into_iter().collect();

let (update_graph, last_active_indices) = self
.0
.full_scan(keychain_spks, stop_gap as usize, parallel_requests as usize)
.map_err(|e| EsploraError::from(*e))?;

let missing_heights = update_graph.missing_heights(wallet.local_chain());
let chain_update = self
.0
.update_local_chain(previous_tip, missing_heights)
.map_err(|e| EsploraError::from(*e))?;

let update = BdkUpdate {
last_active_indices,
graph: update_graph,
chain: Some(chain_update),
// using option and take is not ideal but the only way to take full ownership of the request
// TODO: if the option is None should throw error like "already consumed request" or "invalid request"
let request: BdkFullScanRequest<KeychainKind> = request.0.lock().unwrap().take().unwrap();

let result: BdkFullScanResult<KeychainKind> =
self.0
.full_scan(request, stop_gap as usize, parallel_requests as usize)?;

let update = bdk::wallet::Update {
last_active_indices: result.last_active_indices,
graph: result.graph_update,
chain: Some(result.chain_update),
Copy link

Choose a reason for hiding this comment

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

Refactor the full_scan method to avoid using unwrap() directly on Mutex locks and Option types, as this could lead to panics if the lock is poisoned or the option is None.

- let request: BdkFullScanRequest<KeychainKind> = request.0.lock().unwrap().take().unwrap();
+ let request_lock = request.0.lock().expect("Lock poisoned");
+ let request: BdkFullScanRequest<KeychainKind> = request_lock.take().expect("Request already consumed or invalid");

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
request: Arc<FullScanRequest>,
stop_gap: u64,
parallel_requests: u64,
) -> Result<Arc<Update>, EsploraError> {
let wallet = wallet.get_wallet();
let previous_tip = wallet.latest_checkpoint();
let keychain_spks = wallet.all_unbounded_spk_iters().into_iter().collect();
let (update_graph, last_active_indices) = self
.0
.full_scan(keychain_spks, stop_gap as usize, parallel_requests as usize)
.map_err(|e| EsploraError::from(*e))?;
let missing_heights = update_graph.missing_heights(wallet.local_chain());
let chain_update = self
.0
.update_local_chain(previous_tip, missing_heights)
.map_err(|e| EsploraError::from(*e))?;
let update = BdkUpdate {
last_active_indices,
graph: update_graph,
chain: Some(chain_update),
// using option and take is not ideal but the only way to take full ownership of the request
// TODO: if the option is None should throw error like "already consumed request" or "invalid request"
let request: BdkFullScanRequest<KeychainKind> = request.0.lock().unwrap().take().unwrap();
let result: BdkFullScanResult<KeychainKind> =
self.0
.full_scan(request, stop_gap as usize, parallel_requests as usize)?;
let update = bdk::wallet::Update {
last_active_indices: result.last_active_indices,
graph: result.graph_update,
chain: Some(result.chain_update),
request: Arc<FullScanRequest>,
stop_gap: u64,
parallel_requests: u64,
) -> Result<Arc<Update>, EsploraError> {
// using option and take is not ideal but the only way to take full ownership of the request
// TODO: if the option is None should throw error like "already consumed request" or "invalid request"
let request_lock = request.0.lock().expect("Lock poisoned");
let request: BdkFullScanRequest<KeychainKind> = request_lock.take().expect("Request already consumed or invalid");
let result: BdkFullScanResult<KeychainKind> =
self.0
.full_scan(request, stop_gap as usize, parallel_requests as usize)?;
let update = bdk::wallet::Update {
last_active_indices: result.last_active_indices,
graph: result.graph_update,
chain: Some(result.chain_update),

Comment on lines 54 to 75
// using option and take is not ideal but the only way to take full ownership of the request
// TODO: if the option is None should throw error like "already consumed request" or "invalid request"
let request: BdkSyncRequest = request.0.lock().unwrap().take().unwrap();

let result: BdkSyncResult = self.0.sync(request, parallel_requests as usize)?;

let update = bdk::wallet::Update {
last_active_indices: BTreeMap::default(),
graph: result.graph_update,
chain: Some(result.chain_update),
};

Ok(Arc::new(Update(update)))
}
Copy link

Choose a reason for hiding this comment

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

Similar to the full_scan method, refactor the sync method to handle potential errors more gracefully instead of using unwrap().

- let request: BdkSyncRequest = request.0.lock().unwrap().take().unwrap();
+ let request_lock = request.0.lock().expect("Lock poisoned");
+ let request: BdkSyncRequest = request_lock.take().expect("Request already consumed or invalid");

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
// using option and take is not ideal but the only way to take full ownership of the request
// TODO: if the option is None should throw error like "already consumed request" or "invalid request"
let request: BdkSyncRequest = request.0.lock().unwrap().take().unwrap();
let result: BdkSyncResult = self.0.sync(request, parallel_requests as usize)?;
let update = bdk::wallet::Update {
last_active_indices: BTreeMap::default(),
graph: result.graph_update,
chain: Some(result.chain_update),
};
Ok(Arc::new(Update(update)))
}
// using option and take is not ideal but the only way to take full ownership of the request
// TODO: if the option is None should throw error like "already consumed request" or "invalid request"
let request_lock = request.0.lock().expect("Lock poisoned");
let request: BdkSyncRequest = request_lock.take().expect("Request already consumed or invalid");
let result: BdkSyncResult = self.0.sync(request, parallel_requests as usize)?;
let update = bdk::wallet::Update {
last_active_indices: BTreeMap::default(),
graph: result.graph_update,
chain: Some(result.chain_update),
};
Ok(Arc::new(Update(update)))
}

Comment on lines 113 to 117
pub struct FullScanRequest(pub(crate) Mutex<Option<BdkFullScanRequest<KeychainKind>>>);
pub struct SyncRequest(pub(crate) Mutex<Option<BdkSyncRequest>>);
// pub struct FullScanRequest(pub(crate) Option<BdkFullScanRequest<KeychainKind>>);
// pub struct FullScanRequest(pub(crate) BdkFullScanRequest<KeychainKind>);
// pub struct FullScanRequest(pub(crate) Mutex<BdkFullScanRequest<KeychainKind>>);
Copy link

Choose a reason for hiding this comment

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

The use of Mutex around FullScanRequest and SyncRequest is appropriate for thread-safe access, but ensure that the commented-out alternatives are removed if they are no longer considered.

- // pub struct FullScanRequest(pub(crate) Option<BdkFullScanRequest<KeychainKind>>);
- // pub struct FullScanRequest(pub(crate) BdkFullScanRequest<KeychainKind>);
- // pub struct FullScanRequest(pub(crate) Mutex<BdkFullScanRequest<KeychainKind>>);

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
pub struct FullScanRequest(pub(crate) Mutex<Option<BdkFullScanRequest<KeychainKind>>>);
pub struct SyncRequest(pub(crate) Mutex<Option<BdkSyncRequest>>);
// pub struct FullScanRequest(pub(crate) Option<BdkFullScanRequest<KeychainKind>>);
// pub struct FullScanRequest(pub(crate) BdkFullScanRequest<KeychainKind>);
// pub struct FullScanRequest(pub(crate) Mutex<BdkFullScanRequest<KeychainKind>>);
pub struct FullScanRequest(pub(crate) Mutex<Option<BdkFullScanRequest<KeychainKind>>>);
pub struct SyncRequest(pub(crate) Mutex<Option<BdkSyncRequest>>);

@thunderbiscuit thunderbiscuit force-pushed the chore/alpha10 branch 2 times, most recently from ed80b19 to bd55330 Compare May 6, 2024 19:32
Copy link

@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.

Actionable comments posted: 0

Out of diff range and nitpick comments (1)
bdk-python/tests/test_offline_wallet.py (1)

Line range hint 16-16: Undefined name 'Wallet' used in the test method.

- wallet: Wallet = bdk.Wallet(
+ wallet: bdk.Wallet = bdk.Wallet(

@thunderbiscuit thunderbiscuit force-pushed the chore/alpha10 branch 2 times, most recently from 112d3eb to 11fe3f9 Compare May 6, 2024 22:51
@thunderbiscuit
Copy link
Member Author

@reez @notmandatory I ended up adding 2 new variants on the EsploraError enum, FullScanRequestAlreadyConsumed and SyncRequestAlreadyConsumed. I'm using them like so:

        let request: BdkSyncRequest = request
            .0
            .lock()
            .unwrap()
            .take()
            .ok_or(EsploraError::SyncRequestAlreadyConsumed)?;

Let me know what you think!

Copy link

@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.

Actionable comments posted: 0

Out of diff range and nitpick comments (1)
bdk-python/tests/test_offline_wallet.py (1)

Line range hint 16-16: Undefined name 'Wallet' used.

- wallet: Wallet = bdk.Wallet(
+ wallet: bdk.Wallet = bdk.Wallet(

Copy link

@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.

Actionable comments posted: 0

Out of diff range and nitpick comments (1)
bdk-python/tests/test_offline_wallet.py (1)

Line range hint 16-16: Undefined name 'Wallet' used; should be 'bdk.Wallet'.

-        wallet: Wallet = bdk.Wallet(
+        wallet: bdk.Wallet = bdk.Wallet(

@notmandatory
Copy link
Member

@reez @notmandatory I ended up adding 2 new variants on the EsploraError enum, FullScanRequestAlreadyConsumed and SyncRequestAlreadyConsumed.

⛏️ Only nit I have is to consolidate into one error with a slightly shorter name like RequestAlreadyUsed. But if you'd rather keep two errors and the longer names it's fine with me too.

@reez
Copy link
Collaborator

reez commented May 7, 2024

@reez @notmandatory I ended up adding 2 new variants on the EsploraError enum, FullScanRequestAlreadyConsumed and SyncRequestAlreadyConsumed.

⛏️ Only nit I have is to consolidate into one error with a slightly shorter name like RequestAlreadyUsed. But if you'd rather keep two errors and the longer names it's fine with me too.

I like this idea of consolidating 👍

Copy link
Collaborator

@reez reez left a comment

Choose a reason for hiding this comment

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

I think we need some changes in terms of adding/exposing commit in this PR, and then using apply_update and commit after we create a Request and Update.

Since this spans a few different files in a few different places I didn't add it as a comment to each spot, but for example after:

val fullScanRequest: FullScanRequest = wallet.startFullScan()
val update = esploraClient.fullScan(fullScanRequest, 10uL, 1uL)

... we need to then apply the update and then commit

Let me know if any of that is unclear, or any thoughts or comments on that.

Copy link

@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.

Actionable comments posted: 0

Out of diff range and nitpick comments (1)
bdk-python/tests/test_offline_wallet.py (1)

Line range hint 16-16: Undefined name 'Wallet' used; it should be 'bdk.Wallet'.

- wallet: Wallet = bdk.Wallet(
+ wallet: bdk.Wallet = bdk.Wallet(

.lock()
.unwrap()
.take()
.ok_or(EsploraError::RequestAlreadyConsumed)?;
Copy link
Member

Choose a reason for hiding this comment

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

❤️ good to add a new error for this.

Copy link
Collaborator

@reez reez left a comment

Choose a reason for hiding this comment

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

ACK e9a7628

I believe the related PR's can also be closed when this is merged:

🥳

@thunderbiscuit thunderbiscuit merged commit e9a7628 into bitcoindevkit:master May 8, 2024
25 checks passed
@thunderbiscuit thunderbiscuit deleted the chore/alpha10 branch May 8, 2024 21:14
This was referenced May 9, 2024
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.

3 participants