From 913ae259de1cae95af40f67038810c39920196af Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Mon, 23 May 2016 13:54:34 -0700 Subject: [PATCH] lnwire: document commitment+HTLC update msgs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit adds some cursory documentation along wit minor field modifications to all messages which deal with adding HTLC’s, or updating remote commitment transactions. The messages for dual funding of channel is left purposefully undocumented as all initial negotiations will be single funder by default. A revamp of the testing infrastructure of lnwire will be committed in the near future. --- lnwire/close_complete.go | 81 +++++++++++++++++--------- lnwire/close_complete_test.go | 4 +- lnwire/close_request.go | 71 ++++++++++++++++++----- lnwire/close_request_test.go | 5 +- lnwire/commit_revocation.go | 63 ++++++++++++++++---- lnwire/commit_revocation_test.go | 2 +- lnwire/commit_signature.go | 93 +++++++++++++++++++----------- lnwire/commit_signature_test.go | 13 ++--- lnwire/error_generic.go | 55 ++++++++++++++---- lnwire/funding_request.go | 18 +++--- lnwire/funding_request_test.go | 3 +- lnwire/funding_response.go | 18 +++--- lnwire/funding_response_test.go | 3 +- lnwire/funding_signaccept.go | 3 +- lnwire/funding_signcomplete.go | 3 +- lnwire/htlc_addreject.go | 53 +++++++++++++---- lnwire/htlc_addreject_test.go | 2 +- lnwire/htlc_addrequest.go | 93 ++++++++++++++++++++++-------- lnwire/htlc_addrequest_test.go | 8 +-- lnwire/htlc_settlerequest.go | 51 ++++++++++++---- lnwire/htlc_settlerequest_test.go | 4 +- lnwire/htlc_timeoutrequest.go | 43 +++++++++++--- lnwire/htlc_timeoutrequest_test.go | 2 +- server.go | 2 + 24 files changed, 500 insertions(+), 193 deletions(-) diff --git a/lnwire/close_complete.go b/lnwire/close_complete.go index a802989c..f235d02e 100644 --- a/lnwire/close_complete.go +++ b/lnwire/close_complete.go @@ -2,28 +2,41 @@ package lnwire import ( "fmt" + "github.com/roasbeef/btcd/btcec" - "github.com/roasbeef/btcd/wire" "io" ) +// CloseComplete is sent by Bob signalling a fufillment and completion of +// Alice's prior CloseRequest message. After Alice receives Bob's CloseComplete +// message, she is able to broadcast the fully signed transaction executing a +// cooperative closure of the channel. +// +// NOTE: The responder is able to only send a signature without any additional +// message as all transactions are assembled observing BIP 69 which defines a +// cannonical ordering for input/outputs. Therefore, both sides are able to +// arrive at an identical closure transaction as they know the order of the +// inputs/outputs. type CloseComplete struct { - ReservationID uint64 + // ChannelID serves to identify which channel is to be closed. + ChannelID uint64 - ResponderCloseSig *btcec.Signature // Requester's Commitment - CloseShaHash *wire.ShaHash // TxID of the Close Tx + // ResponderCloseSig is the signature of the responder for the + // transaction which closes the previously active channel. + ResponderCloseSig *btcec.Signature } +// Decode deserializes a serialized CloseComplete message stored in the passed +// io.Reader observing the specified protocol version. +// +// This is part of the lnwire.Message interface. func (c *CloseComplete) Decode(r io.Reader, pver uint32) error { - // ReservationID (8) + // ChannelID (8) // ResponderCloseSig (73) - // First byte length then sig - // CloseShaHash (32) err := readElements(r, - &c.ReservationID, - &c.ResponderCloseSig, - &c.CloseShaHash) + &c.ChannelID, + &c.ResponderCloseSig) if err != nil { return err } @@ -31,21 +44,26 @@ func (c *CloseComplete) Decode(r io.Reader, pver uint32) error { return nil } -// Creates a new CloseComplete +// NewCloseComplete creates a new empty CloseComplete message. +// TODO(roasbeef): add params to all constructors... func NewCloseComplete() *CloseComplete { return &CloseComplete{} } -// Serializes the item from the CloseComplete struct -// Writes the data to w +// A compile time check to ensure CloseComplete implements the lnwire.Message +// interface. +var _ Message = (*CloseComplete)(nil) + +// Encode serializes the target CloseComplete into the passed io.Writer observing +// the protocol version specified. +// +// This is part of the lnwire.Message interface. func (c *CloseComplete) Encode(w io.Writer, pver uint32) error { - // ReservationID - // ResponderCloseSig - // CloseShaHash + // ChannelID (8) + // ResponderCloseSig (73) err := writeElements(w, - c.ReservationID, - c.ResponderCloseSig, - c.CloseShaHash) + c.ChannelID, + c.ResponderCloseSig) if err != nil { return err } @@ -53,34 +71,43 @@ func (c *CloseComplete) Encode(w io.Writer, pver uint32) error { return nil } +// Command returns the integer uniquely identifying this message type on the +// wire. +// +// This is part of the lnwire.Message interface. func (c *CloseComplete) Command() uint32 { return CmdCloseComplete } +// MaxPayloadLength returns the maximum allowed payload size for a CloseComplete +// complete message observing the specified protocol version. +// +// This is part of the lnwire.Message interface. func (c *CloseComplete) MaxPayloadLength(uint32) uint32 { // 8 + 73 + 32 return 113 } -// Makes sure the struct data is valid (e.g. no negatives or invalid pkscripts) +// Validate performs any necessary sanity checks to ensure all fields present +// on the CloseComplete are valid. +// +// This is part of the lnwire.Message interface. func (c *CloseComplete) Validate() error { // We're good! return nil } +// String returns the string representation of the target CloseComplete. +// +// This is part of the lnwire.Message interface. func (c *CloseComplete) String() string { var serializedSig []byte - var shaString string - if c.ResponderCloseSig != nil && c.ResponderCloseSig.R != nil { + if c.ResponderCloseSig != nil { serializedSig = c.ResponderCloseSig.Serialize() } - if c.CloseShaHash != nil { - shaString = (*c).CloseShaHash.String() - } return fmt.Sprintf("\n--- Begin CloseComplete ---\n") + - fmt.Sprintf("ReservationID:\t\t%d\n", c.ReservationID) + + fmt.Sprintf("ReservationID:\t\t%d\n", c.ChannelID) + fmt.Sprintf("ResponderCloseSig:\t%x\n", serializedSig) + - fmt.Sprintf("CloseShaHash:\t\t%s\n", shaString) + fmt.Sprintf("--- End CloseComplete ---\n") } diff --git a/lnwire/close_complete_test.go b/lnwire/close_complete_test.go index c3708cf9..4500bf3b 100644 --- a/lnwire/close_complete_test.go +++ b/lnwire/close_complete_test.go @@ -1,15 +1,13 @@ package lnwire import ( - // "github.com/roasbeef/btcutil" "testing" ) var ( closeComplete = &CloseComplete{ - ReservationID: uint64(12345678), + ChannelID: uint64(12345678), ResponderCloseSig: commitSig, - CloseShaHash: shaHash1, } closeCompleteSerializedString = "0000000000bc614e4630440220333835e58e958f5e92b4ff4e6fa2470dac88094c97506b4d6d1f4e23e52cb481022057483ac18d6b9c9c14f0c626694c9ccf8b27b3dbbedfdf6b6c9a9fa9f427a1dfe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" closeCompleteSerializedMessage = "0709110b000001360000006f0000000000bc614e4630440220333835e58e958f5e92b4ff4e6fa2470dac88094c97506b4d6d1f4e23e52cb481022057483ac18d6b9c9c14f0c626694c9ccf8b27b3dbbedfdf6b6c9a9fa9f427a1dfe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" diff --git a/lnwire/close_request.go b/lnwire/close_request.go index 37de2b9a..3ab8ae00 100644 --- a/lnwire/close_request.go +++ b/lnwire/close_request.go @@ -2,26 +2,48 @@ package lnwire import ( "fmt" + "github.com/roasbeef/btcd/btcec" "github.com/roasbeef/btcutil" "io" ) +// CloseRequest is sent by either side in order to initiate the cooperative +// closure of a channel. This message is rather sparse as both side implicitly +// know to craft a transaction sending the settled funds of both parties to the +// final delivery addresses negotiated during the funding workflow. +// +// NOTE: The requester is able to only send a signature to initiate the +// cooperative channel closure as all transactions are assembled observing +// BIP 69 which defines a cannonical ordering for input/outputs. Therefore, +// both sides are able to arrive at an identical closure transaction as they +// know the order of the inputs/outputs. type CloseRequest struct { - ReservationID uint64 + // ChannelID serves to identify which channel is to be closed. + ChannelID uint64 - RequesterCloseSig *btcec.Signature // Requester's Commitment - Fee btcutil.Amount + // RequesterCloseSig is the signature of the requester for the fully + // assembled closing transaction. + RequesterCloseSig *btcec.Signature + + // 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. + Fee btcutil.Amount } +// 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 { - // ReservationID (8) + // ChannelID (8) // RequesterCloseSig (73) // First byte length then sig // Fee (8) err := readElements(r, - &c.ReservationID, + &c.ChannelID, &c.RequesterCloseSig, &c.Fee) if err != nil { @@ -31,19 +53,25 @@ func (c *CloseRequest) Decode(r io.Reader, pver uint32) error { return nil } -// Creates a new CloseRequest +// NewCloseRequest creates a new CloseRequest. func NewCloseRequest() *CloseRequest { return &CloseRequest{} } -// Serializes the item from the CloseRequest struct -// Writes the data to w +// 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. +// +// This is part of the lnwire.Message interface. func (c *CloseRequest) Encode(w io.Writer, pver uint32) error { - // ReservationID + // ChannelID // RequesterCloseSig // Fee err := writeElements(w, - c.ReservationID, + c.ChannelID, c.RequesterCloseSig, c.Fee) if err != nil { @@ -53,25 +81,40 @@ func (c *CloseRequest) Encode(w io.Writer, pver uint32) error { return nil } +// Command returns the integer uniquely identifying this message type on the +// wire. +// +// This is part of the lnwire.Message interface. func (c *CloseRequest) Command() uint32 { return CmdCloseRequest } -func (c *CloseRequest) MaxPayloadLength(uint32) uint32 { +// MaxPayloadLength returns the maximum allowed payload size for this message +// observing the specified protocol version. +// +// This is part of the lnwire.Message interface. +func (c *CloseRequest) MaxPayloadLength(pver uint32) uint32 { // 8 + 73 + 8 return 89 } -// Makes sure the struct data is valid (e.g. no negatives or invalid pkscripts) +// Validate performs any necessary sanity checks to ensure all fields present +// on the CloseRequest are valid. +// +// This is part of the lnwire.Message interface. func (c *CloseRequest) Validate() error { - // Fee must be greater than 0 + // Fee must be greater than 0. if c.Fee < 0 { return fmt.Errorf("Fee must be greater than zero.") } + // We're good! return nil } +// String returns the string representation of the target CloseRequest. +// +// This is part of the lnwire.Message interface. func (c *CloseRequest) String() string { var serializedSig []byte if c.RequesterCloseSig != nil && c.RequesterCloseSig.R != nil { @@ -79,7 +122,7 @@ func (c *CloseRequest) String() string { } return fmt.Sprintf("\n--- Begin CloseRequest ---\n") + - fmt.Sprintf("ReservationID:\t\t%d\n", c.ReservationID) + + fmt.Sprintf("ChannelID:\t\t%d\n", c.ChannelID) + 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 3f1c4e24..e4d15b9f 100644 --- a/lnwire/close_request_test.go +++ b/lnwire/close_request_test.go @@ -1,13 +1,14 @@ package lnwire import ( - "github.com/roasbeef/btcutil" "testing" + + "github.com/roasbeef/btcutil" ) var ( closeRequest = &CloseRequest{ - ReservationID: uint64(12345678), + ChannelID: uint64(12345678), RequesterCloseSig: commitSig, Fee: btcutil.Amount(12345), } diff --git a/lnwire/commit_revocation.go b/lnwire/commit_revocation.go index 69f55c92..114e4c17 100644 --- a/lnwire/commit_revocation.go +++ b/lnwire/commit_revocation.go @@ -5,17 +5,38 @@ import ( "io" ) -// Multiple Clearing Requests are possible by putting this inside an array of -// clearing requests +// 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. +// 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). +// This piggybacking allows Alice to send the next CommitSignature message +// modifying Bob's commitment transaction without first asking for a revocation +// hash initially. type CommitRevocation struct { - //Next revocation to use + // ChannelID uniquely identifies to which currently active channel this + // CommitRevocation applies to. + ChannelID uint64 + + // Revocation is the pre-image to the revocation hash of the now prior + // commitment transaction. + Revocation [20]byte + + // NextRevocationHash is the next revocation hash to use to create the + // next commitment transaction which is to be created upon receipt of a + // CommitSignature message. NextRevocationHash [20]byte - Revocation [20]byte } +// Decode deserializes a serialized CommitRevocation message stored in the +// passed io.Reader observing the specified protocol version. +// +// This is part of the lnwire.Message interface. func (c *CommitRevocation) Decode(r io.Reader, pver uint32) error { - // NextRevocationHash(20) - // Revocation(20) + // NextRevocationHash (20) + // Revocation (20) err := readElements(r, &c.NextRevocationHash, &c.Revocation, @@ -27,13 +48,19 @@ func (c *CommitRevocation) Decode(r io.Reader, pver uint32) error { return nil } -// Creates a new CommitRevocation +// NewCommitRevocation creates a new CommitRevocation message. func NewCommitRevocation() *CommitRevocation { return &CommitRevocation{} } -// Serializes the item from the CommitRevocation struct -// Writes the data to w +// A compile time check to ensure CommitRevocation implements the lnwire.Message +// interface. +var _ Message = (*CommitRevocation)(nil) + +// Encode serializes the target CommitRevocation into the passed io.Writer +// observing the protocol version specified. +// +// This is part of the lnwire.Message interface. func (c *CommitRevocation) Encode(w io.Writer, pver uint32) error { err := writeElements(w, c.NextRevocationHash, @@ -46,22 +73,38 @@ func (c *CommitRevocation) Encode(w io.Writer, pver uint32) error { return nil } +// Command returns the integer uniquely identifying this message type on the +// wire. +// +// This is part of the lnwire.Message interface. func (c *CommitRevocation) Command() uint32 { return CmdCommitRevocation } +// MaxPayloadLength returns the maximum allowed payload size for a +// CommitRevocation complete message observing the specified protocol version. +// +// This is part of the lnwire.Message interface. func (c *CommitRevocation) MaxPayloadLength(uint32) uint32 { + // 8 + 20 + 20 return 48 } -// Makes sure the struct data is valid (e.g. no negatives or invalid pkscripts) +// Validate performs any necessary sanity checks to ensure all fields present +// on the CommitRevocation are valid. +// +// This is part of the lnwire.Message interface. func (c *CommitRevocation) Validate() error { // We're good! return nil } +// String returns the string representation of the target CommitRevocation. +// +// 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("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 8340ce73..0f62c779 100644 --- a/lnwire/commit_revocation_test.go +++ b/lnwire/commit_revocation_test.go @@ -11,7 +11,7 @@ var ( commitRevocation = &CommitRevocation{ ChannelID: uint64(12345678), - RevocationProof: revocationHash, // technically it's not a hash... fix later + Revocation: revocationHash, // technically it's not a hash... fix later NextRevocationHash: nextHop, // technically it's not a hash... fix later } commitRevocationSerializedString = "0000000000bc614e4132b6b48371f7b022a16eacb9b2b0ebee134d4194a9ded5a30fc5944cb1e2cbcd980f30616a1440" diff --git a/lnwire/commit_signature.go b/lnwire/commit_signature.go index 2d155a87..acf10248 100644 --- a/lnwire/commit_signature.go +++ b/lnwire/commit_signature.go @@ -2,33 +2,47 @@ package lnwire import ( "fmt" + "io" + "github.com/roasbeef/btcd/btcec" "github.com/roasbeef/btcutil" - "io" ) -// Multiple Clearing Requests are possible by putting this inside an array of -// clearing requests +// CommitSignature is sent by either side to stage any pending HTLC's in the +// reciever's pending set which has not explcitly been rejected via an +// HTLCAddReject message. Implictly, the new commitment transaction constructed +// which has been signed by CommitSig includes all HTLC's in the remote node's +// pending set. A CommitSignature message may be sent after a series of HTLCAdd +// messages in order to batch add several HTLC's with a single signature +// covering all implicitly accepted HTLC's. type CommitSignature struct { - // List of HTLC Keys which are updated from all parties - //UpdatedHTLCKeys []uint64 - HighestPosition uint64 + // ChannelID uniquely identifies to which currently active channel this + // CommitSignature applies to. + ChannelID uint64 - // Total miners' fee that was used + // Fee represents the total miner's fee that was used when constructing + // the new commitment transaction. + // TODO(roasbeef): is the above comment correct? Fee btcutil.Amount - // Signature for the new Commitment - CommitSig *btcec.Signature // Requester's Commitment + // CommitSig is Alice's signature for Bob's new commitment transaction. + // Alice is able to send this signature without requesting any additional + // data due to the piggybacking of Bob's next revocation hash in his + // prior CommitRevocation message, as well as the cannonical ordering + // used for all inputs/outputs within commitment transactions. + CommitSig *btcec.Signature } +// Decode deserializes a serialized CommitSignature message stored in the +// passed io.Reader observing the specified protocol version. +// +// This is part of the lnwire.Message interface. func (c *CommitSignature) Decode(r io.Reader, pver uint32) error { // ChannelID(8) - // CommitmentHeight(8) - // RevocationHash(20) // Fee(8) // RequesterCommitSig(73max+2) err := readElements(r, - &c.HighestPosition, + &c.ChannelID, &c.Fee, &c.CommitSig, ) @@ -39,59 +53,68 @@ func (c *CommitSignature) Decode(r io.Reader, pver uint32) error { return nil } -// Creates a new CommitSignature +// NewCommitSignature creates a new empty CommitSignature message. func NewCommitSignature() *CommitSignature { return &CommitSignature{} } -// Serializes the item from the CommitSignature struct -// Writes the data to w -func (c *CommitSignature) Encode(w io.Writer, pver uint32) error { - err := writeElements(w, - c.HighestPosition, - c.Fee, - c.CommitSig, - ) - if err != nil { - return err - } +// A compile time check to ensure CommitSignature implements the lnwire.Message +// interface. +var _ Message = (*CommitSignature)(nil) - return nil +// Encode serializes the target CommitSignature into the passed io.Writer +// observing the protocol version specified. +// +// This is part of the lnwire.Message interface. +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) } +// Command returns the integer uniquely identifying this message type on the +// wire. +// +// This is part of the lnwire.Message interface. func (c *CommitSignature) Command() uint32 { return CmdCommitSignature } +// MaxPayloadLength returns the maximum allowed payload size for a +// CommitSignature complete message observing the specified protocol version. +// +// This is part of the lnwire.Message interface. func (c *CommitSignature) MaxPayloadLength(uint32) uint32 { - return 8192 + // 8 + 8 + 73 + return 89 } -// Makes sure the struct data is valid (e.g. no negatives or invalid pkscripts) +// Validate performs any necessary sanity checks to ensure all fields present +// on the CommitSignature are valid. +// +// This is part of the lnwire.Message interface. func (c *CommitSignature) Validate() error { if c.Fee < 0 { // While fees can be negative, it's too confusing to allow // negative payments. Maybe for some wallets, but not this one! return fmt.Errorf("Amount paid cannot be negative.") } + // We're good! return nil } +// String returns the string representation of the target CommitSignature. +// +// This is part of the lnwire.Message interface. func (c *CommitSignature) String() string { - // c.ChannelID, - // c.CommitmentHeight, - // c.RevocationHash, - // c.UpdatedHTLCKeys, - // c.Fee, - // c.CommitSig, var serializedSig []byte - if c.CommitSig != nil && c.CommitSig.R != nil { + if c.CommitSig != nil { serializedSig = c.CommitSig.Serialize() } return fmt.Sprintf("\n--- Begin CommitSignature ---\n") + - fmt.Sprintf("HighestPosition:\t%d\n", c.HighestPosition) + + fmt.Sprintf("ChannelID:\t%d\n", c.ChannelID) + 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 c90e12aa..20a6fe19 100644 --- a/lnwire/commit_signature_test.go +++ b/lnwire/commit_signature_test.go @@ -1,8 +1,9 @@ package lnwire import ( - "github.com/roasbeef/btcutil" "testing" + + "github.com/roasbeef/btcutil" ) var ( @@ -10,13 +11,9 @@ var ( _ = copy(revocationHash[:], revocationHashBytes) commitSignature = &CommitSignature{ - ChannelID: uint64(12345678), - CommitmentHeight: uint64(12345), - LastCommittedKeyAlice: HTLCKey(12345), - LastCommittedKeyBob: HTLCKey(54321), - RevocationHash: revocationHash, - Fee: btcutil.Amount(10000), - CommitSig: commitSig, + ChannelID: uint64(12345678), + Fee: btcutil.Amount(10000), + CommitSig: commitSig, } commitSignatureSerializedString = "0000000000bc614e00000000000030390000000000003039000000000000d4314132b6b48371f7b022a16eacb9b2b0ebee134d4100000000000027104630440220333835e58e958f5e92b4ff4e6fa2470dac88094c97506b4d6d1f4e23e52cb481022057483ac18d6b9c9c14f0c626694c9ccf8b27b3dbbedfdf6b6c9a9fa9f427a1df" commitSignatureSerializedMessage = "0709110b000007d0000000830000000000bc614e00000000000030390000000000003039000000000000d4314132b6b48371f7b022a16eacb9b2b0ebee134d4100000000000027104630440220333835e58e958f5e92b4ff4e6fa2470dac88094c97506b4d6d1f4e23e52cb481022057483ac18d6b9c9c14f0c626694c9ccf8b27b3dbbedfdf6b6c9a9fa9f427a1df" diff --git a/lnwire/error_generic.go b/lnwire/error_generic.go index 4f7bdfa1..c7ab6bfa 100644 --- a/lnwire/error_generic.go +++ b/lnwire/error_generic.go @@ -5,16 +5,30 @@ import ( "io" ) -// Multiple Clearing Requests are possible by putting this inside an array of -// clearing requests +// 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. type ErrorGeneric struct { - // We can use a different data type for this if necessary... + // ChannelID references the active channel in which the error occured + // within. ChannelID uint64 - // Some kind of message - // Max length 8192 + + // TODO(roasbeef): uint16 for problem type? + // ErrorID uint16 + + // Problem is a human-readable string further elaborating upon the + // nature of the exact error. The maxmium allowed length of this + // message is 8192 bytes. Problem string + + // TODO(roasbeef): add SerializeSize? } +// Decode deserializes a serialized ErrorGeneric message stored in the +// passed io.Reader observing the specified protocol version. +// +// This is part of the lnwire.Message interface. func (c *ErrorGeneric) Decode(r io.Reader, pver uint32) error { // ChannelID(8) // Problem @@ -29,13 +43,19 @@ func (c *ErrorGeneric) Decode(r io.Reader, pver uint32) error { return nil } -// Creates a new ErrorGeneric +// NewErrorGeneric creates a new ErrorGeneric message. func NewErrorGeneric() *ErrorGeneric { return &ErrorGeneric{} } -// Serializes the item from the ErrorGeneric struct -// Writes the data to w +// A compile time check to ensure ErrorGeneric implements the lnwire.Message +// interface. +var _ Message = (*ErrorGeneric)(nil) + +// Encode serializes the target ErrorGeneric into the passed io.Writer +// observing the protocol version specified. +// +// This is part of the lnwire.Message interface. func (c *ErrorGeneric) Encode(w io.Writer, pver uint32) error { err := writeElements(w, c.ChannelID, @@ -48,24 +68,39 @@ func (c *ErrorGeneric) Encode(w io.Writer, pver uint32) error { return nil } +// Command returns the integer uniquely identifying an ErrorGeneric message on +// the wire. +// +// This is part of the lnwire.Message interface. func (c *ErrorGeneric) Command() uint32 { return CmdErrorGeneric } +// MaxPayloadLength returns the maximum allowed payload size for a +// ErrorGeneric complete message observing the specified protocol version. +// +// This is part of the lnwire.Message interface. func (c *ErrorGeneric) MaxPayloadLength(uint32) uint32 { // 8+8192 return 8208 } -// Makes sure the struct data is valid (e.g. no negatives or invalid pkscripts) +// Validate performs any necessary sanity checks to ensure all fields present +// on the ErrorGeneric are valid. +// +// This is part of the lnwire.Message interface. func (c *ErrorGeneric) Validate() error { if len(c.Problem) > 8192 { - return fmt.Errorf("Problem string length too long") + return fmt.Errorf("problem string length too long") } + // We're good! return nil } +// String returns the string representation of the target ErrorGeneric. +// +// 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) + diff --git a/lnwire/funding_request.go b/lnwire/funding_request.go index 98b6a9c2..279acd4b 100644 --- a/lnwire/funding_request.go +++ b/lnwire/funding_request.go @@ -2,10 +2,11 @@ package lnwire import ( "fmt" + "io" + "github.com/roasbeef/btcd/btcec" "github.com/roasbeef/btcd/wire" "github.com/roasbeef/btcutil" - "io" ) type FundingRequest struct { @@ -150,8 +151,6 @@ func (c *FundingRequest) MaxPayloadLength(uint32) uint32 { // Makes sure the struct data is valid (e.g. no negatives or invalid pkscripts) func (c *FundingRequest) Validate() error { - var err error - // No negative values if c.RequesterFundingAmount < 0 { return fmt.Errorf("RequesterFundingAmount cannot be negative") @@ -187,15 +186,16 @@ func (c *FundingRequest) Validate() error { } // DeliveryPkScript is either P2SH or P2PKH - err = ValidatePkScript(c.DeliveryPkScript) - if err != nil { - return err + if !isValidPkScript(c.DeliveryPkScript) { + // TODO(roasbeef): move into actual error + return fmt.Errorf("Valid delivery public key scripts MUST be: " + + "P2PKH, P2WKH, P2SH, or P2WSH.") } // ChangePkScript is either P2SH or P2PKH - err = ValidatePkScript(c.ChangePkScript) - if err != nil { - return err + if !isValidPkScript(c.ChangePkScript) { + return fmt.Errorf("Valid change public key script MUST be: " + + "P2PKH, P2WKH, P2SH, or P2WSH.") } // We're good! diff --git a/lnwire/funding_request_test.go b/lnwire/funding_request_test.go index 38f473d0..e8f50406 100644 --- a/lnwire/funding_request_test.go +++ b/lnwire/funding_request_test.go @@ -1,8 +1,9 @@ package lnwire import ( - "github.com/roasbeef/btcutil" "testing" + + "github.com/roasbeef/btcutil" ) var ( diff --git a/lnwire/funding_response.go b/lnwire/funding_response.go index b6e37240..90416728 100644 --- a/lnwire/funding_response.go +++ b/lnwire/funding_response.go @@ -2,10 +2,11 @@ package lnwire import ( "fmt" + "io" + "github.com/roasbeef/btcd/btcec" "github.com/roasbeef/btcd/wire" "github.com/roasbeef/btcutil" - "io" ) type FundingResponse struct { @@ -134,8 +135,6 @@ func (c *FundingResponse) MaxPayloadLength(uint32) uint32 { // Makes sure the struct data is valid (e.g. no negatives or invalid pkscripts) func (c *FundingResponse) Validate() error { - var err error - // No negative values if c.ResponderFundingAmount < 0 { return fmt.Errorf("ResponderFundingAmount cannot be negative") @@ -160,15 +159,16 @@ func (c *FundingResponse) Validate() error { } // Delivery PkScript is either P2SH or P2PKH - err = ValidatePkScript(c.DeliveryPkScript) - if err != nil { - return err + if !isValidPkScript(c.DeliveryPkScript) { + return fmt.Errorf("Valid delivery public key scripts MUST be: " + + "P2PKH, P2WKH, P2SH, or P2WSH.") } // Change PkScript is either P2SH or P2PKH - err = ValidatePkScript(c.ChangePkScript) - if err != nil { - return err + if !isValidPkScript(c.ChangePkScript) { + // TODO(roasbeef): move into actual error + return fmt.Errorf("Valid change public key scripts MUST be: " + + "P2PKH, P2WKH, P2SH, or P2WSH.") } // We're good! diff --git a/lnwire/funding_response_test.go b/lnwire/funding_response_test.go index 0ba63530..30fb90da 100644 --- a/lnwire/funding_response_test.go +++ b/lnwire/funding_response_test.go @@ -1,8 +1,9 @@ package lnwire import ( - "github.com/roasbeef/btcutil" "testing" + + "github.com/roasbeef/btcutil" ) var ( diff --git a/lnwire/funding_signaccept.go b/lnwire/funding_signaccept.go index 84820ca8..42042bbf 100644 --- a/lnwire/funding_signaccept.go +++ b/lnwire/funding_signaccept.go @@ -2,8 +2,9 @@ package lnwire import ( "fmt" - "github.com/roasbeef/btcd/btcec" "io" + + "github.com/roasbeef/btcd/btcec" ) type FundingSignAccept struct { diff --git a/lnwire/funding_signcomplete.go b/lnwire/funding_signcomplete.go index f3a1bba3..ce81a9af 100644 --- a/lnwire/funding_signcomplete.go +++ b/lnwire/funding_signcomplete.go @@ -2,9 +2,10 @@ package lnwire import ( "fmt" + "io" + "github.com/roasbeef/btcd/btcec" "github.com/roasbeef/btcd/wire" - "io" ) type FundingSignComplete struct { diff --git a/lnwire/htlc_addreject.go b/lnwire/htlc_addreject.go index dadfb390..b93c9c77 100644 --- a/lnwire/htlc_addreject.go +++ b/lnwire/htlc_addreject.go @@ -5,17 +5,28 @@ import ( "io" ) +// 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 +// HTLCKey of the rejected HTLC is present type HTLCAddReject struct { + // ChannelID references the particular active channel to which this + // HTLCAddReject message is binded to. ChannelID uint64 - HTLCKey HTLCKey + + // HTLCKey is used to identify which HTLC previously attempted to be + // added via an HTLCAddRequest message is being declined. + HTLCKey HTLCKey } +// Decode deserializes a serialized HTLCAddReject message stored in the passed +// io.Reader observing the specified protocol version. +// +// This is part of the lnwire.Message interface. func (c *HTLCAddReject) Decode(r io.Reader, pver uint32) error { - // ChannelID(8) - // CommitmentHeight(8) - // NextResponderCommitmentRevocationHash(20) - // ResponderRevocationPreimage(20) - // ResponderCommitSig(2+73max) + // ChannelID (8) + // HTLCKey (8) err := readElements(r, &c.ChannelID, &c.HTLCKey, @@ -27,13 +38,19 @@ func (c *HTLCAddReject) Decode(r io.Reader, pver uint32) error { return nil } -// Creates a new HTLCAddReject +// NewHTLCAddReject returns a new empty HTLCAddReject message. func NewHTLCAddReject() *HTLCAddReject { return &HTLCAddReject{} } -// Serializes the item from the HTLCAddReject struct -// Writes the data to w +// A compile time check to ensure HTLCAddReject implements the lnwire.Message +// interface. +var _ Message = (*HTLCAddReject)(nil) + +// Encode serializes the target HTLCAddReject into the passed io.Writer observing +// the protocol version specified. +// +// This is part of the lnwire.Message interface. func (c *HTLCAddReject) Encode(w io.Writer, pver uint32) error { err := writeElements(w, c.ChannelID, @@ -47,21 +64,35 @@ func (c *HTLCAddReject) Encode(w io.Writer, pver uint32) error { return nil } +// Command returns the integer uniquely identifying this message type on the +// wire. +// +// This is part of the lnwire.Message interface. func (c *HTLCAddReject) Command() uint32 { return CmdHTLCAddReject } +// MaxPayloadLength returns the maximum allowed payload size for a HTLCAddReject +// complete message observing the specified protocol version. +// +// This is part of the lnwire.Message interface. func (c *HTLCAddReject) MaxPayloadLength(uint32) uint32 { - // 16 base size + // 8 + 8 return 16 } -// Makes sure the struct data is valid (e.g. no negatives or invalid pkscripts) +// Validate performs any necessary sanity checks to ensure all fields present +// on the HTLCAddReject are valid. +// +// This is part of the lnwire.Message interface. func (c *HTLCAddReject) Validate() error { // We're good! return nil } +// String returns the string representation of the target HTLCAddReject. +// +// 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) + diff --git a/lnwire/htlc_addreject_test.go b/lnwire/htlc_addreject_test.go index 6be29732..09f10449 100644 --- a/lnwire/htlc_addreject_test.go +++ b/lnwire/htlc_addreject_test.go @@ -7,7 +7,7 @@ import ( var ( htlcAddReject = &HTLCAddReject{ ChannelID: uint64(12345678), - HTLCKey: HTLCKey(12345), + HTLCKey: HTLCKey(12345), } htlcAddRejectSerializedString = "0000000000bc614e0000000000003039" htlcAddRejectSerializedMessage = "0709110b000003fc000000100000000000bc614e0000000000003039" diff --git a/lnwire/htlc_addrequest.go b/lnwire/htlc_addrequest.go index 3a3e2f90..e7eca7ae 100644 --- a/lnwire/htlc_addrequest.go +++ b/lnwire/htlc_addrequest.go @@ -5,56 +5,83 @@ import ( "io" ) -// Multiple Clearing Requests are possible by putting this inside an array of -// clearing requests +// HTLCAddRequest is the message sent by Alice to Bob when she wishes to add an +// HTLC to his remote commitment transaction. In addition to information +// detailing the value, and contract type of the HTLC, and onion blob is also +// included which allows Bob to derive the next hop in the route. The HTLC +// added by this message is to be added to the remote node's "pending" HTLC's. +// A subsequent CommitSignature message will move the pending HTLC to the newly +// created commitment transaction, marking them as "staged". type HTLCAddRequest struct { - // We can use a different data type for this if necessary... + // ChannelID is the particular active channel that this HTLCAddRequest + // is binded to. ChannelID uint64 - // ID of this request - // implicit - // HTLCKey HTLCKey - - // When the HTLC expires + // 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 + // sufficient expiry value to allow her to redeem the incmoing HTLC. Expiry uint32 // Amount to pay in the hop // Difference between hop and first item in blob is the fee to complete + + // Amount is the number of credits this HTLC is worth. Amount CreditsAmount // RefundContext is for payment cancellation - // TODO (j): not currently in use, add later + // TODO(j): not currently in use, add later RefundContext HTLCKey - // Contract Type - // first 4 bits is n, second for is m, in n-of-m "multisig" - // default is 0. + // ContractType defines the particular output script to be used for + // this HTLC. This value defaults to zero for regular HTLCs. For + // multi-sig HTLCs, then first 4 bit represents N, while the second 4 + // bits are M, within the N-of-M multi-sig. ContractType uint8 - // Redemption Hashes - RedemptionHashes []*[20]byte + // RedemptionHashes are the hashes to be used within the HTLC script. + // An HTLC is only fufilled once Bob is provided with the required + // number of pre-images for each of the listed hashes. For regular HTLC's + // this slice only has one hash. However, for "multi-sig" HTLC's, the + // length of this slice should be N. + RedemptionHashes [][20]byte // Data to parse&pass on to the next node // Nested HTLCAddRequests with a uint32 in front for the size Blob []byte + + // OnionBlob is the raw serialized mix header used to route an HTLC in + // a privacy-preserving manner. The mix header is defined currently to + // be parsed as a 4-tuple: (groupElement, routingInfo, headerMAC, body). + // First the receiving node should use the groupElement, and its current + // onion key to derive a shared secret with the source. Once the shared + // secret has been derived, the headerMAC should be checked FIRST. Note + // that the MAC only covers the routingInfo field. If the MAC matches, + // and the shared secret is fresh, then the node should stip off a layer + // of encryption, exposing the next hop to be used in the subsequent + // HTLCAddRequest message. + OnionBlob []byte } +// Decode deserializes a serialized HTLCAddRequest message stored in the passed +// io.Reader observing the specified protocol version. +// +// This is part of the lnwire.Message interface. func (c *HTLCAddRequest) Decode(r io.Reader, pver uint32) error { // ChannelID(8) - // HTLCKey(8) // Expiry(4) // Amount(4) // ContractType(1) // RedemptionHashes (numOfHashes * 20 + numOfHashes) // Blob(2+blobsize) + // OnionBlog err := readElements(r, &c.ChannelID, - &c.HTLCKey, &c.Expiry, &c.Amount, &c.ContractType, &c.RedemptionHashes, &c.Blob, + &c.OnionBlob, ) if err != nil { return err @@ -63,22 +90,28 @@ func (c *HTLCAddRequest) Decode(r io.Reader, pver uint32) error { return nil } -// Creates a new HTLCAddRequest +// NewHTLCAddRequest returns a new empty HTLCAddRequest message. func NewHTLCAddRequest() *HTLCAddRequest { return &HTLCAddRequest{} } -// Serializes the item from the HTLCAddRequest struct -// Writes the data to w +// A compile time check to ensure HTLCAddRequest implements the lnwire.Message +// interface. +var _ Message = (*HTLCAddRequest)(nil) + +// Encode serializes the target HTLCAddRequest into the passed io.Writer observing +// the protocol version specified. +// +// This is part of the lnwire.Message interface. func (c *HTLCAddRequest) Encode(w io.Writer, pver uint32) error { err := writeElements(w, c.ChannelID, - c.HTLCKey, c.Expiry, c.Amount, c.ContractType, c.RedemptionHashes, c.Blob, + c.OnionBlob, ) if err != nil { return err @@ -87,17 +120,28 @@ func (c *HTLCAddRequest) Encode(w io.Writer, pver uint32) error { return nil } +// Command returns the integer uniquely identifying this message type on the +// wire. +// +// This is part of the lnwire.Message interface. func (c *HTLCAddRequest) Command() uint32 { return CmdHTLCAddRequest } +// MaxPayloadLength returns the maximum allowed payload size for a HTLCAddRequest +// complete message observing the specified protocol version. +// +// This is part of the lnwire.Message interface. func (c *HTLCAddRequest) MaxPayloadLength(uint32) uint32 { // base size ~110, but blob can be variable. // shouldn't be bigger than 8K though... return 8192 } -// Makes sure the struct data is valid (e.g. no negatives or invalid pkscripts) +// Validate performs any necessary sanity checks to ensure all fields present +// on the HTLCAddRequest are valid. +// +// This is part of the lnwire.Message interface. func (c *HTLCAddRequest) Validate() error { if c.Amount < 0 { // While fees can be negative, it's too confusing to allow @@ -108,21 +152,24 @@ func (c *HTLCAddRequest) Validate() error { return nil } +// String returns the string representation of the target HTLCAddRequest. +// +// This is part of the lnwire.Message interface. func (c *HTLCAddRequest) String() string { var redemptionHashes string for i, rh := range c.RedemptionHashes { redemptionHashes += fmt.Sprintf("\n\tSlice\t%d\n", i) - redemptionHashes += fmt.Sprintf("\t\tRedemption Hash: %x\n", *rh) + redemptionHashes += fmt.Sprintf("\t\tRedemption Hash: %x\n", rh) } return fmt.Sprintf("\n--- Begin HTLCAddRequest ---\n") + fmt.Sprintf("ChannelID:\t%d\n", c.ChannelID) + - fmt.Sprintf("HTLCKey:\t%d\n", c.HTLCKey) + 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) + fmt.Sprintf("RedemptionHashes:") + redemptionHashes + fmt.Sprintf("Blob:\t\t\t\t%x\n", c.Blob) + + fmt.Sprintf("OnionBlob:\t\t\t\t%x\n", c.OnionBlob) + fmt.Sprintf("--- End HTLCAddRequest ---\n") } diff --git a/lnwire/htlc_addrequest_test.go b/lnwire/htlc_addrequest_test.go index 3e14e915..74a3d922 100644 --- a/lnwire/htlc_addrequest_test.go +++ b/lnwire/htlc_addrequest_test.go @@ -8,18 +8,16 @@ var ( // Need to to do this here _ = copy(revocationHash[:], revocationHashBytes) _ = copy(redemptionHash[:], redemptionHashBytes) - emptyRedemptionHashes = []*[20]byte{} - redemptionHashes = append(emptyRedemptionHashes, &redemptionHash) + emptyRedemptionHashes = [][20]byte{} + redemptionHashes = append(emptyRedemptionHashes, redemptionHash) htlcAddRequest = &HTLCAddRequest{ ChannelID: uint64(12345678), - HTLCKey: HTLCKey(12345), Expiry: uint32(144), Amount: CreditsAmount(123456000), ContractType: uint8(17), RedemptionHashes: redemptionHashes, - - Blob: []byte{255, 0, 255, 0, 255, 0, 255, 0}, + Blob: []byte{255, 0, 255, 0, 255, 0, 255, 0}, } htlcAddRequestSerializedString = "0000000000bc614e00000000000030390000009000000000075bca001100015b315ebabb0d8c0d94281caa2dfee69a1a00436e0008ff00ff00ff00ff00" diff --git a/lnwire/htlc_settlerequest.go b/lnwire/htlc_settlerequest.go index 5eb9e2f8..015d24d1 100644 --- a/lnwire/htlc_settlerequest.go +++ b/lnwire/htlc_settlerequest.go @@ -5,19 +5,32 @@ import ( "io" ) -// Multiple Clearing Requests are possible by putting this inside an array of -// clearing requests +// 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 +// 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 { - // We can use a different data type for this if necessary... + // ChannelID references an active channel which holds the HTLC to be + // settled. ChannelID uint64 - // ID of this request + // HTLCKey denotes the exact HTLC stage within the receiving node's + // commitment transaction to be removed. HTLCKey HTLCKey - // Redemption Proofs (R-Values) - RedemptionProofs []*[20]byte + // RedemptionProofs are the R-value preimages required to fully settle + // an HTLC. The number of preimages in the slice will depend on the + // specific ContractType of the referenced HTLC. + RedemptionProofs [][20]byte } +// Decode deserializes a serialized HTLCSettleRequest message stored in the passed +// io.Reader observing the specified protocol version. +// +// This is part of the lnwire.Message interface. func (c *HTLCSettleRequest) Decode(r io.Reader, pver uint32) error { // ChannelID(8) // HTLCKey(8) @@ -39,11 +52,15 @@ func (c *HTLCSettleRequest) Decode(r io.Reader, pver uint32) error { return nil } -// Creates a new HTLCSettleRequest +// NewHTLCSettleRequest returns a new empty HTLCSettleRequest. func NewHTLCSettleRequest() *HTLCSettleRequest { return &HTLCSettleRequest{} } +// A compile time check to ensure HTLCSettleRequest implements the lnwire.Message +// interface. +var _ Message = (*HTLCSettleRequest)(nil) + // Serializes the item from the HTLCSettleRequest struct // Writes the data to w func (c *HTLCSettleRequest) Encode(w io.Writer, pver uint32) error { @@ -59,26 +76,40 @@ func (c *HTLCSettleRequest) Encode(w io.Writer, pver uint32) error { return nil } +// Command returns the integer uniquely identifying this message type on the +// wire. +// +// This is part of the lnwire.Message interface. func (c *HTLCSettleRequest) Command() uint32 { return CmdHTLCSettleRequest } +// MaxPayloadLength returns the maximum allowed payload size for a HTLCSettleRequest +// complete message observing the specified protocol version. +// +// This is part of the lnwire.Message interface. func (c *HTLCSettleRequest) MaxPayloadLength(uint32) uint32 { - // 21*15+16 + // 8 + 8 + (21 * 15) return 331 } -// Makes sure the struct data is valid (e.g. no negatives or invalid pkscripts) +// Validate performs any necessary sanity checks to ensure all fields present +// on the HTLCSettleRequest are valid. +// +// This is part of the lnwire.Message interface. func (c *HTLCSettleRequest) Validate() error { // We're good! return nil } +// String returns the string representation of the target HTLCSettleRequest. +// +// This is part of the lnwire.Message interface. func (c *HTLCSettleRequest) String() string { var redemptionProofs string for i, rh := range c.RedemptionProofs { redemptionProofs += fmt.Sprintf("\n\tSlice\t%d\n", i) - redemptionProofs += fmt.Sprintf("\t\tRedemption Proof: %x\n", *rh) + redemptionProofs += fmt.Sprintf("\t\tRedemption Proof: %x\n", rh) } return fmt.Sprintf("\n--- Begin HTLCSettleRequest ---\n") + diff --git a/lnwire/htlc_settlerequest_test.go b/lnwire/htlc_settlerequest_test.go index 3f79d871..51018d8c 100644 --- a/lnwire/htlc_settlerequest_test.go +++ b/lnwire/htlc_settlerequest_test.go @@ -7,8 +7,8 @@ import ( var ( // Need to to do this here _ = copy(redemptionHash[:], redemptionHashBytes) - emptyRedemptionProofs = []*[20]byte{} - redemptionProofs = append(emptyRedemptionProofs, &redemptionHash) + emptyRedemptionProofs = [][20]byte{} + redemptionProofs = append(emptyRedemptionProofs, redemptionHash) htlcSettleRequest = &HTLCSettleRequest{ ChannelID: uint64(12345678), diff --git a/lnwire/htlc_timeoutrequest.go b/lnwire/htlc_timeoutrequest.go index 3a27194c..3c0f3573 100644 --- a/lnwire/htlc_timeoutrequest.go +++ b/lnwire/htlc_timeoutrequest.go @@ -5,16 +5,24 @@ import ( "io" ) -// Multiple Clearing Requests are possible by putting this inside an array of -// clearing requests +// HTLCTimeoutRequest is sent by Alice to Bob in order to timeout a previously +// added HTLC. Upon receipt of an HTLCTimeoutRequest the HTLC should be removed +// from the next commitment transaction, with the HTLCTimeoutRequest propgated +// backwards in the route to fully clear the HTLC. type HTLCTimeoutRequest struct { - // We can use a different data type for this if necessary... + // ChannelID is the particular active channel that this HTLCTimeoutRequest + // is binded to. ChannelID uint64 - // ID of this request + // HTLCKey references which HTLC on the remote node's commitment + // transaction has timed out. HTLCKey HTLCKey } +// Decode deserializes a serialized HTLCTimeoutRequest message stored in the passed +// io.Reader observing the specified protocol version. +// +// This is part of the lnwire.Message interface. func (c *HTLCTimeoutRequest) Decode(r io.Reader, pver uint32) error { // ChannelID(8) // HTLCKey(8) @@ -29,13 +37,19 @@ func (c *HTLCTimeoutRequest) Decode(r io.Reader, pver uint32) error { return nil } -// Creates a new HTLCTimeoutRequest +// NewHTLCTimeoutRequest creates a new HTLCTimeoutRequest message. func NewHTLCTimeoutRequest() *HTLCTimeoutRequest { return &HTLCTimeoutRequest{} } -// Serializes the item from the HTLCTimeoutRequest struct -// Writes the data to w +// A compile time check to ensure HTLCTimeoutRequest implements the lnwire.Message +// interface. +var _ Message = (*HTLCTimeoutRequest)(nil) + +// Encode serializes the target HTLCTimeoutRequest into the passed io.Writer observing +// the protocol version specified. +// +// This is part of the lnwire.Message interface. func (c *HTLCTimeoutRequest) Encode(w io.Writer, pver uint32) error { err := writeElements(w, c.ChannelID, @@ -48,21 +62,34 @@ func (c *HTLCTimeoutRequest) Encode(w io.Writer, pver uint32) error { return nil } +// Command returns the integer uniquely identifying this message type on the +// wire. +// +// This is part of the lnwire.Message interface. func (c *HTLCTimeoutRequest) Command() uint32 { return CmdHTLCTimeoutRequest } +// MaxPayloadLength returns the maximum allowed payload size for a HTLCTimeoutRequest +// complete message observing the specified protocol version. +// +// This is part of the lnwire.Message interface. func (c *HTLCTimeoutRequest) MaxPayloadLength(uint32) uint32 { // 16 return 16 } -// Makes sure the struct data is valid (e.g. no negatives or invalid pkscripts) +// Validate performs any necessary sanity checks to ensure all fields present +// on the HTLCTimeoutRequest are valid. +// +// This is part of the lnwire.Message interface. func (c *HTLCTimeoutRequest) Validate() error { // We're good! return nil } +// String returns the string representation of the target HTLCTimeoutRequest. // +// 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) + diff --git a/lnwire/htlc_timeoutrequest_test.go b/lnwire/htlc_timeoutrequest_test.go index 3325f88b..97c20c29 100644 --- a/lnwire/htlc_timeoutrequest_test.go +++ b/lnwire/htlc_timeoutrequest_test.go @@ -7,7 +7,7 @@ import ( var ( htlcTimeoutRequest = &HTLCTimeoutRequest{ ChannelID: uint64(12345678), - HTLCKey: HTLCKey(12345), + HTLCKey: HTLCKey(12345), } htlcTimeoutRequestSerializedString = "0000000000bc614e0000000000003039" htlcTimeoutRequestSerializedMessage = "0709110b00000514000000100000000000bc614e0000000000003039" diff --git a/server.go b/server.go index 97aabdda..fe67771c 100644 --- a/server.go +++ b/server.go @@ -209,6 +209,8 @@ func (s *server) listener(l net.Listener) { srvrLog.Tracef("New inbound connection from %v", conn.RemoteAddr()) peer := newPeer(conn, s) peer.Start() + + s.newPeers <- peer } s.wg.Done()