Skip to content

Commit

Permalink
lnwire: update Sig to support both ECDSA and schnorr sigs
Browse files Browse the repository at this point in the history
In this commit, we update the Sig type to support ECDSA and schnorr
signatures. We need to do this as the HTLC signatures will become
schnorr sigs for taproot channels. The current spec draft opts to
overload this field since both the sigs are actually 64 bytes in length.
The only consideration with this move is that callers need to "coerce" a
sig to the proper type if they need schnorr signatures.
  • Loading branch information
Roasbeef committed Mar 15, 2023
1 parent df453ac commit 5e7a97c
Show file tree
Hide file tree
Showing 29 changed files with 297 additions and 126 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: 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
5 changes: 4 additions & 1 deletion lnwire/fuzz_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,10 @@ func FuzzNodeAnnouncement(f *testing.F) {
t.Fatal("new message was not NodeAnnouncement")
}

if !bytes.Equal(first.Signature[:], second.Signature[:]) {
if !bytes.Equal(
first.Signature.RawBytes(),
second.Signature.RawBytes(),
) {
shouldPanic = true
}

Expand Down
4 changes: 2 additions & 2 deletions lnwire/lnwire.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ func WriteElement(w *bytes.Buffer, element interface{}) error {

case Sig:
// Write buffer
if _, err := w.Write(e[:]); err != nil {
if _, err := w.Write(e.bytes[:]); err != nil {
return err
}

Expand Down Expand Up @@ -618,7 +618,7 @@ func ReadElement(r io.Reader, element interface{}) error {
*e = sigs

case *Sig:
if _, err := io.ReadFull(r, e[:]); err != nil {
if _, err := io.ReadFull(r, e.bytes[:]); err != nil {
return err
}

Expand Down

0 comments on commit 5e7a97c

Please sign in to comment.