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

Taproot support #985

Merged
merged 17 commits into from
Mar 14, 2024
Merged

Taproot support #985

merged 17 commits into from
Mar 14, 2024

Conversation

darosior
Copy link
Member

This introduces Taproot support in the Liana daemon / core library.

We start by introducing support for tr() descriptors alongside wsh() descriptors in the Taproot modules. For Taproot-Liana descriptors whose primary spending path isn't a single key, we deterministically derive an unspendable internal key as per https://delvingbitcoin.org/t/unspendable-keys-in-descriptors/304/21. This is to allow signing devices to not display the internal key as a spendable key when verifying a descriptor. Currently signing device vendors signaled willingness to implement this scheme.

We then adapt the PSBT management logic to use Taproot fields when necessary and upgrade the hot signer to provide Schnorr signatures depending on the PSBT information.

Finally, the functional tests are adapted to be able to run the whole test suite under either P2WSH or Taproot. This is done in a somewhat hacky way as i bailed out of re-implementing a Taproot PSBT signer and finalizer in Python after implementing TapMiniscript support in upstream python-bip380. Instead we use a small Rust program to sign PSBTs for now and we skip a test which explicitly requires an external finalizer.

@darosior
Copy link
Member Author

darosior commented Feb 27, 2024

I still need to:

I should open a few issues for needed followups before i forget about it.

@darosior
Copy link
Member Author

Rebased on master now the PRs this depended on were merged.

@edouardparis edouardparis mentioned this pull request Feb 27, 2024
@darosior darosior force-pushed the 2401_taproot branch 3 times, most recently from 35a8003 to 98a81b4 Compare February 27, 2024 15:26
@darosior
Copy link
Member Author

Alright, i updated python-bip380 and the CI to run the Taproot tests. Looks like one of them is a bit flaky, i'll have a look later. In the meantime it's ready for a first round of review!

@darosior darosior marked this pull request as ready for review February 27, 2024 15:46
@darosior
Copy link
Member Author

So it wasn't that one was flaky, it's just the migration test that we need to disable under Taproot. Obviously older versions can't start with a Taproot descriptor.

@darosior
Copy link
Member Author

darosior commented Mar 11, 2024

Rebased on master. I adapted the tests for the selection of unconfirmed coins from #873 in a separate commit, as it was less mechanic / obvious than the other tests.

What i still need to investigate:

  • test_coin_selection is very slightly flaky. The assertion of the vsize of the ancestor might sometimes fail. This is unrelated to this PR, but can potentially make CI fail here (tracked here: Flaky test_coin_selection #1000);
  • it seems the performance of createspend has been greatly reduced. We might see some timeout on functional tests making heavy use of this call. I need to profile it i suppose. But my hunch is rust-miniscript's way of populating a PSBT input is inefficient.

Copy link
Collaborator

@jp1ac4 jp1ac4 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I went through most of the changes and found a couple of small typos in comments. Otherwise, the code made sense according to my limited understanding of Taproot :)

tests/tools/taproot_signer/src/main.rs Outdated Show resolved Hide resolved
src/descriptors/mod.rs Outdated Show resolved Hide resolved
Copy link
Member Author

@darosior darosior left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just did a mechanical review. In addition to checking the correctness of what's here we need to think about what's missing.

