Open evd0kim opened 1 year ago
This is an interesting API question. I think the most common signing workflow we (the rust-minisrcipt devs) encounter involves iterating over public keys, then requesting a HWW produce a signature with those keys.
To do this directly with private keys we would need an API that could produce derived secret keys .. presumably a variant of the Satisfier
API that could look up signatures based on secret keys rather than on public ones? We deliberately designed the API to discourage people "just using DescriptorSecretKey
as the Pk
type and then using Satisfier
" ... that might work, but we tried not to make it easy :P.
There is also an open question about how much sighashing support or PSBT support belongs in this libarry.
I'd be +1 on making a KeyMap
a Satisifer. You'd need to couple it with the sighash cache of the transaction and the txout it's spending I think. Another problem mention in #481 is that we'd need the merkle root passed into the satisfier for tapkey spends.
You'd need to couple it with the sighash cache of the transaction and the txout
Maybe we should have a structure which paired these, and added a with_
method to KeyMap
, so you could do something like descriptor.satisfy(keymap.with(&sighash_cache))
. This would be more discoverable than implementing Satisfier on a tuple or something, though still not as discoverable as I'd like ... I wish that we could customize the Rust error messages so that attempts to satisfy with a bare keymap would advise this.
Another problem mention in #481 is that we'd need the merkle root passed into the satisfier for tapkey spends
Ah right! We should make a separate issue about this because I keep forgetting it (and even when I'm reminded, my first impulse is to say "but we provide the leafhash!" ... but you're talking about keyspends, not scriptspends).
Thanks for comments.
I am struggle to keep up with you. I have no idea about Satisfier
yet. So I will try to learn more about it.
Now I understand that KeyMap
doesn't really fit my purpose however, I should say that it is not created when there is no private keys provided in the descriptor. So I can't understand what you mean when saying about iterating over public keys and asking for HWW to sign something externally. On the other hand I could probably cast somehow DescriptorSecretKey
into ExtendedPrivKey
and work with it similarly to my PSBT code without KeyMap
.
Now I understand that KeyMap doesn't really fit my purpose
No, but maybe it should :)
So I can't understand what you mean when saying about iterating over public keys and asking for HWW to sign something externally.
What I'm saying is that I never use KeyMap
at all because I never have secret keys in software. I identify keys by their public key, and when I want to sign I just give the public key to a hardware wallet and let it figure out what to do with it.
On the other hand I could probably cast somehow DescriptorSecretKey into ExtendedPrivKey
Yes, the DescriptorSecretKey
structure is completely public so you can destructure it and extract the key out directly. But we ought to provide a convenience method for this at least.
Okay. Thank you.
I was able to use KeyMap
after thinking clearly about the structures and not just poking into them nearly randomly.
DescriptorSecretKey::XPrv(prv) => {
let extended = prv.xkey;
let private = extended.derive_priv(&self.secp, &prv.derivation_path).unwrap();
let public = private.private_key.public_key(&self.secp);
let sig = self.secp.sign_ecdsa(&msg, &private.private_key);
assert!(self.secp.verify_ecdsa(&msg, &sig, &public).is_ok());
psbt.inputs[0].partial_sigs.insert(
public.to_public_key(),
bitcoin::EcdsaSig {
sig,
hash_ty: hash_ty,
},
);
},
I never have secret keys in software.
I understood it. This is my next step to try to export extended keys from various of hardware wallets and apps and sign transactions using descriptors with public keys. It was quite handy to me to design in-software signing because I am going to prototype something not just for signing transactions exclusively.
From an outsider point of view
KeyMap
looks like interesting way to handle keys after importing descriptor.Let's say for example we have such descriptor where we supply
tprv
which will be imported intoKeyMap
We could use
KeyMap
later in similar loopThe problem though is that
public
andprivate
areDescriptorPublicKey
andDescriptorSecretKey
objects do not really contain convenient API even for extracting keys and using them in signing. I have a code example and honestly I am not entirely sure I didn't something wrong. Besides It doesn't actually work and I think the problem is that there is just wrong key in&prv.xkey.private_key
.