Skip to content

Commit 85e5cf1

Browse files
committed
tapchannel: add test to derive limits
This test attempts to find out what the maximum number of HTLC signatures we can pack into a CommitSig message is. This number depends on the number of different fungible asset pieces (asset IDs) we have, as we need to provide a signature for each piece. The resulting values are: aux_leaf_signer_test.go:111: Last valid commit sig msg size with: numAssetIDs=0, numHTLCs=966 aux_leaf_signer_test.go:103: Last valid commit sig msg size with: numAssetIDs=1, numHTLCs=373 aux_leaf_signer_test.go:103: Last valid commit sig msg size with: numAssetIDs=2, numHTLCs=231 aux_leaf_signer_test.go:103: Last valid commit sig msg size with: numAssetIDs=3, numHTLCs=166 aux_leaf_signer_test.go:103: Last valid commit sig msg size with: numAssetIDs=4, numHTLCs=130 aux_leaf_signer_test.go:103: Last valid commit sig msg size with: numAssetIDs=5, numHTLCs=107 aux_leaf_signer_test.go:103: Last valid commit sig msg size with: numAssetIDs=6, numHTLCs=91 aux_leaf_signer_test.go:103: Last valid commit sig msg size with: numAssetIDs=7, numHTLCs=79 aux_leaf_signer_test.go:103: Last valid commit sig msg size with: numAssetIDs=8, numHTLCs=70 aux_leaf_signer_test.go:103: Last valid commit sig msg size with: numAssetIDs=9, numHTLCs=63 aux_leaf_signer_test.go:103: Last valid commit sig msg size with: numAssetIDs=10, numHTLCs=57
1 parent f0907b5 commit 85e5cf1

File tree

1 file changed

+172
-0
lines changed

1 file changed

+172
-0
lines changed

