Taproot tweaks generalization & KeyPair support#696
Taproot tweaks generalization & KeyPair support#696sanket1729 merged 5 commits intorust-bitcoin:masterfrom BP-WG:taproot/improvements
Conversation
|
Rebased and addressed nits by @tcharding |
|
Thanks |
|
@sanket1729 @Kixunil can you pls review this PR since it is quite important for completion of Taproot support - we need to tweak not only public keys, but also private ones, if we are going to even spent taproot key-path :) |
|
I wasn't able to do deep, high-focus reviews lately but I will try to find some time for it today/tomorrow. |
sanket1729
left a comment
There was a problem hiding this comment.
Before proceeding with the above review, we should form consensus on the one comment.
|
Sadly today wasn't great and I don't expect I'll be able to. If I get lucky it'll be tomorrow morning. Otherwise not sooner than Tuesday :( |
|
@Kixunil don't worry; this PR got blocked by the required upstream changes (see my discussion with @sanket1729 above). The rest of stuff has moved to #721 which should be simpler to review. |
d0a87be Add slice 'serialize' method for TweakedPublicKey (Dr. Maxim Orlovsky) 37352d1 Add Display and LowerHex to TweakedPublicKey (Dr. Maxim Orlovsky) Pull request description: Extraction of a portion from #696 which can be done without changes in `rust-secp256k1` ACKs for top commit: Kixunil: ACK d0a87be sanket1729: ACK d0a87be Tree-SHA512: d439ea1a4c4235bea9867e5d87514f928ad481f7a32403922654c33e101cfaba444eec8b61899f2aaaf1dcf5236bb618b9e14674736d3798effd56ca7097dc78
|
Will re-base and use the new secp library once the pending issue with it will be fixed in a new point release (I am talking about #360) |
|
Fixed, rebased, ready for review |
src/util/schnorr.rs
Outdated
There was a problem hiding this comment.
In 8b4c5b9d5d0c11b13a2f0cfbe26d20cd7cf24a86
Is it a good idea to have this? I would rather have users parse UnTweakedPubKey and call assume_dangerous.
There was a problem hiding this comment.
FromStr is required by serde impl. Also, this brings us back to the question raised in #737.
There was a problem hiding this comment.
I suggest don't impl (De)Serialize until we are not confident what the representation should be. We can always add impl later without breaking anything.
There was a problem hiding this comment.
If I am not wrong TweakedPublicKey should be used in PSBT, and removing serde there will be a regression
There was a problem hiding this comment.
I think it's okay to parse as TweakedPublicKey. I agree that there's a safety loophole here because we can't actually distinguish tweaked keys from untweaked keys, but I think it would be too unergonomic (and as @dr-orlovsky says, possibly incompatible with the PSBT API) to make the user do the assume_dangerous dance every time they parse a key.
Especially because untweeaked keys will not exactly be common in the wild .. so we are asking the user to think about an undetectable rare situation that they may not even understand.
There was a problem hiding this comment.
I don't see why we need TweakedPubkeys in PSBT APIs? I think partial sigs should be XOnlyPublicKey -> SchnorrSig.
There was a problem hiding this comment.
In the most common case, those XOnlyKeys would be tweaked, but I don't see any benefit for adding that type in psbt API. In my view, the only purpose of TweakedPublicKey is to guard users using the address API.
The keys in other places in the codebase might also be tweaked public keys, but we don't gain anything by having those being tweaked public keys (for example psbt API should only operate on XOnlyKeys). IMO, we should just remove this commit.
There was a problem hiding this comment.
We will still need this for rawtr processing
There was a problem hiding this comment.
We can parse XOnlyPubKey, and use the assume_dangerous_tweaked API? I think that is preciously how rawtr should work (if it is added in spec).
I feel strongly about this because we did put so much into Tweaking API, and added type safety with TweakedPublicKey. It would be a shame if we can break it this easily.
|
@sanket1729 addressed your requests except the first one, where I gave my explanation why |
src/blockdata/script.rs
Outdated
There was a problem hiding this comment.
In e49a6d98f5b1bdf7bafe130777f9d8ce094d4760:
I think this name should be reserved for a conversion from a TweakedKey to a script, which is the cheapest and (maybe) most common case. Then users with other key types can either obtain one by tweaking (or assume_dangerous :P).
We probably also should have a method like this, which takes an xonly key and a merkle root, but it should be called something longer, new_v1_p2tr_full or something.
There was a problem hiding this comment.
which is the cheapest and (maybe) most common case.
I think the most common case would be p2tr(UntweakedPublicKey). I don't want to go into API design debates :P , but I think this saves the user from importing a trait TapTweak and learning about the trait API in the most common case. For descriptors, tr() descriptor has the internal untweaked key as the argument and the uncommon rawtr() descriptor would have the tweaked key.
I would prefer, new_v1_p2tr(secp, untweaked_key, Option<MerkleRoot>) and new_v1_p2tr_raw(tweaked_key)
Although this also has the benefit that the users know that the tweaking is being done internally in the API and they are expected to use the tweaked keypairs for signing.
Not going to hold against this because we are offered the same functionality.
|
Done reviewing a2e9d2eae63919c9c5988708b932d7adbece0e60 |
sanket1729
left a comment
There was a problem hiding this comment.
I think that the previous API for p2tr that took in UntweakedPublicKey was better, but not going to stop this PR on it. As long as we are offered the same functionality, I don't care too much about it.
src/util/schnorr.rs
Outdated
There was a problem hiding this comment.
In the most common case, those XOnlyKeys would be tweaked, but I don't see any benefit for adding that type in psbt API. In my view, the only purpose of TweakedPublicKey is to guard users using the address API.
The keys in other places in the codebase might also be tweaked public keys, but we don't gain anything by having those being tweaked public keys (for example psbt API should only operate on XOnlyKeys). IMO, we should just remove this commit.
src/blockdata/script.rs
Outdated
There was a problem hiding this comment.
In affd45408adc858af9a9cbc03a61ca526a5d41ad
nit: Would prefer the name be new_v1_p2tr_script_spend
src/blockdata/script.rs
Outdated
There was a problem hiding this comment.
In 7dc5554dcbbb8f3275fa78db2a5e100fca9e3706
Why add a new API that is being deprecated? This should be removed.
There was a problem hiding this comment.
Sorry, my bad. Will remove when will be updating the PR according to the results of other discussions here.
|
I am fine with removing The only thing I am asking is to do that post-merge in a separate PR. I will open one to discuss that specific matter not to force re-reviwing this one once again. |
I did not do that. I don't know how that happened :( . If it is because of merging #591, I don't know why my review was not dismissed. |
|
@dr-orlovsky, looks there are conflicts here now :( . Can you please separate the first commit into another PR? I will ACK the remaining PR asap |
|
@sanket1729 done: #772 Will rebase this one w/o that commit after #762 merge |
nlanson
left a comment
There was a problem hiding this comment.
Left a small documentation suggestion.
src/util/schnorr.rs
Outdated
There was a problem hiding this comment.
Small doc suggestion:
Since both implementations of the TapTweak trait describes what operations are done to the inputted key, I think the second half of the description here should be removed and have just the first two sentences left as a short overview. It could make the three descriptions not conflict/duplicate and make it less confusing.
|
@dr-orlovsky , #762 merged |
|
@sanket1729 done |
Kixunil
left a comment
There was a problem hiding this comment.
Some style comments otherwise looks good. Not rejecting but would like to see some answer to the comments before I ack.
| /// Generates P2TR for key spending path for a known [`TweakedPublicKey`]. | ||
| /// | ||
| /// NB: Make sure that the used key is indeed tweaked (for instance, it comes from `rawtr` | ||
| /// descriptor content); otherwise please use [`Script::new_v1_p2tr`] method. |
There was a problem hiding this comment.
I think this comment here is not needed since tweaking is tracked in the type. Such comment is more appropriate for assume_tweaked.
There was a problem hiding this comment.
The commends are different between types, at least should be
There was a problem hiding this comment.
I mean you don't have a "make sure this is dereferencable" comment on &T documentation because the type already guarantees it and you have that comment on the "constructor".
|
|
||
| #[inline] | ||
| fn witness_version(&self) -> Option<WitnessVersion> { | ||
| WitnessVersion::from_opcode(self.0[0].into()).ok() |
There was a problem hiding this comment.
I think self.0.get(0)? would be better to pass the responsibility for checking to the caller.
| fn tap_tweak<C: Verification>(self, secp: &Secp256k1<C>, merkle_root: Option<TapBranchHash>) -> TweakedKeyPair { | ||
| let pubkey = XOnlyPublicKey::from_keypair(&self); | ||
| let tweak_value = TapTweakHash::from_key_and_tweak(pubkey, merkle_root).into_inner(); | ||
| let mut output_key = self.clone(); |
There was a problem hiding this comment.
This clone is confusing, why not use mut self or let mut output_key = self?
| } | ||
|
|
||
| fn dangerous_assume_tweaked(self) -> TweakedKeyPair { | ||
| TweakedKeyPair(self) |
There was a problem hiding this comment.
I think it'd be cleaner to implement these in terms of public API of TweakedPublicKey/TweakedKeyPair. Maybe even put them into separate modules to enforce this. Not very important but though.
There was a problem hiding this comment.
Not sure I understood
There was a problem hiding this comment.
I mean calling TweakedPublicKey::dangerous_assume_tweaked(self).
There was a problem hiding this comment.
Still not get it. We can't call TweakedPublicKey::dangerous_assume_tweaked(self) since we need key pair, not a public key
| #[inline] | ||
| pub fn into_inner(self) -> KeyPair { | ||
| self.0 | ||
| } |
There was a problem hiding this comment.
Should we also impl From<TweakedKeyPair> for KeyPair?
Also maybe into_raw is a clearer name?
There was a problem hiding this comment.
I think into_inner is fine. But yeah, having a From impl would be nice.
There was a problem hiding this comment.
Will do a From impl in the follow-up PR
|
@Kixunil @apoelstra I propose to merge this PR and address @Kixunil comments right away in a follow-up PR - otherwise I am afraid to have an endless cycle of re-ACKing due to a style/naming changes and API design play. |
|
Ok by me. |
62a27a5 Document that serde impl of LeafVersion uses u8 in consensus encoding (Dr Maxim Orlovsky) 73e6ce4 Re-export Witness at crate level. Closes #770 (Dr Maxim Orlovsky) 6364ebd Code style fixups to taproot key functions (Dr Maxim Orlovsky) 7514f2c Tweaked -> untweaked keys conversions (Dr Maxim Orlovsky) Pull request description: This addresses @Kixunil review comments in #696 post-merge Update: also closes nits from issues #764 and #770 ACKs for top commit: Kixunil: ACK 62a27a5 sanket1729: utACK 62a27a5 Tree-SHA512: 2f10393abab41d1c82f4733d83bf85bd82e268a2891c156eb89744c0fc444fdfec4d60deec2dda6fde2e5881989625c18b9c5ca21d360018edba69b6d2a85eae
ScriptTapTweaktrait to work with both public keys and key pairsUPD: PR is pending rust-bitcoin/rust-secp256k1#342