-
Notifications
You must be signed in to change notification settings - Fork 385
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 message signer & message signature verifier #601
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.
Overall this is a good start but it feels a bit disconnected from everything else in BDK.
There are a few ways to "connect" this to the Wallet, the easiest one is probably to iterate over the signers of a wallet and taking their key (if any) with descriptor_secret_key()
.
You could have an API exposed on the wallet that takes a message and a derivation index, and internally iterates on the signers, derives the keys to the right index and then signs the message.
You should also figure out a good way to handle this when you have multiple keys in your descriptor. You could return a list of signatures, or a map with key -> sig entries, I don't know.. There are a few ways to do it and I haven't thought about them in detail yet, I'd like to see your proposal since you've given this more thoughts than myself!
src/keys/msgsig.rs
Outdated
use bitcoin::{Address, Network, PrivateKey, PublicKey}; | ||
|
||
/// Trait for message signers | ||
pub trait MessageSigner<S> { |
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.
Are there any other signature types you'd plan to support on top of RecoverableSignature
? I don't really understand why you need the generic here and on the verifier
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.
Yes, exactly. The idea behind this is to add other signature types.
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.
As far as I am aware there are no plans to switch to schnorr signatures for Bitcoin signed messages, so I don't think there's really too much room for upgrades here.
I was asking if you had at least one specific use case in memory (like a BIP which uses other sig algorithms) but if you don't have any examples I would just say it's better to drop the generic and stick to the classic ecdsa algorithm.
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.
No, I had no other use cases in mind than multi-sig and possibly schonrr. But since the latter is not planned and multi-sig can be done with a map as suggested by you, I agree it's better to just add a sign method to the wallet.
src/keys/msgsig.rs
Outdated
|
||
/// A message signature verifier using ECDSA | ||
pub struct EcdsaMessageSignatureVerifier { | ||
secp: Secp256k1<All>, |
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 would just take a reference here to avoid cloning the context. If you don't want to add a lifetime to the struct you could just change the api of verify()
to take a secp argument
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 mean, change the member declaration to be a reference and then take one in from_pub
and from_address
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 agree, secp
should at least be changed to a reference. However, regarding a secp
argument at verify()
, this would force BDK to have new methods on the wallet struct for every signing / verification algorithm.
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 don't understand what do you mean here, can you elaborate a bit more?
My interpretation is thatverify()
doesn't have to be a method on the wallet, because you don't need anything from the wallet to verify a message (while for signing you need the private keys)
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 intially wanted to have similar interfaces for signing and verification. Therfore, I thought if signing is moved to the wallet, so should also verification. Combined with my assumption of having schnorr for message signatures at some point, BDK would end up with multiple verify
methods.
However, this is not the case since schnorr is aparently not planned. Moreover, you are right that verify
does not have to be on the wallet - except you want verification to happen with the pubkey of a different pk(...)
wallet. But this feels a little odd.
Therefore, I suggest that we change the PR to have
- a method on the wallet for message signing which uses all private keys of the wallet
- message signature verification which is decoupled from the wallet
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.
secp
as a reference: 707f6c3
src/keys/msgsig.rs
Outdated
fn sign(&self, message: &str) -> RecoverableSignature { | ||
let msg_hash = signed_msg_hash(message); | ||
self.secp.sign_recoverable( | ||
&Message::from_slice(&msg_hash.into_inner()[..]).unwrap(), |
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.
Either replace the unwrap with an expect (for reasonably unlikey errors) or change this function to return a 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.
fb772ed ✔️
src/keys/msgsig.rs
Outdated
|
||
/// A message signer using ECDSA | ||
pub struct EcdsaMessageSigner { | ||
secp: Secp256k1<All>, |
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.
Same thing about secp as for the verifier
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.
secp
as a reference: 707f6c3
Thanks for the review. The additions in this PR are intentionally disconnected from the rest of BDK for single responsibility reasons but also because I was not sure if / how you want it to be connected - especially regarding multi-sig wallets and other signing algorithms. So I chose to add the traits I intended to join your dev call yesterday to discuss this. However, I didn’t manage to attend due to a change in my schedule… |
@LLFourn I was not aware of BIP-322 and therefore did not implement it. However, it looks very much like what I want to achieve. Apparently, BIP-322 is being added to rust-miniscript (rust-bitcoin/rust-miniscript#444). Shall we wait until this is done and then use the miniscript implementation? |
@q-src TBH miniscript doesn't sound like the right place either. It might make sense to have a BIP322 implementation in |
Description
Ths PR adds the possibility to
using ECDSA.
Checklists
All Submissions:
cargo fmt
andcargo clippy
before committingNew Features:
CHANGELOG.md