Skip to content

Commit

Permalink
Merge pull request #7331 from Roasbeef/simple-taproot-wire-msgs
Browse files Browse the repository at this point in the history
[3/?] - lnwire: add new TLV record types + messages for taproot chans
  • Loading branch information
Roasbeef committed Mar 15, 2023
2 parents fe24f19 + c9b962e commit ffe6383
Show file tree
Hide file tree
Showing 45 changed files with 1,121 additions and 147 deletions.
2 changes: 1 addition & 1 deletion channeldb/graph.go
Original file line number Diff line number Diff line change
Expand Up @@ -2726,7 +2726,7 @@ func (l *LightningNode) NodeAnnouncement(signed bool) (*lnwire.NodeAnnouncement,
return nodeAnn, nil
}

sig, err := lnwire.NewSigFromRawSignature(l.AuthSigBytes)
sig, err := lnwire.NewSigFromECDSARawSignature(l.AuthSigBytes)
if err != nil {
return nil, err
}
Expand Down
8 changes: 4 additions & 4 deletions discovery/gossiper.go
Original file line number Diff line number Diff line change
Expand Up @@ -2201,25 +2201,25 @@ func (d *AuthenticatedGossiper) updateChannel(info *channeldb.ChannelEdgeInfo,
BitcoinKey2: info.BitcoinKey2Bytes,
ExtraOpaqueData: edge.ExtraOpaqueData,
}
chanAnn.NodeSig1, err = lnwire.NewSigFromRawSignature(
chanAnn.NodeSig1, err = lnwire.NewSigFromECDSARawSignature(
info.AuthProof.NodeSig1Bytes,
)
if err != nil {
return nil, nil, err
}
chanAnn.NodeSig2, err = lnwire.NewSigFromRawSignature(
chanAnn.NodeSig2, err = lnwire.NewSigFromECDSARawSignature(
info.AuthProof.NodeSig2Bytes,
)
if err != nil {
return nil, nil, err
}
chanAnn.BitcoinSig1, err = lnwire.NewSigFromRawSignature(
chanAnn.BitcoinSig1, err = lnwire.NewSigFromECDSARawSignature(
info.AuthProof.BitcoinSig1Bytes,
)
if err != nil {
return nil, nil, err
}
chanAnn.BitcoinSig2, err = lnwire.NewSigFromRawSignature(
chanAnn.BitcoinSig2, err = lnwire.NewSigFromECDSARawSignature(
info.AuthProof.BitcoinSig2Bytes,
)
if err != nil {
Expand Down
10 changes: 10 additions & 0 deletions docs/release-notes/release-notes-0.17.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +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).

# Contributors (Alphabetical Order)

* Olaoluwa Osuntokun
10 changes: 8 additions & 2 deletions htlcswitch/link_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5374,9 +5374,15 @@ func TestChannelLinkFail(t *testing.T) {

// Flip a bit on the signature, rendering it
// invalid.
sig[19] ^= 1
sigCopy := sig.Copy()
copyBytes := sigCopy.RawBytes()
copyBytes[19] ^= 1
modifiedSig, err := lnwire.NewSigFromWireECDSA(
copyBytes,
)
require.NoError(t, err)
commitSig := &lnwire.CommitSig{
CommitSig: sig,
CommitSig: modifiedSig,
HtlcSigs: htlcSigs,
}

Expand Down
2 changes: 1 addition & 1 deletion lnrpc/routerrpc/router_backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -1283,7 +1283,7 @@ func marshallChannelUpdate(update *lnwire.ChannelUpdate) *lnrpc.ChannelUpdate {
}

return &lnrpc.ChannelUpdate{
Signature: update.Signature[:],
Signature: update.Signature.RawBytes(),
ChainHash: update.ChainHash[:],
ChanId: update.ShortChannelID.ToUint64(),
Timestamp: update.Timestamp,
Expand Down
2 changes: 1 addition & 1 deletion lnrpc/signrpc/signer_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -713,7 +713,7 @@ func (s *Server) VerifyMessage(_ context.Context,
}

// The signature must be fixed-size LN wire format encoded.
wireSig, err := lnwire.NewSigFromRawSignature(in.Signature)
wireSig, err := lnwire.NewSigFromECDSARawSignature(in.Signature)
if err != nil {
return nil, fmt.Errorf("failed to decode signature: %v", err)
}
Expand Down
10 changes: 6 additions & 4 deletions lnwallet/chancloser/chancloser.go
Original file line number Diff line number Diff line change
Expand Up @@ -785,16 +785,18 @@ func (c *ChanCloser) proposeCloseSigned(fee btcutil.Amount) (*lnwire.ClosingSign
return nil, err
}

// We'll note our last signature and proposed fee so when the remote party
// responds we'll be able to decide if we've agreed on fees or not.
// We'll note our last signature and proposed fee so when the remote
// party responds we'll be able to decide if we've agreed on fees or
// not.
c.lastFeeProposal = fee

parsedSig, err := lnwire.NewSigFromSignature(rawSig)
if err != nil {
return nil, err
}

chancloserLog.Infof("ChannelPoint(%v): proposing fee of %v sat to close "+
"chan", c.chanPoint, int64(fee))
chancloserLog.Infof("ChannelPoint(%v): proposing fee of %v sat to "+
"close chan", c.chanPoint, int64(fee))

// We'll assemble a ClosingSigned message using this information and return
// it to the caller so we can kick off the final stage of the channel
Expand Down
4 changes: 2 additions & 2 deletions lnwallet/channel.go
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ type PaymentDescriptor struct {
// local node. This signature is generated by the remote node and
// stored by the local node in the case that local node needs to
// broadcast their commitment transaction.
sig *ecdsa.Signature
sig input.Signature

// addCommitHeight[Remote|Local] encodes the height of the commitment
// which included this HTLC on either the remote or local commitment
Expand Down Expand Up @@ -4333,7 +4333,7 @@ func genHtlcSigValidationJobs(localCommitmentView *commitment,
var (
htlcIndex uint64
sigHash func() ([]byte, error)
sig *ecdsa.Signature
sig input.Signature
err error
)

Expand Down
6 changes: 5 additions & 1 deletion lnwallet/channel_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5331,7 +5331,11 @@ func TestInvalidCommitSigError(t *testing.T) {

// Before the signature gets to Bob, we'll mutate it, such that the
// signature is now actually invalid.
aliceSig[0] ^= 88
aliceSigCopy := aliceSig.Copy()
aliceSigCopyBytes := aliceSigCopy.RawBytes()
aliceSigCopyBytes[0] ^= 88
aliceSig, err = lnwire.NewSigFromWireECDSA(aliceSigCopyBytes)
require.NoError(t, err)

// Bob should reject this new state, and return the proper error.
err = bobChannel.ReceiveNewCommitment(aliceSig, aliceHtlcSigs)
Expand Down
15 changes: 12 additions & 3 deletions lnwallet/rpcwallet/rpcwallet.go
Original file line number Diff line number Diff line change
Expand Up @@ -453,11 +453,20 @@ func (r *RPCKeyRing) SignMessage(keyLoc keychain.KeyLocator,
"signer instance: %v", err)
}

wireSig, err := lnwire.NewSigFromRawSignature(resp.Signature)
wireSig, err := lnwire.NewSigFromECDSARawSignature(resp.Signature)
if err != nil {
return nil, fmt.Errorf("error parsing raw signature: %v", err)
return nil, fmt.Errorf("unable to create sig: %w", err)
}
return wireSig.ToSignature()
sig, err := wireSig.ToSignature()
if err != nil {
return nil, fmt.Errorf("unable to parse sig: %w", err)
}
ecdsaSig, ok := sig.(*ecdsa.Signature)
if !ok {
return nil, fmt.Errorf("unexpected signature type: %T", sig)
}

return ecdsaSig, nil
}

// SignMessageCompact signs the given message, single or double SHA256 hashing
Expand Down
3 changes: 1 addition & 2 deletions lnwallet/sigpool.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"sync"

"github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btcd/btcec/v2/ecdsa"
"github.com/btcsuite/btcd/wire"
"github.com/lightningnetwork/lnd/input"
"github.com/lightningnetwork/lnd/lnwire"
Expand Down Expand Up @@ -36,7 +35,7 @@ type VerifyJob struct {

// Sig is the raw signature generated using the above public key. This
// is the signature to be verified.
Sig *ecdsa.Signature
Sig input.Signature

// SigHash is a function closure generates the sighashes that the
// passed signature is known to have signed.
Expand Down
15 changes: 15 additions & 0 deletions lnwire/accept_channel.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,13 @@ type AcceptChannel struct {
// type.
LeaseExpiry *LeaseExpiry

// LocalNonce is an optional field that transmits the
// local/verification nonce for a party. This nonce will be used to
// verify the very first commitment transaction signature.
// This will only be populated if the simple taproot channels type was
// negotiated.
LocalNonce *Musig2Nonce

// 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 Down Expand Up @@ -134,6 +141,9 @@ func (a *AcceptChannel) Encode(w *bytes.Buffer, pver uint32) error {
if a.LeaseExpiry != nil {
recordProducers = append(recordProducers, a.LeaseExpiry)
}
if a.LocalNonce != nil {
recordProducers = append(recordProducers, a.LocalNonce)
}
err := EncodeMessageExtraData(&a.ExtraData, recordProducers...)
if err != nil {
return err
Expand Down Expand Up @@ -238,9 +248,11 @@ func (a *AcceptChannel) Decode(r io.Reader, pver uint32) error {
var (
chanType ChannelType
leaseExpiry LeaseExpiry
localNonce Musig2Nonce
)
typeMap, err := tlvRecords.ExtractRecords(
&a.UpfrontShutdownScript, &chanType, &leaseExpiry,
&localNonce,
)
if err != nil {
return err
Expand All @@ -253,6 +265,9 @@ func (a *AcceptChannel) Decode(r io.Reader, pver uint32) error {
if val, ok := typeMap[LeaseExpiryRecordType]; ok && val == nil {
a.LeaseExpiry = &leaseExpiry
}
if val, ok := typeMap[NonceRecordType]; ok && val == nil {
a.LocalNonce = &localNonce
}

a.ExtraData = tlvRecords

Expand Down
41 changes: 40 additions & 1 deletion lnwire/channel_reestablish.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"io"

"github.com/btcsuite/btcd/btcec/v2"
"github.com/lightningnetwork/lnd/tlv"
)

// ChannelReestablish is a message sent between peers that have an existing
Expand Down Expand Up @@ -62,6 +63,13 @@ type ChannelReestablish struct {
// current un-revoked commitment transaction of the sending party.
LocalUnrevokedCommitPoint *btcec.PublicKey

// LocalNonce is an optional field that stores a local musig2 nonce.
// This will only be populated if the simple taproot channels type was
// negotiated.
//
// TODO(roasbeef): rename to verification nonce
LocalNonce *Musig2Nonce

// 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 Down Expand Up @@ -108,6 +116,16 @@ func (a *ChannelReestablish) Encode(w *bytes.Buffer, pver uint32) error {
if err := WritePublicKey(w, a.LocalUnrevokedCommitPoint); err != nil {
return err
}

recordProducers := make([]tlv.RecordProducer, 0, 1)
if a.LocalNonce != nil {
recordProducers = append(recordProducers, a.LocalNonce)
}
err := EncodeMessageExtraData(&a.ExtraData, recordProducers...)
if err != nil {
return err
}

return WriteBytes(w, a.ExtraData)
}

Expand Down Expand Up @@ -156,7 +174,28 @@ func (a *ChannelReestablish) Decode(r io.Reader, pver uint32) error {
return err
}

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

var localNonce Musig2Nonce
typeMap, err := tlvRecords.ExtractRecords(
&localNonce,
)
if err != nil {
return err
}

if val, ok := typeMap[NonceRecordType]; ok && val == nil {
a.LocalNonce = &localNonce
}

if len(tlvRecords) != 0 {
a.ExtraData = tlvRecords
}

return nil
}

// MsgType returns the integer uniquely identifying this message type on the
Expand Down
49 changes: 47 additions & 2 deletions lnwire/closing_signed.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"io"

"github.com/btcsuite/btcd/btcutil"
"github.com/lightningnetwork/lnd/tlv"
)

// ClosingSigned is sent by both parties to a channel once the channel is clear
Expand All @@ -29,6 +30,14 @@ type ClosingSigned struct {
// Signature is for the proposed channel close transaction.
Signature Sig

// PartialSig is used to transmit a musig2 extended partial signature
// that signs the latest fee offer. The nonce isn't sent along side, as
// that has already been sent in the initial shutdown message.
//
// NOTE: This field is only populated if a musig2 taproot channel is
// being signed for. In this case, the above Sig type MUST be blank.
PartialSig *PartialSig

// 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 @@ -55,16 +64,52 @@ var _ Message = (*ClosingSigned)(nil)
//
// This is part of the lnwire.Message interface.
func (c *ClosingSigned) Decode(r io.Reader, pver uint32) error {
return ReadElements(
r, &c.ChannelID, &c.FeeSatoshis, &c.Signature, &c.ExtraData,
err := ReadElements(
r, &c.ChannelID, &c.FeeSatoshis, &c.Signature,
)
if err != nil {
return err
}

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

var (
partialSig PartialSig
)
typeMap, err := tlvRecords.ExtractRecords(&partialSig)
if err != nil {
return err
}

// Set the corresponding TLV types if they were included in the stream.
if val, ok := typeMap[PartialSigRecordType]; ok && val == nil {
c.PartialSig = &partialSig
}

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

return nil
}

// Encode serializes the target ClosingSigned into the passed io.Writer
// observing the protocol version specified.
//
// This is part of the lnwire.Message interface.
func (c *ClosingSigned) Encode(w *bytes.Buffer, pver uint32) error {
recordProducers := make([]tlv.RecordProducer, 0, 1)
if c.PartialSig != nil {
recordProducers = append(recordProducers, c.PartialSig)
}
err := EncodeMessageExtraData(&c.ExtraData, recordProducers...)
if err != nil {
return err
}

if err := WriteChannelID(w, c.ChannelID); err != nil {
return err
}
Expand Down

0 comments on commit ffe6383

Please sign in to comment.