tapchannel/aux_leaf_signer_test.go

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
package tapchannel
2+
3+
import (
4+
"bytes"
5+
"crypto/rand"
6+
"encoding/hex"
7+
"fmt"
8+
"testing"
9+
10+
"github.com/btcsuite/btcd/btcec/v2"
11+
"github.com/btcsuite/btcd/btcec/v2/ecdsa"
12+
"github.com/btcsuite/btcd/txscript"
13+
"github.com/lightninglabs/taproot-assets/asset"
14+
cmsg "github.com/lightninglabs/taproot-assets/tapchannelmsg"
15+
"github.com/lightningnetwork/lnd/input"
16+
"github.com/lightningnetwork/lnd/lnwire"
17+
"github.com/lightningnetwork/lnd/tlv"
18+
"github.com/stretchr/testify/require"
19+
)
20+
21+
// Some of these test values and functions are from lnd's lnwire/lnwire_test.go.
22+
var (
23+
testRBytes, _ = hex.DecodeString(
24+
"8ce2bc69281ce27da07e6683571319d18e949ddfa2965fb6caa1bf0314f8" +
25+
"82d7",
26+
)
27+
testSBytes, _ = hex.DecodeString(
28+
"299105481d63e0f4bc2a88121167221b6700d72a0ead154c03be696a292d" +
29+
"24ae",
30+
)
31+
testRScalar = new(btcec.ModNScalar)
32+
testSScalar = new(btcec.ModNScalar)
33+
_ = testRScalar.SetByteSlice(testRBytes)
34+
_ = testSScalar.SetByteSlice(testSBytes)
35+
testSig = ecdsa.NewSignature(testRScalar, testSScalar)
36+
37+
testSchnorrSigStr, _ = hex.DecodeString(
38+
"04e7f9037658a92afeb4f25bae5339e3ddca81a353493827d26f16d92308" +
39+
"e49e2a25e92208678a2df86970da91b03a8af8815a8a60498b35" +
40+
"8daf560b347aa557",
41+
)
42+
testSchnorrSig, _ = lnwire.NewSigFromSchnorrRawSignature(
43+
testSchnorrSigStr,
44+
)
45+
46+
startNumHTLCs = 5
47+
endNumHTLCs = input.MaxHTLCNumber
48+
)
49+
50+
func randPartialSigWithNonce() (*lnwire.PartialSigWithNonce, error) {
51+
var sigBytes [32]byte
52+
if _, err := rand.Read(sigBytes[:]); err != nil {
53+
return nil, fmt.Errorf("unable to generate sig: %w", err)
54+
}
55+
56+
var s btcec.ModNScalar
57+
s.SetByteSlice(sigBytes[:])
58+
59+
var nonce lnwire.Musig2Nonce
60+
if _, err := rand.Read(nonce[:]); err != nil {
61+
return nil, fmt.Errorf("unable to generate nonce: %w", err)
62+
}
63+
64+
return &lnwire.PartialSigWithNonce{
65+
PartialSig: lnwire.NewPartialSig(s),
66+
Nonce: nonce,
67+
}, nil
68+
}
69+
70+
func somePartialSigWithNonce(t *testing.T) lnwire.OptPartialSigWithNonceTLV {
71+
sig, err := randPartialSigWithNonce()
72+
if err != nil {
73+
t.Fatal(err)
74+
}
75+
76+
return tlv.SomeRecordT(tlv.NewRecordT[
77+
lnwire.PartialSigWithNonceType,
78+
lnwire.PartialSigWithNonce,
79+
](*sig))
80+
}
81+
82+
// TestMaxCommitSigMsgSize attempts to find values for the max number of asset
83+
// IDs we want to allow per channel and the resulting maximum number of HTLCs
84+
// that channel can allow. The maximum number of different asset IDs that can be
85+
// committed to a channel directly impacts the number of HTLCs that can be
86+
// created on that channel, because we have a limited message size to exchange
87+
// the second-stage HTLC signatures. The goal of this test is to find the right
88+
// number of asset IDs we should allow per channel to still give us a reasonable
89+
// amount of HTLCs.
90+
func TestMaxCommitSigMsgSize(t *testing.T) {
91+
// This test is only relevant once, to find the values we want to use
92+
// for the maximum number of asset IDs and the resulting maximum number
93+
// of HTLCs. We only need to re-run this if any of the parameters
94+
// change.
95+
t.Skip("Test for manual execution only")
96+
97+
const maxNumAssetIDs = 10
98+
99+
var buf bytes.Buffer
100+
for numID := 0; numID <= maxNumAssetIDs; numID++ {
101+
for htlcs := startNumHTLCs; htlcs <= endNumHTLCs; htlcs++ {
102+
buf.Reset()
103+
104+
msg := makeCommitSig(t, numID, htlcs)
105+
err := msg.Encode(&buf, 0)
106+
require.NoError(t, err)
107+
108+
if buf.Len() > lnwire.MaxMsgBody {
109+
t.Logf("Last valid commit sig msg size with: "+
110+
"numAssetIDs=%d, numHTLCs=%d",
111+
numID, htlcs-1)
112+
113+
break
114+
}
115+
116+
if htlcs == endNumHTLCs {
117+
t.Logf("Last valid commit sig msg size with: "+
118+
"numAssetIDs=%d, numHTLCs=%d",
119+
numID, htlcs)
120+
}
121+
}
122+
}
123+
}
124+
125+
func makeCommitSig(t *testing.T, numAssetIDs, numHTLCs int) *lnwire.CommitSig {
126+
var (
127+
msg = &lnwire.CommitSig{
128+
HtlcSigs: make([]lnwire.Sig, numHTLCs),
129+
}
130+
err error
131+
)
132+
133+
// Static values that are always set for custom channels (which are
134+
// Taproot channels, so have an all-zero legacy commit signature and a
135+
// partial MuSig2 signature).
136+
msg.PartialSig = somePartialSigWithNonce(t)
137+
msg.CommitSig, err = lnwire.NewSigFromSignature(testSig)
138+
require.NoError(t, err)
139+
140+
assetSigs := make([][]*cmsg.AssetSig, numHTLCs)
141+
for i := range numHTLCs {
142+
msg.HtlcSigs[i] = testSchnorrSig
143+
144+
assetSigs[i] = make([]*cmsg.AssetSig, numAssetIDs)
145+
for j := range numAssetIDs {
146+
var assetID asset.ID
147+
148+
_, err := rand.Read(assetID[:])
149+
require.NoError(t, err)
150+
151+
assetSigs[i][j] = cmsg.NewAssetSig(
152+
assetID, testSchnorrSig, txscript.SigHashAll,
153+
)
154+
}
155+
}
156+
157+
if numAssetIDs == 0 {
158+
return msg
159+
}
160+
161+
commitSig := cmsg.NewCommitSig(assetSigs)
162+
163+
var buf bytes.Buffer
164+
err = commitSig.Encode(&buf)
165+
require.NoError(t, err)
166+
167+
msg.CustomRecords = lnwire.CustomRecords{
168+
65543: buf.Bytes(),
169+
}
170+
171+
return msg
172+
}

0 commit comments

Comments
 (0)