src/signer.rs Show resolved Hide resolved
src/descriptors/mod.rs Outdated Show resolved Hide resolved
src/descriptors/mod.rs Outdated Show resolved Hide resolved
// avoid having to duplicate the cumbersome logic here. Could use translate_pk() instead in the
// future.
fn definite_desc(&self) -> descriptor::Descriptor<descriptor::DefiniteDescriptorKey> {
descriptor::Descriptor::<_>::from_str(&self.0.to_string()).expect("Must roundtrip")
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤮

@darosior darosior mentioned this pull request Mar 13, 2024
darosior added a commit that referenced this pull request Mar 13, 2024
3017b88 fuzz: fuzzing integrations, fuzz the descriptors module (Antoine Poinsot)
f7924fb descriptors: lifting *can* fail (Antoine Poinsot)

Pull request description:

  This introduces fuzzing into our project with two fuzz targets exercising our descriptor parsing logic. See the commit messages for details. This found a crash (first commit).

  This was motivated by testing the work on Taproot (#985).

ACKs for top commit:
  darosior:
    ACK 3017b88 - it's not interfering with anything in the repo, been running these for half a day with no crash.

Tree-SHA512: 25c1b64a86585fc5f676c3526e2dae945b74c6b0cb4ce2d9db33dc48aa85aaa11a07b279838703d62c9ca00cf39cc34577ca19c0a8f9aaf5327266eb7be6dce0
tests/test_spend.py Outdated Show resolved Hide resolved
tests/test_spend.py Outdated Show resolved Hide resolved
It'll make it easier to switch to update Taproot info.
@darosior darosior force-pushed the 2401_taproot branch 2 times, most recently from 7086124 to 1639ddf Compare March 13, 2024 16:03
@darosior
Copy link
Member Author

Rebased on master. I found another crash using the fuzz tests which is now fixed. Unfortunately the compiler is insanely slow (like more than 1000x slower) for Taproot which makes the descriptors target useless.

src/descriptors/mod.rs Outdated Show resolved Hide resolved
src/descriptors/analysis.rs Outdated Show resolved Hide resolved
It will be useful when we introduce Taproot support in the next commit.
We introduce support for tr() descriptors alongside wsh() descriptors in
creating (compiling from policy, parsing from string) and working with
(analyizing its policy, getting spend information) a descriptor.

When compiling a Taproot descriptor, if no key from the policy could be
used as single internal key we deterministically generate an unspendable
internal key as per
https://delvingbitcoin.org/t/unspendable-keys-in-descriptors/304/21.
Similarly when lifting the policy of a Taproot descriptor, if the
internal key matches the deterministic unspendable key for this
descriptor we discard it from the analysis.

To fill information about an output for signers, we re-use
rust-miniscript PSBT input updated instead of re-inventing the wheel. It
does necessitate a hack however to use a type they would accept.

We don't change the "max size of a spending input" for now, even though
it means we would significantly overpay fees for descriptors with a
spendable internal key.
It's more robust and bitcoind serializes `wsh()` descriptors using `'`
as hardened marker and `tr()` descriptors using `h`..
We introduce Taproot support in the test framework through a global
toggle. A few modifications are made to some tests to adapt them under
Taproot (notably the hardcoded fees / amounts).

This is based on my introduction of a quick and dirty support for
TapMiniscript in my python-bip380 library:
darosior/python-bip380#23. In addition to this i
didn't want to implement a signer in the Python test suite so here we
introduce a simple Rust program based on our "hot signer" which will
sign a PSBT with an xpriv provided through its stdin and output the
signed PSBT on its stdout. Eventually it would be nicer to have a Python
signer instead of having to call a program.

The whole test suite should pass under both Taproot and P2WSH. Only a
single test is skipped for now under Taproot since it needs a finalizer
in the test suite.

I also caught a bug in the RBF tests which i fixed in place.
They don't add much value and cause flakiness because the size might sometimes be lower than that due to low-R signature grinding.

Fixes wizardsardine#1000.
@darosior
Copy link
Member Author

ACK 4bb2372 -- this underwent multiple rounds of review, Edouard tested it in his follow-up PR to the GUI and i wrote a couple fuzz targets exercising part of the logic introduced here

@darosior darosior merged commit b22f22f into wizardsardine:master Mar 14, 2024
21 checks passed
@darosior darosior deleted the 2401_taproot branch March 14, 2024 10:21
darosior added a commit that referenced this pull request Mar 20, 2024
52c3613 descriptors: adapt 'change_indexes()' to Taproot (Antoine Poinsot)
0c65d20 descriptors: encapsulate change_indexes unit test (Antoine Poinsot)

Pull request description:

  I remember thinking about this helper when working on #985, but for some reason i didn't address it there. Here it is.

ACKs for top commit:
  edouardparis:
    utACK 52c3613

Tree-SHA512: 276fdb4087ba0ec097142d7ff7a4c8762814d6423b9f5535c8951d6ef628c164e4a5191aeb9aa48eaad9afd1361416157774341ef7873fee284d039f9dcf5b3e
darosior added a commit that referenced this pull request Mar 20, 2024
b7f35c0 Add installer dropdown for advanced settings (edouardparis)
59a4b18 fix: merge tap_script_sigs from signed psbt (edouardparis)
02a52b9 add ledger version support for tapminiscript (edouardparis)
2debb32 Add taproot support to installer descriptor editor step (edouardparis)
8bc0cac gui: async-hwi:0.0.16 (edouardparis)
4a4c78d bump liana:master (edouardparis)

Pull request description:

  based on #985

ACKs for top commit:
  darosior:
    tACK b7f35c0 -- i've lightly tested this a couple times. It's good enough to get in and get tested along with the other changes.

Tree-SHA512: 4481be4797cf6fa901de9fec989837381c7817d18dd2c9a45ff1802a15982d1251696e577fb23da2d4ca9f0ed27044dade28f0e7b56703594dae4b3a5065306b
@darosior darosior mentioned this pull request Mar 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
No open projects
Status: Done
Development

Successfully merging this pull request may close these issues.

3 participants