Skip to content

Commit 2742e23

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 47a265d commit 2742e23

File tree

1 file changed

+164
-0
lines changed

1 file changed

+164
-0
lines changed

tapchannel/aux_leaf_signer_test.go

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
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+
129+
assetSigs := make([][]*cmsg.AssetSig, numHTLCs)
130+
for i := range numHTLCs {
131+
msg.HtlcSigs[i] = testSchnorrSig
132+
133+
assetSigs[i] = make([]*cmsg.AssetSig, numAssetIDs)
134+
for j := range numAssetIDs {
135+
var assetID asset.ID
136+
137+
_, err := rand.Read(assetID[:])
138+
require.NoError(t, err)
139+
140+
assetSigs[i][j] = cmsg.NewAssetSig(
141+
assetID, testSchnorrSig, txscript.SigHashAll,
142+
)
143+
}
144+
}
145+
146+
if numAssetIDs == 0 {
147+
return msg
148+
}
149+
150+
commitSig := cmsg.NewCommitSig(assetSigs)
151+
152+
var buf bytes.Buffer
153+
err = commitSig.Encode(&buf)
154+
require.NoError(t, err)
155+
156+
msg.CustomRecords = lnwire.CustomRecords{
157+
// The actual record type is not important for this test, it
158+
// just needs to be in the correct range to be encoded with the
159+
// correct number of bytes in the compact size encoding.
160+
lnwire.MinCustomRecordsTlvType + 123: buf.Bytes(),
161+
}
162+
163+
return msg
164+
}

0 commit comments

Comments
 (0)