-
Notifications
You must be signed in to change notification settings - Fork 311
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
refactor(wallet)!: Add support for custom sorting and deprecate BIP69 #1487
refactor(wallet)!: Add support for custom sorting and deprecate BIP69 #1487
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for that detailed explanation. I think Arc
is in line with what we are going for. I wonder how maintainers would feel to just remove BIP69 entirely since this allows for users to add it back if they must.
} | ||
|
||
impl std::fmt::Debug for TxOrdering { | ||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
core::fmt
crates/wallet/src/wallet/mod.rs
Outdated
@@ -1555,7 +1555,7 @@ impl Wallet { | |||
}; | |||
|
|||
// sort input/outputs according to the chosen algorithm | |||
params.ordering.sort_tx_with_aux_rand(&mut tx, rng); | |||
params.ordering.clone().sort_tx_with_aux_rand(&mut tx, rng); | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Forgive my ignorance but why do we need clone here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the reasons above we need to use some kind of smart pointer inside TxOrdering
. Smart pointers manage data outside of their size
. On the other hand, and I'm quoting a Stack Overflow answer here:
The Copy trait represents values that can be safely duplicated via memcpy
The idea here is, if you have to manage data outside of your size
you cannot copy it with memcpy, so you cannot have smart pointers implementing Copy
.
Before my changes to TxOrdering
, because of the sort_tx_with_aux_rand
signature (sort_tx_with_aux_rand(self...
, notice self is owned by the function), and as params
is later used in create_tx
, Rust[1] performed a copy to avoid the partial move.
That's not possible anymore as TxOrdering
cannot implement Copy
with a smart pointer in its fields, so the new way to avoid the partial move is with clone()
.
[1] Here I'm guessing based on the suggestion from clippy.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great thanks for clarifying
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔧 You should be able to remove this .clone()
by changing the TxOrdering
functions to borrow &self
instead of taking ownership of self
.
impl TxOrdering {
pub fn sort_tx(&self, tx: &mut Transaction) ...
pub fn sort_tx_with_aux_rand(&self, tx: &mut Transaction, rng: &mut impl RngCore) ...
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@nymius what do you think about removing this .clone()
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great! I thought there were stronger reasons to take ownership, but If that's not the case, I prefer the borrow.
We discussed on the dev call today and the consensus is to remove bip69 support completely instead of just deprecating it. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have just a couple small comments, this one looks almost ready.
@@ -42,6 +42,9 @@ use alloc::{boxed::Box, rc::Rc, string::String, vec::Vec}; | |||
use core::cell::RefCell; | |||
use core::fmt; | |||
|
|||
use std::sync::Arc; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔧 Need to change the Arc
type to be compatible with no-std (and WASM).
use std::sync::Arc; | |
use alloc::sync::Arc; |
secret_digest_from_txout(tx_a).cmp(&secret_digest_from_txout(tx_b)) | ||
}); | ||
|
||
let custom_bip69_ordering_1 = TxOrdering::Custom { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
⛏️ A nit, I wouldn't call these variables custom_bip69_ordering_?
since bip69 is only for a specific deterministic lexicographical sort, and not this one with the hashing. Calling these custom_ordering_?
would be better.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Totally, probably leftovers of the Bip69Lexicographic
test I use as template.
@@ -763,16 +766,33 @@ impl fmt::Display for AddForeignUtxoError { | |||
#[cfg(feature = "std")] | |||
impl std::error::Error for AddForeignUtxoError {} | |||
|
|||
type TxSort<T> = dyn Fn(&T, &T) -> std::cmp::Ordering; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔧 Need to change the Ordering
type to be compatible with no-std (and WASM).
type TxSort<T> = dyn Fn(&T, &T) -> std::cmp::Ordering; | |
type TxSort<T> = dyn Fn(&T, &T) -> core::cmp::Ordering; |
As you are the best to judge if your requests have been fulfilled, @notmandatory @rustaceanrob, please, consider resolving conversations as we move this forward. I plan to squash commits once we agree the work here is final. |
When you're ready for a final review be sure to rebase and squash the commits into one or two. |
9d93a4e
to
1348dbe
Compare
Rebased and updated. There is something extra you would like to see in the docs? |
1348dbe
to
3e1fc40
Compare
LGTM |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK 3e1fc40
@nymius I you need to sign your commits before I can merge this PR. |
The deterministic sorting of transaction inputs and outputs proposed in BIP 69 doesn't improve the privacy of transactions as originally intended. In the search of not spreading bad practices but still provide flexibility for possible use cases depending on particular order of the inputs/outpus of a transaction, a new TxOrdering variant has been added to allow the implementation of these orders through the definition of comparison functions. Signed-off-by: Steve Myers <steve@notmandatory.org>
BIP 69 proposed a deterministic way to sort transaction inputs and outputs with the idea of enhancing privacy. It was later discovered there was no such enhancement but rather a decrement in privacy due to this sorting. To avoid the promotion of bad practices, the TxOrdering::Bip69Lexicographic variant which implemented this BIP for BDK is removed with this change. Notice that you can still produce a BIP 69 compliant transaction defining order functions for TxOrdering::Custom. Signed-off-by: Steve Myers <steve@notmandatory.org>
3e1fc40
to
3bee563
Compare
I signed the commits for @nymius . |
Description
Resolves #534.
Resumes from the work in #556.
Add custom sorting function for inputs and outputs through
TxOrdering::Custom
and deprecatesTxOrdering::Bip69Lexicographic
.Notes to the reviewers
I tried consider all discussions in #534 while implementing some changes to the original PR. I created a summary of the considerations I had while implementing this:
Why use smart pointers?
The size of enums and structs should be known at compilation time. A struct whose fields implements some kind of trait cannot be specified without using a smart pointer because the size of the implementations of the trait cannot be known beforehand.
Why
Arc
orRc
instead ofBox
?The majority of the useful smart pointers that I know (
Arc
,Box
,Rc
) for this case implementDrop
which rules out the implementation ofCopy
, making harder to manipulate a simple enum likeTxOrdering
.Clone
can be used instead, implemented byArc
andRc
, but not implemented byBox
.Why
Arc
instead ofRc
?Multi threading I guess.
Why using a type alias like
TxVecSort
?cargo-clippy was accusing a too complex type if using the whole type inlined in the struct inside the enum.
Why
Fn
and notFnMut
?FnMut
is not allowed insideArc
. I think this is due to the&mut self
ocupies the first parameter of thecall
method when desugared (https://rustyyato.github.io/rust/syntactic/sugar/2019/01/17/Closures-Magic-Functions.html), which doesn't respectsArc
limitation of not having mutable references to data stored insideArc
:Quoting the docs:
FnOnce
>FnMut
>Fn
, where>
stands for "is supertrait of", so,Fn
can be used everywhereFnMut
is expected.Why not
&'a dyn FnMut
?It needs to include a lifetime parameter in
TxOrdering
, which will force the addition of a lifetime parameter inTxParams
, which will require the addition of a lifetime parameter in a lot of places more. Which one is preferable?Changelog notice
TxOrdering
variant:TxOrdering::Custom
. A structure that stores the ordering functions to sort the inputs and outputs of a transaction.TxOrdering::Bip69Lexicographic
.Checklists
All Submissions:
cargo fmt
andcargo clippy
before committingNew Features: