@@ -93,9 +93,12 @@ func deserializeOldResult(k, v []byte) (*paymentResultOld, error) {
9393
9494// convertPaymentResult converts a paymentResultOld to a paymentResultNew.
9595func convertPaymentResult (old * paymentResultOld ) * paymentResultNew {
96- var failure * paymentFailure
96+ var failure fn. Option [ paymentFailure ]
9797 if ! old .success {
98- failure = newPaymentFailure (old .failureSourceIdx , old .failure )
98+ failure = fn .Some (newPaymentFailure (
99+ old .failureSourceIdx ,
100+ old .failure ,
101+ ))
99102 }
100103
101104 return newPaymentResult (
@@ -106,7 +109,7 @@ func convertPaymentResult(old *paymentResultOld) *paymentResultNew {
106109
107110// newPaymentResult constructs a new paymentResult.
108111func newPaymentResult (id uint64 , rt * mcRoute , timeFwd , timeReply time.Time ,
109- failure * paymentFailure ) * paymentResultNew {
112+ failure fn. Option [ paymentFailure ] ) * paymentResultNew {
110113
111114 result := & paymentResultNew {
112115 id : id ,
@@ -119,11 +122,11 @@ func newPaymentResult(id uint64, rt *mcRoute, timeFwd, timeReply time.Time,
119122 route : tlv.NewRecordT [tlv.TlvType2 ](* rt ),
120123 }
121124
122- if failure != nil {
125+ failure . WhenSome ( func ( f paymentFailure ) {
123126 result .failure = tlv .SomeRecordT (
124- tlv.NewRecordT [tlv.TlvType3 ](* failure ),
127+ tlv.NewRecordT [tlv.TlvType3 ](f ),
125128 )
126- }
129+ })
127130
128131 return result
129132}
@@ -142,33 +145,49 @@ type paymentResultNew struct {
142145 failure tlv.OptionalRecordT [tlv.TlvType3 , paymentFailure ]
143146}
144147
145- // paymentFailure represents the presence of a payment failure. It may or may
146- // not include additional information about said failure.
147- type paymentFailure struct {
148- info tlv.OptionalRecordT [tlv.TlvType0 , paymentFailureInfo ]
149- }
150-
151148// newPaymentFailure constructs a new paymentFailure struct. If the source
152149// index is nil, then an empty paymentFailure is returned. This represents a
153150// failure with unknown details. Otherwise, the index and failure message are
154151// used to populate the info field of the paymentFailure.
155152func newPaymentFailure (sourceIdx * int ,
156- failureMsg lnwire.FailureMessage ) * paymentFailure {
153+ failureMsg lnwire.FailureMessage ) paymentFailure {
157154
155+ // If we can't identify a failure source, we also won't have a decrypted
156+ // failure message. In this case we return an empty payment failure.
158157 if sourceIdx == nil {
159- return & paymentFailure {}
158+ return paymentFailure {}
160159 }
161160
162- info := paymentFailureInfo {
163- sourceIdx : tlv.NewPrimitiveRecord [tlv.TlvType0 ](
164- uint8 (* sourceIdx ),
161+ info := paymentFailure {
162+ sourceIdx : tlv .SomeRecordT (
163+ tlv.NewPrimitiveRecord [tlv.TlvType0 ](
164+ uint8 (* sourceIdx ),
165+ ),
165166 ),
166- msg : tlv.NewRecordT [tlv.TlvType1 ](failureMessage {failureMsg }),
167167 }
168168
169- return & paymentFailure {
170- info : tlv .SomeRecordT (tlv.NewRecordT [tlv.TlvType0 ](info )),
169+ if failureMsg != nil {
170+ info .msg = tlv .SomeRecordT (
171+ tlv.NewRecordT [tlv.TlvType1 ](
172+ failureMessage {failureMsg },
173+ ),
174+ )
171175 }
176+
177+ return info
178+ }
179+
180+ // paymentFailure holds additional information about a payment failure.
181+ type paymentFailure struct {
182+ // sourceIdx is the hop the error was reported from. In order to be able
183+ // to decrypt the error message, we need to know the source, which is
184+ // why an error message can only be present if the source is known.
185+ sourceIdx tlv.OptionalRecordT [tlv.TlvType0 , uint8 ]
186+
187+ // msg is the error why a payment failed. If we identify the failure of
188+ // a certain hop at the above index, but aren't able to decode the
189+ // failure message we indicate this by not setting this field.
190+ msg tlv.OptionalRecordT [tlv.TlvType1 , failureMessage ]
172191}
173192
174193// Record returns a TLV record that can be used to encode/decode a
@@ -194,14 +213,27 @@ func (r *paymentFailure) Record() tlv.Record {
194213func encodePaymentFailure (w io.Writer , val interface {}, _ * [8 ]byte ) error {
195214 if v , ok := val .(* paymentFailure ); ok {
196215 var recordProducers []tlv.RecordProducer
197- v .info .WhenSome (
198- func (r tlv.RecordT [tlv.TlvType0 , paymentFailureInfo ]) {
199- recordProducers = append (recordProducers , & r )
216+
217+ v .sourceIdx .WhenSome (
218+ func (r tlv.RecordT [tlv.TlvType0 , uint8 ]) {
219+ recordProducers = append (
220+ recordProducers , & r ,
221+ )
222+ },
223+ )
224+
225+ v .msg .WhenSome (
226+ func (r tlv.RecordT [tlv.TlvType1 , failureMessage ]) {
227+ recordProducers = append (
228+ recordProducers , & r ,
229+ )
200230 },
201231 )
202232
203233 return lnwire .EncodeRecordsTo (
204- w , lnwire .ProduceRecordsSorted (recordProducers ... ),
234+ w , lnwire .ProduceRecordsSorted (
235+ recordProducers ... ,
236+ ),
205237 )
206238 }
207239
@@ -210,81 +242,27 @@ func encodePaymentFailure(w io.Writer, val interface{}, _ *[8]byte) error {
210242
211243func decodePaymentFailure (r io.Reader , val interface {}, _ * [8 ]byte ,
212244 l uint64 ) error {
213-
214245 if v , ok := val .(* paymentFailure ); ok {
215246 var h paymentFailure
216247
217- info := tlv .ZeroRecordT [tlv.TlvType0 , paymentFailureInfo ]()
248+ sourceIdx := tlv .ZeroRecordT [tlv.TlvType0 , uint8 ]()
249+ msg := tlv .ZeroRecordT [tlv.TlvType1 , failureMessage ]()
250+
218251 typeMap , err := lnwire .DecodeRecords (
219- r , lnwire .ProduceRecordsSorted (& info )... ,
252+ r ,
253+ lnwire .ProduceRecordsSorted (& sourceIdx , & msg )... ,
220254 )
255+
221256 if err != nil {
222257 return err
223258 }
224259
225- if _ , ok := typeMap [h .info .TlvType ()]; ok {
226- h .info = tlv .SomeRecordT (info )
260+ if _ , ok := typeMap [h .sourceIdx .TlvType ()]; ok {
261+ h .sourceIdx = tlv .SomeRecordT (sourceIdx )
227262 }
228263
229- * v = h
230-
231- return nil
232- }
233-
234- return tlv .NewTypeForDecodingErr (val , "routing.paymentFailure" , l , l )
235- }
236-
237- // paymentFailureInfo holds additional information about a payment failure.
238- type paymentFailureInfo struct {
239- sourceIdx tlv.RecordT [tlv.TlvType0 , uint8 ]
240- msg tlv.RecordT [tlv.TlvType1 , failureMessage ]
241- }
242-
243- // Record returns a TLV record that can be used to encode/decode a
244- // paymentFailureInfo to/from a TLV stream.
245- func (r * paymentFailureInfo ) Record () tlv.Record {
246- recordSize := func () uint64 {
247- var (
248- b bytes.Buffer
249- buf [8 ]byte
250- )
251- if err := encodePaymentFailureInfo (& b , r , & buf ); err != nil {
252- panic (err )
253- }
254-
255- return uint64 (len (b .Bytes ()))
256- }
257-
258- return tlv .MakeDynamicRecord (
259- 0 , r , recordSize , encodePaymentFailureInfo ,
260- decodePaymentFailureInfo ,
261- )
262- }
263-
264- func encodePaymentFailureInfo (w io.Writer , val interface {}, _ * [8 ]byte ) error {
265- if v , ok := val .(* paymentFailureInfo ); ok {
266- return lnwire .EncodeRecordsTo (
267- w , lnwire .ProduceRecordsSorted (
268- & v .sourceIdx , & v .msg ,
269- ),
270- )
271- }
272-
273- return tlv .NewTypeForEncodingErr (val , "routing.paymentFailureInfo" )
274- }
275-
276- func decodePaymentFailureInfo (r io.Reader , val interface {}, _ * [8 ]byte ,
277- l uint64 ) error {
278-
279- if v , ok := val .(* paymentFailureInfo ); ok {
280- var h paymentFailureInfo
281-
282- _ , err := lnwire .DecodeRecords (
283- r ,
284- lnwire .ProduceRecordsSorted (& h .sourceIdx , & h .msg )... ,
285- )
286- if err != nil {
287- return err
264+ if _ , ok := typeMap [h .msg .TlvType ()]; ok {
265+ h .msg = tlv .SomeRecordT (msg )
288266 }
289267
290268 * v = h
@@ -293,7 +271,7 @@ func decodePaymentFailureInfo(r io.Reader, val interface{}, _ *[8]byte,
293271 }
294272
295273 return tlv .NewTypeForDecodingErr (
296- val , "routing.paymentFailureInfo " , l , l ,
274+ val , "routing.paymentFailure " , l , l ,
297275 )
298276}
299277
0 commit comments