From ec02060c9f4dfd5d2bc28e4b5630d94d9882edb6 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 16 Feb 2017 20:08:34 +0800 Subject: [PATCH] lnwire: rename HTLCAddRequest to UpdateAddHTLC --- lnwire/htlc_addrequest.go | 147 ---------------- lnwire/message.go | 7 +- lnwire/update_add_htlc.go | 157 ++++++++++++++++++ ...equest_test.go => update_add_htlc_test.go} | 26 ++- 4 files changed, 172 insertions(+), 165 deletions(-) delete mode 100644 lnwire/htlc_addrequest.go create mode 100644 lnwire/update_add_htlc.go rename lnwire/{htlc_addrequest_test.go => update_add_htlc_test.go} (51%) diff --git a/lnwire/htlc_addrequest.go b/lnwire/htlc_addrequest.go deleted file mode 100644 index c0d5ebd3..00000000 --- a/lnwire/htlc_addrequest.go +++ /dev/null @@ -1,147 +0,0 @@ -package lnwire - -import ( - "fmt" - "io" - - "github.com/roasbeef/btcd/wire" - "github.com/roasbeef/btcutil" -) - -// 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" HTLCs. -// A subsequent CommitSignature message will move the pending HTLC to the newly -// created commitment transaction, marking them as "staged". -type HTLCAddRequest struct { - // ChannelPoint is the particular active channel that this HTLCAddRequest - // is binded to. - 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 - // sufficient expiry value to allow her to redeem the incmoing HTLC. - Expiry uint32 - - // Amount of BTC that the HTLC is worth. - Amount btcutil.Amount - - // RefundContext is for payment cancellation - // TODO(j): not currently in use, add later - RefundContext HTLCKey - - // 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 - - // 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 preimages for each of the listed hashes. For regular HTLCs - // this slice only has one hash. However, for "multi-sig" HTLCs, the - // length of this slice should be N. - RedemptionHashes [][32]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. - // TODO(roasbeef): can be fixed sized now that v1 Sphinx is "done". - OnionBlob []byte -} - -// NewHTLCAddRequest returns a new empty HTLCAddRequest message. -func NewHTLCAddRequest() *HTLCAddRequest { - return &HTLCAddRequest{} -} - -// A compile time check to ensure HTLCAddRequest implements the lnwire.Message -// interface. -var _ Message = (*HTLCAddRequest)(nil) - -// 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 { - // ChannelPoint(8) - // Expiry(4) - // Amount(4) - // ContractType(1) - // RedemptionHashes (numOfHashes * 32 + numOfHashes) - // OnionBlog - err := readElements(r, - &c.ChannelPoint, - &c.Expiry, - &c.Amount, - &c.ContractType, - &c.RedemptionHashes, - &c.OnionBlob, - ) - if err != nil { - return err - } - - return 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.ChannelPoint, - c.Expiry, - c.Amount, - c.ContractType, - c.RedemptionHashes, - c.OnionBlob, - ) - if err != nil { - return err - } - - 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 -} - -// 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 - // negative payments. Maybe for some wallets, but not this one! - return fmt.Errorf("Amount paid cannot be negative.") - } - // We're good! - return nil -} diff --git a/lnwire/message.go b/lnwire/message.go index e98d0032..df998829 100644 --- a/lnwire/message.go +++ b/lnwire/message.go @@ -37,11 +37,10 @@ const ( CmdCloseComplete = uint32(310) // Commands for negotiating HTLCs. - CmdHTLCAddRequest = uint32(1000) - CmdHTLCAddAccept = uint32(1010) CmdHTLCAddReject = uint32(1020) CmdHTLCSettleRequest = uint32(1100) CmdCancelHTLC = uint32(1300) + CmdUpdateAddHTLC = uint32(1000) // Commands for modifying commitment transactions. CmdCommitSig = uint32(2000) @@ -107,14 +106,14 @@ func makeEmptyMessage(command uint32) (Message, error) { msg = &CloseRequest{} case CmdCloseComplete: msg = &CloseComplete{} - case CmdHTLCAddRequest: - msg = &HTLCAddRequest{} case CmdHTLCAddReject: msg = &HTLCAddReject{} case CmdHTLCSettleRequest: msg = &HTLCSettleRequest{} case CmdCancelHTLC: msg = &CancelHTLC{} + case CmdUpdateAddHTLC: + msg = &UpdateAddHTLC{} case CmdCommitSig: msg = &CommitSig{} case CmdRevokeAndAck: diff --git a/lnwire/update_add_htlc.go b/lnwire/update_add_htlc.go new file mode 100644 index 00000000..e7b191fb --- /dev/null +++ b/lnwire/update_add_htlc.go @@ -0,0 +1,157 @@ +package lnwire + +import ( + "fmt" + "io" + + "github.com/roasbeef/btcd/wire" + "github.com/roasbeef/btcutil" +) + +// OnionPacketSize is the size of the serialized Sphinx onion packet included +// in each UpdateAddHTLC message. +const OnionPacketSize = 1254 + +// UpdateAddHTLC 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, the ID, expiry, and the 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 +// CommitSig message will move the pending HTLC to the newly created commitment +// transaction, marking them as "staged". +type UpdateAddHTLC struct { + // ChannelPoint is the particular active channel that this + // UpdateAddHTLC is binded to. + ChannelPoint wire.OutPoint + + // ID is the identification server for this HTLC. This value is + // explicitly included as it allows nodes to survive single-sided + // restarts. The ID value for this sides starts at zero, and increases + // with each offered HTLC. + ID uint64 + + // 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 incoming HTLC. + Expiry uint32 + + // Amount is the amount of satoshis this HTLC is worth. + Amount btcutil.Amount + + // PaymentHash is the payment hash to be included in the HTLC this + // request creates. The pre-image to this HTLC must be revelaed by the + // upstream peer in order to fully settle the HTLC. + PaymentHash [32]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 strip off a layer of encryption, exposing the next hop to be + // used in the subsequent UpdateAddHTLC message. + OnionBlob [OnionPacketSize]byte +} + +// NewUpdateAddHTLC returns a new empty UpdateAddHTLC message. +func NewUpdateAddHTLC() *UpdateAddHTLC { + return &UpdateAddHTLC{} +} + +// A compile time check to ensure UpdateAddHTLC implements the lnwire.Message +// interface. +var _ Message = (*UpdateAddHTLC)(nil) + +// Decode deserializes a serialized UpdateAddHTLC message stored in the passed +// io.Reader observing the specified protocol version. +// +// This is part of the lnwire.Message interface. +func (c *UpdateAddHTLC) Decode(r io.Reader, pver uint32) error { + // ChannelPoint(8) + // ID(4) + // Expiry(4) + // Amount(8) + // PaymentHash(32) + // OnionBlob(1254) + err := readElements(r, + &c.ChannelPoint, + &c.ID, + &c.Expiry, + &c.Amount, + c.PaymentHash[:], + c.OnionBlob[:], + ) + if err != nil { + return err + } + + return nil +} + +// Encode serializes the target UpdateAddHTLC into the passed io.Writer observing +// the protocol version specified. +// +// This is part of the lnwire.Message interface. +func (c *UpdateAddHTLC) Encode(w io.Writer, pver uint32) error { + err := writeElements(w, + c.ChannelPoint, + c.ID, + c.Expiry, + c.Amount, + c.PaymentHash[:], + c.OnionBlob[:], + ) + if err != nil { + return err + } + + return nil +} + +// Command returns the integer uniquely identifying this message type on the +// wire. +// +// This is part of the lnwire.Message interface. +func (c *UpdateAddHTLC) Command() uint32 { + return CmdUpdateAddHTLC +} + +// MaxPayloadLength returns the maximum allowed payload size for a UpdateAddHTLC +// complete message observing the specified protocol version. +// +// This is part of the lnwire.Message interface. +func (c *UpdateAddHTLC) MaxPayloadLength(uint32) uint32 { + // 1342 + return 36 + 8 + 4 + 8 + 32 + 1254 +} + +// Validate performs any necessary sanity checks to ensure all fields present +// on the UpdateAddHTLC are valid. +// +// This is part of the lnwire.Message interface. +func (c *UpdateAddHTLC) Validate() error { + if c.Amount < 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 UpdateAddHTLC. +// +// This is part of the lnwire.Message interface. +func (c *UpdateAddHTLC) String() string { + return fmt.Sprintf("\n--- Begin UpdateAddHTLC ---\n") + + fmt.Sprintf("ChannelPoint:\t%v\n", c.ChannelPoint) + + fmt.Sprintf("ID:\t%v\n", c.ID) + + fmt.Sprintf("Expiry:\t\t%d\n", c.Expiry) + + fmt.Sprintf("Amount\t\t%d\n", c.Amount) + + fmt.Sprintf("PaymentHash:\t\t%x\n", c.PaymentHash) + + fmt.Sprintf("OnionBlob:\t\t\t\t%x\n", c.OnionBlob) + + fmt.Sprintf("--- End UpdateAddHTLC ---\n") +} diff --git a/lnwire/htlc_addrequest_test.go b/lnwire/update_add_htlc_test.go similarity index 51% rename from lnwire/htlc_addrequest_test.go rename to lnwire/update_add_htlc_test.go index 75efe631..3fa84abe 100644 --- a/lnwire/htlc_addrequest_test.go +++ b/lnwire/update_add_htlc_test.go @@ -4,22 +4,20 @@ import ( "bytes" "reflect" "testing" + "github.com/roasbeef/btcutil" ) -func TestHTLCAddRequestEncodeDecode(t *testing.T) { - redemptionHashes := make([][32]byte, 1) - redemptionHashes[0] = revHash - - // First create a new HTLCAR message. - addReq := &HTLCAddRequest{ - ChannelPoint: outpoint1, - Expiry: uint32(144), - Amount: btcutil.Amount(123456000), - ContractType: uint8(17), - RedemptionHashes: redemptionHashes, - OnionBlob: []byte{255, 0, 255, 0, 255, 0, 255, 0}, +func TestUpdateAddHTLCEncodeDecode(t *testing.T) { + // First create a new UPAH message. + addReq := &UpdateAddHTLC{ + ChannelPoint: *outpoint1, + ID: 99, + Expiry: uint32(144), + Amount: btcutil.Amount(123456000), + PaymentHash: revHash, } + copy(addReq.OnionBlob[:], bytes.Repeat([]byte{23}, OnionPacketSize)) // Next encode the HTLCAR message into an empty bytes buffer. var b bytes.Buffer @@ -27,8 +25,8 @@ func TestHTLCAddRequestEncodeDecode(t *testing.T) { t.Fatalf("unable to encode HTLCAddRequest: %v", err) } - // Deserialize the encoded HTLCAR message into a new empty struct. - addReq2 := &HTLCAddRequest{} + // Deserialize the encoded UPAH message into a new empty struct. + addReq2 := &UpdateAddHTLC{} if err := addReq2.Decode(&b, 0); err != nil { t.Fatalf("unable to decode HTLCAddRequest: %v", err) }