Skip to content

Commit 9f038c6

Browse files
committed
htlcswitch: introduce wrapper type error encrypter to identify blinded
Introduce two wrapper types for our existing SphinxErrorEncrypter that are used to represent error encrypters where we're a part of a blinded route. These encrypters are functionally the same as a sphinx encrypter, and are just used as "markers" so that we know that we need to handle our error differently due to our different role. We need to persist this information to account for restart cases where we've resovled the outgoing HTLC, then restart and need to handle the error for the incoming link. Specifically, this is relevant for: - On chain resolution messages received after restart - Forwarding packages that are re-forwarded after restart This is also generally helpful, because we can store this information in one place (the circuit) rather than trying to reconstruct it in various places when forwarding the failure back over the switch.
1 parent 776c889 commit 9f038c6

File tree

2 files changed

+82
-1
lines changed

2 files changed

+82
-1
lines changed

htlcswitch/circuit.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,12 @@ func (c *PaymentCircuit) Decode(r io.Reader) error {
205205
// Test encrypter.
206206
c.ErrorEncrypter = NewMockObfuscator()
207207

208+
case hop.EncrypterTypeIntroduction:
209+
c.ErrorEncrypter = hop.NewIntroductionErrorEncrypter()
210+
211+
case hop.EncrypterTypeRelaying:
212+
c.ErrorEncrypter = hop.NewRelayingErrorEncrypter()
213+
208214
default:
209215
return UnknownEncrypterType(encrypterType)
210216
}

htlcswitch/hop/error_encryptor.go

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,18 @@ const (
2525

2626
// EncrypterTypeMock is used to identify a mock obfuscator instance.
2727
EncrypterTypeMock = 2
28+
29+
// EncrypterTypeIntroduction is used to identify a sphinx onion error
30+
// encrypter where we are the introduction node in a blinded route. It
31+
// has the same functionality as EncrypterTypeSphinx, but is used to
32+
// mark our special-case error handling.
33+
EncrypterTypeIntroduction = 3
34+
35+
// EncrypterTypeRelaying is used to identify a sphinx onion error
36+
// encryper where we are a relaying node in a blinded route. It has
37+
// the same functionality as a EncrypterTypeSphinx, but is used to mark
38+
// our special-case error handling.
39+
EncrypterTypeRelaying = 4
2840
)
2941

3042
// ErrorEncrypterExtracter defines a function signature that extracts an
@@ -197,9 +209,72 @@ func (s *SphinxErrorEncrypter) Reextract(
197209
s.OnionErrorEncrypter = sphinxEncrypter.OnionErrorEncrypter
198210

199211
return nil
200-
201212
}
202213

203214
// A compile time check to ensure SphinxErrorEncrypter implements the
204215
// ErrorEncrypter interface.
205216
var _ ErrorEncrypter = (*SphinxErrorEncrypter)(nil)
217+
218+
// A compile time check to ensure that IntroductionErrorEncrypter implements
219+
// the ErrorEncrypter interface.
220+
var _ ErrorEncrypter = (*IntroductionErrorEncrypter)(nil)
221+
222+
// IntroductionErrorEncrypter is a wrapper type on SphinxErrorEncrypter which
223+
// is used to signal that we have special HTLC error handling for this hop.
224+
type IntroductionErrorEncrypter struct {
225+
// ErrorEncrypter is the underlying error encrypter, embedded
226+
// directly in the struct so that we don't have to re-implement the
227+
// ErrorEncrypter interface.
228+
ErrorEncrypter
229+
}
230+
231+
// NewIntroductionErrorEncrypter returns a blank IntroductionErrorEncrypter.
232+
func NewIntroductionErrorEncrypter() *IntroductionErrorEncrypter {
233+
return &IntroductionErrorEncrypter{
234+
ErrorEncrypter: NewSphinxErrorEncrypter(),
235+
}
236+
}
237+
238+
// Type returns the identifier for an introduction error encrypter.
239+
func (i *IntroductionErrorEncrypter) Type() EncrypterType {
240+
return EncrypterTypeIntroduction
241+
}
242+
243+
// Reextract rederives the error encrypter from the currently held EphemeralKey,
244+
// relying on the logic in the underlying SphinxErrorEncrypter.
245+
func (i *IntroductionErrorEncrypter) Reextract(
246+
extract ErrorEncrypterExtracter) error {
247+
248+
return i.ErrorEncrypter.Reextract(extract)
249+
}
250+
251+
// A compile time check to ensure that RelayingErrorEncrypte implements
252+
// the ErrorEncrypter interface.
253+
var _ ErrorEncrypter = (*RelayingErrorEncrypter)(nil)
254+
255+
// RelayingErrorEncrypter is a wrapper type on SphinxErrorEncrypter which
256+
// is used to signal that we have special HTLC error handling for this hop.
257+
type RelayingErrorEncrypter struct {
258+
ErrorEncrypter
259+
}
260+
261+
// NewRelayingErrorEncrypter returns a blank RelayingErrorEncrypter with
262+
// an underlying SphinxErrorEncrypter.
263+
func NewRelayingErrorEncrypter() *RelayingErrorEncrypter {
264+
return &RelayingErrorEncrypter{
265+
ErrorEncrypter: NewSphinxErrorEncrypter(),
266+
}
267+
}
268+
269+
// Type returns the identifier for a relaying error encrypter.
270+
func (r *RelayingErrorEncrypter) Type() EncrypterType {
271+
return EncrypterTypeRelaying
272+
}
273+
274+
// Reextract rederives the error encrypter from the currently held EphemeralKey,
275+
// relying on the logic in the underlying SphinxErrorEncrypter.
276+
func (r *RelayingErrorEncrypter) Reextract(
277+
extract ErrorEncrypterExtracter) error {
278+
279+
return r.ErrorEncrypter.Reextract(extract)
280+
}

0 commit comments

Comments
 (0)