lnwire: create distinct type for UpdateFailHTLC failure reason

This commit creates a distint type for the opaque failure reason within
the UpdateFailHTLC message. This new type is needed as this is the only
variable length byte slice within the protocol and therefore requires a
length prefix in order to serialize/deserialize properly.
This commit is contained in:
Olaoluwa Osuntokun 2017-02-20 22:02:42 -08:00
parent 4aa7de7f58
commit 8024fd72f8
No known key found for this signature in database
GPG Key ID: 9CC5B105D03521A2
3 changed files with 32 additions and 18 deletions

@ -72,12 +72,6 @@ func writeElement(w io.Writer, element interface{}) error {
if _, err := w.Write(b[:]); err != nil { if _, err := w.Write(b[:]); err != nil {
return err return err
} }
case FailCode:
var b [2]byte
binary.BigEndian.PutUint16(b[:], uint16(e))
if _, err := w.Write(b[:]); err != nil {
return err
}
case ErrorCode: case ErrorCode:
var b [2]byte var b [2]byte
binary.BigEndian.PutUint16(b[:], uint16(e)) binary.BigEndian.PutUint16(b[:], uint16(e))
@ -170,6 +164,16 @@ func writeElement(w io.Writer, element interface{}) error {
if _, err := w.Write(b[:]); err != nil { if _, err := w.Write(b[:]); err != nil {
return err return err
} }
case OpaqueReason:
var l [2]byte
binary.BigEndian.PutUint16(l[:], uint16(len(e)))
if _, err := w.Write(l[:]); err != nil {
return err
}
if _, err := w.Write(e[:]); err != nil {
return err
}
case []byte: case []byte:
if _, err := w.Write(e[:]); err != nil { if _, err := w.Write(e[:]); err != nil {
return err return err
@ -339,12 +343,6 @@ func readElement(r io.Reader, element interface{}) error {
return err return err
} }
*e = b[0] *e = b[0]
case *FailCode:
var b [2]byte
if _, err := io.ReadFull(r, b[:]); err != nil {
return err
}
*e = FailCode(binary.BigEndian.Uint16(b[:]))
case *uint16: case *uint16:
var b [2]byte var b [2]byte
if _, err := io.ReadFull(r, b[:]); err != nil { if _, err := io.ReadFull(r, b[:]); err != nil {
@ -458,6 +456,17 @@ func readElement(r io.Reader, element interface{}) error {
} }
*e = wire.BitcoinNet(binary.BigEndian.Uint32(b[:])) *e = wire.BitcoinNet(binary.BigEndian.Uint32(b[:]))
return nil return nil
case *OpaqueReason:
var l [2]byte
if _, err := io.ReadFull(r, l[:]); err != nil {
return err
}
reasonLen := binary.BigEndian.Uint16(l[:])
*e = OpaqueReason(make([]byte, reasonLen))
if _, err := io.ReadFull(r, *e); err != nil {
return err
}
case []byte: case []byte:
if _, err := io.ReadFull(r, e); err != nil { if _, err := io.ReadFull(r, e); err != nil {
return err return err

@ -71,13 +71,18 @@ func (c FailCode) String() string {
} }
} }
// OpaqueReason is an opaque encrypted byte slice that encodes the exact
// failure reason and additional some supplemental data. The contents of this
// slice can only be decrypted by the sender of the original HTLC.
type OpaqueReason []byte
// UpdateFailHTLC is sent by Alice to Bob in order to remove a previously added // UpdateFailHTLC is sent by Alice to Bob in order to remove a previously added
// HTLC. Upon receipt of an UpdateFailHTLC the HTLC should be removed from the // HTLC. Upon receipt of an UpdateFailHTLC the HTLC should be removed from the
// next commitment transaction, with the UpdateFailHTLC propagated backwards in // next commitment transaction, with the UpdateFailHTLC propagated backwards in
// the route to fully undo the HTLC. // the route to fully undo the HTLC.
type UpdateFailHTLC struct { type UpdateFailHTLC struct {
// ChannelPoint is the particular active channel that this UpdateFailHTLC // ChannelPoint is the particular active channel that this
// is binded to. // UpdateFailHTLC is binded to.
ChannelPoint wire.OutPoint ChannelPoint wire.OutPoint
// ID references which HTLC on the remote node's commitment transaction // ID references which HTLC on the remote node's commitment transaction
@ -88,7 +93,7 @@ type UpdateFailHTLC struct {
// failed. This blob is only fully decryptable by the initiator of the // failed. This blob is only fully decryptable by the initiator of the
// HTLC message. // HTLC message.
// TODO(roasbeef): properly format the encrypted failure reason // TODO(roasbeef): properly format the encrypted failure reason
Reason []byte Reason OpaqueReason
} }
// A compile time check to ensure UpdateFailHTLC implements the lnwire.Message // A compile time check to ensure UpdateFailHTLC implements the lnwire.Message
@ -106,7 +111,7 @@ func (c *UpdateFailHTLC) Decode(r io.Reader, pver uint32) error {
err := readElements(r, err := readElements(r,
&c.ChannelPoint, &c.ChannelPoint,
&c.ID, &c.ID,
c.Reason[:], &c.Reason,
) )
if err != nil { if err != nil {
return err return err
@ -123,7 +128,7 @@ func (c *UpdateFailHTLC) Encode(w io.Writer, pver uint32) error {
err := writeElements(w, err := writeElements(w,
c.ChannelPoint, c.ChannelPoint,
c.ID, c.ID,
c.Reason[:], c.Reason,
) )
if err != nil { if err != nil {
return err return err

@ -12,7 +12,7 @@ func TestUpdateFailHTLC(t *testing.T) {
ChannelPoint: *outpoint1, ChannelPoint: *outpoint1,
ID: 22, ID: 22,
} }
copy(cancelMsg.Reason[:], bytes.Repeat([]byte{21}, 20)) cancelMsg.Reason = []byte{byte(UnknownDestination)}
// Next encode the UFH message into an empty bytes buffer. // Next encode the UFH message into an empty bytes buffer.
var b bytes.Buffer var b bytes.Buffer