mirror of
https://github.com/lightningnetwork/lnd.git
synced 2024-11-19 01:43:16 +01:00
lnwire: add new Sig type to handle conversion to/from btcec.Signature
In this commit, we add a new signature type. We’ll use this type to avoid fully decoding a signature on the wire into a btcec.Signature. This type is only really needed when we need to do signature validation, as a result, always encoding it is a waste. Several helper methods have been added to the new struct in order to ensure that we can use it in the existing codebase without substantial issues.
This commit is contained in:
parent
1afadf4822
commit
0d7b8be11b
@ -6,12 +6,16 @@ import (
|
||||
"github.com/roasbeef/btcd/btcec"
|
||||
)
|
||||
|
||||
// SerializeSigToWire serializes a *Signature to [64]byte in the format
|
||||
// specified by the Lightning RFC.
|
||||
func SerializeSigToWire(b *[64]byte, e *btcec.Signature) error {
|
||||
// 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 *btcec.Signature).
|
||||
type Sig [64]byte
|
||||
|
||||
// Serialize the signature with all the checks that entails.
|
||||
sig := e.Serialize()
|
||||
// NewSigFromRawSignature returns a Sig from a Bitcoin raw signature encoded in
|
||||
// the cannonical DER encoding.
|
||||
func NewSigFromRawSignature(sig []byte) (Sig, error) {
|
||||
var b Sig
|
||||
|
||||
// Extract lengths of R and S. The DER representation is laid out as
|
||||
// 0x30 <length> 0x02 <length r> r 0x02 <length s> s
|
||||
@ -23,14 +27,14 @@ func SerializeSigToWire(b *[64]byte, e *btcec.Signature) error {
|
||||
sLen := sig[5+rLen]
|
||||
|
||||
// Check to make sure R and S can both fit into their intended buffers.
|
||||
// We check S first because these code blocks decrement sLen and
|
||||
// rLen in the case of a 33-byte 0-padded integer returned from
|
||||
// Serialize() and rLen is used in calculating array indices for
|
||||
// S. We can track this with additional variables, but it's more
|
||||
// efficient to just check S first.
|
||||
// We check S first because these code blocks decrement sLen and rLen
|
||||
// in the case of a 33-byte 0-padded integer returned from Serialize()
|
||||
// and rLen is used in calculating array indices for S. We can track
|
||||
// this with additional variables, but it's more efficient to just
|
||||
// check S first.
|
||||
if sLen > 32 {
|
||||
if (sLen > 33) || (sig[6+rLen] != 0x00) {
|
||||
return fmt.Errorf("S is over 32 bytes long " +
|
||||
return b, fmt.Errorf("S is over 32 bytes long " +
|
||||
"without padding")
|
||||
}
|
||||
sLen--
|
||||
@ -42,7 +46,7 @@ func SerializeSigToWire(b *[64]byte, e *btcec.Signature) error {
|
||||
// Do the same for R as we did for S
|
||||
if rLen > 32 {
|
||||
if (rLen > 33) || (sig[4] != 0x00) {
|
||||
return fmt.Errorf("R is over 32 bytes long " +
|
||||
return b, fmt.Errorf("R is over 32 bytes long " +
|
||||
"without padding")
|
||||
}
|
||||
rLen--
|
||||
@ -50,13 +54,33 @@ func SerializeSigToWire(b *[64]byte, e *btcec.Signature) error {
|
||||
} else {
|
||||
copy(b[32-rLen:], sig[4:4+rLen])
|
||||
}
|
||||
return nil
|
||||
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// DeserializeSigFromWire deserializes a *Signature from [64]byte in the format
|
||||
// specified by the Lightning RFC.
|
||||
func DeserializeSigFromWire(e **btcec.Signature, b [64]byte) error {
|
||||
// NewSigFromSignature creates a new signature as used on the wire, from an
|
||||
// existing btcec.Signature.
|
||||
func NewSigFromSignature(e *btcec.Signature) (Sig, error) {
|
||||
// Serialize the signature with all the checks that entails.
|
||||
return NewSigFromRawSignature(e.Serialize())
|
||||
}
|
||||
|
||||
// ToSignature converts the fixed-sized signature to a btcec.Signature objects
|
||||
// which can be used for signature validation checks.
|
||||
func (b *Sig) ToSignature() (*btcec.Signature, error) {
|
||||
// Parse the signature with strict checks.
|
||||
sigBytes := b.ToSignatureBytes()
|
||||
sig, err := btcec.ParseDERSignature(sigBytes, btcec.S256())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return sig, nil
|
||||
}
|
||||
|
||||
// ToSignatureBytes serializes the target fixed-sized signature into the raw
|
||||
// bytes of a DER encoding.
|
||||
func (b *Sig) ToSignatureBytes() []byte {
|
||||
// Extract canonically-padded bigint representations from buffer
|
||||
r := extractCanonicalPadding(b[0:32])
|
||||
s := extractCanonicalPadding(b[32:64])
|
||||
@ -75,13 +99,7 @@ func DeserializeSigFromWire(e **btcec.Signature, b [64]byte) error {
|
||||
copy(sigBytes[4:], r) // Copy R
|
||||
copy(sigBytes[rLen+6:], s) // Copy S
|
||||
|
||||
// Parse the signature with strict checks.
|
||||
sig, err := btcec.ParseDERSignature(sigBytes, btcec.S256())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*e = sig
|
||||
return nil
|
||||
return sigBytes
|
||||
}
|
||||
|
||||
// extractCanonicalPadding is a utility function to extract the canonical
|
||||
|
Loading…
Reference in New Issue
Block a user