-
Notifications
You must be signed in to change notification settings - Fork 2.1k
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
[2/?] - input: add taproot chan scripts, control block logic, and spending routines #7333
Conversation
There was a problem hiding this 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.
ec40eea
to
c6b0367
Compare
There was a problem hiding this 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.
c6b0367
to
1d1ab0b
Compare
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. |
3525b86
to
ff278d8
Compare
There was a problem hiding this 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
There was a problem hiding this 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.
@@ -443,6 +479,274 @@ func SenderHtlcSpendTimeout(receiverSig Signature, | |||
return witnessStack, nil | |||
} | |||
|
|||
// SenderHTLCTapLeafTimeout returns the full tapscript leaf for the timeout |
There was a problem hiding this comment.
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.
@@ -784,6 +1356,163 @@ func SecondLevelHtlcScript(revocationKey, delayKey *btcec.PublicKey, | |||
return builder.Script() | |||
} | |||
|
|||
// TODO(roasbeef): move all taproot stuff to new file? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍🙏
There was a problem hiding this 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.
048e4c7
to
507f101
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM 🎉
func TaprootCommitScriptToRemote(remoteKey *btcec.PublicKey, | ||
) (*btcec.PublicKey, error) { |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🌊⛵️🏖
input/script_utils.go
Outdated
@@ -1880,12 +1882,16 @@ func NewLocalCommitScriptTree(csvTimeout uint32, | |||
// | |||
// The revocation path is simply: | |||
// | |||
// <local_delayedpubkey> OP_CHECKSIG |
There was a problem hiding this comment.
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.
507f101
to
388a70c
Compare
input/script_utils.go
Outdated
@@ -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 |
There was a problem hiding this comment.
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" + |
There was a problem hiding this comment.
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) { |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
missing the opposite leaf
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
Code Style and Documentation
[skip ci]
in the commit message for small changes.📝 Please see our Contribution Guidelines for further guidance.