Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[custom channels 3/5]: Extract PART3 from mega staging branch #9072

Merged
merged 21 commits into from
Sep 19, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
116a643
lnwallet: add new AuxFundingDesc struct
Roasbeef Apr 5, 2024
72beb79
lnwallet: use AuxFundingDesc to populate all custom chan info
Roasbeef Apr 5, 2024
84cc9a1
funding: create new AuxFundingController interface
Roasbeef Apr 5, 2024
65f54cb
config+serer: add AuxFundingController as top level cfg option
Roasbeef Apr 5, 2024
7144a1c
lnwallet: add TaprootInternalKey method to ShimIntent
Roasbeef Apr 16, 2024
bed4562
lnwallet: for PsbtIntent return the internal key in the POutput
Roasbeef Apr 16, 2024
7ec48a5
funding+lnwallet: only blind tapscript root early in funding flow
Roasbeef Apr 18, 2024
bcb6658
funding+lnwallet: finish hook up new aux funding flow
Roasbeef Apr 18, 2024
5c854a2
multi: add tapscript root to gossip message
guggero May 17, 2024
0b64b80
funding: inform aux controller about channel ready/finalize
guggero May 17, 2024
aa0c680
lnwallet: add new AuxSigner interface to mirror SigPool
Roasbeef Apr 9, 2024
953fb07
lnwallet: allow read-only access to HtlcView's HTLCs
guggero Sep 13, 2024
f52a163
lnwallet: clarify usage of cancel and response channels
guggero Sep 11, 2024
1e85c50
lnwallet: add WithAuxSigner option to channel
Roasbeef Apr 9, 2024
bd84fd2
lnwire: add custom records field to type `CommitSig`
guggero Sep 2, 2024
83fdbda
multi: obtain+verify aux sigs for all second level HTLCs
Roasbeef Apr 9, 2024
ea83300
lnwallet: sort sig jobs before submission
jharveyb Sep 8, 2024
5e1a98c
lnrpc+rpcserver: add and populate custom channel data
guggero May 17, 2024
d49da57
lnd: add aux data parser
guggero May 17, 2024
cdc3a4a
channeldb: add NextHeight, fix formatting
guggero May 27, 2024
52e50d8
htlcswitch: override amount check on custom records
guggero May 23, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 23 additions & 15 deletions lnwire/commit_sig.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ type CommitSig struct {
// being signed for. In this case, the above Sig type MUST be blank.
PartialSig OptPartialSigWithNonceTLV

// CustomRecords maps TLV types to byte slices, storing arbitrary data
// intended for inclusion in the ExtraData field.
CustomRecords CustomRecords

// ExtraData is the set of data that was appended to this message to
// fill out the full maximum transport message size. These fields can
// be used to specify optional data such as custom TLV fields.
Expand All @@ -53,9 +57,7 @@ type CommitSig struct {

// NewCommitSig creates a new empty CommitSig message.
func NewCommitSig() *CommitSig {
return &CommitSig{
ExtraData: make([]byte, 0),
}
return &CommitSig{}
}

// A compile time check to ensure CommitSig implements the lnwire.Message
Expand All @@ -67,34 +69,37 @@ var _ Message = (*CommitSig)(nil)
//
// This is part of the lnwire.Message interface.
func (c *CommitSig) Decode(r io.Reader, pver uint32) error {
// msgExtraData is a temporary variable used to read the message extra
// data field from the reader.
var msgExtraData ExtraOpaqueData

err := ReadElements(r,
&c.ChanID,
&c.CommitSig,
&c.HtlcSigs,
&msgExtraData,
)
if err != nil {
return err
}

var tlvRecords ExtraOpaqueData
if err := ReadElements(r, &tlvRecords); err != nil {
return err
}

// Extract TLV records from the extra data field.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was this commit pulled into an earlier version: 78f31da ?

Or was it just re-worked from scratch?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had it reworked from scratch... So we kind of did the same thing twice unfortunately.

partialSig := c.PartialSig.Zero()
typeMap, err := tlvRecords.ExtractRecords(&partialSig)

customRecords, parsed, extraData, err := ParseAndExtractCustomRecords(
msgExtraData, &partialSig,
)
if err != nil {
return err
}

// Set the corresponding TLV types if they were included in the stream.
if val, ok := typeMap[c.PartialSig.TlvType()]; ok && val == nil {
if _, ok := parsed[partialSig.TlvType()]; ok {
c.PartialSig = tlv.SomeRecordT(partialSig)
}

if len(tlvRecords) != 0 {
c.ExtraData = tlvRecords
}
c.CustomRecords = customRecords
c.ExtraData = extraData

return nil
}
Expand All @@ -108,7 +113,10 @@ func (c *CommitSig) Encode(w *bytes.Buffer, pver uint32) error {
c.PartialSig.WhenSome(func(sig PartialSigWithNonceTLV) {
recordProducers = append(recordProducers, &sig)
})
err := EncodeMessageExtraData(&c.ExtraData, recordProducers...)

extraData, err := MergeAndEncode(
recordProducers, c.ExtraData, c.CustomRecords,
)
if err != nil {
return err
}
Expand All @@ -125,7 +133,7 @@ func (c *CommitSig) Encode(w *bytes.Buffer, pver uint32) error {
return err
}

return WriteBytes(w, c.ExtraData)
return WriteBytes(w, extraData)
}

// MsgType returns the integer uniquely identifying this message type on the
Expand Down
168 changes: 168 additions & 0 deletions lnwire/commit_sig_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
package lnwire

import (
"bytes"
"fmt"
"testing"

"github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btcd/btcec/v2/schnorr/musig2"
"github.com/lightningnetwork/lnd/tlv"
"github.com/stretchr/testify/require"
)

// testCase is a test case for the CommitSig message.
type commitSigTestCase struct {
// Msg is the message to be encoded and decoded.
Msg CommitSig

// ExpectEncodeError is a flag that indicates whether we expect the
// encoding of the message to fail.
ExpectEncodeError bool
}

// generateCommitSigTestCases generates a set of CommitSig message test cases.
func generateCommitSigTestCases(t *testing.T) []commitSigTestCase {
// Firstly, we'll set basic values for the message fields.
//
// Generate random channel ID.
chanIDBytes, err := generateRandomBytes(32)
require.NoError(t, err)

var chanID ChannelID
copy(chanID[:], chanIDBytes)

// Generate random commit sig.
commitSigBytes, err := generateRandomBytes(64)
require.NoError(t, err)

sig, err := NewSigFromSchnorrRawSignature(commitSigBytes)
require.NoError(t, err)

sigScalar := new(btcec.ModNScalar)
sigScalar.SetByteSlice(sig.RawBytes())

var nonce [musig2.PubNonceSize]byte
copy(nonce[:], commitSigBytes)

sigWithNonce := NewPartialSigWithNonce(nonce, *sigScalar)
partialSig := MaybePartialSigWithNonce(sigWithNonce)

// Define custom records.
recordKey1 := uint64(MinCustomRecordsTlvType + 1)
recordValue1, err := generateRandomBytes(10)
require.NoError(t, err)

recordKey2 := uint64(MinCustomRecordsTlvType + 2)
recordValue2, err := generateRandomBytes(10)
require.NoError(t, err)

customRecords := CustomRecords{
recordKey1: recordValue1,
recordKey2: recordValue2,
}

// Construct an instance of extra data that contains records with TLV
// types below the minimum custom records threshold and that lack
// corresponding fields in the message struct. Content should persist in
// the extra data field after encoding and decoding.
var (
recordBytes45 = []byte("recordBytes45")
tlvRecord45 = tlv.NewPrimitiveRecord[tlv.TlvType45](
recordBytes45,
)

recordBytes55 = []byte("recordBytes55")
tlvRecord55 = tlv.NewPrimitiveRecord[tlv.TlvType55](
recordBytes55,
)
)

var extraData ExtraOpaqueData
err = extraData.PackRecords(
[]tlv.RecordProducer{&tlvRecord45, &tlvRecord55}...,
)
require.NoError(t, err)

invalidCustomRecords := CustomRecords{
MinCustomRecordsTlvType - 1: recordValue1,
}

return []commitSigTestCase{
{
Msg: CommitSig{
ChanID: chanID,
CommitSig: sig,
PartialSig: partialSig,
CustomRecords: customRecords,
ExtraData: extraData,
},
},
// Add a test case where the blinding point field is not
// populated.
{
Msg: CommitSig{
ChanID: chanID,
CommitSig: sig,
CustomRecords: customRecords,
},
},
// Add a test case where the custom records field is not
// populated.
{
Msg: CommitSig{
ChanID: chanID,
CommitSig: sig,
PartialSig: partialSig,
},
},
// Add a case where the custom records are invalid.
{
Msg: CommitSig{
ChanID: chanID,
CommitSig: sig,
PartialSig: partialSig,
CustomRecords: invalidCustomRecords,
},
ExpectEncodeError: true,
},
}
}

// TestCommitSigEncodeDecode tests CommitSig message encoding and decoding for
// all supported field values.
func TestCommitSigEncodeDecode(t *testing.T) {
t.Parallel()

// Generate test cases.
testCases := generateCommitSigTestCases(t)

// Execute test cases.
for tcIdx, tc := range testCases {
t.Run(fmt.Sprintf("testcase-%d", tcIdx), func(t *testing.T) {
// Encode test case message.
var buf bytes.Buffer
err := tc.Msg.Encode(&buf, 0)

// Check if we expect an encoding error.
if tc.ExpectEncodeError {
require.Error(t, err)
return
}

require.NoError(t, err)

// Decode the encoded message bytes message.
var actualMsg CommitSig
decodeReader := bytes.NewReader(buf.Bytes())
err = actualMsg.Decode(decodeReader, 0)
require.NoError(t, err)

// The signature type isn't serialized.
actualMsg.CommitSig.ForceSchnorr()

// Compare the two messages to ensure equality.
require.Equal(t, tc.Msg, actualMsg)
})
}
}
2 changes: 2 additions & 0 deletions lnwire/lnwire_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -945,6 +945,8 @@ func TestLightningWireProtocol(t *testing.T) {
}
}

req.CustomRecords = randCustomRecords(t, r)

// 50/50 chance to attach a partial sig.
if r.Int31()%2 == 0 {
req.PartialSig = somePartialSigWithNonce(t, r)
Expand Down