diff --git a/lnwire/single_funding_complete.go b/lnwire/single_funding_complete.go index 17dea842..2102e8b0 100644 --- a/lnwire/single_funding_complete.go +++ b/lnwire/single_funding_complete.go @@ -28,17 +28,25 @@ type SingleFundingComplete struct { // CommitSignature is Alice's signature for Bob's version of the // commitment transaction. CommitSignature *btcec.Signature + + // RevocationKey is the initial key to be used for the revocation + // clause within the self-output of the initiators's commitment + // transaction. Once an initial new state is created, the initiator + // will send a pre-image which will allow the initiator to sweep the + // initiator's funds if the violate the contract. + RevocationKey *btcec.PublicKey } // NewSingleFundingComplete creates, and returns a new empty // SingleFundingResponse. func NewSingleFundingComplete(chanID uint64, fundingPoint *wire.OutPoint, - commitSig *btcec.Signature) *SingleFundingComplete { + commitSig *btcec.Signature, revokeKey *btcec.PublicKey) *SingleFundingComplete { return &SingleFundingComplete{ ChannelID: chanID, FundingOutPoint: fundingPoint, CommitSignature: commitSig, + RevocationKey: revokeKey, } } @@ -50,11 +58,13 @@ func NewSingleFundingComplete(chanID uint64, fundingPoint *wire.OutPoint, func (s *SingleFundingComplete) Decode(r io.Reader, pver uint32) error { // ChannelID (8) // FundingOutPoint (36) - // Commitment Signature (73) + // CommitmentSignature (73) + // RevocationKey (33) err := readElements(r, &s.ChannelID, &s.FundingOutPoint, - &s.CommitSignature) + &s.CommitSignature, + &s.RevocationKey) if err != nil { return err } @@ -71,10 +81,12 @@ func (s *SingleFundingComplete) Encode(w io.Writer, pver uint32) error { // ChannelID (8) // FundingOutPoint (36) // Commitment Signature (73) + // RevocationKey (33) err := writeElements(w, s.ChannelID, s.FundingOutPoint, - s.CommitSignature) + s.CommitSignature, + s.RevocationKey) if err != nil { return err } @@ -92,13 +104,12 @@ func (s *SingleFundingComplete) Command() uint32 { // MaxPayloadLength returns the maximum allowed payload length for a // SingleFundingComplete. This is calculated by summing the max length of all -// the fields within a SingleFundingResponse. To enforce a maximum -// DeliveryPkScript size, the size of a P2PKH public key script is used. -// Therefore, the final breakdown is: 8 + 36 + 73 = 117 +// the fields within a SingleFundingResponse. Therefore, the final breakdown +// is: 8 + 36 + 73 = 150 // // This is part of the lnwire.Message interface. func (s *SingleFundingComplete) MaxPayloadLength(uint32) uint32 { - return 117 + return 150 } // Validate examines each populated field within the SingleFundingComplete for @@ -115,6 +126,8 @@ func (s *SingleFundingComplete) Validate() error { return fmt.Errorf("commitment signature must be non-nil") } + // TODO(roasbeef): fin validation + // We're good! return nil } @@ -123,9 +136,15 @@ func (s *SingleFundingComplete) Validate() error { // // This is part of the lnwire.Message interface. func (s *SingleFundingComplete) String() string { + var rk []byte + if s.RevocationKey != nil { + rk = s.RevocationKey.SerializeCompressed() + } + return fmt.Sprintf("\n--- Begin SingleFundingComplete ---\n") + fmt.Sprintf("ChannelID:\t\t\t%d\n", s.ChannelID) + fmt.Sprintf("FundingOutPoint:\t\t\t%x\n", s.FundingOutPoint) + fmt.Sprintf("CommitSignature\t\t\t\t%x\n", s.CommitSignature) + + fmt.Sprintf("RevocationKey\t\t\t\t%x\n", rk) + fmt.Sprintf("--- End SingleFundingComplete ---\n") } diff --git a/lnwire/single_funding_complete_test.go b/lnwire/single_funding_complete_test.go index d4a749b6..42ace411 100644 --- a/lnwire/single_funding_complete_test.go +++ b/lnwire/single_funding_complete_test.go @@ -8,7 +8,7 @@ import ( func TestSingleFundingCompleteWire(t *testing.T) { // First create a new SFC message. - sfc := NewSingleFundingComplete(22, outpoint1, commitSig1) + sfc := NewSingleFundingComplete(22, outpoint1, commitSig1, pubKey) // Next encode the SFC message into an empty bytes buffer. var b bytes.Buffer diff --git a/lnwire/single_funding_request.go b/lnwire/single_funding_request.go index 4bb07127..12c3b415 100644 --- a/lnwire/single_funding_request.go +++ b/lnwire/single_funding_request.go @@ -1,7 +1,6 @@ package lnwire import ( - "bytes" "fmt" "io" @@ -63,12 +62,6 @@ type SingleFundingRequest struct { // an odd y-coordinate. ChannelDerivationPoint *btcec.PublicKey - // RevocationHash is the initial revocation hash to be used for the - // initiator's commitment transaction to derive their revocation public - // key as: P + G*revocationHash, where P is the initiator's channel - // public key. - RevocationHash [20]byte - // DeliveryPkScript defines the public key script that the initiator // would like to use to receive their balance in the case of a // cooperative close. Only the following script templates are @@ -81,7 +74,7 @@ type SingleFundingRequest struct { // NewSingleFundingRequest creates, and returns a new empty SingleFundingRequest. func NewSingleFundingRequest(chanID uint64, chanType uint8, coinType uint64, fee btcutil.Amount, amt btcutil.Amount, delay uint32, ck, - cdp *btcec.PublicKey, revocation [20]byte, deliveryScript PkScript) *SingleFundingRequest { + cdp *btcec.PublicKey, deliveryScript PkScript) *SingleFundingRequest { return &SingleFundingRequest{ ChannelID: chanID, @@ -92,7 +85,6 @@ func NewSingleFundingRequest(chanID uint64, chanType uint8, coinType uint64, CsvDelay: delay, CommitmentKey: ck, ChannelDerivationPoint: cdp, - RevocationHash: revocation, DeliveryPkScript: deliveryScript, } } @@ -107,10 +99,10 @@ func (c *SingleFundingRequest) Decode(r io.Reader, pver uint32) error { // ChannelType (1) // CoinType (8) // FeePerKb (8) - // FundingAmount (8) - // CsvDelay (4) - // Channel Derivation Point (32) - // Revocation Hash (20) + // PaymentAmount (8) + // Delay (4) + // Pubkey (33) + // Pubkey (33) // DeliveryPkScript (final delivery) err := readElements(r, &c.ChannelID, @@ -121,7 +113,6 @@ func (c *SingleFundingRequest) Decode(r io.Reader, pver uint32) error { &c.CsvDelay, &c.CommitmentKey, &c.ChannelDerivationPoint, - &c.RevocationHash, &c.DeliveryPkScript) if err != nil { return err @@ -141,9 +132,9 @@ func (c *SingleFundingRequest) Encode(w io.Writer, pver uint32) error { // CoinType (8) // FeePerKb (8) // PaymentAmount (8) - // LockTime (4) - // Revocation Hash (20) - // Pubkey (32) + // Delay (4) + // Pubkey (33) + // Pubkey (33) // DeliveryPkScript (final delivery) err := writeElements(w, c.ChannelID, @@ -154,7 +145,6 @@ func (c *SingleFundingRequest) Encode(w io.Writer, pver uint32) error { c.CsvDelay, c.CommitmentKey, c.ChannelDerivationPoint, - c.RevocationHash, c.DeliveryPkScript) if err != nil { return err @@ -175,11 +165,11 @@ func (c *SingleFundingRequest) Command() uint32 { // SingleFundingRequest. This is calculated by summing the max length of all // the fields within a SingleFundingRequest. To enforce a maximum // DeliveryPkScript size, the size of a P2PKH public key script is used. -// Therefore, the final breakdown is: 8 + 1 + 8 + 8 + 8 + 4 + 33 + 33 + 20 + 25 = 114. +// Therefore, the final breakdown is: 8 + 1 + 8 + 8 + 8 + 4 + 33 + 33 + 25 = 158. // // This is part of the lnwire.Message interface. func (c *SingleFundingRequest) MaxPayloadLength(uint32) uint32 { - return 148 + return 158 } // Validate examines each populated field within the SingleFundingRequest for @@ -212,12 +202,6 @@ func (c *SingleFundingRequest) Validate() error { //"y-coordinate") //} - // The revocation hash MUST be non-zero. - var zeroHash [20]byte - if bytes.Equal(c.RevocationHash[:], zeroHash[:]) { - return fmt.Errorf("Initial revocation hash must be non-zero") - } - // The delivery pkScript must be amongst the supported script // templates. if !isValidPkScript(c.DeliveryPkScript) { @@ -249,7 +233,6 @@ func (c *SingleFundingRequest) String() string { fmt.Sprintf("FundingAmount:\t\t\t%s\n", c.FundingAmount.String()) + fmt.Sprintf("CsvDelay\t\t\t%d\n", c.CsvDelay) + fmt.Sprintf("ChannelDerivationPoint\t\t\t\t%x\n", serializedPubkey) + - fmt.Sprintf("RevocationHash\t\t\t%x\n", c.RevocationHash) + fmt.Sprintf("DeliveryPkScript\t\t%x\n", c.DeliveryPkScript) + fmt.Sprintf("--- End SingleFundingRequest ---\n") } diff --git a/lnwire/single_funding_request_test.go b/lnwire/single_funding_request_test.go index 726c0507..ffcd20e5 100644 --- a/lnwire/single_funding_request_test.go +++ b/lnwire/single_funding_request_test.go @@ -8,10 +8,9 @@ import ( func TestSingleFundingRequestWire(t *testing.T) { // First create a new SFR message. - var rev [20]byte cdp := pubKey delivery := PkScript(bytes.Repeat([]byte{0x02}, 25)) - sfr := NewSingleFundingRequest(20, 21, 22, 23, 5, 5, cdp, cdp, rev, delivery) + sfr := NewSingleFundingRequest(20, 21, 22, 23, 5, 5, cdp, cdp, delivery) // Next encode the SFR message into an empty bytes buffer. var b bytes.Buffer diff --git a/lnwire/single_funding_response.go b/lnwire/single_funding_response.go index d94657fe..cc0713af 100644 --- a/lnwire/single_funding_response.go +++ b/lnwire/single_funding_response.go @@ -1,7 +1,6 @@ package lnwire import ( - "bytes" "fmt" "io" @@ -17,29 +16,30 @@ type SingleFundingResponse struct { // the initiated single funder workflow. ChannelID uint64 - // RevocationHash is the initial revocation hash to be used for the - // responders's commitment transaction to derive their revocation public - // key as: P + G*revocationHash, where P is the initiator's channel - // public key. - RevocationHash [20]byte + // ChannelDerivationPoint is an secp256k1 point which will be used to + // derive the public key the responder will use for the half of the + // 2-of-2 multi-sig. Using the channel derivation point (CDP), and the + // responder's identity public key (A), the channel public key is + // computed as: C = A + CDP. In order to be valid all CDP's MUST have + // an odd y-coordinate. + ChannelDerivationPoint *btcec.PublicKey // CommitmentKey is key the responder to the funding workflow wishes to // use within their versino of the commitment transaction for any // delayed (CSV) or immediate outputs to them. CommitmentKey *btcec.PublicKey + // RevocationKey is the initial key to be used for the revocation + // clause within the self-output of the responder's commitment + // transaction. Once an initial new state is created, the responder + // will send a pre-image which will allow the initiator to sweep the + // responder's funds if the violate the contract. + RevocationKey *btcec.PublicKey + // CsvDelay is the number of blocks to use for the relative time lock // in the pay-to-self output of both commitment transactions. CsvDelay uint32 - // ChannelDerivationPoint is an secp256k1 point which will be used to - // derive the public key the responder will use for the half of the - // 2-of-2 multi-sig. Using the channel derivation point (CDP), and the - // initiators identity public key (A), the channel public key is - // computed as: C = A + CDP. In order to be valid all CDP's MUST have - // an odd y-coordinate. - ChannelDerivationPoint *btcec.PublicKey - // DeliveryPkScript defines the public key script that the initiator // would like to use to receive their balance in the case of a // cooperative close. Only the following script templates are @@ -49,20 +49,23 @@ type SingleFundingResponse struct { // NewSingleFundingResponse creates, and returns a new empty // SingleFundingResponse. -func NewSingleFundingResponse(chanID uint64, revocation [20]byte, - ck, cdp *btcec.PublicKey, delay uint32, - deliveryScript PkScript) *SingleFundingResponse { +func NewSingleFundingResponse(chanID uint64, rk, ck, cdp *btcec.PublicKey, + delay uint32, deliveryScript PkScript) *SingleFundingResponse { return &SingleFundingResponse{ ChannelID: chanID, - RevocationHash: revocation, - CommitmentKey: ck, - CsvDelay: delay, ChannelDerivationPoint: cdp, + CommitmentKey: ck, + RevocationKey: rk, + CsvDelay: delay, DeliveryPkScript: deliveryScript, } } +// A compile time check to ensure SingleFundingResponse implements the +// lnwire.Message interface. +var _ Message = (*SingleFundingResponse)(nil) + // Decode deserializes the serialized SingleFundingResponse stored in the passed // io.Reader into the target SingleFundingResponse using the deserialization // rules defined by the passed protocol version. @@ -70,14 +73,16 @@ func NewSingleFundingResponse(chanID uint64, revocation [20]byte, // This is part of the lnwire.Message interface. func (c *SingleFundingResponse) Decode(r io.Reader, pver uint32) error { // ChannelID (8) - // Revocation Hash (20) - // Pubkey (32) + // ChannelDerivationPoint (33) + // CommitmentKey (33) + // RevocationKey (33) + // CsvDelay (4) // DeliveryPkScript (final delivery) err := readElements(r, &c.ChannelID, - &c.RevocationHash, - &c.CommitmentKey, &c.ChannelDerivationPoint, + &c.CommitmentKey, + &c.RevocationKey, &c.CsvDelay, &c.DeliveryPkScript) if err != nil { @@ -94,14 +99,16 @@ func (c *SingleFundingResponse) Decode(r io.Reader, pver uint32) error { // This is part of the lnwire.Message interface. func (c *SingleFundingResponse) Encode(w io.Writer, pver uint32) error { // ChannelID (8) - // Revocation Hash (20) - // Channel Derivation Point (32) + // ChannelDerivationPoint (33) + // CommitmentKey (33) + // RevocationKey (33) + // CsvDelay (4) // DeliveryPkScript (final delivery) err := writeElements(w, c.ChannelID, - c.RevocationHash, - c.CommitmentKey, c.ChannelDerivationPoint, + c.CommitmentKey, + c.RevocationKey, c.CsvDelay, c.DeliveryPkScript) if err != nil { @@ -123,11 +130,11 @@ func (c *SingleFundingResponse) Command() uint32 { // SingleFundingResponse. This is calculated by summing the max length of all // the fields within a SingleFundingResponse. To enforce a maximum // DeliveryPkScript size, the size of a P2PKH public key script is used. -// Therefore, the final breakdown is: 8 + 20 + 33 + 33 + 4 + 25 = 123 +// Therefore, the final breakdown is: 8 + (33 * 3) + 8 + 25 // // This is part of the lnwire.Message interface. func (c *SingleFundingResponse) MaxPayloadLength(uint32) uint32 { - return 123 + return 140 } // Validate examines each populated field within the SingleFundingResponse for @@ -136,11 +143,6 @@ func (c *SingleFundingResponse) MaxPayloadLength(uint32) uint32 { // // This is part of the lnwire.Message interface. func (c *SingleFundingResponse) Validate() error { - var zeroHash [20]byte - if bytes.Equal(zeroHash[:], c.RevocationHash[:]) { - return fmt.Errorf("revocation has must be non-zero") - } - // The channel derivation point must be non-nil, and have an odd // y-coordinate. if c.ChannelDerivationPoint == nil { @@ -166,15 +168,25 @@ func (c *SingleFundingResponse) Validate() error { // // This is part of the lnwire.Message interface. func (c *SingleFundingResponse) String() string { - var serializedPubkey []byte - if &c.ChannelDerivationPoint != nil && c.ChannelDerivationPoint.X != nil { - serializedPubkey = c.ChannelDerivationPoint.SerializeCompressed() + var cdp []byte + var ck []byte + var rk []byte + if &c.ChannelDerivationPoint != nil { + cdp = c.ChannelDerivationPoint.SerializeCompressed() + } + if &c.CommitmentKey != nil { + ck = c.CommitmentKey.SerializeCompressed() + } + if &c.RevocationKey != nil { + rk = c.RevocationKey.SerializeCompressed() } return fmt.Sprintf("\n--- Begin SingleFundingResponse ---\n") + fmt.Sprintf("ChannelID:\t\t\t%d\n", c.ChannelID) + - fmt.Sprintf("RevocationHash\t\t\t%x\n", c.RevocationHash) + - fmt.Sprintf("ChannelDerivationPoint\t\t\t\t%x\n", serializedPubkey) + + fmt.Sprintf("ChannelDerivationPoint\t\t\t\t%x\n", cdp) + + fmt.Sprintf("CommitmentKey\t\t\t\t%x\n", ck) + + fmt.Sprintf("RevocationKey\t\t\t\t%x\n", rk) + + fmt.Sprintf("CsvDelay\t\t%d\n", c.CsvDelay) + fmt.Sprintf("DeliveryPkScript\t\t%x\n", c.DeliveryPkScript) + fmt.Sprintf("--- End SingleFundingResponse ---\n") } diff --git a/lnwire/single_funding_response_test.go b/lnwire/single_funding_response_test.go index 8348f87b..67200e9d 100644 --- a/lnwire/single_funding_response_test.go +++ b/lnwire/single_funding_response_test.go @@ -8,10 +8,8 @@ import ( func TestSingleFundingResponseWire(t *testing.T) { // First create a new SFR message. - var rev [20]byte - cdp := pubKey delivery := PkScript(bytes.Repeat([]byte{0x02}, 25)) - sfr := NewSingleFundingResponse(22, rev, cdp, cdp, 5, delivery) + sfr := NewSingleFundingResponse(22, pubKey, pubKey, pubKey, 5, delivery) // Next encode the SFR message into an empty bytes buffer. var b bytes.Buffer