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:
Olaoluwa Osuntokun 2018-01-30 19:40:30 -08:00
parent 1afadf4822
commit 0d7b8be11b
No known key found for this signature in database
GPG Key ID: 964EA263DD637C21

@ -6,12 +6,16 @@ import (
"github.com/roasbeef/btcd/btcec" "github.com/roasbeef/btcd/btcec"
) )
// SerializeSigToWire serializes a *Signature to [64]byte in the format // Sig is a fixed-sized ECDSA signature. Unlike Bitcoin, we use fixed sized
// specified by the Lightning RFC. // signatures on the wire, instead of DER encoded signatures. This type
func SerializeSigToWire(b *[64]byte, e *btcec.Signature) error { // 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. // NewSigFromRawSignature returns a Sig from a Bitcoin raw signature encoded in
sig := e.Serialize() // 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 // Extract lengths of R and S. The DER representation is laid out as
// 0x30 <length> 0x02 <length r> r 0x02 <length s> s // 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] sLen := sig[5+rLen]
// 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.
// We check S first because these code blocks decrement sLen and // We check S first because these code blocks decrement sLen and rLen
// rLen in the case of a 33-byte 0-padded integer returned from // in the case of a 33-byte 0-padded integer returned from Serialize()
// Serialize() and rLen is used in calculating array indices for // and rLen is used in calculating array indices for S. We can track
// S. We can track this with additional variables, but it's more // this with additional variables, but it's more efficient to just
// efficient to just 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 fmt.Errorf("S is over 32 bytes long " + return b, fmt.Errorf("S is over 32 bytes long " +
"without padding") "without padding")
} }
sLen-- sLen--
@ -42,7 +46,7 @@ func SerializeSigToWire(b *[64]byte, e *btcec.Signature) 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 fmt.Errorf("R is over 32 bytes long " + return b, fmt.Errorf("R is over 32 bytes long " +
"without padding") "without padding")
} }
rLen-- rLen--
@ -50,13 +54,33 @@ func SerializeSigToWire(b *[64]byte, e *btcec.Signature) error {
} else { } else {
copy(b[32-rLen:], sig[4:4+rLen]) copy(b[32-rLen:], sig[4:4+rLen])
} }
return nil
return b, nil
} }
// DeserializeSigFromWire deserializes a *Signature from [64]byte in the format // NewSigFromSignature creates a new signature as used on the wire, from an
// specified by the Lightning RFC. // existing btcec.Signature.
func DeserializeSigFromWire(e **btcec.Signature, b [64]byte) error { 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 // Extract canonically-padded bigint representations from buffer
r := extractCanonicalPadding(b[0:32]) r := extractCanonicalPadding(b[0:32])
s := extractCanonicalPadding(b[32:64]) 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[4:], r) // Copy R
copy(sigBytes[rLen+6:], s) // Copy S copy(sigBytes[rLen+6:], s) // Copy S
// Parse the signature with strict checks. return sigBytes
sig, err := btcec.ParseDERSignature(sigBytes, btcec.S256())
if err != nil {
return err
}
*e = sig
return nil
} }
// extractCanonicalPadding is a utility function to extract the canonical // extractCanonicalPadding is a utility function to extract the canonical