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

[2/?] - input: add taproot chan scripts, control block logic, and spending routines #7333

Conversation

Roasbeef
Copy link
Member

@Roasbeef Roasbeef commented Jan 17, 2023

Change Description

In this commit, we add the current draft set of taproot scripts, control block handling logic, and also spending routines.

Reviewers will want to be familiar with the current spec draft before diving in: https://github.com/Roasbeef/lightning-rfc/blob/simple-taproot-chans/bolt-simple-taproot.md

This PR is a draft PR, as it still needs tests for all the new routines (they work in #6877) and also the witness estimate constants to be updated.

Steps to Test

Steps for reviewers to follow to test the change.

Pull Request Checklist

Testing

  • Your PR passes all CI checks.
  • Tests covering the positive and negative (error paths) are included.
  • Bug fixes contain tests triggering the bug to prevent regressions.

Code Style and Documentation

📝 Please see our Contribution Guidelines for further guidance.

Copy link
Collaborator

@guggero guggero left a comment

Choose a reason for hiding this comment

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

Was curious about the PR and took a quick glance at it.
Noticed a few things that I wanted to point out, this is by no means a full review.

input/script_utils.go Outdated Show resolved Hide resolved
input/script_utils.go Show resolved Hide resolved
input/script_utils.go Outdated Show resolved Hide resolved
input/script_utils.go Outdated Show resolved Hide resolved
@saubyk saubyk requested a review from Crypt-iQ January 17, 2023 18:06
@saubyk saubyk added this to the v0.16.0 milestone Jan 17, 2023
input/script_utils.go Outdated Show resolved Hide resolved
@saubyk saubyk added taproot funding Related to the opening of new channels with funding transactions on the blockchain labels Jan 19, 2023
@Roasbeef Roasbeef changed the title input: add taproot chan scripts, control block logic, and spending routines [2/?] - input: add taproot chan scripts, control block logic, and spending routines Jan 19, 2023
@guggero guggero self-requested a review January 19, 2023 08:43
input/script_utils.go Show resolved Hide resolved
input/script_utils.go Show resolved Hide resolved
input/script_utils.go Outdated Show resolved Hide resolved
input/script_utils.go Outdated Show resolved Hide resolved
input/script_utils.go Outdated Show resolved Hide resolved
input/script_utils.go Outdated Show resolved Hide resolved
input/script_utils.go Show resolved Hide resolved
input/script_utils.go Show resolved Hide resolved
input/script_utils.go Outdated Show resolved Hide resolved
input/script_utils.go Outdated Show resolved Hide resolved
input/script_utils.go Outdated Show resolved Hide resolved
input/script_utils.go Outdated Show resolved Hide resolved
input/script_utils.go Outdated Show resolved Hide resolved
input/script_utils.go Show resolved Hide resolved
Copy link
Collaborator

@guggero guggero left a comment

Choose a reason for hiding this comment

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

Did a first more detailed pass. Amazing work! Very easy to read diff and code!
Given the number of small things that are off (witness stack indexes, sighash flags present), I guess it would be nice to have unit tests that cover at least some very basic paths. Let me know if I should help out with these.

input/script_utils.go Outdated Show resolved Hide resolved
input/script_utils.go Outdated Show resolved Hide resolved
input/script_utils.go Outdated Show resolved Hide resolved
input/script_utils.go Outdated Show resolved Hide resolved
input/script_utils.go Show resolved Hide resolved
input/script_utils.go Outdated Show resolved Hide resolved
input/script_utils.go Outdated Show resolved Hide resolved
input/script_utils.go Show resolved Hide resolved
input/script_utils.go Outdated Show resolved Hide resolved
input/script_utils.go Outdated Show resolved Hide resolved
input/script_utils.go Outdated Show resolved Hide resolved
input/script_utils.go Outdated Show resolved Hide resolved
@Roasbeef Roasbeef marked this pull request as ready for review February 4, 2023 13:12
@Roasbeef
Copy link
Member Author

Roasbeef commented Feb 4, 2023

Pushed up a new commit that adds exhaustive tests to the new scripts. This tracks the current draft PR, which'll be updated soon to have some small changes (remove implicit CSV 0, etc). Removed it from draft now as unit tests are in place.

@guggero guggero self-requested a review February 6, 2023 09:19
Copy link
Collaborator

@guggero guggero left a comment

Choose a reason for hiding this comment

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

Last two commits look good, great unit tests!
Since there are still a few discussions open that need to be resolved in the spec as well, I'll wait with the final pass.

Just two things I noticed:

  • The TestTaprootReceiverHtlcSpend seems to be flaky, there seems to be a y coordinate odd issue
  • Running the unit tests with coverage, the following functions don't seem to be covered yet: (though I'm not sure if we are aiming for 100% unit test coverage on these new functions, as they'll be executed in the itests for sure)
    • GenTaprootFundingScript
    • TaprootSecondLevelHtlcScript
    • TaprootCommitScriptToSelf
    • TaprootCommitScriptToRemote
    • TaprootOutputKeyAnchor

Copy link
Collaborator

@ellemouton ellemouton left a comment

Choose a reason for hiding this comment

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

Finally did a full pass - Looking great! 🔥

I guess any spec changes/changes resulting from the discussion in this PR would only affect comments and variable names.

input/script_utils.go Outdated Show resolved Hide resolved
input/script_utils.go Outdated Show resolved Hide resolved
input/script_utils.go Outdated Show resolved Hide resolved
input/script_utils.go Outdated Show resolved Hide resolved
input/script_utils.go Outdated Show resolved Hide resolved
input/script_utils.go Outdated Show resolved Hide resolved
input/script_utils.go Outdated Show resolved Hide resolved
input/script_utils.go Outdated Show resolved Hide resolved
input/script_utils.go Outdated Show resolved Hide resolved
input/script_utils.go Outdated Show resolved Hide resolved
@saubyk saubyk modified the milestones: v0.16.0, v0.16.1 Feb 14, 2023
@@ -443,6 +479,274 @@ func SenderHtlcSpendTimeout(receiverSig Signature,
return witnessStack, nil
}

// SenderHTLCTapLeafTimeout returns the full tapscript leaf for the timeout
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: change this to Offered... so it's easier to follow the specs.

input/script_utils.go Show resolved Hide resolved
input/script_utils.go Outdated Show resolved Hide resolved
input/script_utils.go Outdated Show resolved Hide resolved
@@ -784,6 +1356,163 @@ func SecondLevelHtlcScript(revocationKey, delayKey *btcec.PublicKey,
return builder.Script()
}

// TODO(roasbeef): move all taproot stuff to new file?
Copy link
Collaborator

Choose a reason for hiding this comment

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

👍🙏

Copy link
Collaborator

@yyforyongyu yyforyongyu left a comment

Choose a reason for hiding this comment

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

Very thorough unit tests🙏 I think it's very close, my major question is the OP_SIZE check, whether it's still necessary.

input/script_utils.go Outdated Show resolved Hide resolved
input/script_utils.go Show resolved Hide resolved
input/taproot_test.go Show resolved Hide resolved
input/taproot_test.go Show resolved Hide resolved
input/script_utils.go Outdated Show resolved Hide resolved
@Roasbeef Roasbeef force-pushed the simple-taproot-chans-scripts branch 5 times, most recently from 048e4c7 to 507f101 Compare May 26, 2023 01:52
Copy link
Collaborator

@guggero guggero left a comment

Choose a reason for hiding this comment

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

LGTM 🎉

Comment on lines +2241 to +2253
func TaprootCommitScriptToRemote(remoteKey *btcec.PublicKey,
) (*btcec.PublicKey, error) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Yeah, my mental parser always throws a fit when seeing this 😅 I think mostly because the indentation isn't preserved, which is a whole new visual pattern to learn when scanning code...

@@ -1135,7 +1136,8 @@ func TestTaprootCommitScriptToSelf(t *testing.T) {
},
}

