From 9851a6147b1f53e326e31f9b2545456b9165c816 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Mon, 16 Jan 2023 19:44:17 -0800 Subject: [PATCH] lnwire: TestLightningWireProtocol quick check tests for taproot fields --- docs/release-notes/release-notes-0.17.0.md | 9 ++ lnwire/lnwire_test.go | 125 ++++++++++++++++++++- lnwire/signature.go | 2 +- lnwire/signature_test.go | 23 ++-- 4 files changed, 148 insertions(+), 11 deletions(-) diff --git a/docs/release-notes/release-notes-0.17.0.md b/docs/release-notes/release-notes-0.17.0.md index 440615109..cd1e6d8c8 100644 --- a/docs/release-notes/release-notes-0.17.0.md +++ b/docs/release-notes/release-notes-0.17.0.md @@ -1,5 +1,10 @@ # Release Notes +## BOLT Specs + +* The `lnwire` library is now able to [parse messages for the new experimental + taproot channels spec proposal](https://github.com/lightningnetwork/lnd/pull/7331). + ## DB * Split channeldb [`UpdateInvoice` @@ -285,3 +290,7 @@ * Yong Yu * ziggie1984 * zx9r + +# Contributors (Alphabetical Order) + +* Olaoluwa Osuntokun diff --git a/lnwire/lnwire_test.go b/lnwire/lnwire_test.go index 703c94211..f5c028581 100644 --- a/lnwire/lnwire_test.go +++ b/lnwire/lnwire_test.go @@ -4,7 +4,9 @@ import ( "bytes" "encoding/binary" "encoding/hex" + "fmt" "image/color" + "io" "math" "math/rand" "net" @@ -39,6 +41,42 @@ var ( const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" +func randLocalNonce(r *rand.Rand) *Musig2Nonce { + var nonce Musig2Nonce + _, _ = io.ReadFull(r, nonce[:]) + + return &nonce +} + +func randPartialSig(r *rand.Rand) (*PartialSig, error) { + var sigBytes [32]byte + if _, err := r.Read(sigBytes[:]); err != nil { + return nil, fmt.Errorf("unable to generate sig: %w", err) + } + + var s btcec.ModNScalar + s.SetByteSlice(sigBytes[:]) + + return &PartialSig{ + Sig: s, + }, nil +} + +func randPartialSigWithNonce(r *rand.Rand) (*PartialSigWithNonce, error) { + var sigBytes [32]byte + if _, err := r.Read(sigBytes[:]); err != nil { + return nil, fmt.Errorf("unable to generate sig: %w", err) + } + + var s btcec.ModNScalar + s.SetByteSlice(sigBytes[:]) + + return &PartialSigWithNonce{ + PartialSig: NewPartialSig(s), + Nonce: *randLocalNonce(r), + }, nil +} + func randAlias(r *rand.Rand) NodeAlias { var a NodeAlias for i := range a { @@ -438,6 +476,8 @@ func TestLightningWireProtocol(t *testing.T) { req.LeaseExpiry = new(LeaseExpiry) *req.LeaseExpiry = LeaseExpiry(1337) + + req.LocalNonce = randLocalNonce(r) } else { req.UpfrontShutdownScript = []byte{} } @@ -510,6 +550,8 @@ func TestLightningWireProtocol(t *testing.T) { req.LeaseExpiry = new(LeaseExpiry) *req.LeaseExpiry = LeaseExpiry(1337) + + req.LocalNonce = randLocalNonce(r) } else { req.UpfrontShutdownScript = []byte{} } @@ -544,6 +586,16 @@ func TestLightningWireProtocol(t *testing.T) { return } + // 1/2 chance to attach a partial sig. + if r.Intn(2) == 0 { + req.PartialSig, err = randPartialSigWithNonce(r) + if err != nil { + t.Fatalf("unable to generate sig: %v", + err) + return + } + } + v[0] = reflect.ValueOf(req) }, MsgFundingSigned: func(v []reflect.Value, r *rand.Rand) { @@ -564,6 +616,16 @@ func TestLightningWireProtocol(t *testing.T) { return } + // 1/2 chance to attach a partial sig. + if r.Intn(2) == 0 { + req.PartialSig, err = randPartialSigWithNonce(r) + if err != nil { + t.Fatalf("unable to generate sig: %v", + err) + return + } + } + v[0] = reflect.ValueOf(req) }, MsgChannelReady: func(v []reflect.Value, r *rand.Rand) { @@ -581,8 +643,43 @@ func TestLightningWireProtocol(t *testing.T) { req := NewChannelReady(ChannelID(c), pubKey) + if r.Int31()%2 == 0 { + scid := NewShortChanIDFromInt(uint64(r.Int63())) + req.AliasScid = &scid + req.NextLocalNonce = randLocalNonce(r) + } + v[0] = reflect.ValueOf(*req) }, + MsgShutdown: func(v []reflect.Value, r *rand.Rand) { + var c [32]byte + _, err := r.Read(c[:]) + if err != nil { + t.Fatalf("unable to generate chan id: %v", err) + return + } + + shutdownAddr, err := randDeliveryAddress(r) + if err != nil { + t.Fatalf("unable to generate delivery "+ + "address: %v", err) + return + } + + req := Shutdown{ + ChannelID: ChannelID(c), + Address: shutdownAddr, + ExtraData: make([]byte, 0), + } + + if r.Int31()%2 == 0 { + req.ShutdownNonce = (*ShutdownNonce)( + randLocalNonce(r), + ) + } + + v[0] = reflect.ValueOf(req) + }, MsgClosingSigned: func(v []reflect.Value, r *rand.Rand) { req := ClosingSigned{ FeeSatoshis: btcutil.Amount(r.Int63()), @@ -600,6 +697,15 @@ func TestLightningWireProtocol(t *testing.T) { return } + if r.Int31()%2 == 0 { + req.PartialSig, err = randPartialSig(r) + if err != nil { + t.Fatalf("unable to generate sig: %v", + err) + return + } + } + v[0] = reflect.ValueOf(req) }, MsgCommitSig: func(v []reflect.Value, r *rand.Rand) { @@ -619,7 +725,7 @@ func TestLightningWireProtocol(t *testing.T) { // Only create the slice if there will be any signatures // in it to prevent false positive test failures due to // an empty slice versus a nil slice. - numSigs := uint16(r.Int31n(1020)) + numSigs := uint16(r.Int31n(1019)) if numSigs > 0 { req.HtlcSigs = make([]Sig, numSigs) } @@ -631,6 +737,16 @@ func TestLightningWireProtocol(t *testing.T) { } } + // 50/50 chance to attach a partial sig. + if r.Int31()%2 == 0 { + req.PartialSig, err = randPartialSigWithNonce(r) + if err != nil { + t.Fatalf("unable to generate sig: %v", + err) + return + } + } + v[0] = reflect.ValueOf(*req) }, MsgRevokeAndAck: func(v []reflect.Value, r *rand.Rand) { @@ -650,6 +766,11 @@ func TestLightningWireProtocol(t *testing.T) { return } + // 50/50 chance to attach a local nonce. + if r.Int31()%2 == 0 { + req.LocalNonce = randLocalNonce(r) + } + v[0] = reflect.ValueOf(*req) }, MsgChannelAnnouncement: func(v []reflect.Value, r *rand.Rand) { @@ -870,6 +991,8 @@ func TestLightningWireProtocol(t *testing.T) { t.Fatalf("unable to generate key: %v", err) return } + + req.LocalNonce = randLocalNonce(r) } v[0] = reflect.ValueOf(req) diff --git a/lnwire/signature.go b/lnwire/signature.go index 57c27e4d1..db6d59052 100644 --- a/lnwire/signature.go +++ b/lnwire/signature.go @@ -250,7 +250,7 @@ func (s *Sig) ToSignatureBytes() []byte { // For schnorr signatures, we can use the same internal 64 bytes. case sigTypeSchnorr: // We'll make a copy of the signature so we don't return a - // refrence into the raw slice. + // reference into the raw slice. var sig [64]byte copy(sig[:], s.bytes[:]) return sig[:] diff --git a/lnwire/signature_test.go b/lnwire/signature_test.go index eee5eb4a0..73263f1a6 100644 --- a/lnwire/signature_test.go +++ b/lnwire/signature_test.go @@ -26,7 +26,8 @@ func TestSignatureSerializeDeserialize(t *testing.T) { return err } - e2 := e2Input.(*ecdsa.Signature) + e2, ok := e2Input.(*ecdsa.Signature) + require.True(t, ok) if !e.IsEqual(e2) { return fmt.Errorf("pre/post-serialize sigs don't " + @@ -192,15 +193,19 @@ func TestNewSigFromRawSignature(t *testing.T) { expectedSig: Sig{ bytes: [64]byte{ // r value - 0x4e, 0x45, 0xe1, 0x69, 0x32, 0xb8, 0xaf, 0x51, - 0x49, 0x61, 0xa1, 0xd3, 0xa1, 0xa2, 0x5f, 0xdf, - 0x3f, 0x4f, 0x77, 0x32, 0xe9, 0xd6, 0x24, 0xc6, - 0xc6, 0x15, 0x48, 0xab, 0x5f, 0xb8, 0xcd, 0x41, + 0x4e, 0x45, 0xe1, 0x69, 0x32, 0xb8, + 0xaf, 0x51, 0x49, 0x61, 0xa1, 0xd3, + 0xa1, 0xa2, 0x5f, 0xdf, 0x3f, 0x4f, + 0x77, 0x32, 0xe9, 0xd6, 0x24, 0xc6, + 0xc6, 0x15, 0x48, 0xab, 0x5f, 0xb8, + 0xcd, 0x41, // s value - 0x18, 0x15, 0x22, 0xec, 0x8e, 0xca, 0x07, 0xde, - 0x48, 0x60, 0xa4, 0xac, 0xdd, 0x12, 0x90, 0x9d, - 0x83, 0x1c, 0xc5, 0x6c, 0xbb, 0xac, 0x46, 0x22, - 0x08, 0x22, 0x21, 0xa8, 0x76, 0x8d, 0x1d, 0x09, + 0x18, 0x15, 0x22, 0xec, 0x8e, 0xca, + 0x07, 0xde, 0x48, 0x60, 0xa4, 0xac, + 0xdd, 0x12, 0x90, 0x9d, 0x83, 0x1c, + 0xc5, 0x6c, 0xbb, 0xac, 0x46, 0x22, + 0x08, 0x22, 0x21, 0xa8, 0x76, 0x8d, + 0x1d, 0x09, }, }, },