diff --git a/lnwire/close_complete.go b/lnwire/close_complete.go index 81a5178e2..2908e57e0 100644 --- a/lnwire/close_complete.go +++ b/lnwire/close_complete.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/roasbeef/btcd/btcec" + "github.com/roasbeef/btcd/wire" "io" ) @@ -19,8 +20,8 @@ import ( // arrive at an identical closure transaction as they know the order of the // inputs/outputs. type CloseComplete struct { - // ChannelID serves to identify which channel is to be closed. - ChannelID uint64 + // ChannelPoint serves to identify which channel is to be closed. + ChannelPoint *wire.OutPoint // ResponderCloseSig is the signature of the responder for the // transaction which closes the previously active channel. @@ -42,10 +43,10 @@ var _ Message = (*CloseComplete)(nil) // // This is part of the lnwire.Message interface. func (c *CloseComplete) Decode(r io.Reader, pver uint32) error { - // ChannelID (8) + // ChannelPoint (8) // ResponderCloseSig (73) err := readElements(r, - &c.ChannelID, + &c.ChannelPoint, &c.ResponderCloseSig) if err != nil { return err @@ -59,10 +60,10 @@ func (c *CloseComplete) Decode(r io.Reader, pver uint32) error { // // This is part of the lnwire.Message interface. func (c *CloseComplete) Encode(w io.Writer, pver uint32) error { - // ChannelID (8) + // ChannelPoint (8) // ResponderCloseSig (73) err := writeElements(w, - c.ChannelID, + c.ChannelPoint, c.ResponderCloseSig) if err != nil { return err @@ -84,8 +85,8 @@ func (c *CloseComplete) Command() uint32 { // // This is part of the lnwire.Message interface. func (c *CloseComplete) MaxPayloadLength(uint32) uint32 { - // 8 + 73 + 32 - return 113 + // 141 + 73 + 32 + return 141 } // Validate performs any necessary sanity checks to ensure all fields present @@ -107,7 +108,7 @@ func (c *CloseComplete) String() string { } return fmt.Sprintf("\n--- Begin CloseComplete ---\n") + - fmt.Sprintf("ReservationID:\t\t%d\n", c.ChannelID) + + fmt.Sprintf("ReservationID:\t\t%d\n", c.ChannelPoint) + fmt.Sprintf("ResponderCloseSig:\t%x\n", serializedSig) + fmt.Sprintf("--- End CloseComplete ---\n") } diff --git a/lnwire/close_complete_test.go b/lnwire/close_complete_test.go index 43dcccdbb..ee49e65c7 100644 --- a/lnwire/close_complete_test.go +++ b/lnwire/close_complete_test.go @@ -8,7 +8,7 @@ import ( func TestCloseCompleteEncodeDecode(t *testing.T) { cc := &CloseComplete{ - ChannelID: uint64(12345678), + ChannelPoint: outpoint1, ResponderCloseSig: commitSig, } diff --git a/lnwire/close_request.go b/lnwire/close_request.go index 3ab8ae00f..2010a1d82 100644 --- a/lnwire/close_request.go +++ b/lnwire/close_request.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/roasbeef/btcd/btcec" + "github.com/roasbeef/btcd/wire" "github.com/roasbeef/btcutil" "io" @@ -20,8 +21,8 @@ import ( // both sides are able to arrive at an identical closure transaction as they // know the order of the inputs/outputs. type CloseRequest struct { - // ChannelID serves to identify which channel is to be closed. - ChannelID uint64 + // ChannelPoint serves to identify which channel is to be closed. + ChannelPoint *wire.OutPoint // RequesterCloseSig is the signature of the requester for the fully // assembled closing transaction. @@ -30,20 +31,34 @@ type CloseRequest struct { // Fee is the required fee-per-KB the closing transaction must have. // It is recommended that a "sufficient" fee be paid in order to achieve // timely channel closure. + // TODO(roasbeef): if initiator always pays fees, then no longer needed. Fee btcutil.Amount } +// NewCloseRequest creates a new CloseRequest. +func NewCloseRequest(cp *wire.OutPoint, sig *btcec.Signature) *CloseRequest { + // TODO(roasbeef): update once fees aren't hardcoded + return &CloseRequest{ + ChannelPoint: cp, + RequesterCloseSig: sig, + } +} + +// A compile time check to ensure CloseRequest implements the lnwire.Message +// interface. +var _ Message = (*CloseRequest)(nil) + // Decode deserializes a serialized CloseRequest stored in the passed io.Reader // observing the specified protocol version. // // This is part of the lnwire.Message interface. func (c *CloseRequest) Decode(r io.Reader, pver uint32) error { - // ChannelID (8) + // ChannelPoint (8) // RequesterCloseSig (73) // First byte length then sig // Fee (8) err := readElements(r, - &c.ChannelID, + &c.ChannelPoint, &c.RequesterCloseSig, &c.Fee) if err != nil { @@ -53,15 +68,6 @@ func (c *CloseRequest) Decode(r io.Reader, pver uint32) error { return nil } -// NewCloseRequest creates a new CloseRequest. -func NewCloseRequest() *CloseRequest { - return &CloseRequest{} -} - -// A compile time check to ensure CloseRequest implements the lnwire.Message -// interface. -var _ Message = (*CloseRequest)(nil) - // Encode serializes the target CloseRequest into the passed io.Writer observing // the protocol version specified. // @@ -71,7 +77,7 @@ func (c *CloseRequest) Encode(w io.Writer, pver uint32) error { // RequesterCloseSig // Fee err := writeElements(w, - c.ChannelID, + c.ChannelPoint, c.RequesterCloseSig, c.Fee) if err != nil { @@ -94,8 +100,8 @@ func (c *CloseRequest) Command() uint32 { // // This is part of the lnwire.Message interface. func (c *CloseRequest) MaxPayloadLength(pver uint32) uint32 { - // 8 + 73 + 8 - return 89 + // 36 + 73 + 8 + return 117 } // Validate performs any necessary sanity checks to ensure all fields present @@ -122,7 +128,7 @@ func (c *CloseRequest) String() string { } return fmt.Sprintf("\n--- Begin CloseRequest ---\n") + - fmt.Sprintf("ChannelID:\t\t%d\n", c.ChannelID) + + fmt.Sprintf("ChannelPoint:\t\t%d\n", c.ChannelPoint) + fmt.Sprintf("CloseSig\t\t%x\n", serializedSig) + fmt.Sprintf("Fee:\t\t\t%d\n", c.Fee) + fmt.Sprintf("--- End CloseRequest ---\n") diff --git a/lnwire/close_request_test.go b/lnwire/close_request_test.go index e4d15b9f5..483984468 100644 --- a/lnwire/close_request_test.go +++ b/lnwire/close_request_test.go @@ -1,35 +1,35 @@ package lnwire import ( + "bytes" + "reflect" "testing" "github.com/roasbeef/btcutil" ) -var ( - closeRequest = &CloseRequest{ - ChannelID: uint64(12345678), - RequesterCloseSig: commitSig, - Fee: btcutil.Amount(12345), - } - closeRequestSerializedString = "0000000000bc614e4630440220333835e58e958f5e92b4ff4e6fa2470dac88094c97506b4d6d1f4e23e52cb481022057483ac18d6b9c9c14f0c626694c9ccf8b27b3dbbedfdf6b6c9a9fa9f427a1df0000000000003039" - closeRequestSerializedMessage = "0709110b0000012c000000570000000000bc614e4630440220333835e58e958f5e92b4ff4e6fa2470dac88094c97506b4d6d1f4e23e52cb481022057483ac18d6b9c9c14f0c626694c9ccf8b27b3dbbedfdf6b6c9a9fa9f427a1df0000000000003039" -) - func TestCloseRequestEncodeDecode(t *testing.T) { - // All of these types being passed are of the message interface type - // Test serialization, runs: message.Encode(b, 0) - // Returns bytes - // Compares the expected serialized string from the original - s := SerializeTest(t, closeRequest, closeRequestSerializedString, filename) + cr := &CloseRequest{ + ChannelPoint: outpoint1, + RequesterCloseSig: commitSig, + Fee: btcutil.Amount(10000), + } - // Test deserialization, runs: message.Decode(s, 0) - // Makes sure the deserialized struct is the same as the original - newMessage := NewCloseRequest() - DeserializeTest(t, s, newMessage, closeRequest) + // Next encode the CR message into an empty bytes buffer. + var b bytes.Buffer + if err := cr.Encode(&b, 0); err != nil { + t.Fatalf("unable to encode CloseRequest: %v", err) + } - // Test message using Message interface - // Serializes into buf: WriteMessage(buf, message, uint32(1), wire.TestNet3) - // Deserializes into msg: _, msg, _ , err := ReadMessage(buf, uint32(1), wire.TestNet3) - MessageSerializeDeserializeTest(t, closeRequest, closeRequestSerializedMessage) + // Deserialize the encoded CR message into a new empty struct. + cr2 := &CloseRequest{} + if err := cr2.Decode(&b, 0); err != nil { + t.Fatalf("unable to decode CloseRequest: %v", err) + } + + // Assert equality of the two instances. + if !reflect.DeepEqual(cr, cr2) { + t.Fatalf("encode/decode error messages don't match %#v vs %#v", + cr, cr2) + } } diff --git a/lnwire/commit_revocation.go b/lnwire/commit_revocation.go index dedf1130b..9c5d9724d 100644 --- a/lnwire/commit_revocation.go +++ b/lnwire/commit_revocation.go @@ -3,12 +3,14 @@ package lnwire import ( "fmt" "io" + + "github.com/roasbeef/btcd/wire" ) // CommitRevocation is sent by either side once a CommitSignature message has // been received, and validated. This message serves to revoke the prior // commitment transaction, which was the most up to date version until a -// CommitSignature message referencing the specified ChannelID was received. +// CommitSignature message referencing the specified ChannelPoint was received. // Additionally, this message also piggyback's the next revocation hash that // Alice should use when constructing the Bob's version of the next commitment // transaction (which would be done before sending a CommitSignature message). @@ -16,9 +18,9 @@ import ( // modifying Bob's commitment transaction without first asking for a revocation // hash initially. type CommitRevocation struct { - // ChannelID uniquely identifies to which currently active channel this + // ChannelPoint uniquely identifies to which currently active channel this // CommitRevocation applies to. - ChannelID uint64 + ChannelPoint *wire.OutPoint // Revocation is the pre-image to the revocation hash of the now prior // commitment transaction. @@ -44,11 +46,11 @@ var _ Message = (*CommitRevocation)(nil) // // This is part of the lnwire.Message interface. func (c *CommitRevocation) Decode(r io.Reader, pver uint32) error { - // ChannelID (8) + // ChannelPoint (8) // NextRevocationHash (20) // Revocation (20) err := readElements(r, - &c.ChannelID, + &c.ChannelPoint, &c.NextRevocationHash, &c.Revocation, ) @@ -65,7 +67,7 @@ func (c *CommitRevocation) Decode(r io.Reader, pver uint32) error { // This is part of the lnwire.Message interface. func (c *CommitRevocation) Encode(w io.Writer, pver uint32) error { err := writeElements(w, - c.ChannelID, + c.ChannelPoint, c.NextRevocationHash, c.Revocation, ) @@ -89,8 +91,8 @@ func (c *CommitRevocation) Command() uint32 { // // This is part of the lnwire.Message interface. func (c *CommitRevocation) MaxPayloadLength(uint32) uint32 { - // 8 + 20 + 20 - return 48 + // 36 + 20 + 20 + return 76 } // Validate performs any necessary sanity checks to ensure all fields present @@ -107,7 +109,7 @@ func (c *CommitRevocation) Validate() error { // This is part of the lnwire.Message interface. func (c *CommitRevocation) String() string { return fmt.Sprintf("\n--- Begin CommitRevocation ---\n") + - fmt.Sprintf("ChannelID:\t%d\n", c.ChannelID) + + fmt.Sprintf("ChannelPoint:\t%d\n", c.ChannelPoint) + fmt.Sprintf("NextRevocationHash:\t%x\n", c.NextRevocationHash) + fmt.Sprintf("Revocation:\t%x\n", c.Revocation) + fmt.Sprintf("--- End CommitRevocation ---\n") diff --git a/lnwire/commit_revocation_test.go b/lnwire/commit_revocation_test.go index 537e1d160..d32e1800f 100644 --- a/lnwire/commit_revocation_test.go +++ b/lnwire/commit_revocation_test.go @@ -11,7 +11,7 @@ func TestCommitRevocationEncodeDecode(t *testing.T) { copy(nextHop[:], nextHopBytes) cr := &CommitRevocation{ - ChannelID: uint64(12345678), + ChannelPoint: outpoint1, Revocation: revocationHash, NextRevocationHash: nextHop, } diff --git a/lnwire/commit_signature.go b/lnwire/commit_signature.go index 1563004e4..cf37d57d8 100644 --- a/lnwire/commit_signature.go +++ b/lnwire/commit_signature.go @@ -5,6 +5,7 @@ import ( "io" "github.com/roasbeef/btcd/btcec" + "github.com/roasbeef/btcd/wire" "github.com/roasbeef/btcutil" ) @@ -16,9 +17,9 @@ import ( // messages in order to batch add several HTLC's with a single signature // covering all implicitly accepted HTLC's. type CommitSignature struct { - // ChannelID uniquely identifies to which currently active channel this + // ChannelPoint uniquely identifies to which currently active channel this // CommitSignature applies to. - ChannelID uint64 + ChannelPoint *wire.OutPoint // Fee represents the total miner's fee that was used when constructing // the new commitment transaction. @@ -47,11 +48,11 @@ var _ Message = (*CommitSignature)(nil) // // This is part of the lnwire.Message interface. func (c *CommitSignature) Decode(r io.Reader, pver uint32) error { - // ChannelID(8) + // ChannelPoint(8) // Fee(8) // RequesterCommitSig(73max+2) err := readElements(r, - &c.ChannelID, + &c.ChannelPoint, &c.Fee, &c.CommitSig, ) @@ -69,7 +70,7 @@ func (c *CommitSignature) Decode(r io.Reader, pver uint32) error { func (c *CommitSignature) Encode(w io.Writer, pver uint32) error { // TODO(roasbeef): make similar modificaiton to all other encode/decode // messags - return writeElements(w, c.ChannelID, c.Fee, c.CommitSig) + return writeElements(w, c.ChannelPoint, c.Fee, c.CommitSig) } // Command returns the integer uniquely identifying this message type on the @@ -85,8 +86,8 @@ func (c *CommitSignature) Command() uint32 { // // This is part of the lnwire.Message interface. func (c *CommitSignature) MaxPayloadLength(uint32) uint32 { - // 8 + 8 + 73 - return 89 + // 36 + 8 + 73 + return 117 } // Validate performs any necessary sanity checks to ensure all fields present @@ -114,7 +115,7 @@ func (c *CommitSignature) String() string { } return fmt.Sprintf("\n--- Begin CommitSignature ---\n") + - fmt.Sprintf("ChannelID:\t%d\n", c.ChannelID) + + fmt.Sprintf("ChannelPoint:\t%d\n", c.ChannelPoint) + fmt.Sprintf("Fee:\t\t\t%s\n", c.Fee.String()) + fmt.Sprintf("CommitSig:\t\t%x\n", serializedSig) + fmt.Sprintf("--- End CommitSignature ---\n") diff --git a/lnwire/commit_signature_test.go b/lnwire/commit_signature_test.go index 6e29ef090..8bc0616f6 100644 --- a/lnwire/commit_signature_test.go +++ b/lnwire/commit_signature_test.go @@ -12,9 +12,9 @@ func TestCommitSignatureEncodeDecode(t *testing.T) { copy(revocationHash[:], revocationHashBytes) commitSignature := &CommitSignature{ - ChannelID: uint64(12345678), - Fee: btcutil.Amount(10000), - CommitSig: commitSig, + ChannelPoint: outpoint1, + Fee: btcutil.Amount(10000), + CommitSig: commitSig, } // Next encode the CS message into an empty bytes buffer. diff --git a/lnwire/error_generic.go b/lnwire/error_generic.go index efd5b938e..70dcfdf25 100644 --- a/lnwire/error_generic.go +++ b/lnwire/error_generic.go @@ -3,16 +3,19 @@ package lnwire import ( "fmt" "io" + + "github.com/roasbeef/btcd/wire" ) // ErrorGeneric represents a generic error bound to an exact channel. The // message format is purposefully general in order to allow expressino of a wide // array of possible errors. Each ErrorGeneric message is directed at a particular -// open channel referenced by ChannelID. +// open channel referenced by ChannelPoint. type ErrorGeneric struct { - // ChannelID references the active channel in which the error occured - // within. - ChannelID uint64 + // ChannelPoint references the active channel in which the error occured + // within. A ChannelPoint of zeroHash:0 denotes this error applies to + // the entire established connection. + ChannelPoint *wire.OutPoint // ErrorID quickly defines the nature of the error according to error // type. @@ -38,10 +41,10 @@ var _ Message = (*ErrorGeneric)(nil) // // This is part of the lnwire.Message interface. func (c *ErrorGeneric) Decode(r io.Reader, pver uint32) error { - // ChannelID(8) + // ChannelPoint(8) // Problem err := readElements(r, - &c.ChannelID, + &c.ChannelPoint, &c.ErrorID, &c.Problem, ) @@ -58,7 +61,7 @@ func (c *ErrorGeneric) Decode(r io.Reader, pver uint32) error { // This is part of the lnwire.Message interface. func (c *ErrorGeneric) Encode(w io.Writer, pver uint32) error { err := writeElements(w, - c.ChannelID, + c.ChannelPoint, c.ErrorID, c.Problem, ) @@ -104,7 +107,7 @@ func (c *ErrorGeneric) Validate() error { // This is part of the lnwire.Message interface. func (c *ErrorGeneric) String() string { return fmt.Sprintf("\n--- Begin ErrorGeneric ---\n") + - fmt.Sprintf("ChannelID:\t%d\n", c.ChannelID) + + fmt.Sprintf("ChannelPoint:\t%d\n", c.ChannelPoint) + fmt.Sprintf("ErrorID:\t%d\n", c.ErrorID) + fmt.Sprintf("Problem:\t%s\n", c.Problem) + fmt.Sprintf("--- End ErrorGeneric ---\n") diff --git a/lnwire/error_generic_test.go b/lnwire/error_generic_test.go index c15c0b898..a07e8a605 100644 --- a/lnwire/error_generic_test.go +++ b/lnwire/error_generic_test.go @@ -8,9 +8,9 @@ import ( func TestErrorGenericEncodeDecode(t *testing.T) { eg := &ErrorGeneric{ - ChannelID: uint64(12345678), - ErrorID: 99, - Problem: "Hello world!", + ChannelPoint: outpoint1, + ErrorID: 99, + Problem: "Hello world!", } // Next encode the EG message into an empty bytes buffer. diff --git a/lnwire/htlc_addreject.go b/lnwire/htlc_addreject.go index af57d78f0..4b8661005 100644 --- a/lnwire/htlc_addreject.go +++ b/lnwire/htlc_addreject.go @@ -3,31 +3,19 @@ package lnwire import ( "fmt" "io" + + "github.com/roasbeef/btcd/wire" ) -// ChannelPoint represents a unique state update within currently active -// channel. A channel update across all open chnnels can be uniquely identified -// by a two-tuple: (fundingTXID, HTLCKey). All explicit updates to an open -// channel will reference a ChannelPoint to apply the update to. -type ChannelPoint struct { - // ChannelID references the particular active channel to which this - // HTLCAddReject message is binded to. - ChannelID uint64 - - // HTLCKey is used to identify which HTLC previously attempted to be - // added via an HTLCAddRequest message is being declined. - HTLCKey HTLCKey -} - // HTLCAddReject is sent by Bob when he wishes to reject a particular HTLC that // Alice attempted to add via an HTLCAddRequest message. The rejected HTLC is // referenced by its unique HTLCKey ID. An HTLCAddReject message is bound to a -// single active channel, referenced by a unique ChannelID. Additionally, the +// single active channel, referenced by a unique ChannelPoint. Additionally, the // HTLCKey of the rejected HTLC is present type HTLCAddReject struct { - // ChannelID references the particular active channel to which this + // ChannelPoint references the particular active channel to which this // HTLCAddReject message is binded to. - ChannelID uint64 + ChannelPoint *wire.OutPoint // HTLCKey is used to identify which HTLC previously attempted to be // added via an HTLCAddRequest message is being declined. @@ -39,10 +27,10 @@ type HTLCAddReject struct { // // This is part of the lnwire.Message interface. func (c *HTLCAddReject) Decode(r io.Reader, pver uint32) error { - // ChannelID (8) + // ChannelPoint (8) // HTLCKey (8) err := readElements(r, - &c.ChannelID, + &c.ChannelPoint, &c.HTLCKey, ) if err != nil { @@ -67,7 +55,7 @@ var _ Message = (*HTLCAddReject)(nil) // This is part of the lnwire.Message interface. func (c *HTLCAddReject) Encode(w io.Writer, pver uint32) error { err := writeElements(w, - c.ChannelID, + c.ChannelPoint, c.HTLCKey, ) @@ -91,8 +79,8 @@ func (c *HTLCAddReject) Command() uint32 { // // This is part of the lnwire.Message interface. func (c *HTLCAddReject) MaxPayloadLength(uint32) uint32 { - // 8 + 8 - return 16 + // 36 + 8 + return 44 } // Validate performs any necessary sanity checks to ensure all fields present @@ -109,7 +97,7 @@ func (c *HTLCAddReject) Validate() error { // This is part of the lnwire.Message interface. func (c *HTLCAddReject) String() string { return fmt.Sprintf("\n--- Begin HTLCAddReject ---\n") + - fmt.Sprintf("ChannelID:\t\t%d\n", c.ChannelID) + + fmt.Sprintf("ChannelPoint:\t\t%d\n", c.ChannelPoint) + fmt.Sprintf("HTLCKey:\t\t%d\n", c.HTLCKey) + fmt.Sprintf("--- End HTLCAddReject ---\n") } diff --git a/lnwire/htlc_addreject_test.go b/lnwire/htlc_addreject_test.go index 09f10449f..53b0885f3 100644 --- a/lnwire/htlc_addreject_test.go +++ b/lnwire/htlc_addreject_test.go @@ -1,32 +1,33 @@ package lnwire import ( + "bytes" + "reflect" "testing" ) -var ( - htlcAddReject = &HTLCAddReject{ - ChannelID: uint64(12345678), - HTLCKey: HTLCKey(12345), - } - htlcAddRejectSerializedString = "0000000000bc614e0000000000003039" - htlcAddRejectSerializedMessage = "0709110b000003fc000000100000000000bc614e0000000000003039" -) - func TestHTLCAddRejectEncodeDecode(t *testing.T) { - // All of these types being passed are of the message interface type - // Test serialization, runs: message.Encode(b, 0) - // Returns bytes - // Compares the expected serialized string from the original - s := SerializeTest(t, htlcAddReject, htlcAddRejectSerializedString, filename) + // First create a new HTLCAR message. + rejectReq := &HTLCAddReject{ + ChannelPoint: outpoint1, + HTLCKey: 22, + } - // Test deserialization, runs: message.Decode(s, 0) - // Makes sure the deserialized struct is the same as the original - newMessage := NewHTLCAddReject() - DeserializeTest(t, s, newMessage, htlcAddReject) + // Next encode the HTLCAR message into an empty bytes buffer. + var b bytes.Buffer + if err := rejectReq.Encode(&b, 0); err != nil { + t.Fatalf("unable to encode HTLCSettleRequest: %v", err) + } - // Test message using Message interface - // Serializes into buf: WriteMessage(buf, message, uint32(1), wire.TestNet3) - // Deserializes into msg: _, msg, _ , err := ReadMessage(buf, uint32(1), wire.TestNet3) - MessageSerializeDeserializeTest(t, htlcAddReject, htlcAddRejectSerializedMessage) + // Deserialize the encoded HTLCAR message into a new empty struct. + rejectReq2 := &HTLCAddReject{} + if err := rejectReq2.Decode(&b, 0); err != nil { + t.Fatalf("unable to decode HTLCAddReject: %v", err) + } + + // Assert equality of the two instances. + if !reflect.DeepEqual(rejectReq, rejectReq2) { + t.Fatalf("encode/decode error messages don't match %#v vs %#v", + rejectReq, rejectReq2) + } } diff --git a/lnwire/htlc_addrequest.go b/lnwire/htlc_addrequest.go index 09d7ff066..dbbb421b8 100644 --- a/lnwire/htlc_addrequest.go +++ b/lnwire/htlc_addrequest.go @@ -3,6 +3,8 @@ package lnwire import ( "fmt" "io" + + "github.com/roasbeef/btcd/wire" ) // HTLCAddRequest is the message sent by Alice to Bob when she wishes to add an @@ -13,9 +15,9 @@ import ( // A subsequent CommitSignature message will move the pending HTLC to the newly // created commitment transaction, marking them as "staged". type HTLCAddRequest struct { - // ChannelID is the particular active channel that this HTLCAddRequest + // ChannelPoint is the particular active channel that this HTLCAddRequest // is binded to. - ChannelID uint64 + ChannelPoint *wire.OutPoint // Expiry is the number of blocks after which this HTLC should expire. // It is the receiver's duty to ensure that the outgoing HTLC has a @@ -72,14 +74,14 @@ var _ Message = (*HTLCAddRequest)(nil) // // This is part of the lnwire.Message interface. func (c *HTLCAddRequest) Decode(r io.Reader, pver uint32) error { - // ChannelID(8) + // ChannelPoint(8) // Expiry(4) // Amount(4) // ContractType(1) // RedemptionHashes (numOfHashes * 20 + numOfHashes) // OnionBlog err := readElements(r, - &c.ChannelID, + &c.ChannelPoint, &c.Expiry, &c.Amount, &c.ContractType, @@ -99,7 +101,7 @@ func (c *HTLCAddRequest) Decode(r io.Reader, pver uint32) error { // This is part of the lnwire.Message interface. func (c *HTLCAddRequest) Encode(w io.Writer, pver uint32) error { err := writeElements(w, - c.ChannelID, + c.ChannelPoint, c.Expiry, c.Amount, c.ContractType, @@ -156,7 +158,7 @@ func (c *HTLCAddRequest) String() string { } return fmt.Sprintf("\n--- Begin HTLCAddRequest ---\n") + - fmt.Sprintf("ChannelID:\t%d\n", c.ChannelID) + + fmt.Sprintf("ChannelPoint:\t%d\n", c.ChannelPoint) + fmt.Sprintf("Expiry:\t\t%d\n", c.Expiry) + fmt.Sprintf("Amount\t\t%d\n", c.Amount) + fmt.Sprintf("ContractType:\t%d (%b)\n", c.ContractType, c.ContractType) + diff --git a/lnwire/htlc_addrequest_test.go b/lnwire/htlc_addrequest_test.go index cec612af4..da8258cae 100644 --- a/lnwire/htlc_addrequest_test.go +++ b/lnwire/htlc_addrequest_test.go @@ -12,7 +12,7 @@ func TestHTLCAddRequestEncodeDecode(t *testing.T) { // First create a new HTLCAR message. addReq := &HTLCAddRequest{ - ChannelID: uint64(12345678), + ChannelPoint: outpoint1, Expiry: uint32(144), Amount: CreditsAmount(123456000), ContractType: uint8(17), diff --git a/lnwire/htlc_settlerequest.go b/lnwire/htlc_settlerequest.go index 80d78fd28..0184f024d 100644 --- a/lnwire/htlc_settlerequest.go +++ b/lnwire/htlc_settlerequest.go @@ -3,19 +3,21 @@ package lnwire import ( "fmt" "io" + + "github.com/roasbeef/btcd/wire" ) // HTLCSettleRequest is sent by Alice to Bob when she wishes to settle a // particular HTLC referenced by its HTLCKey within a specific active channel -// referenced by ChannelID. The message allows multiple hash preimages to be +// referenced by ChannelPoint. The message allows multiple hash preimages to be // presented in order to support N-of-M HTLC contracts. A subsequent // CommitSignature message will be sent by Alice to "lock-in" the removal of the // specified HTLC, possible containing a batch signature covering several settled // HTLC's. type HTLCSettleRequest struct { - // ChannelID references an active channel which holds the HTLC to be + // ChannelPoint references an active channel which holds the HTLC to be // settled. - ChannelID uint64 + ChannelPoint *wire.OutPoint // HTLCKey denotes the exact HTLC stage within the receiving node's // commitment transaction to be removed. @@ -28,11 +30,11 @@ type HTLCSettleRequest struct { } // NewHTLCSettleRequest returns a new empty HTLCSettleRequest. -func NewHTLCSettleRequest(chanID uint64, key HTLCKey, +func NewHTLCSettleRequest(chanPoint *wire.OutPoint, key HTLCKey, redemptionProofs [][20]byte) *HTLCSettleRequest { return &HTLCSettleRequest{ - ChannelID: chanID, + ChannelPoint: chanPoint, HTLCKey: key, RedemptionProofs: redemptionProofs, } @@ -47,11 +49,11 @@ var _ Message = (*HTLCSettleRequest)(nil) // // This is part of the lnwire.Message interface. func (c *HTLCSettleRequest) Decode(r io.Reader, pver uint32) error { - // ChannelID(8) + // ChannelPoint(8) // HTLCKey(8) // RedemptionProofs(N*20) err := readElements(r, - &c.ChannelID, + &c.ChannelPoint, &c.HTLCKey, &c.RedemptionProofs, ) @@ -68,7 +70,7 @@ func (c *HTLCSettleRequest) Decode(r io.Reader, pver uint32) error { // This is part of the lnwire.Message interface. func (c *HTLCSettleRequest) Encode(w io.Writer, pver uint32) error { err := writeElements(w, - c.ChannelID, + c.ChannelPoint, c.HTLCKey, c.RedemptionProofs, ) @@ -92,8 +94,8 @@ func (c *HTLCSettleRequest) Command() uint32 { // // This is part of the lnwire.Message interface. func (c *HTLCSettleRequest) MaxPayloadLength(uint32) uint32 { - // 8 + 8 + (21 * 15) - return 331 + // 36 + 8 + (21 * 15) + return 359 } // Validate performs any necessary sanity checks to ensure all fields present @@ -116,7 +118,7 @@ func (c *HTLCSettleRequest) String() string { } return fmt.Sprintf("\n--- Begin HTLCSettleRequest ---\n") + - fmt.Sprintf("ChannelID:\t%d\n", c.ChannelID) + + fmt.Sprintf("ChannelPoint:\t%d\n", c.ChannelPoint) + fmt.Sprintf("HTLCKey:\t%d\n", c.HTLCKey) + fmt.Sprintf("RedemptionHashes:") + redemptionProofs + diff --git a/lnwire/htlc_settlerequest_test.go b/lnwire/htlc_settlerequest_test.go index 443877ab6..92d96d710 100644 --- a/lnwire/htlc_settlerequest_test.go +++ b/lnwire/htlc_settlerequest_test.go @@ -11,7 +11,7 @@ func TestHTLCSettleRequestEncodeDecode(t *testing.T) { copy(redemptionProofs[0][:], bytes.Repeat([]byte{0x09}, 20)) // First create a new HTLCSR message. - settleReq := NewHTLCSettleRequest(22, HTLCKey(23), redemptionProofs) + settleReq := NewHTLCSettleRequest(outpoint1, HTLCKey(23), redemptionProofs) // Next encode the HTLCSR message into an empty bytes buffer. var b bytes.Buffer diff --git a/lnwire/htlc_timeoutrequest.go b/lnwire/htlc_timeoutrequest.go index 3c0f3573d..1e38e9c88 100644 --- a/lnwire/htlc_timeoutrequest.go +++ b/lnwire/htlc_timeoutrequest.go @@ -3,6 +3,8 @@ package lnwire import ( "fmt" "io" + + "github.com/roasbeef/btcd/wire" ) // HTLCTimeoutRequest is sent by Alice to Bob in order to timeout a previously @@ -10,9 +12,9 @@ import ( // from the next commitment transaction, with the HTLCTimeoutRequest propgated // backwards in the route to fully clear the HTLC. type HTLCTimeoutRequest struct { - // ChannelID is the particular active channel that this HTLCTimeoutRequest + // ChannelPoint is the particular active channel that this HTLCTimeoutRequest // is binded to. - ChannelID uint64 + ChannelPoint *wire.OutPoint // HTLCKey references which HTLC on the remote node's commitment // transaction has timed out. @@ -24,10 +26,10 @@ type HTLCTimeoutRequest struct { // // This is part of the lnwire.Message interface. func (c *HTLCTimeoutRequest) Decode(r io.Reader, pver uint32) error { - // ChannelID(8) + // ChannelPoint(8) // HTLCKey(8) err := readElements(r, - &c.ChannelID, + &c.ChannelPoint, &c.HTLCKey, ) if err != nil { @@ -52,7 +54,7 @@ var _ Message = (*HTLCTimeoutRequest)(nil) // This is part of the lnwire.Message interface. func (c *HTLCTimeoutRequest) Encode(w io.Writer, pver uint32) error { err := writeElements(w, - c.ChannelID, + c.ChannelPoint, c.HTLCKey, ) if err != nil { @@ -75,8 +77,8 @@ func (c *HTLCTimeoutRequest) Command() uint32 { // // This is part of the lnwire.Message interface. func (c *HTLCTimeoutRequest) MaxPayloadLength(uint32) uint32 { - // 16 - return 16 + // 36 + 8 + return 44 } // Validate performs any necessary sanity checks to ensure all fields present @@ -92,7 +94,7 @@ func (c *HTLCTimeoutRequest) Validate() error { // This is part of the lnwire.Message interface. func (c *HTLCTimeoutRequest) String() string { return fmt.Sprintf("\n--- Begin HTLCTimeoutRequest ---\n") + - fmt.Sprintf("ChannelID:\t%d\n", c.ChannelID) + + fmt.Sprintf("ChannelPoint:\t%d\n", c.ChannelPoint) + fmt.Sprintf("HTLCKey:\t%d\n", c.HTLCKey) + fmt.Sprintf("--- End HTLCTimeoutRequest ---\n") } diff --git a/lnwire/htlc_timeoutrequest_test.go b/lnwire/htlc_timeoutrequest_test.go index 97c20c292..e8f5e065a 100644 --- a/lnwire/htlc_timeoutrequest_test.go +++ b/lnwire/htlc_timeoutrequest_test.go @@ -1,32 +1,33 @@ package lnwire import ( + "bytes" + "reflect" "testing" ) -var ( - htlcTimeoutRequest = &HTLCTimeoutRequest{ - ChannelID: uint64(12345678), - HTLCKey: HTLCKey(12345), - } - htlcTimeoutRequestSerializedString = "0000000000bc614e0000000000003039" - htlcTimeoutRequestSerializedMessage = "0709110b00000514000000100000000000bc614e0000000000003039" -) - func TestHTLCTimeoutRequestEncodeDecode(t *testing.T) { - // All of these types being passed are of the message interface type - // Test serialization, runs: message.Encode(b, 0) - // Returns bytes - // Compares the expected serialized string from the original - s := SerializeTest(t, htlcTimeoutRequest, htlcTimeoutRequestSerializedString, filename) + // First create a new HTLCTR message. + timeoutReq := &HTLCTimeoutRequest{ + ChannelPoint: outpoint1, + HTLCKey: 22, + } - // Test deserialization, runs: message.Decode(s, 0) - // Makes sure the deserialized struct is the same as the original - newMessage := NewHTLCTimeoutRequest() - DeserializeTest(t, s, newMessage, htlcTimeoutRequest) + // Next encode the HTLCTR message into an empty bytes buffer. + var b bytes.Buffer + if err := timeoutReq.Encode(&b, 0); err != nil { + t.Fatalf("unable to encode HTLCTimeoutRequest: %v", err) + } - // Test message using Message interface - // Serializes into buf: WriteMessage(buf, message, uint32(1), wire.TestNet3) - // Deserializes into msg: _, msg, _ , err := ReadMessage(buf, uint32(1), wire.TestNet3) - MessageSerializeDeserializeTest(t, htlcTimeoutRequest, htlcTimeoutRequestSerializedMessage) + // Deserialize the encoded HTLCTR message into a new empty struct. + timeoutReq2 := &HTLCTimeoutRequest{} + if err := timeoutReq2.Decode(&b, 0); err != nil { + t.Fatalf("unable to decode HTLCTimeoutRequest: %v", err) + } + + // Assert equality of the two instances. + if !reflect.DeepEqual(timeoutReq, timeoutReq2) { + t.Fatalf("encode/decode error messages don't match %#v vs %#v", + timeoutReq, timeoutReq2) + } } diff --git a/lnwire/lnwire.go b/lnwire/lnwire.go index e4d88d9b7..08c4ffcda 100644 --- a/lnwire/lnwire.go +++ b/lnwire/lnwire.go @@ -256,7 +256,7 @@ func writeElement(w io.Writer, element interface{}) error { if _, err := w.Write(idx[:]); err != nil { return err } - case wire.OutPoint: + case *wire.OutPoint: // TODO(roasbeef): consolidate with above // First write out the previous txid. var h [32]byte @@ -497,7 +497,7 @@ func readElement(r io.Reader, element interface{}) error { } (*e).PreviousOutPoint.Index = binary.BigEndian.Uint32(idxBytes[:]) return nil - case *wire.OutPoint: + case **wire.OutPoint: // TODO(roasbeef): consolidate with above var h [32]byte if _, err = io.ReadFull(r, h[:]); err != nil { @@ -507,15 +507,15 @@ func readElement(r io.Reader, element interface{}) error { if err != nil { return err } - (*e).Hash = *hash - // Index var idxBytes [4]byte _, err = io.ReadFull(r, idxBytes[:]) if err != nil { return err } - (*e).Index = binary.BigEndian.Uint32(idxBytes[:]) + index := binary.BigEndian.Uint32(idxBytes[:]) + + *e = wire.NewOutPoint(hash, index) default: return fmt.Errorf("Unknown type in readElement: %T", e) } diff --git a/lnwire/single_funding_complete.go b/lnwire/single_funding_complete.go index 531dea9cf..17dea8429 100644 --- a/lnwire/single_funding_complete.go +++ b/lnwire/single_funding_complete.go @@ -17,12 +17,13 @@ import ( type SingleFundingComplete struct { // ChannelID serves to uniquely identify the future channel created by // the initiated single funder workflow. + // TODO(roasbeef): change all to PendingChannelID, document schema ChannelID uint64 // FundingOutPoint is the outpoint (txid:index) of the funding // transaction. With this value, Bob will be able to generate a // signature for Alice's version of the commitment transaction. - FundingOutPoint wire.OutPoint + FundingOutPoint *wire.OutPoint // CommitSignature is Alice's signature for Bob's version of the // commitment transaction. @@ -31,7 +32,7 @@ type SingleFundingComplete struct { // NewSingleFundingComplete creates, and returns a new empty // SingleFundingResponse. -func NewSingleFundingComplete(chanID uint64, fundingPoint wire.OutPoint, +func NewSingleFundingComplete(chanID uint64, fundingPoint *wire.OutPoint, commitSig *btcec.Signature) *SingleFundingComplete { return &SingleFundingComplete{ diff --git a/lnwire/single_funding_complete_test.go b/lnwire/single_funding_complete_test.go index 73679fc50..d4a749b69 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) // 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 3cfa10988..62471b536 100644 --- a/lnwire/single_funding_request.go +++ b/lnwire/single_funding_request.go @@ -48,9 +48,11 @@ type SingleFundingRequest struct { // CsvDelay is the number of blocks to use for the relative time lock // in the pay-to-self output of both commitment transactions. - // TODO(roasbeef): bool for seconds or blocks? CsvDelay uint32 + // CommitmentKey... + CommitmentKey *btcec.PublicKey + // ChannelDerivationPoint is an secp256k1 point which will be used to // derive the public key the initiator will use for the half of the // 2-of-2 multi-sig. Using the channel derivation point (CDP), and the @@ -76,15 +78,17 @@ type SingleFundingRequest struct { // NewSingleFundingRequest creates, and returns a new empty SingleFundingRequest. func NewSingleFundingRequest(chanID uint64, chanType uint8, coinType uint64, - fee btcutil.Amount, delay uint32, cdp *btcec.PublicKey, revocation [20]byte, - deliveryScript PkScript) *SingleFundingRequest { + fee btcutil.Amount, amt btcutil.Amount, delay uint32, ck, + cdp *btcec.PublicKey, revocation [20]byte, deliveryScript PkScript) *SingleFundingRequest { return &SingleFundingRequest{ ChannelID: chanID, ChannelType: chanType, CoinType: coinType, FeePerKb: fee, + FundingAmount: amt, CsvDelay: delay, + CommitmentKey: ck, ChannelDerivationPoint: cdp, RevocationHash: revocation, DeliveryPkScript: deliveryScript, @@ -113,6 +117,7 @@ func (c *SingleFundingRequest) Decode(r io.Reader, pver uint32) error { &c.FeePerKb, &c.FundingAmount, &c.CsvDelay, + &c.CommitmentKey, &c.ChannelDerivationPoint, &c.RevocationHash, &c.DeliveryPkScript) @@ -145,6 +150,7 @@ func (c *SingleFundingRequest) Encode(w io.Writer, pver uint32) error { c.FeePerKb, c.FundingAmount, c.CsvDelay, + c.CommitmentKey, c.ChannelDerivationPoint, c.RevocationHash, c.DeliveryPkScript) @@ -167,11 +173,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 + 32 + 20 + 25 = 114. +// Therefore, the final breakdown is: 8 + 1 + 8 + 8 + 8 + 4 + 33 + 33 + 20 + 25 = 114. // // This is part of the lnwire.Message interface. func (c *SingleFundingRequest) MaxPayloadLength(uint32) uint32 { - return 114 + return 148 } // Validate examines each populated field within the SingleFundingRequest for @@ -199,10 +205,10 @@ func (c *SingleFundingRequest) Validate() error { if c.ChannelDerivationPoint == nil { return fmt.Errorf("The channel derivation point must be non-nil") } - if c.ChannelDerivationPoint.Y.Bit(0) != 1 { - return fmt.Errorf("The channel derivation point must have an odd " + - "y-coordinate") - } + //if c.ChannelDerivationPoint.Y.Bit(0) != 1 { + //return fmt.Errorf("The channel derivation point must have an odd " + + //"y-coordinate") + //} // The revocation hash MUST be non-zero. var zeroHash [20]byte @@ -231,6 +237,8 @@ func (c *SingleFundingRequest) String() string { serializedPubkey = c.ChannelDerivationPoint.SerializeCompressed() } + // TODO(roasbeef): remove string methods? + return fmt.Sprintf("\n--- Begin SingleFundingRequest ---\n") + fmt.Sprintf("ChannelID:\t\t\t%d\n", c.ChannelID) + fmt.Sprintf("ChannelType:\t\t\t%x\n", c.ChannelType) + diff --git a/lnwire/single_funding_request_test.go b/lnwire/single_funding_request_test.go index be110d6e1..726c0507d 100644 --- a/lnwire/single_funding_request_test.go +++ b/lnwire/single_funding_request_test.go @@ -11,7 +11,7 @@ func TestSingleFundingRequestWire(t *testing.T) { var rev [20]byte cdp := pubKey delivery := PkScript(bytes.Repeat([]byte{0x02}, 25)) - sfr := NewSingleFundingRequest(20, 21, 22, 23, 5, cdp, rev, delivery) + sfr := NewSingleFundingRequest(20, 21, 22, 23, 5, 5, cdp, cdp, rev, 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 ea22a0840..d94657feb 100644 --- a/lnwire/single_funding_response.go +++ b/lnwire/single_funding_response.go @@ -23,6 +23,15 @@ type SingleFundingResponse struct { // public key. RevocationHash [20]byte + // 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 + + // 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 @@ -41,11 +50,14 @@ type SingleFundingResponse struct { // NewSingleFundingResponse creates, and returns a new empty // SingleFundingResponse. func NewSingleFundingResponse(chanID uint64, revocation [20]byte, - cdp *btcec.PublicKey, deliveryScript PkScript) *SingleFundingResponse { + ck, cdp *btcec.PublicKey, delay uint32, + deliveryScript PkScript) *SingleFundingResponse { return &SingleFundingResponse{ ChannelID: chanID, RevocationHash: revocation, + CommitmentKey: ck, + CsvDelay: delay, ChannelDerivationPoint: cdp, DeliveryPkScript: deliveryScript, } @@ -64,7 +76,9 @@ func (c *SingleFundingResponse) Decode(r io.Reader, pver uint32) error { err := readElements(r, &c.ChannelID, &c.RevocationHash, + &c.CommitmentKey, &c.ChannelDerivationPoint, + &c.CsvDelay, &c.DeliveryPkScript) if err != nil { return err @@ -86,7 +100,9 @@ func (c *SingleFundingResponse) Encode(w io.Writer, pver uint32) error { err := writeElements(w, c.ChannelID, c.RevocationHash, + c.CommitmentKey, c.ChannelDerivationPoint, + c.CsvDelay, c.DeliveryPkScript) if err != nil { return err @@ -107,11 +123,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 + 32 + 25 = 85 +// Therefore, the final breakdown is: 8 + 20 + 33 + 33 + 4 + 25 = 123 // // This is part of the lnwire.Message interface. func (c *SingleFundingResponse) MaxPayloadLength(uint32) uint32 { - return 85 + return 123 } // Validate examines each populated field within the SingleFundingResponse for @@ -130,10 +146,10 @@ func (c *SingleFundingResponse) Validate() error { if c.ChannelDerivationPoint == nil { return fmt.Errorf("The channel derivation point must be non-nil") } - if c.ChannelDerivationPoint.Y.Bit(0) != 1 { - return fmt.Errorf("The channel derivation point must have an odd " + - "y-coordinate") - } + //if c.ChannelDerivationPoint.Y.Bit(0) != 1 { + // return fmt.Errorf("The channel derivation point must have an odd " + + // "y-coordinate") + //} // The delivery pkScript must be amongst the supported script // templates. diff --git a/lnwire/single_funding_response_test.go b/lnwire/single_funding_response_test.go index 3c519e95b..8348f87b7 100644 --- a/lnwire/single_funding_response_test.go +++ b/lnwire/single_funding_response_test.go @@ -11,7 +11,7 @@ func TestSingleFundingResponseWire(t *testing.T) { var rev [20]byte cdp := pubKey delivery := PkScript(bytes.Repeat([]byte{0x02}, 25)) - sfr := NewSingleFundingResponse(22, rev, cdp, delivery) + sfr := NewSingleFundingResponse(22, rev, cdp, cdp, 5, delivery) // Next encode the SFR message into an empty bytes buffer. var b bytes.Buffer