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

feat(electrum)!: Update bdk_electrum to use merkle proofs #1489

Merged
merged 3 commits into from
Jul 9, 2024

Conversation

LagginTimes
Copy link
Contributor

@LagginTimes LagginTimes commented Jun 25, 2024

Fixes #980.

Description

This PR is the first step in reworking bdk_electrum to use merkle proofs. When we fetch a transaction, we now also obtain the merkle proof and block header for verification. We then insert an anchor only after validation that the transaction exists in a confirmed block. The loop logic that previously existed in full_scan to account for re-orgs has also been removed as part of this rework.

This is a breaking change because graph_updates now provide the full ConfirmationTimeHeightAnchor type. This removes the need for the ElectrumFullScanResult and ElectrumSyncResult structs that existed only to provide the option for converting the anchor type from ConfirmationHeightAnchor into ConfirmationTimeHeightAnchor.

Notes to the reviewers

Changelog notice

  • ConfirmationTimeHeightAnchor and ConfirmationHeightAnchor have been removed.
  • ConfirmationBlockTime has been introduced as a new anchor type.
  • bdk_electrum's full_scan and sync now return graph_updates with ConfirmationBlockTime.

Checklists

All Submissions:

  • I've signed all my commits
  • I followed the contribution guidelines
  • I ran cargo fmt and cargo clippy before committing

New Features:

  • I've added tests for the new feature
  • I've added docs for the new feature

@notmandatory
Copy link
Member

Since this doesn't touch the wallet APIs I moved it to the beta milestone.

@notmandatory notmandatory modified the milestones: 1.0.0-alpha, 1.0.0-beta Jun 25, 2024
@LagginTimes LagginTimes marked this pull request as draft June 26, 2024 16:18
@LagginTimes
Copy link
Contributor Author

LagginTimes commented Jun 26, 2024

Since this doesn't touch the wallet APIs I moved it to the beta milestone.

I'm okay with this!

@LagginTimes LagginTimes marked this pull request as ready for review June 26, 2024 16:57
Copy link
Contributor

@LLFourn LLFourn left a comment

Choose a reason for hiding this comment

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

Thanks this simplifies a lot. Left a few comments around the anchors/merkle proof bit.

crates/electrum/src/bdk_electrum_client.rs Outdated Show resolved Hide resolved
crates/electrum/src/bdk_electrum_client.rs Outdated Show resolved Hide resolved
.transaction_get_merkle(&txid, confirmation_height as usize)
{
let header = self.inner.block_header(merkle_res.block_height)?;
let is_confirmed_tx = electrum_client::utils::validate_merkle_proof(
Copy link
Contributor

Choose a reason for hiding this comment

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

Is it possible to use rust bitcoin's merkle proof validator for this? Why does electrum have its own validation logic?

Copy link
Contributor Author

@LagginTimes LagginTimes Jun 27, 2024

Choose a reason for hiding this comment

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

The validation logic being used right now was implemented as a utility in rust-electrum-client, which was needed for LDK's electrum integration:
bitcoindevkit/rust-electrum-client#122

Would using rust bitcoin be more advantageous in this scenario?

Copy link
Contributor

Choose a reason for hiding this comment

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

I have no idea. I am just curious why @tnull added that when there is presumably this algorithm is implemented in rust-bitcoin.

Copy link
Contributor

@tnull tnull Jun 28, 2024

Choose a reason for hiding this comment

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

IIRC, Electrum's get_merkle/GetMerkleRes doesn't provide sufficient/slightly different data, so that we couldn't construct bitcoin::MerkleBlock/ PartialMerkleTree to use upstream's validation logic (which of course would have been our preferred way).

@notmandatory
Copy link
Member

@LagginTimes oops, I didn't read all the comments before, looks like the wallet API will need to be updated so I've moved this back to the alpha milestone.

@LagginTimes LagginTimes force-pushed the electrum_spv branch 3 times, most recently from 180ee9f to feba152 Compare July 3, 2024 16:31
Copy link
Contributor

@ValuedMammal ValuedMammal left a comment

Choose a reason for hiding this comment

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

I did a first pass, mostly documentation nits. Sorry I was reviewing while you were pushing, so comments might be outdated

crates/chain/src/chain_data.rs Show resolved Hide resolved
crates/chain/tests/test_tx_graph.rs Outdated Show resolved Hide resolved
crates/electrum/src/bdk_electrum_client.rs Outdated Show resolved Hide resolved
crates/electrum/src/bdk_electrum_client.rs Outdated Show resolved Hide resolved
crates/electrum/src/bdk_electrum_client.rs Show resolved Hide resolved
crates/electrum/src/bdk_electrum_client.rs Outdated Show resolved Hide resolved
crates/electrum/tests/test_electrum.rs Show resolved Hide resolved
@LagginTimes LagginTimes force-pushed the electrum_spv branch 5 times, most recently from eb71012 to 756b8b1 Compare July 7, 2024 11:53
@notmandatory
Copy link
Member

@LagginTimes hey sorry I just merged some smaller PRs and now this one needs a rebase.

@LagginTimes LagginTimes force-pushed the electrum_spv branch 2 times, most recently from 44df255 to ac3a388 Compare July 8, 2024 15:23
Both `bdk_electrum` and `bdk_esplora` now report the exact block
that the transaction is in, which removes the need for having the
old `ConfirmationTimeHeightAnchor` and `ConfirmationHeightAnchor`.
This PR introduces a new, simpler anchor type that can be modified
to support additional data in the future.
@evanlinjin
Copy link
Member

I think we should not wait for complete tests before merging this PR. As long as the examples work fine it is good. This is for "beta" which does not need to be bug free. Also having this PR merged means we can work on the other anchor changes (which I need to create a ticket for).

@evanlinjin
Copy link
Member

Also, the anchor changes that I am suggesting is going to conflict with ConfirmationBlockTime.

Copy link
Contributor

@ValuedMammal ValuedMammal left a comment

Choose a reason for hiding this comment

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

ACK 1a62488

if unused_spk_count > stop_gap {
return Ok(scanned_spks);
unused_spk_count = unused_spk_count.saturating_add(1);
if unused_spk_count >= stop_gap {
Copy link
Contributor

Choose a reason for hiding this comment

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

💯

// Prune `new_blocks` to only include blocks that are actually new.
.filter(|(height, _)| Some(*height) > agreement_height)
.map(|(height, hash)| BlockId { height, hash })
.filter(|(height, _)| Some(*<&u32>::clone(height)) > agreement_height)
Copy link
Contributor

Choose a reason for hiding this comment

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

nit, feel free to ignore

Suggested change
.filter(|(height, _)| Some(*<&u32>::clone(height)) > agreement_height)
.filter(|(&height, _)| Some(height) > agreement_height)

@@ -19,6 +21,222 @@ fn get_balance(
Ok(balance)
}

#[test]
pub fn test_update_tx_graph_without_keychain() -> anyhow::Result<()> {
Copy link
Contributor

Choose a reason for hiding this comment

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

📌 If I recall, the name of this test is a relic from before the sync and full_scan concepts were developed. I might now call it sync_should_update_chain_and_tx_graph or similar, but not terribly important at the moment.

Copy link
Member

@notmandatory notmandatory left a comment

Choose a reason for hiding this comment

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

ACK 1a62488

Thanks for also adding the extra esplora tests for electrum!

@notmandatory notmandatory merged commit d99b3ef into bitcoindevkit:master Jul 9, 2024
12 checks passed
@notmandatory notmandatory mentioned this pull request Jul 20, 2024
30 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api A breaking API change
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

Update bdk_electrum to use electrum's merkle proof API
6 participants