mirror of
https://github.com/lightningnetwork/lnd.git
synced 2024-11-19 01:43:16 +01:00
lnwire: update Sig to support both ECDSA and schnorr sigs
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.
This commit is contained in:
parent
eccc77315b
commit
b368e476c5
@ -2727,7 +2727,7 @@ func (l *LightningNode) NodeAnnouncement(signed bool) (*lnwire.NodeAnnouncement,
|
|||||||
return nodeAnn, nil
|
return nodeAnn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
sig, err := lnwire.NewSigFromRawSignature(l.AuthSigBytes)
|
sig, err := lnwire.NewSigFromECDSARawSignature(l.AuthSigBytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -2199,25 +2199,25 @@ func (d *AuthenticatedGossiper) updateChannel(info *channeldb.ChannelEdgeInfo,
|
|||||||
BitcoinKey2: info.BitcoinKey2Bytes,
|
BitcoinKey2: info.BitcoinKey2Bytes,
|
||||||
ExtraOpaqueData: edge.ExtraOpaqueData,
|
ExtraOpaqueData: edge.ExtraOpaqueData,
|
||||||
}
|
}
|
||||||
chanAnn.NodeSig1, err = lnwire.NewSigFromRawSignature(
|
chanAnn.NodeSig1, err = lnwire.NewSigFromECDSARawSignature(
|
||||||
info.AuthProof.NodeSig1Bytes,
|
info.AuthProof.NodeSig1Bytes,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
chanAnn.NodeSig2, err = lnwire.NewSigFromRawSignature(
|
chanAnn.NodeSig2, err = lnwire.NewSigFromECDSARawSignature(
|
||||||
info.AuthProof.NodeSig2Bytes,
|
info.AuthProof.NodeSig2Bytes,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
chanAnn.BitcoinSig1, err = lnwire.NewSigFromRawSignature(
|
chanAnn.BitcoinSig1, err = lnwire.NewSigFromECDSARawSignature(
|
||||||
info.AuthProof.BitcoinSig1Bytes,
|
info.AuthProof.BitcoinSig1Bytes,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
chanAnn.BitcoinSig2, err = lnwire.NewSigFromRawSignature(
|
chanAnn.BitcoinSig2, err = lnwire.NewSigFromECDSARawSignature(
|
||||||
info.AuthProof.BitcoinSig2Bytes,
|
info.AuthProof.BitcoinSig2Bytes,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -5494,9 +5494,15 @@ func TestChannelLinkFail(t *testing.T) {
|
|||||||
|
|
||||||
// Flip a bit on the signature, rendering it
|
// Flip a bit on the signature, rendering it
|
||||||
// invalid.
|
// 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 := &lnwire.CommitSig{
|
||||||
CommitSig: sig,
|
CommitSig: modifiedSig,
|
||||||
HtlcSigs: htlcSigs,
|
HtlcSigs: htlcSigs,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1283,7 +1283,7 @@ func marshallChannelUpdate(update *lnwire.ChannelUpdate) *lnrpc.ChannelUpdate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &lnrpc.ChannelUpdate{
|
return &lnrpc.ChannelUpdate{
|
||||||
Signature: update.Signature[:],
|
Signature: update.Signature.RawBytes(),
|
||||||
ChainHash: update.ChainHash[:],
|
ChainHash: update.ChainHash[:],
|
||||||
ChanId: update.ShortChannelID.ToUint64(),
|
ChanId: update.ShortChannelID.ToUint64(),
|
||||||
Timestamp: update.Timestamp,
|
Timestamp: update.Timestamp,
|
||||||
|
@ -713,7 +713,7 @@ func (s *Server) VerifyMessage(_ context.Context,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The signature must be fixed-size LN wire format encoded.
|
// 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 {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to decode signature: %v", err)
|
return nil, fmt.Errorf("failed to decode signature: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -785,16 +785,18 @@ func (c *ChanCloser) proposeCloseSigned(fee btcutil.Amount) (*lnwire.ClosingSign
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// We'll note our last signature and proposed fee so when the remote party
|
// We'll note our last signature and proposed fee so when the remote
|
||||||
// responds we'll be able to decide if we've agreed on fees or not.
|
// party responds we'll be able to decide if we've agreed on fees or
|
||||||
|
// not.
|
||||||
c.lastFeeProposal = fee
|
c.lastFeeProposal = fee
|
||||||
|
|
||||||
parsedSig, err := lnwire.NewSigFromSignature(rawSig)
|
parsedSig, err := lnwire.NewSigFromSignature(rawSig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
chancloserLog.Infof("ChannelPoint(%v): proposing fee of %v sat to close "+
|
chancloserLog.Infof("ChannelPoint(%v): proposing fee of %v sat to "+
|
||||||
"chan", c.chanPoint, int64(fee))
|
"close chan", c.chanPoint, int64(fee))
|
||||||
|
|
||||||
// We'll assemble a ClosingSigned message using this information and return
|
// 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
|
// it to the caller so we can kick off the final stage of the channel
|
||||||
|
@ -320,7 +320,7 @@ type PaymentDescriptor struct {
|
|||||||
// local node. This signature is generated by the remote node and
|
// local node. This signature is generated by the remote node and
|
||||||
// stored by the local node in the case that local node needs to
|
// stored by the local node in the case that local node needs to
|
||||||
// broadcast their commitment transaction.
|
// broadcast their commitment transaction.
|
||||||
sig *ecdsa.Signature
|
sig input.Signature
|
||||||
|
|
||||||
// addCommitHeight[Remote|Local] encodes the height of the commitment
|
// addCommitHeight[Remote|Local] encodes the height of the commitment
|
||||||
// which included this HTLC on either the remote or local commitment
|
// which included this HTLC on either the remote or local commitment
|
||||||
@ -4331,7 +4331,7 @@ func genHtlcSigValidationJobs(localCommitmentView *commitment,
|
|||||||
var (
|
var (
|
||||||
htlcIndex uint64
|
htlcIndex uint64
|
||||||
sigHash func() ([]byte, error)
|
sigHash func() ([]byte, error)
|
||||||
sig *ecdsa.Signature
|
sig input.Signature
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -5331,7 +5331,11 @@ func TestInvalidCommitSigError(t *testing.T) {
|
|||||||
|
|
||||||
// Before the signature gets to Bob, we'll mutate it, such that the
|
// Before the signature gets to Bob, we'll mutate it, such that the
|
||||||
// signature is now actually invalid.
|
// 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.
|
// Bob should reject this new state, and return the proper error.
|
||||||
err = bobChannel.ReceiveNewCommitment(aliceSig, aliceHtlcSigs)
|
err = bobChannel.ReceiveNewCommitment(aliceSig, aliceHtlcSigs)
|
||||||
|
@ -454,11 +454,20 @@ func (r *RPCKeyRing) SignMessage(keyLoc keychain.KeyLocator,
|
|||||||
"signer instance: %v", err)
|
"signer instance: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
wireSig, err := lnwire.NewSigFromRawSignature(resp.Signature)
|
wireSig, err := lnwire.NewSigFromECDSARawSignature(resp.Signature)
|
||||||
if err != nil {
|
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
|
// SignMessageCompact signs the given message, single or double SHA256 hashing
|
||||||
|
@ -5,7 +5,6 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/btcec/v2"
|
"github.com/btcsuite/btcd/btcec/v2"
|
||||||
"github.com/btcsuite/btcd/btcec/v2/ecdsa"
|
|
||||||
"github.com/btcsuite/btcd/wire"
|
"github.com/btcsuite/btcd/wire"
|
||||||
"github.com/lightningnetwork/lnd/input"
|
"github.com/lightningnetwork/lnd/input"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
@ -36,7 +35,7 @@ type VerifyJob struct {
|
|||||||
|
|
||||||
// Sig is the raw signature generated using the above public key. This
|
// Sig is the raw signature generated using the above public key. This
|
||||||
// is the signature to be verified.
|
// is the signature to be verified.
|
||||||
Sig *ecdsa.Signature
|
Sig input.Signature
|
||||||
|
|
||||||
// SigHash is a function closure generates the sighashes that the
|
// SigHash is a function closure generates the sighashes that the
|
||||||
// passed signature is known to have signed.
|
// passed signature is known to have signed.
|
||||||
|
@ -596,12 +596,12 @@ func FuzzCustomMessage(f *testing.F) {
|
|||||||
// does not mutate them.
|
// does not mutate them.
|
||||||
func FuzzParseRawSignature(f *testing.F) {
|
func FuzzParseRawSignature(f *testing.F) {
|
||||||
f.Fuzz(func(t *testing.T, data []byte) {
|
f.Fuzz(func(t *testing.T, data []byte) {
|
||||||
sig, err := NewSigFromRawSignature(data)
|
sig, err := NewSigFromECDSARawSignature(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
sig2, err := NewSigFromRawSignature(sig.ToSignatureBytes())
|
sig2, err := NewSigFromECDSARawSignature(sig.ToSignatureBytes())
|
||||||
require.NoError(t, err, "failed to reparse signature")
|
require.NoError(t, err, "failed to reparse signature")
|
||||||
|
|
||||||
require.Equal(t, sig, sig2, "signature mismatch")
|
require.Equal(t, sig, sig2, "signature mismatch")
|
||||||
@ -614,10 +614,10 @@ func FuzzParseRawSignature(f *testing.F) {
|
|||||||
func FuzzConvertFixedSignature(f *testing.F) {
|
func FuzzConvertFixedSignature(f *testing.F) {
|
||||||
f.Fuzz(func(t *testing.T, data []byte) {
|
f.Fuzz(func(t *testing.T, data []byte) {
|
||||||
var sig Sig
|
var sig Sig
|
||||||
if len(data) > len(sig) {
|
if len(data) > len(sig.bytes[:]) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
copy(sig[:], data)
|
copy(sig.bytes[:], data)
|
||||||
|
|
||||||
derSig, err := sig.ToSignature()
|
derSig, err := sig.ToSignature()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -183,7 +183,7 @@ func WriteElement(w *bytes.Buffer, element interface{}) error {
|
|||||||
|
|
||||||
case Sig:
|
case Sig:
|
||||||
// Write buffer
|
// Write buffer
|
||||||
if _, err := w.Write(e[:]); err != nil {
|
if _, err := w.Write(e.bytes[:]); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -618,7 +618,7 @@ func ReadElement(r io.Reader, element interface{}) error {
|
|||||||
*e = sigs
|
*e = sigs
|
||||||
|
|
||||||
case *Sig:
|
case *Sig:
|
||||||
if _, err := io.ReadFull(r, e[:]); err != nil {
|
if _, err := io.ReadFull(r, e.bytes[:]); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,15 +5,10 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/btcec/v2/ecdsa"
|
"github.com/btcsuite/btcd/btcec/v2/ecdsa"
|
||||||
|
"github.com/btcsuite/btcd/btcec/v2/schnorr"
|
||||||
"github.com/lightningnetwork/lnd/input"
|
"github.com/lightningnetwork/lnd/input"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Sig is a fixed-sized ECDSA signature. Unlike Bitcoin, we use fixed sized
|
|
||||||
// signatures on the wire, instead of DER encoded signatures. This type
|
|
||||||
// provides several methods to convert to/from a regular Bitcoin DER encoded
|
|
||||||
// signature (raw bytes and *ecdsa.Signature).
|
|
||||||
type Sig [64]byte
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
errSigTooShort = errors.New("malformed signature: too short")
|
errSigTooShort = errors.New("malformed signature: too short")
|
||||||
errBadLength = errors.New("malformed signature: bad length")
|
errBadLength = errors.New("malformed signature: bad length")
|
||||||
@ -23,14 +18,74 @@ var (
|
|||||||
errSTooLong = errors.New("S is over 32 bytes long without padding")
|
errSTooLong = errors.New("S is over 32 bytes long without padding")
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewSigFromRawSignature returns a Sig from a Bitcoin raw signature encoded in
|
// sigType represents the type of signature that is carried within the Sig.
|
||||||
// the canonical DER encoding.
|
// Today this can either be an ECDSA sig or a schnorr sig. Both of these can
|
||||||
func NewSigFromRawSignature(sig []byte) (Sig, error) {
|
// fit cleanly into 64 bytes.
|
||||||
var b Sig
|
type sigType uint
|
||||||
|
|
||||||
|
const (
|
||||||
|
// sigTypeECDSA represents an ECDSA signature.
|
||||||
|
sigTypeECDSA sigType = iota
|
||||||
|
|
||||||
|
// sigTypeSchnorr represents a schnorr signature.
|
||||||
|
sigTypeSchnorr
|
||||||
|
)
|
||||||
|
|
||||||
|
// Sig is a fixed-sized ECDSA signature or 64-byte schnorr signature. For the
|
||||||
|
// ECDSA sig, unlike Bitcoin, we use fixed sized signatures on the wire,
|
||||||
|
// instead of DER encoded signatures. This type provides several methods to
|
||||||
|
// convert to/from a regular Bitcoin DER encoded signature (raw bytes and
|
||||||
|
// *ecdsa.Signature).
|
||||||
|
type Sig struct {
|
||||||
|
bytes [64]byte
|
||||||
|
|
||||||
|
sigType sigType
|
||||||
|
}
|
||||||
|
|
||||||
|
// ForceSchnorr forces the signature to be interpreted as a schnorr signature.
|
||||||
|
// This is useful when reading an HTLC sig off the wire for a taproot channel.
|
||||||
|
// In this case, in order to obtain an input.Signature, we need to know that
|
||||||
|
// the sig is a schnorr sig.
|
||||||
|
func (s *Sig) ForceSchnorr() {
|
||||||
|
s.sigType = sigTypeSchnorr
|
||||||
|
}
|
||||||
|
|
||||||
|
// RawBytes returns the raw bytes of signature.
|
||||||
|
func (s *Sig) RawBytes() []byte {
|
||||||
|
return s.bytes[:]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy copies the signature into a new Sig instance.
|
||||||
|
func (s *Sig) Copy() Sig {
|
||||||
|
var sCopy Sig
|
||||||
|
copy(sCopy.bytes[:], s.bytes[:])
|
||||||
|
sCopy.sigType = s.sigType
|
||||||
|
|
||||||
|
return sCopy
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSigFromWireECDSA returns a Sig instance based on an ECDSA signature
|
||||||
|
// that's already in the 64-byte format we expect.
|
||||||
|
func NewSigFromWireECDSA(sig []byte) (Sig, error) {
|
||||||
|
if len(sig) != 64 {
|
||||||
|
return Sig{}, fmt.Errorf("%w: %v bytes", errSigTooShort,
|
||||||
|
len(sig))
|
||||||
|
}
|
||||||
|
|
||||||
|
var s Sig
|
||||||
|
copy(s.bytes[:], sig)
|
||||||
|
|
||||||
|
return s, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSigFromECDSARawSignature returns a Sig from a Bitcoin raw signature
|
||||||
|
// encoded in the canonical DER encoding.
|
||||||
|
func NewSigFromECDSARawSignature(sig []byte) (Sig, error) {
|
||||||
|
var b [64]byte
|
||||||
|
|
||||||
// Check the total length is above the minimal.
|
// Check the total length is above the minimal.
|
||||||
if len(sig) < ecdsa.MinSigLen {
|
if len(sig) < ecdsa.MinSigLen {
|
||||||
return b, errSigTooShort
|
return Sig{}, errSigTooShort
|
||||||
}
|
}
|
||||||
|
|
||||||
// The DER representation is laid out as:
|
// The DER representation is laid out as:
|
||||||
@ -46,7 +101,7 @@ func NewSigFromRawSignature(sig []byte) (Sig, error) {
|
|||||||
// siglen should be less than the entire message and greater than
|
// siglen should be less than the entire message and greater than
|
||||||
// the minimal message size.
|
// the minimal message size.
|
||||||
if sigLen+2 > len(sig) || sigLen+2 < ecdsa.MinSigLen {
|
if sigLen+2 > len(sig) || sigLen+2 < ecdsa.MinSigLen {
|
||||||
return b, errBadLength
|
return Sig{}, errBadLength
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reading <length r>, remaining: [r 0x02 <length s> s]
|
// Reading <length r>, remaining: [r 0x02 <length s> s]
|
||||||
@ -56,7 +111,7 @@ func NewSigFromRawSignature(sig []byte) (Sig, error) {
|
|||||||
// Assuming s is one byte, then we have 0x30, <length>, 0x20,
|
// Assuming s is one byte, then we have 0x30, <length>, 0x20,
|
||||||
// <length r>, 0x20, <length s>, s, a total of 7 bytes.
|
// <length r>, 0x20, <length s>, s, a total of 7 bytes.
|
||||||
if rLen <= 0 || rLen+7 > len(sig) {
|
if rLen <= 0 || rLen+7 > len(sig) {
|
||||||
return b, errBadRLength
|
return Sig{}, errBadRLength
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reading <length s>, remaining: [s]
|
// Reading <length s>, remaining: [s]
|
||||||
@ -67,7 +122,7 @@ func NewSigFromRawSignature(sig []byte) (Sig, error) {
|
|||||||
// We know r is rLen bytes, and we have 0x30, <length>, 0x20,
|
// We know r is rLen bytes, and we have 0x30, <length>, 0x20,
|
||||||
// <length r>, 0x20, <length s>, a total of rLen+6 bytes.
|
// <length r>, 0x20, <length s>, a total of rLen+6 bytes.
|
||||||
if sLen <= 0 || sLen+rLen+6 > len(sig) {
|
if sLen <= 0 || sLen+rLen+6 > len(sig) {
|
||||||
return b, errBadSLength
|
return Sig{}, errBadSLength
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check to make sure R and S can both fit into their intended buffers.
|
// Check to make sure R and S can both fit into their intended buffers.
|
||||||
@ -78,7 +133,7 @@ func NewSigFromRawSignature(sig []byte) (Sig, error) {
|
|||||||
// check S first.
|
// check S first.
|
||||||
if sLen > 32 {
|
if sLen > 32 {
|
||||||
if (sLen > 33) || (sig[6+rLen] != 0x00) {
|
if (sLen > 33) || (sig[6+rLen] != 0x00) {
|
||||||
return b, errSTooLong
|
return Sig{}, errSTooLong
|
||||||
}
|
}
|
||||||
sLen--
|
sLen--
|
||||||
copy(b[64-sLen:], sig[7+rLen:])
|
copy(b[64-sLen:], sig[7+rLen:])
|
||||||
@ -89,7 +144,7 @@ func NewSigFromRawSignature(sig []byte) (Sig, error) {
|
|||||||
// Do the same for R as we did for S
|
// Do the same for R as we did for S
|
||||||
if rLen > 32 {
|
if rLen > 32 {
|
||||||
if (rLen > 33) || (sig[4] != 0x00) {
|
if (rLen > 33) || (sig[4] != 0x00) {
|
||||||
return b, errRTooLong
|
return Sig{}, errRTooLong
|
||||||
}
|
}
|
||||||
rLen--
|
rLen--
|
||||||
copy(b[32-rLen:], sig[5:5+rLen])
|
copy(b[32-rLen:], sig[5:5+rLen])
|
||||||
@ -97,11 +152,24 @@ func NewSigFromRawSignature(sig []byte) (Sig, error) {
|
|||||||
copy(b[32-rLen:], sig[4:4+rLen])
|
copy(b[32-rLen:], sig[4:4+rLen])
|
||||||
}
|
}
|
||||||
|
|
||||||
return b, nil
|
return Sig{
|
||||||
|
bytes: b,
|
||||||
|
sigType: sigTypeECDSA,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSigFromSchnorrRawSignature converts a raw schnorr signature into an
|
||||||
|
// lnwire.Sig.
|
||||||
|
func NewSigFromSchnorrRawSignature(sig []byte) (Sig, error) {
|
||||||
|
var s Sig
|
||||||
|
copy(s.bytes[:], sig)
|
||||||
|
s.sigType = sigTypeSchnorr
|
||||||
|
|
||||||
|
return s, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewSigFromSignature creates a new signature as used on the wire, from an
|
// NewSigFromSignature creates a new signature as used on the wire, from an
|
||||||
// existing ecdsa.Signature.
|
// existing ecdsa.Signature or schnorr.Signature.
|
||||||
func NewSigFromSignature(e input.Signature) (Sig, error) {
|
func NewSigFromSignature(e input.Signature) (Sig, error) {
|
||||||
if e == nil {
|
if e == nil {
|
||||||
return Sig{}, fmt.Errorf("cannot decode empty signature")
|
return Sig{}, fmt.Errorf("cannot decode empty signature")
|
||||||
@ -113,45 +181,85 @@ func NewSigFromSignature(e input.Signature) (Sig, error) {
|
|||||||
return Sig{}, fmt.Errorf("cannot decode empty signature")
|
return Sig{}, fmt.Errorf("cannot decode empty signature")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Serialize the signature with all the checks that entails.
|
switch ecSig := e.(type) {
|
||||||
return NewSigFromRawSignature(e.Serialize())
|
// If this is a schnorr signature, then we can just pack it as normal,
|
||||||
}
|
// since the default encoding is already 64 bytes.
|
||||||
|
case *schnorr.Signature:
|
||||||
|
return NewSigFromSchnorrRawSignature(e.Serialize())
|
||||||
|
|
||||||
// ToSignature converts the fixed-sized signature to a ecdsa.Signature objects
|
// For ECDSA signatures, we'll need to do a bit more work to map the
|
||||||
// which can be used for signature validation checks.
|
// signature into a compact 64 byte form.
|
||||||
func (b *Sig) ToSignature() (*ecdsa.Signature, error) {
|
case *ecdsa.Signature:
|
||||||
// Parse the signature with strict checks.
|
// Serialize the signature with all the checks that entails.
|
||||||
sigBytes := b.ToSignatureBytes()
|
return NewSigFromECDSARawSignature(e.Serialize())
|
||||||
sig, err := ecdsa.ParseDERSignature(sigBytes)
|
|
||||||
if err != nil {
|
default:
|
||||||
return nil, err
|
return Sig{}, fmt.Errorf("unknown wire sig type: %T", ecSig)
|
||||||
}
|
}
|
||||||
|
|
||||||
return sig, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToSignatureBytes serializes the target fixed-sized signature into the raw
|
// ToSignature converts the fixed-sized signature to a input.Signature which
|
||||||
// bytes of a DER encoding.
|
// can be used for signature validation checks.
|
||||||
func (b *Sig) ToSignatureBytes() []byte {
|
func (s *Sig) ToSignature() (input.Signature, error) {
|
||||||
// Extract canonically-padded bigint representations from buffer
|
switch s.sigType {
|
||||||
r := extractCanonicalPadding(b[0:32])
|
case sigTypeSchnorr:
|
||||||
s := extractCanonicalPadding(b[32:64])
|
return schnorr.ParseSignature(s.bytes[:])
|
||||||
rLen := uint8(len(r))
|
|
||||||
sLen := uint8(len(s))
|
|
||||||
|
|
||||||
// Create a canonical serialized signature. DER format is:
|
case sigTypeECDSA:
|
||||||
// 0x30 <length> 0x02 <length r> r 0x02 <length s> s
|
// Parse the signature with strict checks.
|
||||||
sigBytes := make([]byte, 6+rLen+sLen)
|
sigBytes := s.ToSignatureBytes()
|
||||||
sigBytes[0] = 0x30 // DER signature magic value
|
sig, err := ecdsa.ParseDERSignature(sigBytes)
|
||||||
sigBytes[1] = 4 + rLen + sLen // Length of rest of signature
|
if err != nil {
|
||||||
sigBytes[2] = 0x02 // Big integer magic value
|
return nil, err
|
||||||
sigBytes[3] = rLen // Length of R
|
}
|
||||||
sigBytes[rLen+4] = 0x02 // Big integer magic value
|
|
||||||
sigBytes[rLen+5] = sLen // Length of S
|
|
||||||
copy(sigBytes[4:], r) // Copy R
|
|
||||||
copy(sigBytes[rLen+6:], s) // Copy S
|
|
||||||
|
|
||||||
return sigBytes
|
return sig, nil
|
||||||
|
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("unknown sig type: %v", s.sigType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToSignatureBytes serializes the target fixed-sized signature into the
|
||||||
|
// encoding of the primary domain for the signature. For ECDSA signatures, this
|
||||||
|
// is the raw bytes of a DER encoding.
|
||||||
|
func (s *Sig) ToSignatureBytes() []byte {
|
||||||
|
switch s.sigType {
|
||||||
|
// For ECDSA signatures, we'll convert to DER encoding.
|
||||||
|
case sigTypeECDSA:
|
||||||
|
// Extract canonically-padded bigint representations from buffer
|
||||||
|
r := extractCanonicalPadding(s.bytes[0:32])
|
||||||
|
s := extractCanonicalPadding(s.bytes[32:64])
|
||||||
|
rLen := uint8(len(r))
|
||||||
|
sLen := uint8(len(s))
|
||||||
|
|
||||||
|
// Create a canonical serialized signature. DER format is:
|
||||||
|
// 0x30 <length> 0x02 <length r> r 0x02 <length s> s
|
||||||
|
sigBytes := make([]byte, 6+rLen+sLen)
|
||||||
|
sigBytes[0] = 0x30 // DER signature magic value
|
||||||
|
sigBytes[1] = 4 + rLen + sLen // Length of rest of signature
|
||||||
|
sigBytes[2] = 0x02 // Big integer magic value
|
||||||
|
sigBytes[3] = rLen // Length of R
|
||||||
|
sigBytes[rLen+4] = 0x02 // Big integer magic value
|
||||||
|
sigBytes[rLen+5] = sLen // Length of S
|
||||||
|
copy(sigBytes[4:], r) // Copy R
|
||||||
|
copy(sigBytes[rLen+6:], s) // Copy S
|
||||||
|
|
||||||
|
return sigBytes
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
var sig [64]byte
|
||||||
|
copy(sig[:], s.bytes[:])
|
||||||
|
return sig[:]
|
||||||
|
|
||||||
|
default:
|
||||||
|
// TODO(roasbeef): can only be called via public methods so
|
||||||
|
// never reachable?
|
||||||
|
panic("sig type not set")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// extractCanonicalPadding is a utility function to extract the canonical
|
// extractCanonicalPadding is a utility function to extract the canonical
|
||||||
|
@ -21,11 +21,13 @@ func TestSignatureSerializeDeserialize(t *testing.T) {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
e2, err := sig.ToSignature()
|
e2Input, err := sig.ToSignature()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
e2 := e2Input.(*ecdsa.Signature)
|
||||||
|
|
||||||
if !e.IsEqual(e2) {
|
if !e.IsEqual(e2) {
|
||||||
return fmt.Errorf("pre/post-serialize sigs don't " +
|
return fmt.Errorf("pre/post-serialize sigs don't " +
|
||||||
"match")
|
"match")
|
||||||
@ -188,16 +190,18 @@ func TestNewSigFromRawSignature(t *testing.T) {
|
|||||||
rawSig: normalSig,
|
rawSig: normalSig,
|
||||||
expectedErr: nil,
|
expectedErr: nil,
|
||||||
expectedSig: Sig{
|
expectedSig: Sig{
|
||||||
// r value
|
bytes: [64]byte{
|
||||||
0x4e, 0x45, 0xe1, 0x69, 0x32, 0xb8, 0xaf, 0x51,
|
// r value
|
||||||
0x49, 0x61, 0xa1, 0xd3, 0xa1, 0xa2, 0x5f, 0xdf,
|
0x4e, 0x45, 0xe1, 0x69, 0x32, 0xb8, 0xaf, 0x51,
|
||||||
0x3f, 0x4f, 0x77, 0x32, 0xe9, 0xd6, 0x24, 0xc6,
|
0x49, 0x61, 0xa1, 0xd3, 0xa1, 0xa2, 0x5f, 0xdf,
|
||||||
0xc6, 0x15, 0x48, 0xab, 0x5f, 0xb8, 0xcd, 0x41,
|
0x3f, 0x4f, 0x77, 0x32, 0xe9, 0xd6, 0x24, 0xc6,
|
||||||
// s value
|
0xc6, 0x15, 0x48, 0xab, 0x5f, 0xb8, 0xcd, 0x41,
|
||||||
0x18, 0x15, 0x22, 0xec, 0x8e, 0xca, 0x07, 0xde,
|
// s value
|
||||||
0x48, 0x60, 0xa4, 0xac, 0xdd, 0x12, 0x90, 0x9d,
|
0x18, 0x15, 0x22, 0xec, 0x8e, 0xca, 0x07, 0xde,
|
||||||
0x83, 0x1c, 0xc5, 0x6c, 0xbb, 0xac, 0x46, 0x22,
|
0x48, 0x60, 0xa4, 0xac, 0xdd, 0x12, 0x90, 0x9d,
|
||||||
0x08, 0x22, 0x21, 0xa8, 0x76, 0x8d, 0x1d, 0x09,
|
0x83, 0x1c, 0xc5, 0x6c, 0xbb, 0xac, 0x46, 0x22,
|
||||||
|
0x08, 0x22, 0x21, 0xa8, 0x76, 0x8d, 0x1d, 0x09,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -266,7 +270,7 @@ func TestNewSigFromRawSignature(t *testing.T) {
|
|||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
tc := tc
|
tc := tc
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
result, err := NewSigFromRawSignature(tc.rawSig)
|
result, err := NewSigFromECDSARawSignature(tc.rawSig)
|
||||||
require.Equal(t, tc.expectedErr, err)
|
require.Equal(t, tc.expectedErr, err)
|
||||||
require.Equal(t, tc.expectedSig, result)
|
require.Equal(t, tc.expectedSig, result)
|
||||||
})
|
})
|
||||||
|
@ -154,7 +154,7 @@ func WriteShortChannelID(buf *bytes.Buffer, shortChanID ShortChannelID) error {
|
|||||||
|
|
||||||
// WriteSig appends the signature to the provided buffer.
|
// WriteSig appends the signature to the provided buffer.
|
||||||
func WriteSig(buf *bytes.Buffer, sig Sig) error {
|
func WriteSig(buf *bytes.Buffer, sig Sig) error {
|
||||||
return WriteBytes(buf, sig[:])
|
return WriteBytes(buf, sig.bytes[:])
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteSigs appends the slice of signatures to the provided buffer with its
|
// WriteSigs appends the slice of signatures to the provided buffer with its
|
||||||
|
@ -147,7 +147,9 @@ func TestWriteShortChannelID(t *testing.T) {
|
|||||||
|
|
||||||
func TestWriteSig(t *testing.T) {
|
func TestWriteSig(t *testing.T) {
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
data := Sig{1, 2, 3}
|
data := Sig{
|
||||||
|
bytes: [64]byte{1, 2, 3},
|
||||||
|
}
|
||||||
expectedBytes := [64]byte{1, 2, 3}
|
expectedBytes := [64]byte{1, 2, 3}
|
||||||
|
|
||||||
err := WriteSig(buf, data)
|
err := WriteSig(buf, data)
|
||||||
@ -158,14 +160,14 @@ func TestWriteSig(t *testing.T) {
|
|||||||
|
|
||||||
func TestWriteSigs(t *testing.T) {
|
func TestWriteSigs(t *testing.T) {
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
sig1, sig2, sig3 := Sig{1}, Sig{2}, Sig{3}
|
sig1, sig2, sig3 := Sig{bytes: [64]byte{1}}, Sig{bytes: [64]byte{2}}, Sig{bytes: [64]byte{3}}
|
||||||
data := []Sig{sig1, sig2, sig3}
|
data := []Sig{sig1, sig2, sig3}
|
||||||
|
|
||||||
// First two bytes encode the length of the slice.
|
// First two bytes encode the length of the slice.
|
||||||
expectedBytes := []byte{0, 3}
|
expectedBytes := []byte{0, 3}
|
||||||
expectedBytes = append(expectedBytes, sig1[:]...)
|
expectedBytes = append(expectedBytes, sig1.bytes[:]...)
|
||||||
expectedBytes = append(expectedBytes, sig2[:]...)
|
expectedBytes = append(expectedBytes, sig2.bytes[:]...)
|
||||||
expectedBytes = append(expectedBytes, sig3[:]...)
|
expectedBytes = append(expectedBytes, sig3.bytes[:]...)
|
||||||
|
|
||||||
err := WriteSigs(buf, data)
|
err := WriteSigs(buf, data)
|
||||||
|
|
||||||
|
@ -36,25 +36,25 @@ func CreateChanAnnouncement(chanProof *channeldb.ChannelAuthProof,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
chanAnn.BitcoinSig1, err = lnwire.NewSigFromRawSignature(
|
chanAnn.BitcoinSig1, err = lnwire.NewSigFromECDSARawSignature(
|
||||||
chanProof.BitcoinSig1Bytes,
|
chanProof.BitcoinSig1Bytes,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
chanAnn.BitcoinSig2, err = lnwire.NewSigFromRawSignature(
|
chanAnn.BitcoinSig2, err = lnwire.NewSigFromECDSARawSignature(
|
||||||
chanProof.BitcoinSig2Bytes,
|
chanProof.BitcoinSig2Bytes,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
chanAnn.NodeSig1, err = lnwire.NewSigFromRawSignature(
|
chanAnn.NodeSig1, err = lnwire.NewSigFromECDSARawSignature(
|
||||||
chanProof.NodeSig1Bytes,
|
chanProof.NodeSig1Bytes,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
chanAnn.NodeSig2, err = lnwire.NewSigFromRawSignature(
|
chanAnn.NodeSig2, err = lnwire.NewSigFromECDSARawSignature(
|
||||||
chanProof.NodeSig2Bytes,
|
chanProof.NodeSig2Bytes,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -17,7 +17,7 @@ func TestCreateChanAnnouncement(t *testing.T) {
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
key := [33]byte{0x1}
|
key := [33]byte{0x1}
|
||||||
sig := lnwire.Sig{0x1}
|
var sig lnwire.Sig
|
||||||
features := lnwire.NewRawFeatureVector(lnwire.AnchorsRequired)
|
features := lnwire.NewRawFeatureVector(lnwire.AnchorsRequired)
|
||||||
var featuresBuf bytes.Buffer
|
var featuresBuf bytes.Buffer
|
||||||
if err := features.Encode(&featuresBuf); err != nil {
|
if err := features.Encode(&featuresBuf); err != nil {
|
||||||
|
@ -143,7 +143,9 @@ func ChannelUpdateFromEdge(info *channeldb.ChannelEdgeInfo,
|
|||||||
update := UnsignedChannelUpdateFromEdge(info, policy)
|
update := UnsignedChannelUpdateFromEdge(info, policy)
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
update.Signature, err = lnwire.NewSigFromRawSignature(policy.SigBytes)
|
update.Signature, err = lnwire.NewSigFromECDSARawSignature(
|
||||||
|
policy.SigBytes,
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -506,7 +506,7 @@ func TestChannelUpdateValidation(t *testing.T) {
|
|||||||
|
|
||||||
// Set up a channel update message with an invalid signature to be
|
// Set up a channel update message with an invalid signature to be
|
||||||
// returned to the sender.
|
// returned to the sender.
|
||||||
var invalidSignature [64]byte
|
var invalidSignature lnwire.Sig
|
||||||
errChanUpdate := lnwire.ChannelUpdate{
|
errChanUpdate := lnwire.ChannelUpdate{
|
||||||
Signature: invalidSignature,
|
Signature: invalidSignature,
|
||||||
FeeRate: 500,
|
FeeRate: 500,
|
||||||
|
@ -843,7 +843,7 @@ func newServer(cfg *Config, listenAddrs []net.Addr,
|
|||||||
"self node announcement: %v", err)
|
"self node announcement: %v", err)
|
||||||
}
|
}
|
||||||
selfNode.AuthSigBytes = authSig.Serialize()
|
selfNode.AuthSigBytes = authSig.Serialize()
|
||||||
nodeAnn.Signature, err = lnwire.NewSigFromRawSignature(
|
nodeAnn.Signature, err = lnwire.NewSigFromECDSARawSignature(
|
||||||
selfNode.AuthSigBytes,
|
selfNode.AuthSigBytes,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -398,7 +398,7 @@ func (b *JusticeKit) encodeV0(w io.Writer) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Write 64-byte revocation signature for commit to-local output.
|
// Write 64-byte revocation signature for commit to-local output.
|
||||||
_, err = w.Write(b.CommitToLocalSig[:])
|
_, err = w.Write(b.CommitToLocalSig.RawBytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -410,7 +410,7 @@ func (b *JusticeKit) encodeV0(w io.Writer) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Write 64-byte commit to-remote signature, which may be blank.
|
// Write 64-byte commit to-remote signature, which may be blank.
|
||||||
_, err = w.Write(b.CommitToRemoteSig[:])
|
_, err = w.Write(b.CommitToRemoteSig.RawBytes())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -472,14 +472,20 @@ func (b *JusticeKit) decodeV0(r io.Reader) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Read 64-byte revocation signature for commit to-local output.
|
// Read 64-byte revocation signature for commit to-local output.
|
||||||
_, err = io.ReadFull(r, b.CommitToLocalSig[:])
|
var localSig [64]byte
|
||||||
|
_, err = io.ReadFull(r, localSig[:])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
b.CommitToLocalSig, err = lnwire.NewSigFromWireECDSA(localSig[:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
commitToRemotePubkey PubKey
|
commitToRemotePubkey PubKey
|
||||||
commitToRemoteSig lnwire.Sig
|
commitToRemoteSig [64]byte
|
||||||
)
|
)
|
||||||
|
|
||||||
// Read 33-byte commit to-remote public key, which may be discarded.
|
// Read 33-byte commit to-remote public key, which may be discarded.
|
||||||
@ -498,7 +504,12 @@ func (b *JusticeKit) decodeV0(r io.Reader) error {
|
|||||||
// valid compressed public key was read from the reader.
|
// valid compressed public key was read from the reader.
|
||||||
if btcec.IsCompressedPubKey(commitToRemotePubkey[:]) {
|
if btcec.IsCompressedPubKey(commitToRemotePubkey[:]) {
|
||||||
b.CommitToRemotePubKey = commitToRemotePubkey
|
b.CommitToRemotePubKey = commitToRemotePubkey
|
||||||
b.CommitToRemoteSig = commitToRemoteSig
|
b.CommitToRemoteSig, err = lnwire.NewSigFromWireECDSA(
|
||||||
|
commitToRemoteSig[:],
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -28,8 +28,10 @@ func makePubKey(i uint64) blob.PubKey {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func makeSig(i int) lnwire.Sig {
|
func makeSig(i int) lnwire.Sig {
|
||||||
var sig lnwire.Sig
|
var sigBytes [64]byte
|
||||||
binary.BigEndian.PutUint64(sig[:8], uint64(i))
|
binary.BigEndian.PutUint64(sigBytes[:8], uint64(i))
|
||||||
|
|
||||||
|
sig, _ := lnwire.NewSigFromWireECDSA(sigBytes[:])
|
||||||
return sig
|
return sig
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -320,8 +320,8 @@ func testJusticeDescriptor(t *testing.T, blobType blob.Type) {
|
|||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
|
|
||||||
// Complete our justice kit by copying the signatures into the payload.
|
// Complete our justice kit by copying the signatures into the payload.
|
||||||
copy(justiceKit.CommitToLocalSig[:], toLocalSig[:])
|
justiceKit.CommitToLocalSig = toLocalSig
|
||||||
copy(justiceKit.CommitToRemoteSig[:], toRemoteSig[:])
|
justiceKit.CommitToRemoteSig = toRemoteSig
|
||||||
|
|
||||||
justiceDesc := &lookout.JusticeDescriptor{
|
justiceDesc := &lookout.JusticeDescriptor{
|
||||||
BreachedCommitTx: breachTxn,
|
BreachedCommitTx: breachTxn,
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
|
|
||||||
"github.com/btcsuite/btcd/wire"
|
"github.com/btcsuite/btcd/wire"
|
||||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||||
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
"github.com/lightningnetwork/lnd/watchtower/blob"
|
"github.com/lightningnetwork/lnd/watchtower/blob"
|
||||||
"github.com/lightningnetwork/lnd/watchtower/lookout"
|
"github.com/lightningnetwork/lnd/watchtower/lookout"
|
||||||
"github.com/lightningnetwork/lnd/watchtower/wtdb"
|
"github.com/lightningnetwork/lnd/watchtower/wtdb"
|
||||||
@ -57,6 +58,12 @@ func makeArray64(i uint64) [64]byte {
|
|||||||
return arr
|
return arr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func makeTestSig(i uint64) lnwire.Sig {
|
||||||
|
sigBytes := makeArray64(i)
|
||||||
|
sig, _ := lnwire.NewSigFromWireECDSA(sigBytes[:])
|
||||||
|
return sig
|
||||||
|
}
|
||||||
|
|
||||||
func makeAddrSlice(size int) []byte {
|
func makeAddrSlice(size int) []byte {
|
||||||
addr := make([]byte, size)
|
addr := make([]byte, size)
|
||||||
if _, err := io.ReadFull(rand.Reader, addr); err != nil {
|
if _, err := io.ReadFull(rand.Reader, addr); err != nil {
|
||||||
@ -141,7 +148,7 @@ func TestLookoutBreachMatching(t *testing.T) {
|
|||||||
RevocationPubKey: makePubKey(1),
|
RevocationPubKey: makePubKey(1),
|
||||||
LocalDelayPubKey: makePubKey(1),
|
LocalDelayPubKey: makePubKey(1),
|
||||||
CSVDelay: 144,
|
CSVDelay: 144,
|
||||||
CommitToLocalSig: makeArray64(1),
|
CommitToLocalSig: makeTestSig(1),
|
||||||
}
|
}
|
||||||
blob2 := &blob.JusticeKit{
|
blob2 := &blob.JusticeKit{
|
||||||
BlobType: blobType,
|
BlobType: blobType,
|
||||||
@ -149,7 +156,7 @@ func TestLookoutBreachMatching(t *testing.T) {
|
|||||||
RevocationPubKey: makePubKey(2),
|
RevocationPubKey: makePubKey(2),
|
||||||
LocalDelayPubKey: makePubKey(2),
|
LocalDelayPubKey: makePubKey(2),
|
||||||
CSVDelay: 144,
|
CSVDelay: 144,
|
||||||
CommitToLocalSig: makeArray64(2),
|
CommitToLocalSig: makeTestSig(2),
|
||||||
}
|
}
|
||||||
|
|
||||||
key1 := blob.NewBreachKeyFromHash(&hash1)
|
key1 := blob.NewBreachKeyFromHash(&hash1)
|
||||||
|
@ -369,24 +369,26 @@ func (t *backupTask) craftSessionPayload(
|
|||||||
|
|
||||||
// Re-encode the DER signature into a fixed-size 64 byte
|
// Re-encode the DER signature into a fixed-size 64 byte
|
||||||
// signature.
|
// signature.
|
||||||
signature, err := lnwire.NewSigFromRawSignature(rawSignature)
|
signature, err := lnwire.NewSigFromECDSARawSignature(
|
||||||
|
rawSignature,
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return hint, nil, err
|
return hint, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally, copy the serialized signature into the justice kit,
|
// Finally, copy the serialized signature into the justice kit,
|
||||||
// using the input's witness type to select the appropriate
|
// using the input's witness type to select the appropriate
|
||||||
// field.
|
// field
|
||||||
switch inp.WitnessType() {
|
switch inp.WitnessType() {
|
||||||
case input.CommitmentRevoke:
|
case input.CommitmentRevoke:
|
||||||
copy(justiceKit.CommitToLocalSig[:], signature[:])
|
justiceKit.CommitToLocalSig = signature
|
||||||
|
|
||||||
case input.CommitSpendNoDelayTweakless:
|
case input.CommitSpendNoDelayTweakless:
|
||||||
fallthrough
|
fallthrough
|
||||||
case input.CommitmentNoDelay:
|
case input.CommitmentNoDelay:
|
||||||
fallthrough
|
fallthrough
|
||||||
case input.CommitmentToRemoteConfirmed:
|
case input.CommitmentToRemoteConfirmed:
|
||||||
copy(justiceKit.CommitToRemoteSig[:], signature[:])
|
justiceKit.CommitToRemoteSig = signature
|
||||||
default:
|
default:
|
||||||
return hint, nil, fmt.Errorf("invalid witness type: %v",
|
return hint, nil, fmt.Errorf("invalid witness type: %v",
|
||||||
inp.WitnessType())
|
inp.WitnessType())
|
||||||
|
@ -618,8 +618,9 @@ func testBackupTask(t *testing.T, test backupTaskTest) {
|
|||||||
// moment, it is tested indirectly by other packages and integration
|
// moment, it is tested indirectly by other packages and integration
|
||||||
// tests.
|
// tests.
|
||||||
// TODO(conner): include signature validation checks
|
// TODO(conner): include signature validation checks
|
||||||
|
emptyToLocalSig := bytes.Equal(
|
||||||
emptyToLocalSig := bytes.Equal(jKit.CommitToLocalSig[:], zeroSig[:])
|
jKit.CommitToLocalSig.RawBytes(), zeroSig[:],
|
||||||
|
)
|
||||||
if hasToLocal {
|
if hasToLocal {
|
||||||
require.False(t, emptyToLocalSig, "to-local signature should "+
|
require.False(t, emptyToLocalSig, "to-local signature should "+
|
||||||
"not be empty")
|
"not be empty")
|
||||||
@ -628,7 +629,9 @@ func testBackupTask(t *testing.T, test backupTaskTest) {
|
|||||||
"be empty")
|
"be empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
emptyToRemoteSig := bytes.Equal(jKit.CommitToRemoteSig[:], zeroSig[:])
|
emptyToRemoteSig := bytes.Equal(
|
||||||
|
jKit.CommitToRemoteSig.RawBytes(), zeroSig[:],
|
||||||
|
)
|
||||||
if hasToRemote {
|
if hasToRemote {
|
||||||
require.False(t, emptyToRemoteSig, "to-remote signature "+
|
require.False(t, emptyToRemoteSig, "to-remote signature "+
|
||||||
"should not be empty")
|
"should not be empty")
|
||||||
|
@ -91,8 +91,10 @@ func Decode(invoice string, net *chaincfg.Params) (*Invoice, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var sig lnwire.Sig
|
sig, err := lnwire.NewSigFromWireECDSA(sigBase256[:64])
|
||||||
copy(sig[:], sigBase256[:64])
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
recoveryID := sigBase256[64]
|
recoveryID := sigBase256[64]
|
||||||
|
|
||||||
// The signature is over the hrp + the data the invoice, encoded in
|
// The signature is over the hrp + the data the invoice, encoded in
|
||||||
@ -121,7 +123,7 @@ func Decode(invoice string, net *chaincfg.Params) (*Invoice, error) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
headerByte := recoveryID + 27 + 4
|
headerByte := recoveryID + 27 + 4
|
||||||
compactSign := append([]byte{headerByte}, sig[:]...)
|
compactSign := append([]byte{headerByte}, sig.RawBytes()...)
|
||||||
pubkey, _, err := ecdsa.RecoverCompact(compactSign, hash)
|
pubkey, _, err := ecdsa.RecoverCompact(compactSign, hash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -91,8 +91,10 @@ func (invoice *Invoice) Encode(signer MessageSigner) (string, error) {
|
|||||||
// From the header byte we can extract the recovery ID, and the last 64
|
// From the header byte we can extract the recovery ID, and the last 64
|
||||||
// bytes encode the signature.
|
// bytes encode the signature.
|
||||||
recoveryID := sign[0] - 27 - 4
|
recoveryID := sign[0] - 27 - 4
|
||||||
var sig lnwire.Sig
|
sig, err := lnwire.NewSigFromWireECDSA(sign[1:])
|
||||||
copy(sig[:], sign[1:])
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
// If the pubkey field was explicitly set, it must be set to the pubkey
|
// If the pubkey field was explicitly set, it must be set to the pubkey
|
||||||
// used to create the signature.
|
// used to create the signature.
|
||||||
@ -112,7 +114,10 @@ func (invoice *Invoice) Encode(signer MessageSigner) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Convert the signature to base32 before writing it to the buffer.
|
// Convert the signature to base32 before writing it to the buffer.
|
||||||
signBase32, err := bech32.ConvertBits(append(sig[:], recoveryID), 8, 5, true)
|
signBase32, err := bech32.ConvertBits(
|
||||||
|
append(sig.RawBytes(), recoveryID),
|
||||||
|
8, 5, true,
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user