From 438c6b96219878e918f88dc137d63d98a65fc694 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Mon, 31 Jul 2017 18:42:32 -0700 Subject: [PATCH] lnwallet: move latest SignDescriptor + serialization --- lnwallet/interface.go | 60 ----------------------- lnwallet/signdescriptor.go | 85 +++++++++++++++++++++++++++------ lnwallet/signdescriptor_test.go | 4 +- 3 files changed, 72 insertions(+), 77 deletions(-) diff --git a/lnwallet/interface.go b/lnwallet/interface.go index 92f6adac..94d4d0de 100644 --- a/lnwallet/interface.go +++ b/lnwallet/interface.go @@ -224,66 +224,6 @@ type BlockChainIO interface { GetBlock(blockHash *chainhash.Hash) (*wire.MsgBlock, error) } -// SignDescriptor houses the necessary information required to successfully sign -// a given output. This struct is used by the Signer interface in order to gain -// access to critical data needed to generate a valid signature. -type SignDescriptor struct { - // Pubkey is the public key to which the signature should be generated - // over. The Signer should then generate a signature with the private - // key corresponding to this public key. - PubKey *btcec.PublicKey - - // SingleTweak is a scalar value that will be added to the private key - // corresponding to the above public key to obtain the private key to - // be used to sign this input. This value is typically derived via the - // following computation: - // - // * derivedKey = privkey + sha256(perCommitmentPoint || pubKey) mod N - // - // NOTE: If this value is nil, then the input can be signed using only - // the above public key. Either a SingleTweak should be set or a - // DoubleTweak, not both. - SingleTweak []byte - - // DoubleTweak is a private key that will be used in combination with - // its corresponding private key to derive the private key that is to - // be used to sign the target input. Within the Lightning protocol, - // this value is typically the commitment secret from a previously - // revoked commitment transaction. This value is in combination with - // two hash values, and the original private key to derive the private - // key to be used when signing. - // - // * k = (privKey*sha256(pubKey || tweakPub) + - // tweakPriv*sha256(tweakPub || pubKey)) mod N - // - // NOTE: If this value is nil, then the input can be signed using only - // the above public key. Either a SingleTweak should be set or a - // DoubleTweak, not both. - DoubleTweak *btcec.PrivateKey - - // WitnessScript is the full script required to properly redeem the - // output. This field will only be populated if a p2wsh or a p2sh - // output is being signed. - WitnessScript []byte - - // Output is the target output which should be signed. The PkScript and - // Value fields within the output should be properly populated, - // otherwise an invalid signature may be generated. - Output *wire.TxOut - - // HashType is the target sighash type that should be used when - // generating the final sighash, and signature. - HashType txscript.SigHashType - - // SigHashes is the pre-computed sighash midstate to be used when - // generating the final sighash for signing. - SigHashes *txscript.TxSigHashes - - // InputIndex is the target input within the transaction that should be - // signed. - InputIndex int -} - // Signer represents an abstract object capable of generating raw signatures as // well as full complete input scripts given a valid SignDescriptor and // transaction. This interface fully abstracts away signing paving the way for diff --git a/lnwallet/signdescriptor.go b/lnwallet/signdescriptor.go index 8e1ff391..08c24e5d 100644 --- a/lnwallet/signdescriptor.go +++ b/lnwallet/signdescriptor.go @@ -2,6 +2,7 @@ package lnwallet import ( "encoding/binary" + "errors" "io" "github.com/lightningnetwork/lnd/lnwire" @@ -10,6 +11,12 @@ import ( "github.com/roasbeef/btcd/wire" ) +var ( + // ErrTweakOverdose signals a SignDescriptor is invalid because both of its + // SingleTweak and DoubleTweak are non-nil. + ErrTweakOverdose = errors.New("sign descriptor should only have one tweak") +) + // SignDescriptor houses the necessary information required to successfully sign // a given output. This struct is used by the Signer interface in order to gain // access to critical data needed to generate a valid signature. @@ -19,14 +26,33 @@ type SignDescriptor struct { // key corresponding to this public key. PubKey *btcec.PublicKey - // PrivateTweak is a scalar value that should be added to the private - // key corresponding to the above public key to obtain the private key - // to be used to sign this input. This value is typically a leaf node - // from the revocation tree. + // SingleTweak is a scalar value that will be added to the private key + // corresponding to the above public key to obtain the private key to + // be used to sign this input. This value is typically derived via the + // following computation: + // + // * derivedKey = privkey + sha256(perCommitmentPoint || pubKey) mod N // // NOTE: If this value is nil, then the input can be signed using only - // the above public key. - PrivateTweak []byte + // the above public key. Either a SingleTweak should be set or a + // DoubleTweak, not both. + SingleTweak []byte + + // DoubleTweak is a private key that will be used in combination with + // its corresponding private key to derive the private key that is to + // be used to sign the target input. Within the Lightning protocol, + // this value is typically the commitment secret from a previously + // revoked commitment transaction. This value is in combination with + // two hash values, and the original private key to derive the private + // key to be used when signing. + // + // * k = (privKey*sha256(pubKey || tweakPub) + + // tweakPriv*sha256(tweakPub || pubKey)) mod N + // + // NOTE: If this value is nil, then the input can be signed using only + // the above public key. Either a SingleTweak should be set or a + // DoubleTweak, not both. + DoubleTweak *btcec.PrivateKey // WitnessScript is the full script required to properly redeem the // output. This field will only be populated if a p2wsh or a p2sh @@ -62,7 +88,15 @@ func WriteSignDescriptor(w io.Writer, sd *SignDescriptor) error { return err } - if err := wire.WriteVarBytes(w, 0, sd.PrivateTweak); err != nil { + if err := wire.WriteVarBytes(w, 0, sd.SingleTweak); err != nil { + return err + } + + var doubleTweakBytes []byte + if sd.DoubleTweak != nil { + doubleTweakBytes = sd.DoubleTweak.Serialize() + } + if err := wire.WriteVarBytes(w, 0, doubleTweakBytes); err != nil { return err } @@ -96,20 +130,41 @@ func ReadSignDescriptor(r io.Reader, sd *SignDescriptor) error { return err } - privateTweak, err := wire.ReadVarBytes(r, 0, 32, "privateTweak") + singleTweak, err := wire.ReadVarBytes(r, 0, 32, "singleTweak") if err != nil { return err } - // Serializing a SignDescriptor with a nil-valued PrivateTweak results in - // deserializing a zero-length slice. Since a nil-valued PrivateTweak has - // special meaning and a zero-length slice for a PrivateTweak is invalid, + // Serializing a SignDescriptor with a nil-valued SingleTweak results in + // deserializing a zero-length slice. Since a nil-valued SingleTweak has + // special meaning and a zero-length slice for a SingleTweak is invalid, // we can use the zero-length slice as the flag for a nil-valued - // PrivateTweak. - if len(privateTweak) == 0 { - sd.PrivateTweak = nil + // SingleTweak. + if len(singleTweak) == 0 { + sd.SingleTweak = nil } else { - sd.PrivateTweak = privateTweak + sd.SingleTweak = singleTweak + } + + doubleTweakBytes, err := wire.ReadVarBytes(r, 0, 32, "doubleTweak") + if err != nil { + return err + } + + // Serializing a SignDescriptor with a nil-valued DoubleTweak results in + // deserializing a zero-length slice. Since a nil-valued DoubleTweak has + // special meaning and a zero-length slice for a DoubleTweak is invalid, + // we can use the zero-length slice as the flag for a nil-valued + // DoubleTweak. + if len(doubleTweakBytes) == 0 { + sd.DoubleTweak = nil + } else { + sd.DoubleTweak, _ = btcec.PrivKeyFromBytes(btcec.S256(), doubleTweakBytes) + } + + // Only one tweak should ever be set, fail if both are present. + if sd.SingleTweak != nil && sd.DoubleTweak != nil { + return ErrTweakOverdose } witnessScript, err := wire.ReadVarBytes(r, 0, 100, "witnessScript") diff --git a/lnwallet/signdescriptor_test.go b/lnwallet/signdescriptor_test.go index ddd22f34..4225665f 100644 --- a/lnwallet/signdescriptor_test.go +++ b/lnwallet/signdescriptor_test.go @@ -34,7 +34,7 @@ func TestSignDescriptorSerialization(t *testing.T) { signDescriptors := []SignDescriptor{ { - PrivateTweak: []byte{ + SingleTweak: []byte{ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, @@ -66,7 +66,7 @@ func TestSignDescriptorSerialization(t *testing.T) { // Test serializing a SignDescriptor with a nil-valued PrivateTweak { - PrivateTweak: nil, + SingleTweak: nil, WitnessScript: []byte{ 0x00, 0x14, 0xee, 0x91, 0x41, 0x7e, 0x85, 0x6c, 0xde, 0x10, 0xa2, 0x91, 0x1e, 0xdc, 0xbd, 0xbd, 0x69, 0xe2,