for i, testCase := range testCases {
for i, testCase := range testCases { //nolint:paralleltest
Copy link
Collaborator

Choose a reason for hiding this comment

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

IMO we can also disable that linter in general as there are good reasons for not running some tests in parallel some times.

Copy link
Collaborator

@yyforyongyu yyforyongyu left a comment

Choose a reason for hiding this comment

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

🌊⛵️🏖

@@ -1880,12 +1882,16 @@ func NewLocalCommitScriptTree(csvTimeout uint32,
//
// The revocation path is simply:
//
// <local_delayedpubkey> OP_CHECKSIG
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is not fixed yet, can be confusing for future development.

In this commit, we add a helper function to take a taproot output key
and turn it into a v1 witness program.
In this commit, we add GenTaprootFundingScript, which'll return the
taproot pkScript and output for a taproot+musig2 channel. This uses
musig2 key aggregation with sorting activated.

The final key produced uses a bip86 tweak, meaning that the output key
provably doesn't commit to any script path. In the future, we may want
to permit this, as then it allows for a greater degree of
programmability of the funding output.
Unlike the old HTLC scripts, we now need to handle the various control
block interactions. As is, we opt to simply re-compute the entire tree
when needed, as the tree only has two leaves.
In this commit, we restore usage of the NUMS key for the to remote
output, as this allows a remote party to scan the chain in order to find
their remote output that in emergency recovery scenarios.
In this commit, we modify the to_local script to use a script path for
the revocation scenario. With this change, we ensure that the internal
key is always revealed which means the anchor outputs can still always
be swept.
We undo the prior hack here to make the final script more readable. The
difference is just 1 byte between the two.
@Roasbeef Roasbeef force-pushed the simple-taproot-chans-scripts branch from 507f101 to 388a70c Compare May 26, 2023 23:25
@Roasbeef Roasbeef merged commit 12463c1 into lightningnetwork:simple-taproot-chans-staging May 26, 2023
21 of 23 checks passed
@@ -1059,6 +1060,62 @@ func CommitScriptToSelf(csvTimeout uint32, selfKey, revokeKey *btcec.PublicKey)
return builder.Script()
}

// TaprootCommitScriptToSelf creates the taproot witness program that commits
// to the revocation (keyspend) and delay path (script path) in a single
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: no longer keyspend

}

// TaprootNUMSHex is the hex encoded version of the taproot NUMs key.
const TaprootNUMSHex = "02dca094751109d0bd055d03565874e8276dd53e926b44e3bd1bb" +
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is there some way that we can have a test or linter job that yells if somebody ever tries to change this?

// TaprootAnchorSpend constructs a valid witness allowing a node to sweep their
// anchor output.
func TaprootAnchorSpend(signer Signer, signDesc *SignDescriptor,
revokeTx *wire.MsgTx) (wire.TxWitness, error) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: can't spend anchor w/ revoke

@@ -1858,12 +1879,20 @@ func NewLocalCommitScriptTree(csvTimeout uint32,
// Where the to_delay_script is listed above, and the delay_control_block
// computed as:
//
// delay_control_block = (output_key_y_parity | 0xc0) || revocationpubkey
// delay_control_block = (output_key_y_parity | 0xc0) || taproot_nums_key
Copy link
Collaborator

Choose a reason for hiding this comment

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

missing the opposite leaf

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
funding Related to the opening of new channels with funding transactions on the blockchain no-changelog taproot chans taproot
Projects
No open projects
Status: Done
Development

Successfully merging this pull request may close these issues.

None yet