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

Is there a way of having aggregate signature in first Tr descriptor parameter? #319

Open
dr-orlovsky opened this issue Mar 22, 2022 · 14 comments

Comments

@dr-orlovsky
Copy link
Contributor

Today Tr descriptor

  1. Fails to parse the whole descriptor if the first parameter contains a method (for instance, tr(musig(a,b)) will treat b as a second parameter to the descriptor itself, i.e. script).
  2. this providing no way for key aggregation as a part of the first parameter.
@sanket1729
Copy link
Member

Currently, there is no way to do this. However, I would not mind supporting a specific fragment musig(or even nested musig) in this case. PRs welcome. That would be for major release 8.0 though. I don't think we want to add it for 7.0.0 now.

If really want to use it today custom musig supporting satisfiers, you can use a different syntax today, maybe tr(musig<a,b,c>) that does interfere with the parsing as implemented.

@dr-orlovsky
Copy link
Contributor Author

dr-orlovsky commented Mar 22, 2022

It will really be nice to have it in this release since w/o it taproot is not working in practice for any multisig or script-based wallet. Why? Well, because in multisig or script-based taproot wallet you have two options for having internal_key, none of which is possible with the current 0.7.0:

  • using aggregate of all keys - and this is not possible without musig fragment;
  • using nonce key, deteministically unspendable, and it is not possible to combine custom plain keys with other types of keys used in normal wallet descriptor (xpub-based) - and the one can't have deterministically unspendable xpub.

@sanket1729
Copy link
Member

You are right, for full compatibility, we need musig. Currently we you can use taproot descriptors if

  • If there is a single internal key. Use that as an internal key.
  • Sample unspendable key according to the recommendation in the BIP. I think this is possible to implement for the user. But I would mind supporting this feature here or in rust-secp because it will be for many use-cases. Your options are either
    • Use a fixed hard-coded internal key as per BIP341 recommendation. This is privacy loss as everyone looking at the chain can link payments .
    • Use fresh random keys every time. But this will result in a blowup in the number of descriptors.
    • Wait until there is some spec for the unspendable fragment. This is still an ongoing discussion and might take some time to settle in :(.

Plus, musig2 descriptor spec is still not settled. So, supporting the KeyAgg here in rust-miniscript would be premature. I

am sorry that this is the state and If the above options are not acceptable to you, you would have to wait till the spec somewhat settles down. Musig2 BIP32 tweaking signing spec was merged yesterday to libsecp-zkp. It will take some time for rust-miniscript to have access to it. Even then, we will need an upstream BIP for musig2 descriptors before we merge it here

@dr-orlovsky
Copy link
Contributor Author

dr-orlovsky commented Mar 23, 2022

Use a fixed hard-coded internal key as per BIP341 recommendation. This is privacy loss as everyone looking at the chain can link payments .

With the current miniscript this can't be done: descriptors need xpubs, which can't be combined with the hard-coded key in the first parameter of tr descriptor. This can be achieved only if we introduce a dedicated new fragment like hardcoded_pk, always taking not a Pk: MiniscriptKey but just a XOnlyPublicKey - and let tr descriptor to host it in the first parameter.

Use fresh random keys every time. But this will result in a blowup in the number of descriptors.

Again, not possible for the reason above

Wait until there is some spec for the unspendable fragment. This is still an ongoing discussion and might take some time to settle in :(.

So this is also not possible with current miniscript.

I.e. we left with no options of real world use of scripts with miniscript 7.0.0 taproot descriptors.

@dr-orlovsky
Copy link
Contributor Author

Plus, musig2 descriptor spec is still not settled. So, supporting the KeyAgg here in rust-miniscript would be premature.

We may have a partial support for musig: implement it for scriptPubkey PSBT construction, but not for signing. MuSig2 spec is for signing procedure and musig setup, but it is not required for computing the aggregated pubkey from a set of derived xpubs. We can even name this fragment, acceptable only as a first parameter to tr descriptor differently, like nonsigning_keyagg or something.

@sanket1729
Copy link
Member

sanket1729 commented Mar 23, 2022

With the current miniscript this can't be done: descriptors need xpubs, which can't be combined with the hard-coded key in the first parameter of tr descriptor. This can be achieved only if we introduce a dedicated new fragment like hardcoded_pk, always taking not a Pk: MiniscriptKey but just a XOnlyPublicKey - and let tr descriptor to host it in the first parameter.

This is possible, are you using Pk = DescriptorPublicKey? This is the only type that you should be using. See an example below: tr(xpk,multi_a(1,xpub,xpub)) that I tested locally.

    let _addr_tr = Descriptor::<DescriptorPublicKey>::from_str(   "tr(e4a3d72a31498dc4bec565b14e088c3463fc5e3d886e7c1cee4156caacb098d0,multi_a(1,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/0/0/*,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/1/0/*))"
        )
        .unwrap()
        .derived_descriptor(&secp_ctx, 5)
        .unwrap()
        .address(bitcoin::Network::Bitcoin).unwrap();

@sanket1729
Copy link
Member

MuSig2 spec is for signing procedure and musig setup, but it is not required for computing the aggregated pubkey from a set of derived xpubs.

I am working on it. Maybe, I can add some experimental support here soonish, but it won't be 7.0.0 for sure. You can track the support here: BlockstreamResearch/rust-secp256k1-zkp#48. It is still in draft, maybe by the end of this week, the PR will be ready for review. Then after some after review and a release of rust-secp-zkp, I can work on support here.

@sanket1729
Copy link
Member

sanket1729 commented Mar 23, 2022

Another thing that you can do is use xpub(H||hex)/NUM as the internal key where H is specified in BIP341. All keys derived from H must be unspendable. However, note that at some point in the future we will have explicit unspend(Hex,NUM) (note NUM can also be *) fragment in descriptor spec that might to this/or something else.

You will have to update your code to gain the benefit that looking at the descriptor parties can infer it is unspendable, but it requires ad-hoc logic if you are the xpub(H||hex)/NUM solution.

@dr-orlovsky
Copy link
Contributor Author

dr-orlovsky commented Mar 23, 2022

No, I am not using DescriptorPubkey, since I need much more advanced functionality (proofs that I have a xpub at last hardened derivation path point; multiple wildcard elements, complex index ranges and etc). Thus I am using my own BIP-32 related type system and miniscript xpub type defined in https://docs.rs/bitcoin_hd/0.6.0-rc.1/bitcoin_hd/index.html and https://docs.rs/bitcoin_hd/0.6.0-rc.1/bitcoin_hd/account/struct.TrackingAccount.html.

But otherwise I am getting your idea, it looks nice! Basically I can do an enum type on top of my type + normal public key or any other form of provably unspendable key. Got it, this should work, will try it out!

@sanket1729
Copy link
Member

Keeping this open for Musig2 discussions.

@cryptoquick
Copy link

Where are the MuSig2 spec discussions taking place? I'm kinda curious, since I'd love to see MuSig2 support in miniscript. That could open up a ton of possibilities, including support in BDK, MuSig2 channels in LDK, and the MyCitadel and BitMask wallets.

@apoelstra
Copy link
Member

@cryptoquick I'd recommend you check out bitcoin/bips#1372 -- or you can find people on IRC #secp256k1 on Libera if you have small things to discuss.

@cryptoquick
Copy link

Thanks for the quick response, @apoelstra! I'll check it out.

@sanket1729
Copy link
Member

@cryptoquick, there is some discussion at https://gist.github.com/sipa/06c5c844df155d4e5044c2c8cac9c05e.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants