Skip to content

Commit 6a54be2

Browse files
committed
assets: add no-csv option to the asset HTLC to support package relay
This commit enables package relayed HTLCs by making the CSV check in the success path optional.
1 parent e72353a commit 6a54be2

File tree

2 files changed

+35
-10
lines changed

2 files changed

+35
-10
lines changed

assets/htlc/script.go

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,12 @@ import (
1111
"github.com/lightningnetwork/lnd/lntypes"
1212
)
1313

14-
// GenSuccessPathScript constructs an HtlcScript for the success payment path.
14+
// GenSuccessPathScript constructs a script for the success path of the HTLC
15+
// payment. Optionally includes a CHECKSEQUENCEVERIFY (CSV) of 1 if `csv` is
16+
// true, to prevent potential pinning attacks when the HTLC is not part of a
17+
// package relay.
1518
func GenSuccessPathScript(receiverHtlcKey *btcec.PublicKey,
16-
swapHash lntypes.Hash) ([]byte, error) {
19+
swapHash lntypes.Hash, csvOne bool) ([]byte, error) {
1720

1821
builder := txscript.NewScriptBuilder()
1922

@@ -24,9 +27,22 @@ func GenSuccessPathScript(receiverHtlcKey *btcec.PublicKey,
2427
builder.AddOp(txscript.OP_EQUALVERIFY)
2528
builder.AddOp(txscript.OP_HASH160)
2629
builder.AddData(input.Ripemd160H(swapHash[:]))
27-
builder.AddOp(txscript.OP_EQUALVERIFY)
28-
builder.AddInt64(1)
29-
builder.AddOp(txscript.OP_CHECKSEQUENCEVERIFY)
30+
// OP_EQUAL will leave 0 or 1 on the stack depending on whether the hash
31+
// matches.
32+
// - If it matches and CSV is not used, the script will
33+
// evaulate to true.
34+
// - If it matches and CSV is used, we'll have 1 on the stack which is
35+
// used to verify the CSV condition.
36+
// - If it does not match, we'll have 0 on the stack which will cause
37+
// the script to fail even if CSV is used.
38+
builder.AddOp(txscript.OP_EQUAL)
39+
40+
if csvOne {
41+
// If csvOne is true, we add a CHECKSEQUENCEVERIFY to ensure
42+
// that the HTLC can only be claimed after at least one
43+
// confirmation.
44+
builder.AddOp(txscript.OP_CHECKSEQUENCEVERIFY)
45+
}
3046

3147
return builder.Script()
3248
}
@@ -61,7 +77,9 @@ func CreateOpTrueLeaf() (asset.ScriptKey, txscript.TapLeaf,
6177
tapLeaf := txscript.NewBaseTapLeaf(tapScript)
6278
tree := txscript.AssembleTaprootScriptTree(tapLeaf)
6379
rootHash := tree.RootNode.TapHash()
64-
tapKey := txscript.ComputeTaprootOutputKey(asset.NUMSPubKey, rootHash[:])
80+
tapKey := txscript.ComputeTaprootOutputKey(
81+
asset.NUMSPubKey, rootHash[:],
82+
)
6583

6684
merkleRootHash := tree.RootNode.TapHash()
6785

assets/htlc/swapkit.go

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,16 @@ type SwapKit struct {
4747
// AddressParams is the chain parameters of the chain the deposit is
4848
// being created on.
4949
AddressParams *address.ChainParams
50+
51+
// CheckCSV indicates whether the success path script should include a
52+
// CHECKSEQUENCEVERIFY check. This is used to prevent potential pinning
53+
// attacks when the HTLC is not part of a package relay.
54+
CheckCSV bool
5055
}
5156

5257
// GetSuccessScript returns the success path script of the swap HTLC.
5358
func (s *SwapKit) GetSuccessScript() ([]byte, error) {
54-
return GenSuccessPathScript(s.ReceiverPubKey, s.SwapHash)
59+
return GenSuccessPathScript(s.ReceiverPubKey, s.SwapHash, s.CheckCSV)
5560
}
5661

5762
// GetTimeoutScript returns the timeout path script of the swap HTLC.
@@ -192,7 +197,7 @@ func (s *SwapKit) GenTimeoutBtcControlBlock(taprootAssetRoot []byte) (
192197
InternalKey: internalKey,
193198
LeafVersion: txscript.BaseLeafVersion,
194199
InclusionProof: append(
195-
successLeafHash[:], taprootAssetRoot[:]...,
200+
successLeafHash[:], taprootAssetRoot...,
196201
),
197202
}
198203

@@ -233,7 +238,7 @@ func (s *SwapKit) GenSuccessBtcControlBlock(taprootAssetRoot []byte) (
233238
InternalKey: internalKey,
234239
LeafVersion: txscript.BaseLeafVersion,
235240
InclusionProof: append(
236-
timeOutLeafHash[:], taprootAssetRoot[:]...,
241+
timeOutLeafHash[:], taprootAssetRoot...,
237242
),
238243
}
239244

@@ -322,7 +327,9 @@ func (s *SwapKit) CreatePreimageWitness(ctx context.Context,
322327
Value: sweepBtcPacket.Inputs[1].WitnessUtxo.Value,
323328
}
324329

325-
//sweepBtcPacket.UnsignedTx.TxIn[0].Sequence = 1
330+
if s.CheckCSV {
331+
sweepBtcPacket.UnsignedTx.TxIn[0].Sequence = 1
332+
}
326333

327334
successScript, err := s.GetSuccessScript()
328335
if err != nil {

0 commit comments

Comments
 (0)