Skip to content

Commit e730432

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 a304937 commit e730432

File tree

1 file changed

+165
-0
lines changed

1 file changed

+165
-0
lines changed

tapchannel/aux_leaf_signer_test.go

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

0 commit comments

Comments
 (0)