Skip to content

Commit dba17e7

Browse files
committed
bolt-simple-taproot: fix and make scripts smaller
+ script layout and readability
1 parent ec8c7b4 commit dba17e7

File tree

1 file changed

+60
-51
lines changed

1 file changed

+60
-51
lines changed

bolt-simple-taproot.md

Lines changed: 60 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -54,16 +54,16 @@ Created: 2022-04-20
5454
- [Test Vectors](#test-vectors)
5555
- [Acknowledgements](#acknowledgements)
5656

57-
# Introduction
57+
# Introduction
5858

59-
## Abstract
59+
## Abstract
6060

6161

6262
The activation of the Taproot soft-fork suite enables a number of updates to
6363
the Lightning Network, allowing developers to improve the privacy, security,
64-
and flexibility of the system. This document specifies extensions to BOLTs 2,
64+
and flexibility of the system. This document specifies extensions to BOLTs 2,
6565
3, and 5 which describe a new Taproot based channels to update to the Lightning
66-
Network to take advantage of _some_ of these new capabilities. Namely, we
66+
Network to take advantage of _some_ of these new capabilities. Namely, we
6767
mechanically translate the current funding and commitment design to utilize
6868
`musig2` and the new tapscript tree capabilities.
6969

@@ -150,7 +150,7 @@ A `tap_branch` can commit to either a `tap_leaf` or `tap_branch`. Before
150150
hashing, a `tap_branch` sorts the two `tap_node` arguments based on
151151
lexicographical ordering:
152152
```
153-
tagged_hash("TapBranch, sort(node_1, node_2)
153+
tagged_hash("TapBranch", sort(node_1, node_2))
154154
```
155155

156156
A tapscript tree is constructed by hashing each pair of leaves into a
@@ -171,7 +171,7 @@ script path.
171171
[BIP 86](https://github.com/bitcoin/bips/blob/master/bip-0086.mediawiki) defines a taproot output key derivation scheme that wherein only the internal
172172
key is committed to without a script root:
173173
```
174-
taproot_output_key = taproot_internal_key + tagged_hash("TapTweak", taproot_internal_key)*G
174+
taproot_output_key = taproot_internal_key + tagged_hash("TapTweak", taproot_internal_key)*G
175175
```
176176

177177
We use BIP 86 whenever we want to ensure that a script path spend isn't
@@ -219,7 +219,7 @@ will be absent.
219219

220220
The final witness to spend a script path output is:
221221
```
222-
control_block || leaf_script || witness
222+
<witness1> ... <witnessN> <leaf_script> <control_block>
223223
```
224224

225225
### MuSig2
@@ -396,7 +396,7 @@ The sending node:
396396
The sending node SHOULD:
397397

398398
- use the `NonceGen` algorithm defined in `bip-musig2` to generate
399-
`lcaol_musig2_pubnonce` and `remote_musig2_pubnonce` to ensure it
399+
`local_musig2_pubnonce` and `remote_musig2_pubnonce` to ensure it
400400
generates nonces in a safe manner.
401401

402402
The receiving node MUST fail the channel if:
@@ -416,7 +416,7 @@ step.
416416

417417
The `remote_musig2_pubnonce` will be used to sign the _remote_ party's
418418
commitment transaction, while the `local_musig2_pubnonce` will be used to sign
419-
the local party's commitment transaction.
419+
the local party's commitment transaction.
420420

421421
We require two nonces, as there're actually two messages being signed: the
422422
local commitment and the remote commitment. If only one nonce was used, when a
@@ -454,7 +454,7 @@ The receiver:
454454

455455
The sender:
456456

457-
- MUST derive the aggregated `musig2` public key using the exchanged `funding_pubkey`s
457+
- MUST derive the aggregated `musig2` public key using the exchanged `funding_pubkey`s
458458
- Before aggregating the two funding public keys, the keys MUST be sorted
459459
using the `KeySort` routine of `bip-musig2`.
460460

@@ -610,7 +610,7 @@ The receiver MUST:
610610
- Fail the channel if the received schnorr partial signature failed to verify
611611
using the `PartialSigVerify` paramterized with the local combined nonce
612612
(`local_musig2_pubnonce` of the verifying party, and the
613-
`remote_musig2_pubnonce` of the sending party) algorithm of `musig2` .
613+
`remote_musig2_pubnonce` of the sending party) algorithm of `musig2`.
614614

615615
- Fail the channel is _any_ of the received HTLC signatures does not validate
616616
according to the message extensions and sighash algorithm described in BIP
@@ -713,15 +713,12 @@ The new output has the following form:
713713

714714
* `OP_1 to_local_output_key`
715715
* where:
716-
* `to_local_output_key = <revocationpubkey> + tagged_hash("TapTweak", <revocationpubkey> || to_delay_script_root`
716+
* `to_local_output_key = revocationpubkey + tagged_hash("TapTweak", revocationpubkey || to_delay_script_root)`
717717
* `to_delay_script_root = tapscript_root([to_delay_script])`
718718
* `to_delay_script` is the delay script:
719719
```
720-
to_self_delay
721-
OP_CHECKSEQUENCEVERIFY
722-
OP_DROP
723-
<local_delayedpubkey>
724-
OP_CHECKSIGVERIFY
720+
<local_delayedpubkey> OP_CHECKSIG
721+
<to_self_delay> OP_CHECKSEQUENCEVERIFY OP_DROP
725722
```
726723
727724
The parity (even or odd) of the y-coordinate of the derived
@@ -731,7 +728,7 @@ The `tapscript_root` routine constructs a valid taproot commitment according to
731728
BIP 341+342. Namely, a leaf version of `0xc0` MUST be used. As there's only a
732729
single script, one can derive the tapscript root as:
733730
```
734-
tapscript_root = tagged_hash("TapLeaf, 0xc0 || compact_size_of(to_delay_script) || to_delay_script)
731+
tapscript_root = tagged_hash("TapLeaf", 0xc0 || compact_size_of(to_delay_script) || to_delay_script)
735732
```
736733
737734
In the case of a commitment breach, the `to_delay_script_root` can be used
@@ -742,23 +739,23 @@ top-level key spend path. A valid witness is then just:
742739
```
743740
744741
In the case of a routine force close, the script path must be revealed so the
745-
broadcaster can sweep their funds after a delay. The control block to spend is
742+
broadcaster can sweep their funds after a delay. The control block to spend is
746743
only `33` bytes, as it just includes the internal key (along with the y-parity
747744
bit and leaf version):
748745
```
749-
delay_control_block = (parity_of_y | 0x0c) || <revocationpubkey>
746+
delay_control_block = (output_key_y_parity | 0xc0) || revocationpubkey
750747
```
751748
752749
A valid witness is then:
753750
```
754-
<delay_control_block> <to_delay_script> <local_delayedsig>
751+
<local_delayedsig> <to_delay_script> <delay_control_block>
755752
```
756753
757-
A with base channels, the `nSequence` field must be set to `to_self_delay`.
754+
As with base channels, the `nSequence` field must be set to `to_self_delay`.
758755
759756
#### To Remote Outputs
760757
761-
As we inheirit the anchor output semmeantics we want to ensure that the remote
758+
As we inherit the anchor output semantics we want to ensure that the remote
762759
party can unilaterally sweep their funds after the 1 block CSV delay. In order
763760
to achieve this property, we'll utilize a NUMs point (`simple_taproot_nums`) By
764761
using this point as the internal key, we ensure that the remote party isn't
@@ -769,21 +766,22 @@ The to remote output has the following form:
769766
* `OP_1 to_remote_output_key`
770767
* where:
771768
* `taproot_nums_point = 0245b18183a06ee58228f07d9716f0f121cd194e4d924b037522503a7160432f15`
772-
* `to_remote_output_key = taproot_nums_point + tagged_hash("TapTweak", taproot_nums_point|| to_remote_script_root`
769+
* `to_remote_output_key = taproot_nums_point + tagged_hash("TapTweak", taproot_nums_point || to_remote_script_root)`
773770
* `to_remote_script_root = tapscript_root([to_remote_script])`
774771
* `to_remote_script` is the remote script:
775772
```
776-
<remotepubkey> OP_CHECKSIGVERIFY 1 OP_CHECKSEQUENCEVERIFY
773+
<remotepubkey> OP_CHECKSIG
774+
OP_CHECKSEQUENCEVERIFY
777775
```
778776
779777
This output can be swept by the remote party with the following witness:
780778
```
781-
<to_remote_control_block> <to_remote_script> <remote_sig>
779+
<remote_sig> <to_remote_script> <to_remote_control_block>
782780
```
783781
784782
where `to_remote_control_block` is:
785783
```
786-
(parity_of_y(remotepubkey) | 0x0c) || <remotepubkey>
784+
(output_key_y_parity | 0xc0) || taproot_nums_point
787785
```
788786
789787
#### Anchor Outputs
@@ -798,13 +796,25 @@ An anchor output has the following form:
798796
* `OP_1 anchor_output_key`
799797
* where:
800798
* `anchor_internal_key = remotepubkey/local_delayedpubkey`
801-
* `anchor_output_key= anchor_internal_key + tagged_hash("TapTweak", anchor_internal_key || anchor_script_root)`
802-
* `anchor_script = tapscript_root([anchor_script])`
799+
* `anchor_output_key = anchor_internal_key + tagged_hash("TapTweak", anchor_internal_key || anchor_script_root)`
800+
* `anchor_script_root = tapscript_root([anchor_script])`
803801
* `anchor_script`:
804802
```
805803
OP_16 OP_CHECKSEQUENCEVERIFY
806804
```
807805
806+
This output can be swept by anyone after 16 blocks with the following witness:
807+
```
808+
<anchor_script> <anchor_control_block>
809+
```
810+
811+
where `anchor_control_block` is:
812+
```
813+
(output_key_y_parity | 0xc0) || anchor_internal_key
814+
```
815+
816+
`nSequence` needs to be set to 16.
817+
808818
### HTLC Scripts & Transactions
809819
810820
#### Offered HTLCs
@@ -821,15 +831,14 @@ An offered HTLC has the following form:
821831
* `htlc_script_root = tapscript_root([htlc_timeout, htlc_success])`
822832
* `htlc_timeout`:
823833
```
824-
<local_htlcpubkey> OP_CHECKSIGADD <remote_htlcpubkey> OP_CHECKSIGADD 2 OP_EQUALVERIFY
825-
1 OP_CHECKSEQUENCEVERIFY
834+
<local_htlcpubkey> OP_CHECKSIGVERIFY
835+
<remote_htlcpubkey> OP_CHECKSIG
826836
```
827837
* `htlc_success`:
828838
```
829839
OP_SIZE 32 OP_EQUALVERIFY OP_HASH160 <RIPEMD160(payment_hash)> OP_EQUALVERIFY
830-
<remote_htlcpubkey>
831-
OP_CHECKSIGVERIFY
832-
1 OP_CHECKSEQUENCEVERIFY
840+
<remote_htlcpubkey> OP_CHECKSIG
841+
OP_CHECKSEQUENCEVERIFY
833842
```
834843
835844
In order to spend a offered HTLC, via either script path, an `inclusion_proof`
@@ -846,19 +855,21 @@ Accepted HTLCs inherit a similar format:
846855
* `htlc_script_root = tapscript_root([htlc_timeout, htlc_success])`
847856
* `htlc_timeout`:
848857
```
849-
<remote_htlcpubkey>
850-
OP_CHECKSIGVERIFY
851-
1 OP_CHECKSEQUENCEVERIFY OP_DROP
852-
<cltv_expiry>
853-
OP_CHECKLOCKTIMEVERIFY
858+
<remote_htlcpubkey> OP_CHECKSIG
859+
OP_CHECKSEQUENCEVERIFY
860+
<cltv_expiry> OP_CHECKLOCKTIMEVERIFY OP_DROP
854861
```
855862
* `htlc_success`:
856863
```
857864
OP_SIZE 32 OP_EQUALVERIFY OP_HASH160 <RIPEMD160(payment_hash)> OP_EQUALVERIFY
858-
<local_htlcpubkey> OP_CHECKSIGADD <remote_htlcpubkey> OP_CHECKSIGADD 2 OP_EQUALVERIFY
859-
1 OP_CHECKSEQUENCEVERIFY
865+
<local_htlcpubkey> OP_CHECKSIGVERIFY
866+
<remote_htlcpubkey> OP_CHECKSIG
860867
```
861868
869+
Note that there is no `OP_CHECKSEQUENCEVERIFY` in the offered HTLC's timeout path
870+
and in the accepted HTLC's success path. This is not needed here as these paths
871+
require a remote signature that commits to the sequence, which needs to be set at 1.
872+
862873
In order to spend an accepted HTLC, via either script path, an
863874
`inclusion_proof` must be specified along with the control block. This
864875
`inclusion_proof` is simply the `tap_leaf` hash of the path _not_ taken.
@@ -886,7 +897,8 @@ A HTLC-Success transaction has the following structure:
886897
* input:
887898
* txid: commitment_tx
888899
* vout: htlc_index
889-
* witness: `control_block || htlc_success_script || <localsig> <remotesig> <preimage>`
900+
* sequence: 1
901+
* witness: `<remotehtlcsig> <localhtlcsig> <preimage> <htlc_success_script> <control_block>`
890902
* output:
891903
* value: htlc_value
892904
* script:
@@ -896,10 +908,8 @@ A HTLC-Success transaction has the following structure:
896908
* `htlc_script_root = tapscript_root([htlc_success])`
897909
* `htlc_success`:
898910
```
899-
<local_delayedpubkey>
900-
OP_CHECKSIGVERIFY
901-
<to_self_delay>
902-
OP_CHECKSEQUENCEVERIFY
911+
<local_delayedpubkey> OP_CHECKSIG
912+
<to_self_delay> OP_CHECKSEQUENCEVERIFY OP_DROP
903913
```
904914
905915
##### HTLC-Timeout Transactions
@@ -911,7 +921,8 @@ A HTLC-Timeout transaction has the following structure:
911921
* input:
912922
* txid: commitment_tx
913923
* vout: htlc_index
914-
* witness: `control_block || htlc_timeout_script || <localsig> <remotesig>`
924+
* sequence: 1
925+
* witness: `<remotehtlcsig> <localhtlcsig> <htlc_timeout_script> <control_block>`
915926
* output:
916927
* value: htlc_value
917928
* script:
@@ -921,10 +932,8 @@ A HTLC-Timeout transaction has the following structure:
921932
* `htlc_script_root = tapscript_root([htlc_timeout])`
922933
* `htlc_timeout`:
923934
```
924-
<local_delayedpubkey>
925-
OP_CHECKSIGVERIFY
926-
<to_self_delay>
927-
OP_CHECKSEQUENCEVERIFY
935+
<local_delayedpubkey> OP_CHECKSIG
936+
<to_self_delay> OP_CHECKSEQUENCEVERIFY OP_DROP
928937
```
929938
930939
# Appendix

0 commit comments

Comments
 (0)