2017-05-01 18:58:08 +02:00
|
|
|
package htlcswitch
|
|
|
|
|
|
|
|
import (
|
2018-06-01 05:31:40 +02:00
|
|
|
"bytes"
|
2023-10-11 13:42:59 +02:00
|
|
|
"context"
|
2017-05-01 18:58:08 +02:00
|
|
|
"crypto/sha256"
|
2017-05-02 01:29:30 +02:00
|
|
|
"encoding/binary"
|
2017-07-30 23:09:10 +02:00
|
|
|
"fmt"
|
2018-06-01 05:31:40 +02:00
|
|
|
"io"
|
2018-07-05 22:27:35 +02:00
|
|
|
"net"
|
2019-02-21 14:52:13 +01:00
|
|
|
"os"
|
2022-08-16 05:20:47 +02:00
|
|
|
"path/filepath"
|
2017-05-01 18:58:08 +02:00
|
|
|
"sync"
|
2018-06-01 05:31:40 +02:00
|
|
|
"sync/atomic"
|
2017-11-11 00:09:19 +01:00
|
|
|
"testing"
|
2018-01-31 00:53:39 +01:00
|
|
|
"time"
|
2017-05-01 18:58:08 +02:00
|
|
|
|
2022-02-23 14:48:00 +01:00
|
|
|
"github.com/btcsuite/btcd/btcec/v2"
|
server+htlcswitch: prevent privacy leaks, allow alias routing
This intent of this change is to prevent privacy leaks when routing
with aliases and also to allow routing when using an alias. The
aliases are our aliases.
Introduces are two maps:
* aliasToReal:
This is an N->1 mapping for a channel. The keys are the set of
aliases and the value is the confirmed, on-chain SCID.
* baseIndex:
This is also an N->1 mapping for a channel. The keys are the set
of aliases and the value is the "base" SCID (whatever is in the
OpenChannel.ShortChannelID field). There is also a base->base
mapping, so not all keys are aliases.
The above maps are populated when a link is added to the switch and
when the channel has confirmed on-chain. The maps are not removed
from if the link is removed, but this is fine since forwarding won't
occur.
* getLinkByMapping
This function is introduced to adhere to the spec requirements that
using the confirmed SCID of a private, scid-alias-feature-bit
channel does not work. Lnd implements a stricter version of the spec
and disallows this behavior if the feature-bit was negotiated, rather
than just the channel type. The old, privacy-leak behavior is
preserved.
The spec also requires that if we must fail back an HTLC, the
ChannelUpdate must use the SCID of whatever was in the onion, to avoid
a privacy leak. This is also done by passing in the relevant SCID to
the mailbox and link. Lnd will also cancel back on the "incoming" side
if the InterceptableSwitch was used or if the link failed to decrypt
the onion. In this case, we are cautious and replace the SCID if an
alias exists.
2022-04-04 22:44:51 +02:00
|
|
|
"github.com/btcsuite/btcd/btcec/v2/ecdsa"
|
2022-02-23 14:48:00 +01:00
|
|
|
"github.com/btcsuite/btcd/btcutil"
|
2018-07-18 04:24:04 +02:00
|
|
|
"github.com/btcsuite/btcd/wire"
|
2017-05-01 18:58:08 +02:00
|
|
|
"github.com/go-errors/errors"
|
2019-01-11 11:19:16 +01:00
|
|
|
sphinx "github.com/lightningnetwork/lightning-onion"
|
2017-05-02 01:29:30 +02:00
|
|
|
"github.com/lightningnetwork/lnd/chainntnfs"
|
|
|
|
"github.com/lightningnetwork/lnd/channeldb"
|
2022-11-18 12:15:22 +01:00
|
|
|
"github.com/lightningnetwork/lnd/channeldb/models"
|
2019-12-09 17:50:11 +01:00
|
|
|
"github.com/lightningnetwork/lnd/clock"
|
2018-01-17 05:18:53 +01:00
|
|
|
"github.com/lightningnetwork/lnd/contractcourt"
|
2024-06-03 18:43:33 +02:00
|
|
|
"github.com/lightningnetwork/lnd/fn"
|
2019-08-30 23:05:53 +02:00
|
|
|
"github.com/lightningnetwork/lnd/htlcswitch/hop"
|
2019-02-21 14:52:13 +01:00
|
|
|
"github.com/lightningnetwork/lnd/invoices"
|
2018-06-08 05:18:10 +02:00
|
|
|
"github.com/lightningnetwork/lnd/lnpeer"
|
2020-08-27 21:34:55 +02:00
|
|
|
"github.com/lightningnetwork/lnd/lntest/mock"
|
2019-01-15 11:31:22 +01:00
|
|
|
"github.com/lightningnetwork/lnd/lntypes"
|
2019-10-31 03:43:05 +01:00
|
|
|
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
2017-05-01 18:58:08 +02:00
|
|
|
"github.com/lightningnetwork/lnd/lnwire"
|
2018-08-02 11:14:55 +02:00
|
|
|
"github.com/lightningnetwork/lnd/ticker"
|
2024-05-02 16:52:47 +02:00
|
|
|
"github.com/lightningnetwork/lnd/tlv"
|
2017-05-01 18:58:08 +02:00
|
|
|
)
|
|
|
|
|
server+htlcswitch: prevent privacy leaks, allow alias routing
This intent of this change is to prevent privacy leaks when routing
with aliases and also to allow routing when using an alias. The
aliases are our aliases.
Introduces are two maps:
* aliasToReal:
This is an N->1 mapping for a channel. The keys are the set of
aliases and the value is the confirmed, on-chain SCID.
* baseIndex:
This is also an N->1 mapping for a channel. The keys are the set
of aliases and the value is the "base" SCID (whatever is in the
OpenChannel.ShortChannelID field). There is also a base->base
mapping, so not all keys are aliases.
The above maps are populated when a link is added to the switch and
when the channel has confirmed on-chain. The maps are not removed
from if the link is removed, but this is fine since forwarding won't
occur.
* getLinkByMapping
This function is introduced to adhere to the spec requirements that
using the confirmed SCID of a private, scid-alias-feature-bit
channel does not work. Lnd implements a stricter version of the spec
and disallows this behavior if the feature-bit was negotiated, rather
than just the channel type. The old, privacy-leak behavior is
preserved.
The spec also requires that if we must fail back an HTLC, the
ChannelUpdate must use the SCID of whatever was in the onion, to avoid
a privacy leak. This is also done by passing in the relevant SCID to
the mailbox and link. Lnd will also cancel back on the "incoming" side
if the InterceptableSwitch was used or if the link failed to decrypt
the onion. In this case, we are cautious and replace the SCID if an
alias exists.
2022-04-04 22:44:51 +02:00
|
|
|
func isAlias(scid lnwire.ShortChannelID) bool {
|
|
|
|
return scid.BlockHeight >= 16_000_000 && scid.BlockHeight < 16_250_000
|
|
|
|
}
|
|
|
|
|
2018-01-17 05:18:53 +01:00
|
|
|
type mockPreimageCache struct {
|
|
|
|
sync.Mutex
|
2019-02-20 02:06:00 +01:00
|
|
|
preimageMap map[lntypes.Hash]lntypes.Preimage
|
2018-01-17 05:18:53 +01:00
|
|
|
}
|
|
|
|
|
2019-02-20 02:06:00 +01:00
|
|
|
func newMockPreimageCache() *mockPreimageCache {
|
|
|
|
return &mockPreimageCache{
|
|
|
|
preimageMap: make(map[lntypes.Hash]lntypes.Preimage),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *mockPreimageCache) LookupPreimage(
|
|
|
|
hash lntypes.Hash) (lntypes.Preimage, bool) {
|
|
|
|
|
2018-01-17 05:18:53 +01:00
|
|
|
m.Lock()
|
|
|
|
defer m.Unlock()
|
|
|
|
|
2019-02-20 02:06:00 +01:00
|
|
|
p, ok := m.preimageMap[hash]
|
2018-01-17 05:18:53 +01:00
|
|
|
return p, ok
|
|
|
|
}
|
|
|
|
|
2019-02-20 02:06:00 +01:00
|
|
|
func (m *mockPreimageCache) AddPreimages(preimages ...lntypes.Preimage) error {
|
2018-01-17 05:18:53 +01:00
|
|
|
m.Lock()
|
|
|
|
defer m.Unlock()
|
|
|
|
|
2019-02-20 02:05:04 +01:00
|
|
|
for _, preimage := range preimages {
|
2019-02-20 02:06:00 +01:00
|
|
|
m.preimageMap[preimage.Hash()] = preimage
|
2019-02-20 02:05:04 +01:00
|
|
|
}
|
2018-01-17 05:18:53 +01:00
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2022-02-04 14:32:15 +01:00
|
|
|
func (m *mockPreimageCache) SubscribeUpdates(
|
|
|
|
chanID lnwire.ShortChannelID, htlc *channeldb.HTLC,
|
|
|
|
payload *hop.Payload,
|
|
|
|
nextHopOnionBlob []byte) (*contractcourt.WitnessSubscription, error) {
|
|
|
|
|
|
|
|
return nil, nil
|
2018-01-17 05:18:53 +01:00
|
|
|
}
|
|
|
|
|
2023-11-03 11:48:09 +01:00
|
|
|
// TODO(yy): replace it with chainfee.MockEstimator.
|
2017-11-24 05:31:45 +01:00
|
|
|
type mockFeeEstimator struct {
|
2019-10-31 03:43:05 +01:00
|
|
|
byteFeeIn chan chainfee.SatPerKWeight
|
2021-06-23 14:28:25 +02:00
|
|
|
relayFee chan chainfee.SatPerKWeight
|
2017-11-24 05:31:45 +01:00
|
|
|
|
|
|
|
quit chan struct{}
|
|
|
|
}
|
|
|
|
|
2021-02-15 20:07:10 +01:00
|
|
|
func newMockFeeEstimator() *mockFeeEstimator {
|
|
|
|
return &mockFeeEstimator{
|
|
|
|
byteFeeIn: make(chan chainfee.SatPerKWeight),
|
2021-06-23 14:28:25 +02:00
|
|
|
relayFee: make(chan chainfee.SatPerKWeight),
|
2021-02-15 20:07:10 +01:00
|
|
|
quit: make(chan struct{}),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-28 03:20:58 +02:00
|
|
|
func (m *mockFeeEstimator) EstimateFeePerKW(
|
2019-10-31 03:43:05 +01:00
|
|
|
numBlocks uint32) (chainfee.SatPerKWeight, error) {
|
2018-07-28 03:20:58 +02:00
|
|
|
|
2017-11-24 05:31:45 +01:00
|
|
|
select {
|
|
|
|
case feeRate := <-m.byteFeeIn:
|
|
|
|
return feeRate, nil
|
|
|
|
case <-m.quit:
|
|
|
|
return 0, fmt.Errorf("exiting")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-31 03:43:05 +01:00
|
|
|
func (m *mockFeeEstimator) RelayFeePerKW() chainfee.SatPerKWeight {
|
2021-06-23 14:28:25 +02:00
|
|
|
select {
|
|
|
|
case feeRate := <-m.relayFee:
|
|
|
|
return feeRate
|
|
|
|
case <-m.quit:
|
|
|
|
return 0
|
|
|
|
}
|
2018-10-29 09:31:44 +01:00
|
|
|
}
|
|
|
|
|
2017-11-24 05:31:45 +01:00
|
|
|
func (m *mockFeeEstimator) Start() error {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
func (m *mockFeeEstimator) Stop() error {
|
|
|
|
close(m.quit)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2019-10-31 03:43:05 +01:00
|
|
|
var _ chainfee.Estimator = (*mockFeeEstimator)(nil)
|
2017-11-24 05:31:45 +01:00
|
|
|
|
2018-02-28 07:18:52 +01:00
|
|
|
type mockForwardingLog struct {
|
|
|
|
sync.Mutex
|
2018-02-28 07:19:21 +01:00
|
|
|
|
2018-02-28 07:18:52 +01:00
|
|
|
events map[time.Time]channeldb.ForwardingEvent
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *mockForwardingLog) AddForwardingEvents(events []channeldb.ForwardingEvent) error {
|
|
|
|
m.Lock()
|
|
|
|
defer m.Unlock()
|
|
|
|
|
|
|
|
for _, event := range events {
|
|
|
|
m.events[event.Timestamp] = event
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2017-05-01 18:58:08 +02:00
|
|
|
type mockServer struct {
|
2018-06-01 00:41:41 +02:00
|
|
|
started int32 // To be used atomically.
|
|
|
|
shutdown int32 // To be used atomically.
|
2017-05-01 18:58:08 +02:00
|
|
|
wg sync.WaitGroup
|
2017-07-09 00:52:51 +02:00
|
|
|
quit chan struct{}
|
2017-05-01 18:58:08 +02:00
|
|
|
|
2017-11-12 00:05:09 +01:00
|
|
|
t testing.TB
|
2017-11-11 00:09:19 +01:00
|
|
|
|
2017-05-01 18:58:08 +02:00
|
|
|
name string
|
|
|
|
messages chan lnwire.Message
|
|
|
|
|
2017-06-17 00:08:19 +02:00
|
|
|
id [33]byte
|
2017-05-01 18:58:08 +02:00
|
|
|
htlcSwitch *Switch
|
|
|
|
|
2017-07-09 00:46:27 +02:00
|
|
|
registry *mockInvoiceRegistry
|
2019-02-09 17:22:32 +01:00
|
|
|
pCache *mockPreimageCache
|
2017-07-09 00:46:27 +02:00
|
|
|
interceptorFuncs []messageInterceptor
|
2017-05-01 18:58:08 +02:00
|
|
|
}
|
|
|
|
|
2018-06-08 05:18:10 +02:00
|
|
|
var _ lnpeer.Peer = (*mockServer)(nil)
|
2017-05-01 18:58:08 +02:00
|
|
|
|
2018-06-01 05:31:40 +02:00
|
|
|
func initSwitchWithDB(startingHeight uint32, db *channeldb.DB) (*Switch, error) {
|
2024-08-21 08:39:37 +02:00
|
|
|
signAliasUpdate := func(u *lnwire.ChannelUpdate1) (*ecdsa.Signature,
|
server+htlcswitch: prevent privacy leaks, allow alias routing
This intent of this change is to prevent privacy leaks when routing
with aliases and also to allow routing when using an alias. The
aliases are our aliases.
Introduces are two maps:
* aliasToReal:
This is an N->1 mapping for a channel. The keys are the set of
aliases and the value is the confirmed, on-chain SCID.
* baseIndex:
This is also an N->1 mapping for a channel. The keys are the set
of aliases and the value is the "base" SCID (whatever is in the
OpenChannel.ShortChannelID field). There is also a base->base
mapping, so not all keys are aliases.
The above maps are populated when a link is added to the switch and
when the channel has confirmed on-chain. The maps are not removed
from if the link is removed, but this is fine since forwarding won't
occur.
* getLinkByMapping
This function is introduced to adhere to the spec requirements that
using the confirmed SCID of a private, scid-alias-feature-bit
channel does not work. Lnd implements a stricter version of the spec
and disallows this behavior if the feature-bit was negotiated, rather
than just the channel type. The old, privacy-leak behavior is
preserved.
The spec also requires that if we must fail back an HTLC, the
ChannelUpdate must use the SCID of whatever was in the onion, to avoid
a privacy leak. This is also done by passing in the relevant SCID to
the mailbox and link. Lnd will also cancel back on the "incoming" side
if the InterceptableSwitch was used or if the link failed to decrypt
the onion. In this case, we are cautious and replace the SCID if an
alias exists.
2022-04-04 22:44:51 +02:00
|
|
|
error) {
|
|
|
|
|
|
|
|
return testSig, nil
|
|
|
|
}
|
|
|
|
|
2018-06-01 05:31:40 +02:00
|
|
|
cfg := Config{
|
2021-09-21 19:18:17 +02:00
|
|
|
DB: db,
|
|
|
|
FetchAllOpenChannels: db.ChannelStateDB().FetchAllOpenChannels,
|
2022-08-02 18:54:47 +02:00
|
|
|
FetchAllChannels: db.ChannelStateDB().FetchAllChannels,
|
2021-09-21 19:18:17 +02:00
|
|
|
FetchClosedChannels: db.ChannelStateDB().FetchClosedChannels,
|
|
|
|
SwitchPackager: channeldb.NewSwitchPackager(),
|
2018-03-06 21:31:05 +01:00
|
|
|
FwdingLog: &mockForwardingLog{
|
|
|
|
events: make(map[time.Time]channeldb.ForwardingEvent),
|
|
|
|
},
|
server+htlcswitch: prevent privacy leaks, allow alias routing
This intent of this change is to prevent privacy leaks when routing
with aliases and also to allow routing when using an alias. The
aliases are our aliases.
Introduces are two maps:
* aliasToReal:
This is an N->1 mapping for a channel. The keys are the set of
aliases and the value is the confirmed, on-chain SCID.
* baseIndex:
This is also an N->1 mapping for a channel. The keys are the set
of aliases and the value is the "base" SCID (whatever is in the
OpenChannel.ShortChannelID field). There is also a base->base
mapping, so not all keys are aliases.
The above maps are populated when a link is added to the switch and
when the channel has confirmed on-chain. The maps are not removed
from if the link is removed, but this is fine since forwarding won't
occur.
* getLinkByMapping
This function is introduced to adhere to the spec requirements that
using the confirmed SCID of a private, scid-alias-feature-bit
channel does not work. Lnd implements a stricter version of the spec
and disallows this behavior if the feature-bit was negotiated, rather
than just the channel type. The old, privacy-leak behavior is
preserved.
The spec also requires that if we must fail back an HTLC, the
ChannelUpdate must use the SCID of whatever was in the onion, to avoid
a privacy leak. This is also done by passing in the relevant SCID to
the mailbox and link. Lnd will also cancel back on the "incoming" side
if the InterceptableSwitch was used or if the link failed to decrypt
the onion. In this case, we are cautious and replace the SCID if an
alias exists.
2022-04-04 22:44:51 +02:00
|
|
|
FetchLastChannelUpdate: func(scid lnwire.ShortChannelID) (
|
2024-08-21 08:39:37 +02:00
|
|
|
*lnwire.ChannelUpdate1, error) {
|
server+htlcswitch: prevent privacy leaks, allow alias routing
This intent of this change is to prevent privacy leaks when routing
with aliases and also to allow routing when using an alias. The
aliases are our aliases.
Introduces are two maps:
* aliasToReal:
This is an N->1 mapping for a channel. The keys are the set of
aliases and the value is the confirmed, on-chain SCID.
* baseIndex:
This is also an N->1 mapping for a channel. The keys are the set
of aliases and the value is the "base" SCID (whatever is in the
OpenChannel.ShortChannelID field). There is also a base->base
mapping, so not all keys are aliases.
The above maps are populated when a link is added to the switch and
when the channel has confirmed on-chain. The maps are not removed
from if the link is removed, but this is fine since forwarding won't
occur.
* getLinkByMapping
This function is introduced to adhere to the spec requirements that
using the confirmed SCID of a private, scid-alias-feature-bit
channel does not work. Lnd implements a stricter version of the spec
and disallows this behavior if the feature-bit was negotiated, rather
than just the channel type. The old, privacy-leak behavior is
preserved.
The spec also requires that if we must fail back an HTLC, the
ChannelUpdate must use the SCID of whatever was in the onion, to avoid
a privacy leak. This is also done by passing in the relevant SCID to
the mailbox and link. Lnd will also cancel back on the "incoming" side
if the InterceptableSwitch was used or if the link failed to decrypt
the onion. In this case, we are cautious and replace the SCID if an
alias exists.
2022-04-04 22:44:51 +02:00
|
|
|
|
2024-08-21 08:39:37 +02:00
|
|
|
return &lnwire.ChannelUpdate1{
|
server+htlcswitch: prevent privacy leaks, allow alias routing
This intent of this change is to prevent privacy leaks when routing
with aliases and also to allow routing when using an alias. The
aliases are our aliases.
Introduces are two maps:
* aliasToReal:
This is an N->1 mapping for a channel. The keys are the set of
aliases and the value is the confirmed, on-chain SCID.
* baseIndex:
This is also an N->1 mapping for a channel. The keys are the set
of aliases and the value is the "base" SCID (whatever is in the
OpenChannel.ShortChannelID field). There is also a base->base
mapping, so not all keys are aliases.
The above maps are populated when a link is added to the switch and
when the channel has confirmed on-chain. The maps are not removed
from if the link is removed, but this is fine since forwarding won't
occur.
* getLinkByMapping
This function is introduced to adhere to the spec requirements that
using the confirmed SCID of a private, scid-alias-feature-bit
channel does not work. Lnd implements a stricter version of the spec
and disallows this behavior if the feature-bit was negotiated, rather
than just the channel type. The old, privacy-leak behavior is
preserved.
The spec also requires that if we must fail back an HTLC, the
ChannelUpdate must use the SCID of whatever was in the onion, to avoid
a privacy leak. This is also done by passing in the relevant SCID to
the mailbox and link. Lnd will also cancel back on the "incoming" side
if the InterceptableSwitch was used or if the link failed to decrypt
the onion. In this case, we are cautious and replace the SCID if an
alias exists.
2022-04-04 22:44:51 +02:00
|
|
|
ShortChannelID: scid,
|
|
|
|
}, nil
|
2018-05-08 05:00:32 +02:00
|
|
|
},
|
2020-08-27 21:34:55 +02:00
|
|
|
Notifier: &mock.ChainNotifier{
|
|
|
|
SpendChan: make(chan *chainntnfs.SpendDetail),
|
|
|
|
EpochChan: make(chan *chainntnfs.BlockEpoch),
|
|
|
|
ConfChan: make(chan *chainntnfs.TxConfirmation),
|
|
|
|
},
|
2022-10-20 13:15:02 +02:00
|
|
|
FwdEventTicker: ticker.NewForce(
|
|
|
|
DefaultFwdEventInterval,
|
|
|
|
),
|
|
|
|
LogEventTicker: ticker.NewForce(DefaultLogInterval),
|
|
|
|
AckEventTicker: ticker.NewForce(DefaultAckInterval),
|
|
|
|
HtlcNotifier: &mockHTLCNotifier{},
|
|
|
|
Clock: clock.NewDefaultClock(),
|
|
|
|
MailboxDeliveryTimeout: time.Hour,
|
2024-06-03 18:43:33 +02:00
|
|
|
MaxFeeExposure: DefaultMaxFeeExposure,
|
2022-10-20 13:15:02 +02:00
|
|
|
SignAliasUpdate: signAliasUpdate,
|
|
|
|
IsAlias: isAlias,
|
2018-06-01 05:31:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return New(cfg, startingHeight)
|
2017-12-11 00:38:17 +01:00
|
|
|
}
|
|
|
|
|
2022-08-16 05:20:47 +02:00
|
|
|
func initSwitchWithTempDB(t testing.TB, startingHeight uint32) (*Switch,
|
|
|
|
error) {
|
|
|
|
|
|
|
|
tempPath := filepath.Join(t.TempDir(), "switchdb")
|
|
|
|
db, err := channeldb.Open(tempPath)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
t.Cleanup(func() { db.Close() })
|
|
|
|
|
|
|
|
s, err := initSwitchWithDB(startingHeight, db)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return s, nil
|
|
|
|
}
|
|
|
|
|
2018-06-01 05:31:40 +02:00
|
|
|
func newMockServer(t testing.TB, name string, startingHeight uint32,
|
2018-06-30 01:02:59 +02:00
|
|
|
db *channeldb.DB, defaultDelta uint32) (*mockServer, error) {
|
2018-06-01 05:31:40 +02:00
|
|
|
|
2017-06-17 00:08:19 +02:00
|
|
|
var id [33]byte
|
|
|
|
h := sha256.Sum256([]byte(name))
|
|
|
|
copy(id[:], h[:])
|
|
|
|
|
2019-02-09 17:22:32 +01:00
|
|
|
pCache := newMockPreimageCache()
|
|
|
|
|
2022-08-16 05:20:47 +02:00
|
|
|
var (
|
|
|
|
htlcSwitch *Switch
|
|
|
|
err error
|
|
|
|
)
|
|
|
|
if db == nil {
|
|
|
|
htlcSwitch, err = initSwitchWithTempDB(t, startingHeight)
|
|
|
|
} else {
|
|
|
|
htlcSwitch, err = initSwitchWithDB(startingHeight, db)
|
|
|
|
}
|
2017-12-11 00:38:17 +01:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2022-08-16 05:20:47 +02:00
|
|
|
t.Cleanup(func() { _ = htlcSwitch.Stop() })
|
|
|
|
|
2019-02-09 17:22:32 +01:00
|
|
|
registry := newMockRegistry(defaultDelta)
|
|
|
|
|
2022-08-16 05:20:47 +02:00
|
|
|
t.Cleanup(func() { registry.cleanup() })
|
|
|
|
|
2017-05-01 18:58:08 +02:00
|
|
|
return &mockServer{
|
2017-12-11 00:38:17 +01:00
|
|
|
t: t,
|
|
|
|
id: id,
|
|
|
|
name: name,
|
|
|
|
messages: make(chan lnwire.Message, 3000),
|
|
|
|
quit: make(chan struct{}),
|
2019-02-09 17:22:32 +01:00
|
|
|
registry: registry,
|
2017-12-11 00:38:17 +01:00
|
|
|
htlcSwitch: htlcSwitch,
|
2019-02-09 17:22:32 +01:00
|
|
|
pCache: pCache,
|
2017-07-09 00:46:27 +02:00
|
|
|
interceptorFuncs: make([]messageInterceptor, 0),
|
2017-12-11 00:38:17 +01:00
|
|
|
}, nil
|
2017-05-01 18:58:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *mockServer) Start() error {
|
|
|
|
if !atomic.CompareAndSwapInt32(&s.started, 0, 1) {
|
2017-07-09 01:30:20 +02:00
|
|
|
return errors.New("mock server already started")
|
2017-05-01 18:58:08 +02:00
|
|
|
}
|
|
|
|
|
2017-07-09 01:30:20 +02:00
|
|
|
if err := s.htlcSwitch.Start(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2017-05-01 18:58:08 +02:00
|
|
|
|
|
|
|
s.wg.Add(1)
|
|
|
|
go func() {
|
|
|
|
defer s.wg.Done()
|
|
|
|
|
2017-07-09 01:30:20 +02:00
|
|
|
defer func() {
|
|
|
|
s.htlcSwitch.Stop()
|
|
|
|
}()
|
|
|
|
|
2017-05-01 18:58:08 +02:00
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case msg := <-s.messages:
|
2017-07-09 00:46:27 +02:00
|
|
|
var shouldSkip bool
|
|
|
|
|
|
|
|
for _, interceptor := range s.interceptorFuncs {
|
|
|
|
skip, err := interceptor(msg)
|
|
|
|
if err != nil {
|
2017-11-11 00:09:19 +01:00
|
|
|
s.t.Fatalf("%v: error in the "+
|
|
|
|
"interceptor: %v", s.name, err)
|
2017-07-09 00:46:27 +02:00
|
|
|
return
|
|
|
|
}
|
|
|
|
shouldSkip = shouldSkip || skip
|
|
|
|
}
|
|
|
|
|
|
|
|
if shouldSkip {
|
|
|
|
continue
|
2017-05-01 18:58:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if err := s.readHandler(msg); err != nil {
|
2017-11-11 00:09:19 +01:00
|
|
|
s.t.Fatal(err)
|
2017-07-09 01:30:20 +02:00
|
|
|
return
|
2017-05-01 18:58:08 +02:00
|
|
|
}
|
|
|
|
case <-s.quit:
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2018-08-26 02:11:40 +02:00
|
|
|
func (s *mockServer) QuitSignal() <-chan struct{} {
|
|
|
|
return s.quit
|
|
|
|
}
|
|
|
|
|
2017-05-02 01:29:30 +02:00
|
|
|
// mockHopIterator represents the test version of hop iterator which instead
|
|
|
|
// of encrypting the path in onion blob just stores the path as a list of hops.
|
|
|
|
type mockHopIterator struct {
|
2019-11-05 00:10:15 +01:00
|
|
|
hops []*hop.Payload
|
2017-05-02 01:29:30 +02:00
|
|
|
}
|
|
|
|
|
2019-11-05 00:10:15 +01:00
|
|
|
func newMockHopIterator(hops ...*hop.Payload) hop.Iterator {
|
2017-05-02 01:29:30 +02:00
|
|
|
return &mockHopIterator{hops: hops}
|
|
|
|
}
|
|
|
|
|
2024-04-25 15:46:31 +02:00
|
|
|
func (r *mockHopIterator) HopPayload() (*hop.Payload, hop.RouteRole, error) {
|
2017-06-17 00:08:19 +02:00
|
|
|
h := r.hops[0]
|
|
|
|
r.hops = r.hops[1:]
|
2024-04-25 15:46:31 +02:00
|
|
|
return h, hop.RouteRoleCleartext, nil
|
2019-07-31 06:52:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func (r *mockHopIterator) ExtraOnionBlob() []byte {
|
|
|
|
return nil
|
2017-05-02 01:29:30 +02:00
|
|
|
}
|
|
|
|
|
2018-02-24 02:18:25 +01:00
|
|
|
func (r *mockHopIterator) ExtractErrorEncrypter(
|
2024-04-23 18:33:04 +02:00
|
|
|
extracter hop.ErrorEncrypterExtracter, _ bool) (hop.ErrorEncrypter,
|
2019-09-05 13:35:39 +02:00
|
|
|
lnwire.FailCode) {
|
2018-02-24 02:18:25 +01:00
|
|
|
|
|
|
|
return extracter(nil)
|
|
|
|
}
|
|
|
|
|
2017-06-17 00:08:19 +02:00
|
|
|
func (r *mockHopIterator) EncodeNextHop(w io.Writer) error {
|
2017-05-02 01:29:30 +02:00
|
|
|
var hopLength [4]byte
|
|
|
|
binary.BigEndian.PutUint32(hopLength[:], uint32(len(r.hops)))
|
|
|
|
|
|
|
|
if _, err := w.Write(hopLength[:]); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, hop := range r.hops {
|
2019-11-05 00:10:15 +01:00
|
|
|
fwdInfo := hop.ForwardingInfo()
|
|
|
|
if err := encodeFwdInfo(w, &fwdInfo); err != nil {
|
2017-05-02 01:29:30 +02:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2019-08-30 23:11:20 +02:00
|
|
|
func encodeFwdInfo(w io.Writer, f *hop.ForwardingInfo) error {
|
2017-06-17 00:08:19 +02:00
|
|
|
if err := binary.Write(w, binary.BigEndian, f.NextHop); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := binary.Write(w, binary.BigEndian, f.AmountToForward); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := binary.Write(w, binary.BigEndian, f.OutgoingCTLV); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2019-09-05 13:35:39 +02:00
|
|
|
var _ hop.Iterator = (*mockHopIterator)(nil)
|
2017-05-02 01:29:30 +02:00
|
|
|
|
2017-06-29 15:40:45 +02:00
|
|
|
// mockObfuscator mock implementation of the failure obfuscator which only
|
|
|
|
// encodes the failure and do not makes any onion obfuscation.
|
2018-02-24 02:18:25 +01:00
|
|
|
type mockObfuscator struct {
|
|
|
|
ogPacket *sphinx.OnionPacket
|
2019-10-09 16:37:25 +02:00
|
|
|
failure lnwire.FailureMessage
|
2018-02-24 02:18:25 +01:00
|
|
|
}
|
2017-06-29 15:40:45 +02:00
|
|
|
|
2017-12-11 00:38:17 +01:00
|
|
|
// NewMockObfuscator initializes a dummy mockObfuscator used for testing.
|
2019-09-05 13:35:39 +02:00
|
|
|
func NewMockObfuscator() hop.ErrorEncrypter {
|
2017-06-29 15:40:45 +02:00
|
|
|
return &mockObfuscator{}
|
|
|
|
}
|
|
|
|
|
2018-02-24 02:18:25 +01:00
|
|
|
func (o *mockObfuscator) OnionPacket() *sphinx.OnionPacket {
|
|
|
|
return o.ogPacket
|
|
|
|
}
|
|
|
|
|
2019-09-05 13:35:39 +02:00
|
|
|
func (o *mockObfuscator) Type() hop.EncrypterType {
|
|
|
|
return hop.EncrypterTypeMock
|
2018-02-24 02:18:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func (o *mockObfuscator) Encode(w io.Writer) error {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (o *mockObfuscator) Decode(r io.Reader) error {
|
2018-03-12 21:37:49 +01:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2019-09-05 13:35:39 +02:00
|
|
|
func (o *mockObfuscator) Reextract(
|
|
|
|
extracter hop.ErrorEncrypterExtracter) error {
|
|
|
|
|
2018-02-24 02:18:25 +01:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2022-10-14 11:03:31 +02:00
|
|
|
var fakeHmac = []byte("hmachmachmachmachmachmachmachmac")
|
|
|
|
|
2017-10-11 04:36:52 +02:00
|
|
|
func (o *mockObfuscator) EncryptFirstHop(failure lnwire.FailureMessage) (
|
2017-06-29 15:40:45 +02:00
|
|
|
lnwire.OpaqueReason, error) {
|
|
|
|
|
2019-10-09 16:37:25 +02:00
|
|
|
o.failure = failure
|
|
|
|
|
2017-06-29 15:40:45 +02:00
|
|
|
var b bytes.Buffer
|
2022-10-14 11:03:31 +02:00
|
|
|
b.Write(fakeHmac)
|
|
|
|
|
2017-06-29 15:40:45 +02:00
|
|
|
if err := lnwire.EncodeFailure(&b, failure, 0); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return b.Bytes(), nil
|
|
|
|
}
|
|
|
|
|
2017-10-11 04:36:52 +02:00
|
|
|
func (o *mockObfuscator) IntermediateEncrypt(reason lnwire.OpaqueReason) lnwire.OpaqueReason {
|
2017-06-29 15:40:45 +02:00
|
|
|
return reason
|
2019-05-01 03:28:39 +02:00
|
|
|
}
|
2017-06-29 15:40:45 +02:00
|
|
|
|
2019-05-01 03:28:39 +02:00
|
|
|
func (o *mockObfuscator) EncryptMalformedError(reason lnwire.OpaqueReason) lnwire.OpaqueReason {
|
2022-10-14 11:03:31 +02:00
|
|
|
var b bytes.Buffer
|
|
|
|
b.Write(fakeHmac)
|
|
|
|
|
|
|
|
b.Write(reason)
|
|
|
|
|
|
|
|
return b.Bytes()
|
2017-06-29 15:40:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// mockDeobfuscator mock implementation of the failure deobfuscator which
|
|
|
|
// only decodes the failure do not makes any onion obfuscation.
|
|
|
|
type mockDeobfuscator struct{}
|
|
|
|
|
2017-10-11 04:36:52 +02:00
|
|
|
func newMockDeobfuscator() ErrorDecrypter {
|
2017-06-29 15:40:45 +02:00
|
|
|
return &mockDeobfuscator{}
|
|
|
|
}
|
|
|
|
|
2022-10-14 11:03:31 +02:00
|
|
|
func (o *mockDeobfuscator) DecryptError(reason lnwire.OpaqueReason) (
|
|
|
|
*ForwardingError, error) {
|
|
|
|
|
|
|
|
if !bytes.Equal(reason[:32], fakeHmac) {
|
|
|
|
return nil, errors.New("fake decryption error")
|
|
|
|
}
|
|
|
|
reason = reason[32:]
|
2017-10-11 04:36:52 +02:00
|
|
|
|
2017-06-29 15:40:45 +02:00
|
|
|
r := bytes.NewReader(reason)
|
|
|
|
failure, err := lnwire.DecodeFailure(r, 0)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2017-10-11 04:36:52 +02:00
|
|
|
|
2020-01-14 14:07:42 +01:00
|
|
|
return NewForwardingError(failure, 1), nil
|
2017-06-29 15:40:45 +02:00
|
|
|
}
|
|
|
|
|
2017-10-11 04:36:52 +02:00
|
|
|
var _ ErrorDecrypter = (*mockDeobfuscator)(nil)
|
2017-06-29 15:40:45 +02:00
|
|
|
|
2017-05-02 01:29:30 +02:00
|
|
|
// mockIteratorDecoder test version of hop iterator decoder which decodes the
|
|
|
|
// encoded array of hops.
|
2018-02-24 02:18:25 +01:00
|
|
|
type mockIteratorDecoder struct {
|
|
|
|
mu sync.RWMutex
|
2017-05-02 01:29:30 +02:00
|
|
|
|
2019-09-05 13:35:39 +02:00
|
|
|
responses map[[32]byte][]hop.DecodeHopIteratorResponse
|
2019-05-01 03:28:39 +02:00
|
|
|
|
|
|
|
decodeFail bool
|
2018-02-24 02:18:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func newMockIteratorDecoder() *mockIteratorDecoder {
|
|
|
|
return &mockIteratorDecoder{
|
2019-09-05 13:35:39 +02:00
|
|
|
responses: make(map[[32]byte][]hop.DecodeHopIteratorResponse),
|
2018-02-24 02:18:25 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *mockIteratorDecoder) DecodeHopIterator(r io.Reader, rHash []byte,
|
2019-09-05 13:35:39 +02:00
|
|
|
cltv uint32) (hop.Iterator, lnwire.FailCode) {
|
2017-06-29 15:40:45 +02:00
|
|
|
|
2017-05-02 01:29:30 +02:00
|
|
|
var b [4]byte
|
|
|
|
_, err := r.Read(b[:])
|
|
|
|
if err != nil {
|
2017-06-29 15:40:45 +02:00
|
|
|
return nil, lnwire.CodeTemporaryChannelFailure
|
2017-05-02 01:29:30 +02:00
|
|
|
}
|
|
|
|
hopLength := binary.BigEndian.Uint32(b[:])
|
|
|
|
|
2019-11-05 00:10:15 +01:00
|
|
|
hops := make([]*hop.Payload, hopLength)
|
2017-05-02 01:29:30 +02:00
|
|
|
for i := uint32(0); i < hopLength; i++ {
|
2019-11-05 00:10:15 +01:00
|
|
|
var f hop.ForwardingInfo
|
|
|
|
if err := decodeFwdInfo(r, &f); err != nil {
|
2017-06-29 15:40:45 +02:00
|
|
|
return nil, lnwire.CodeTemporaryChannelFailure
|
2017-05-02 01:29:30 +02:00
|
|
|
}
|
|
|
|
|
2019-11-05 00:10:15 +01:00
|
|
|
var nextHopBytes [8]byte
|
|
|
|
binary.BigEndian.PutUint64(nextHopBytes[:], f.NextHop.ToUint64())
|
|
|
|
|
|
|
|
hops[i] = hop.NewLegacyPayload(&sphinx.HopData{
|
|
|
|
Realm: [1]byte{}, // hop.BitcoinNetwork
|
|
|
|
NextAddress: nextHopBytes,
|
|
|
|
ForwardAmount: uint64(f.AmountToForward),
|
|
|
|
OutgoingCltv: f.OutgoingCTLV,
|
|
|
|
})
|
2017-05-02 01:29:30 +02:00
|
|
|
}
|
|
|
|
|
2017-06-29 15:40:45 +02:00
|
|
|
return newMockHopIterator(hops...), lnwire.CodeNone
|
2017-05-02 01:29:30 +02:00
|
|
|
}
|
|
|
|
|
2018-02-24 02:18:25 +01:00
|
|
|
func (p *mockIteratorDecoder) DecodeHopIterators(id []byte,
|
2019-09-05 13:35:39 +02:00
|
|
|
reqs []hop.DecodeHopIteratorRequest) (
|
|
|
|
[]hop.DecodeHopIteratorResponse, error) {
|
2018-02-24 02:18:25 +01:00
|
|
|
|
|
|
|
idHash := sha256.Sum256(id)
|
|
|
|
|
|
|
|
p.mu.RLock()
|
|
|
|
if resps, ok := p.responses[idHash]; ok {
|
|
|
|
p.mu.RUnlock()
|
|
|
|
return resps, nil
|
|
|
|
}
|
|
|
|
p.mu.RUnlock()
|
|
|
|
|
|
|
|
batchSize := len(reqs)
|
|
|
|
|
2019-09-05 13:35:39 +02:00
|
|
|
resps := make([]hop.DecodeHopIteratorResponse, 0, batchSize)
|
2018-02-24 02:18:25 +01:00
|
|
|
for _, req := range reqs {
|
|
|
|
iterator, failcode := p.DecodeHopIterator(
|
|
|
|
req.OnionReader, req.RHash, req.IncomingCltv,
|
|
|
|
)
|
|
|
|
|
2019-05-01 03:28:39 +02:00
|
|
|
if p.decodeFail {
|
|
|
|
failcode = lnwire.CodeTemporaryChannelFailure
|
|
|
|
}
|
|
|
|
|
2019-09-05 13:35:39 +02:00
|
|
|
resp := hop.DecodeHopIteratorResponse{
|
2018-02-24 02:18:25 +01:00
|
|
|
HopIterator: iterator,
|
|
|
|
FailCode: failcode,
|
|
|
|
}
|
|
|
|
resps = append(resps, resp)
|
|
|
|
}
|
|
|
|
|
|
|
|
p.mu.Lock()
|
|
|
|
p.responses[idHash] = resps
|
|
|
|
p.mu.Unlock()
|
|
|
|
|
|
|
|
return resps, nil
|
|
|
|
}
|
|
|
|
|
2019-08-30 23:11:20 +02:00
|
|
|
func decodeFwdInfo(r io.Reader, f *hop.ForwardingInfo) error {
|
2017-06-17 00:08:19 +02:00
|
|
|
if err := binary.Read(r, binary.BigEndian, &f.NextHop); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := binary.Read(r, binary.BigEndian, &f.AmountToForward); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := binary.Read(r, binary.BigEndian, &f.OutgoingCTLV); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2017-05-01 18:58:08 +02:00
|
|
|
// messageInterceptor is function that handles the incoming peer messages and
|
2017-07-09 00:46:27 +02:00
|
|
|
// may decide should the peer skip the message or not.
|
|
|
|
type messageInterceptor func(m lnwire.Message) (bool, error)
|
2017-05-01 18:58:08 +02:00
|
|
|
|
|
|
|
// Record is used to set the function which will be triggered when new
|
|
|
|
// lnwire message was received.
|
2017-07-09 00:46:27 +02:00
|
|
|
func (s *mockServer) intersect(f messageInterceptor) {
|
|
|
|
s.interceptorFuncs = append(s.interceptorFuncs, f)
|
2017-05-01 18:58:08 +02:00
|
|
|
}
|
|
|
|
|
2018-06-08 05:18:10 +02:00
|
|
|
func (s *mockServer) SendMessage(sync bool, msgs ...lnwire.Message) error {
|
2017-11-11 00:15:19 +01:00
|
|
|
|
2018-06-08 05:18:10 +02:00
|
|
|
for _, msg := range msgs {
|
|
|
|
select {
|
|
|
|
case s.messages <- msg:
|
|
|
|
case <-s.quit:
|
|
|
|
return errors.New("server is stopped")
|
|
|
|
}
|
2017-05-01 18:58:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2019-03-06 02:08:22 +01:00
|
|
|
func (s *mockServer) SendMessageLazy(sync bool, msgs ...lnwire.Message) error {
|
|
|
|
panic("not implemented")
|
|
|
|
}
|
|
|
|
|
2017-05-01 18:58:08 +02:00
|
|
|
func (s *mockServer) readHandler(message lnwire.Message) error {
|
|
|
|
var targetChan lnwire.ChannelID
|
|
|
|
|
|
|
|
switch msg := message.(type) {
|
|
|
|
case *lnwire.UpdateAddHTLC:
|
|
|
|
targetChan = msg.ChanID
|
2018-02-07 04:11:11 +01:00
|
|
|
case *lnwire.UpdateFulfillHTLC:
|
2017-05-01 18:58:08 +02:00
|
|
|
targetChan = msg.ChanID
|
|
|
|
case *lnwire.UpdateFailHTLC:
|
|
|
|
targetChan = msg.ChanID
|
2017-06-29 15:40:45 +02:00
|
|
|
case *lnwire.UpdateFailMalformedHTLC:
|
|
|
|
targetChan = msg.ChanID
|
2017-05-01 18:58:08 +02:00
|
|
|
case *lnwire.RevokeAndAck:
|
|
|
|
targetChan = msg.ChanID
|
|
|
|
case *lnwire.CommitSig:
|
|
|
|
targetChan = msg.ChanID
|
2023-03-15 21:42:21 +01:00
|
|
|
case *lnwire.ChannelReady:
|
2017-09-07 15:04:07 +02:00
|
|
|
// Ignore
|
|
|
|
return nil
|
2017-07-09 01:30:20 +02:00
|
|
|
case *lnwire.ChannelReestablish:
|
|
|
|
targetChan = msg.ChanID
|
2017-11-24 05:31:45 +01:00
|
|
|
case *lnwire.UpdateFee:
|
|
|
|
targetChan = msg.ChanID
|
2017-05-01 18:58:08 +02:00
|
|
|
default:
|
2017-11-11 00:15:19 +01:00
|
|
|
return fmt.Errorf("unknown message type: %T", msg)
|
2017-05-01 18:58:08 +02:00
|
|
|
}
|
|
|
|
|
2018-08-21 04:23:15 +02:00
|
|
|
// Dispatch the commitment update message to the proper channel link
|
|
|
|
// dedicated to this channel. If the link is not found, we will discard
|
|
|
|
// the message.
|
2017-05-01 18:58:08 +02:00
|
|
|
link, err := s.htlcSwitch.GetLink(targetChan)
|
|
|
|
if err != nil {
|
2018-08-21 04:23:15 +02:00
|
|
|
return nil
|
2017-05-01 18:58:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Create goroutine for this, in order to be able to properly stop
|
|
|
|
// the server when handler stacked (server unavailable)
|
2017-11-11 00:15:19 +01:00
|
|
|
link.HandleChannelUpdate(message)
|
2017-05-01 18:58:08 +02:00
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2017-06-17 00:08:19 +02:00
|
|
|
func (s *mockServer) PubKey() [33]byte {
|
2017-05-01 18:58:08 +02:00
|
|
|
return s.id
|
|
|
|
}
|
|
|
|
|
2018-06-08 05:18:10 +02:00
|
|
|
func (s *mockServer) IdentityKey() *btcec.PublicKey {
|
2022-02-23 14:48:00 +01:00
|
|
|
pubkey, _ := btcec.ParsePubKey(s.id[:])
|
2018-06-08 05:18:10 +02:00
|
|
|
return pubkey
|
|
|
|
}
|
|
|
|
|
2018-07-05 22:27:35 +02:00
|
|
|
func (s *mockServer) Address() net.Addr {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2023-01-20 05:26:05 +01:00
|
|
|
func (s *mockServer) AddNewChannel(channel *lnpeer.NewChannel,
|
2018-07-05 22:27:35 +02:00
|
|
|
cancel <-chan struct{}) error {
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2023-03-16 14:25:17 +01:00
|
|
|
func (s *mockServer) AddPendingChannel(_ lnwire.ChannelID,
|
|
|
|
cancel <-chan struct{}) error {
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2023-06-08 13:42:07 +02:00
|
|
|
func (s *mockServer) RemovePendingChannel(_ lnwire.ChannelID) error {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-04-03 02:39:29 +02:00
|
|
|
func (s *mockServer) WipeChannel(*wire.OutPoint) {}
|
2017-05-03 16:02:22 +02:00
|
|
|
|
2019-11-08 14:31:47 +01:00
|
|
|
func (s *mockServer) LocalFeatures() *lnwire.FeatureVector {
|
2019-09-11 14:41:08 +02:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2019-11-08 14:31:47 +01:00
|
|
|
func (s *mockServer) RemoteFeatures() *lnwire.FeatureVector {
|
2019-09-11 14:41:08 +02:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2024-08-14 20:03:39 +02:00
|
|
|
func (s *mockServer) Disconnect(err error) {}
|
|
|
|
|
2017-07-09 01:30:20 +02:00
|
|
|
func (s *mockServer) Stop() error {
|
2017-05-01 18:58:08 +02:00
|
|
|
if !atomic.CompareAndSwapInt32(&s.shutdown, 0, 1) {
|
2017-07-09 01:30:20 +02:00
|
|
|
return nil
|
2017-05-01 18:58:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
close(s.quit)
|
|
|
|
s.wg.Wait()
|
2017-07-09 01:30:20 +02:00
|
|
|
|
|
|
|
return nil
|
2017-05-01 18:58:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *mockServer) String() string {
|
2017-06-17 00:08:19 +02:00
|
|
|
return s.name
|
2017-05-01 18:58:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
type mockChannelLink struct {
|
2017-11-02 21:53:42 +01:00
|
|
|
htlcSwitch *Switch
|
|
|
|
|
2017-06-17 00:08:19 +02:00
|
|
|
shortChanID lnwire.ShortChannelID
|
|
|
|
|
server+htlcswitch: prevent privacy leaks, allow alias routing
This intent of this change is to prevent privacy leaks when routing
with aliases and also to allow routing when using an alias. The
aliases are our aliases.
Introduces are two maps:
* aliasToReal:
This is an N->1 mapping for a channel. The keys are the set of
aliases and the value is the confirmed, on-chain SCID.
* baseIndex:
This is also an N->1 mapping for a channel. The keys are the set
of aliases and the value is the "base" SCID (whatever is in the
OpenChannel.ShortChannelID field). There is also a base->base
mapping, so not all keys are aliases.
The above maps are populated when a link is added to the switch and
when the channel has confirmed on-chain. The maps are not removed
from if the link is removed, but this is fine since forwarding won't
occur.
* getLinkByMapping
This function is introduced to adhere to the spec requirements that
using the confirmed SCID of a private, scid-alias-feature-bit
channel does not work. Lnd implements a stricter version of the spec
and disallows this behavior if the feature-bit was negotiated, rather
than just the channel type. The old, privacy-leak behavior is
preserved.
The spec also requires that if we must fail back an HTLC, the
ChannelUpdate must use the SCID of whatever was in the onion, to avoid
a privacy leak. This is also done by passing in the relevant SCID to
the mailbox and link. Lnd will also cancel back on the "incoming" side
if the InterceptableSwitch was used or if the link failed to decrypt
the onion. In this case, we are cautious and replace the SCID if an
alias exists.
2022-04-04 22:44:51 +02:00
|
|
|
// Only used for zero-conf channels.
|
|
|
|
realScid lnwire.ShortChannelID
|
|
|
|
|
|
|
|
aliases []lnwire.ShortChannelID
|
|
|
|
|
2017-06-17 00:08:19 +02:00
|
|
|
chanID lnwire.ChannelID
|
|
|
|
|
2018-06-08 05:18:10 +02:00
|
|
|
peer lnpeer.Peer
|
2017-06-17 00:08:19 +02:00
|
|
|
|
2017-12-11 00:38:17 +01:00
|
|
|
mailBox MailBox
|
|
|
|
|
2017-05-01 18:58:08 +02:00
|
|
|
packets chan *htlcPacket
|
2017-12-11 01:19:40 +01:00
|
|
|
|
|
|
|
eligible bool
|
2017-11-02 21:53:42 +01:00
|
|
|
|
server+htlcswitch: prevent privacy leaks, allow alias routing
This intent of this change is to prevent privacy leaks when routing
with aliases and also to allow routing when using an alias. The
aliases are our aliases.
Introduces are two maps:
* aliasToReal:
This is an N->1 mapping for a channel. The keys are the set of
aliases and the value is the confirmed, on-chain SCID.
* baseIndex:
This is also an N->1 mapping for a channel. The keys are the set
of aliases and the value is the "base" SCID (whatever is in the
OpenChannel.ShortChannelID field). There is also a base->base
mapping, so not all keys are aliases.
The above maps are populated when a link is added to the switch and
when the channel has confirmed on-chain. The maps are not removed
from if the link is removed, but this is fine since forwarding won't
occur.
* getLinkByMapping
This function is introduced to adhere to the spec requirements that
using the confirmed SCID of a private, scid-alias-feature-bit
channel does not work. Lnd implements a stricter version of the spec
and disallows this behavior if the feature-bit was negotiated, rather
than just the channel type. The old, privacy-leak behavior is
preserved.
The spec also requires that if we must fail back an HTLC, the
ChannelUpdate must use the SCID of whatever was in the onion, to avoid
a privacy leak. This is also done by passing in the relevant SCID to
the mailbox and link. Lnd will also cancel back on the "incoming" side
if the InterceptableSwitch was used or if the link failed to decrypt
the onion. In this case, we are cautious and replace the SCID if an
alias exists.
2022-04-04 22:44:51 +02:00
|
|
|
unadvertised bool
|
|
|
|
|
|
|
|
zeroConf bool
|
|
|
|
|
|
|
|
optionFeature bool
|
|
|
|
|
2017-11-02 21:53:42 +01:00
|
|
|
htlcID uint64
|
2019-04-19 11:11:16 +02:00
|
|
|
|
2020-01-14 14:07:42 +01:00
|
|
|
checkHtlcTransitResult *LinkError
|
2019-10-09 16:58:51 +02:00
|
|
|
|
2020-01-14 14:07:42 +01:00
|
|
|
checkHtlcForwardResult *LinkError
|
server+htlcswitch: prevent privacy leaks, allow alias routing
This intent of this change is to prevent privacy leaks when routing
with aliases and also to allow routing when using an alias. The
aliases are our aliases.
Introduces are two maps:
* aliasToReal:
This is an N->1 mapping for a channel. The keys are the set of
aliases and the value is the confirmed, on-chain SCID.
* baseIndex:
This is also an N->1 mapping for a channel. The keys are the set
of aliases and the value is the "base" SCID (whatever is in the
OpenChannel.ShortChannelID field). There is also a base->base
mapping, so not all keys are aliases.
The above maps are populated when a link is added to the switch and
when the channel has confirmed on-chain. The maps are not removed
from if the link is removed, but this is fine since forwarding won't
occur.
* getLinkByMapping
This function is introduced to adhere to the spec requirements that
using the confirmed SCID of a private, scid-alias-feature-bit
channel does not work. Lnd implements a stricter version of the spec
and disallows this behavior if the feature-bit was negotiated, rather
than just the channel type. The old, privacy-leak behavior is
preserved.
The spec also requires that if we must fail back an HTLC, the
ChannelUpdate must use the SCID of whatever was in the onion, to avoid
a privacy leak. This is also done by passing in the relevant SCID to
the mailbox and link. Lnd will also cancel back on the "incoming" side
if the InterceptableSwitch was used or if the link failed to decrypt
the onion. In this case, we are cautious and replace the SCID if an
alias exists.
2022-04-04 22:44:51 +02:00
|
|
|
|
|
|
|
failAliasUpdate func(sid lnwire.ShortChannelID,
|
2024-08-21 08:39:37 +02:00
|
|
|
incoming bool) *lnwire.ChannelUpdate1
|
server+htlcswitch: prevent privacy leaks, allow alias routing
This intent of this change is to prevent privacy leaks when routing
with aliases and also to allow routing when using an alias. The
aliases are our aliases.
Introduces are two maps:
* aliasToReal:
This is an N->1 mapping for a channel. The keys are the set of
aliases and the value is the confirmed, on-chain SCID.
* baseIndex:
This is also an N->1 mapping for a channel. The keys are the set
of aliases and the value is the "base" SCID (whatever is in the
OpenChannel.ShortChannelID field). There is also a base->base
mapping, so not all keys are aliases.
The above maps are populated when a link is added to the switch and
when the channel has confirmed on-chain. The maps are not removed
from if the link is removed, but this is fine since forwarding won't
occur.
* getLinkByMapping
This function is introduced to adhere to the spec requirements that
using the confirmed SCID of a private, scid-alias-feature-bit
channel does not work. Lnd implements a stricter version of the spec
and disallows this behavior if the feature-bit was negotiated, rather
than just the channel type. The old, privacy-leak behavior is
preserved.
The spec also requires that if we must fail back an HTLC, the
ChannelUpdate must use the SCID of whatever was in the onion, to avoid
a privacy leak. This is also done by passing in the relevant SCID to
the mailbox and link. Lnd will also cancel back on the "incoming" side
if the InterceptableSwitch was used or if the link failed to decrypt
the onion. In this case, we are cautious and replace the SCID if an
alias exists.
2022-04-04 22:44:51 +02:00
|
|
|
|
|
|
|
confirmedZC bool
|
2017-05-01 18:58:08 +02:00
|
|
|
}
|
|
|
|
|
2017-12-11 00:38:17 +01:00
|
|
|
// completeCircuit is a helper method for adding the finalized payment circuit
|
|
|
|
// to the switch's circuit map. In testing, this should be executed after
|
|
|
|
// receiving an htlc from the downstream packets channel.
|
|
|
|
func (f *mockChannelLink) completeCircuit(pkt *htlcPacket) error {
|
|
|
|
switch htlc := pkt.htlc.(type) {
|
|
|
|
case *lnwire.UpdateAddHTLC:
|
|
|
|
pkt.outgoingChanID = f.shortChanID
|
|
|
|
pkt.outgoingHTLCID = f.htlcID
|
|
|
|
htlc.ID = f.htlcID
|
|
|
|
|
|
|
|
keystone := Keystone{pkt.inKey(), pkt.outKey()}
|
2021-07-23 03:33:57 +02:00
|
|
|
err := f.htlcSwitch.circuits.OpenCircuits(keystone)
|
|
|
|
if err != nil {
|
2017-12-11 00:38:17 +01:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
f.htlcID++
|
|
|
|
|
|
|
|
case *lnwire.UpdateFulfillHTLC, *lnwire.UpdateFailHTLC:
|
2022-03-23 15:25:02 +01:00
|
|
|
if pkt.circuit != nil {
|
|
|
|
err := f.htlcSwitch.teardownCircuit(pkt)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2017-12-11 00:38:17 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
f.mailBox.AckPacket(pkt.inKey())
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (f *mockChannelLink) deleteCircuit(pkt *htlcPacket) error {
|
2021-07-23 03:33:57 +02:00
|
|
|
return f.htlcSwitch.circuits.DeleteCircuits(pkt.inKey())
|
2017-12-11 00:38:17 +01:00
|
|
|
}
|
|
|
|
|
2017-11-02 21:53:42 +01:00
|
|
|
func newMockChannelLink(htlcSwitch *Switch, chanID lnwire.ChannelID,
|
server+htlcswitch: prevent privacy leaks, allow alias routing
This intent of this change is to prevent privacy leaks when routing
with aliases and also to allow routing when using an alias. The
aliases are our aliases.
Introduces are two maps:
* aliasToReal:
This is an N->1 mapping for a channel. The keys are the set of
aliases and the value is the confirmed, on-chain SCID.
* baseIndex:
This is also an N->1 mapping for a channel. The keys are the set
of aliases and the value is the "base" SCID (whatever is in the
OpenChannel.ShortChannelID field). There is also a base->base
mapping, so not all keys are aliases.
The above maps are populated when a link is added to the switch and
when the channel has confirmed on-chain. The maps are not removed
from if the link is removed, but this is fine since forwarding won't
occur.
* getLinkByMapping
This function is introduced to adhere to the spec requirements that
using the confirmed SCID of a private, scid-alias-feature-bit
channel does not work. Lnd implements a stricter version of the spec
and disallows this behavior if the feature-bit was negotiated, rather
than just the channel type. The old, privacy-leak behavior is
preserved.
The spec also requires that if we must fail back an HTLC, the
ChannelUpdate must use the SCID of whatever was in the onion, to avoid
a privacy leak. This is also done by passing in the relevant SCID to
the mailbox and link. Lnd will also cancel back on the "incoming" side
if the InterceptableSwitch was used or if the link failed to decrypt
the onion. In this case, we are cautious and replace the SCID if an
alias exists.
2022-04-04 22:44:51 +02:00
|
|
|
shortChanID, realScid lnwire.ShortChannelID, peer lnpeer.Peer,
|
|
|
|
eligible, unadvertised, zeroConf, optionFeature bool,
|
2017-11-02 21:53:42 +01:00
|
|
|
) *mockChannelLink {
|
2017-06-17 00:08:19 +02:00
|
|
|
|
server+htlcswitch: prevent privacy leaks, allow alias routing
This intent of this change is to prevent privacy leaks when routing
with aliases and also to allow routing when using an alias. The
aliases are our aliases.
Introduces are two maps:
* aliasToReal:
This is an N->1 mapping for a channel. The keys are the set of
aliases and the value is the confirmed, on-chain SCID.
* baseIndex:
This is also an N->1 mapping for a channel. The keys are the set
of aliases and the value is the "base" SCID (whatever is in the
OpenChannel.ShortChannelID field). There is also a base->base
mapping, so not all keys are aliases.
The above maps are populated when a link is added to the switch and
when the channel has confirmed on-chain. The maps are not removed
from if the link is removed, but this is fine since forwarding won't
occur.
* getLinkByMapping
This function is introduced to adhere to the spec requirements that
using the confirmed SCID of a private, scid-alias-feature-bit
channel does not work. Lnd implements a stricter version of the spec
and disallows this behavior if the feature-bit was negotiated, rather
than just the channel type. The old, privacy-leak behavior is
preserved.
The spec also requires that if we must fail back an HTLC, the
ChannelUpdate must use the SCID of whatever was in the onion, to avoid
a privacy leak. This is also done by passing in the relevant SCID to
the mailbox and link. Lnd will also cancel back on the "incoming" side
if the InterceptableSwitch was used or if the link failed to decrypt
the onion. In this case, we are cautious and replace the SCID if an
alias exists.
2022-04-04 22:44:51 +02:00
|
|
|
aliases := make([]lnwire.ShortChannelID, 0)
|
|
|
|
var realConfirmed bool
|
|
|
|
|
|
|
|
if zeroConf {
|
|
|
|
aliases = append(aliases, shortChanID)
|
|
|
|
}
|
|
|
|
|
|
|
|
if realScid != hop.Source {
|
|
|
|
realConfirmed = true
|
|
|
|
}
|
|
|
|
|
2017-05-01 18:58:08 +02:00
|
|
|
return &mockChannelLink{
|
server+htlcswitch: prevent privacy leaks, allow alias routing
This intent of this change is to prevent privacy leaks when routing
with aliases and also to allow routing when using an alias. The
aliases are our aliases.
Introduces are two maps:
* aliasToReal:
This is an N->1 mapping for a channel. The keys are the set of
aliases and the value is the confirmed, on-chain SCID.
* baseIndex:
This is also an N->1 mapping for a channel. The keys are the set
of aliases and the value is the "base" SCID (whatever is in the
OpenChannel.ShortChannelID field). There is also a base->base
mapping, so not all keys are aliases.
The above maps are populated when a link is added to the switch and
when the channel has confirmed on-chain. The maps are not removed
from if the link is removed, but this is fine since forwarding won't
occur.
* getLinkByMapping
This function is introduced to adhere to the spec requirements that
using the confirmed SCID of a private, scid-alias-feature-bit
channel does not work. Lnd implements a stricter version of the spec
and disallows this behavior if the feature-bit was negotiated, rather
than just the channel type. The old, privacy-leak behavior is
preserved.
The spec also requires that if we must fail back an HTLC, the
ChannelUpdate must use the SCID of whatever was in the onion, to avoid
a privacy leak. This is also done by passing in the relevant SCID to
the mailbox and link. Lnd will also cancel back on the "incoming" side
if the InterceptableSwitch was used or if the link failed to decrypt
the onion. In this case, we are cautious and replace the SCID if an
alias exists.
2022-04-04 22:44:51 +02:00
|
|
|
htlcSwitch: htlcSwitch,
|
|
|
|
chanID: chanID,
|
|
|
|
shortChanID: shortChanID,
|
|
|
|
realScid: realScid,
|
|
|
|
peer: peer,
|
|
|
|
eligible: eligible,
|
|
|
|
unadvertised: unadvertised,
|
|
|
|
zeroConf: zeroConf,
|
|
|
|
optionFeature: optionFeature,
|
|
|
|
aliases: aliases,
|
|
|
|
confirmedZC: realConfirmed,
|
2017-05-01 18:58:08 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
server+htlcswitch: prevent privacy leaks, allow alias routing
This intent of this change is to prevent privacy leaks when routing
with aliases and also to allow routing when using an alias. The
aliases are our aliases.
Introduces are two maps:
* aliasToReal:
This is an N->1 mapping for a channel. The keys are the set of
aliases and the value is the confirmed, on-chain SCID.
* baseIndex:
This is also an N->1 mapping for a channel. The keys are the set
of aliases and the value is the "base" SCID (whatever is in the
OpenChannel.ShortChannelID field). There is also a base->base
mapping, so not all keys are aliases.
The above maps are populated when a link is added to the switch and
when the channel has confirmed on-chain. The maps are not removed
from if the link is removed, but this is fine since forwarding won't
occur.
* getLinkByMapping
This function is introduced to adhere to the spec requirements that
using the confirmed SCID of a private, scid-alias-feature-bit
channel does not work. Lnd implements a stricter version of the spec
and disallows this behavior if the feature-bit was negotiated, rather
than just the channel type. The old, privacy-leak behavior is
preserved.
The spec also requires that if we must fail back an HTLC, the
ChannelUpdate must use the SCID of whatever was in the onion, to avoid
a privacy leak. This is also done by passing in the relevant SCID to
the mailbox and link. Lnd will also cancel back on the "incoming" side
if the InterceptableSwitch was used or if the link failed to decrypt
the onion. In this case, we are cautious and replace the SCID if an
alias exists.
2022-04-04 22:44:51 +02:00
|
|
|
// addAlias is not part of any interface method.
|
|
|
|
func (f *mockChannelLink) addAlias(alias lnwire.ShortChannelID) {
|
|
|
|
f.aliases = append(f.aliases, alias)
|
|
|
|
}
|
|
|
|
|
2021-08-03 20:59:15 +02:00
|
|
|
func (f *mockChannelLink) handleSwitchPacket(pkt *htlcPacket) error {
|
2017-12-11 00:38:17 +01:00
|
|
|
f.mailBox.AddPacket(pkt)
|
|
|
|
return nil
|
2017-05-01 18:58:08 +02:00
|
|
|
}
|
|
|
|
|
2024-07-31 02:05:04 +02:00
|
|
|
func (f *mockChannelLink) getDustSum(whoseCommit lntypes.ChannelParty,
|
2024-06-03 18:43:33 +02:00
|
|
|
dryRunFee fn.Option[chainfee.SatPerKWeight]) lnwire.MilliSatoshi {
|
|
|
|
|
2021-09-28 17:43:51 +02:00
|
|
|
return 0
|
|
|
|
}
|
|
|
|
|
|
|
|
func (f *mockChannelLink) getFeeRate() chainfee.SatPerKWeight {
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
|
|
|
|
func (f *mockChannelLink) getDustClosure() dustClosure {
|
|
|
|
dustLimit := btcutil.Amount(400)
|
|
|
|
return dustHelper(
|
|
|
|
channeldb.SingleFunderTweaklessBit, dustLimit, dustLimit,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2024-06-03 18:43:33 +02:00
|
|
|
func (f *mockChannelLink) getCommitFee(remote bool) btcutil.Amount {
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
|
2017-05-01 18:58:08 +02:00
|
|
|
func (f *mockChannelLink) HandleChannelUpdate(lnwire.Message) {
|
|
|
|
}
|
|
|
|
|
2023-07-17 12:53:24 +02:00
|
|
|
func (f *mockChannelLink) UpdateForwardingPolicy(_ models.ForwardingPolicy) {
|
2017-06-17 00:08:19 +02:00
|
|
|
}
|
2019-09-27 16:21:34 +02:00
|
|
|
func (f *mockChannelLink) CheckHtlcForward([32]byte, lnwire.MilliSatoshi,
|
2022-09-19 12:06:34 +02:00
|
|
|
lnwire.MilliSatoshi, uint32, uint32, models.InboundFee, uint32,
|
server+htlcswitch: prevent privacy leaks, allow alias routing
This intent of this change is to prevent privacy leaks when routing
with aliases and also to allow routing when using an alias. The
aliases are our aliases.
Introduces are two maps:
* aliasToReal:
This is an N->1 mapping for a channel. The keys are the set of
aliases and the value is the confirmed, on-chain SCID.
* baseIndex:
This is also an N->1 mapping for a channel. The keys are the set
of aliases and the value is the "base" SCID (whatever is in the
OpenChannel.ShortChannelID field). There is also a base->base
mapping, so not all keys are aliases.
The above maps are populated when a link is added to the switch and
when the channel has confirmed on-chain. The maps are not removed
from if the link is removed, but this is fine since forwarding won't
occur.
* getLinkByMapping
This function is introduced to adhere to the spec requirements that
using the confirmed SCID of a private, scid-alias-feature-bit
channel does not work. Lnd implements a stricter version of the spec
and disallows this behavior if the feature-bit was negotiated, rather
than just the channel type. The old, privacy-leak behavior is
preserved.
The spec also requires that if we must fail back an HTLC, the
ChannelUpdate must use the SCID of whatever was in the onion, to avoid
a privacy leak. This is also done by passing in the relevant SCID to
the mailbox and link. Lnd will also cancel back on the "incoming" side
if the InterceptableSwitch was used or if the link failed to decrypt
the onion. In this case, we are cautious and replace the SCID if an
alias exists.
2022-04-04 22:44:51 +02:00
|
|
|
lnwire.ShortChannelID) *LinkError {
|
2019-10-09 16:58:51 +02:00
|
|
|
|
|
|
|
return f.checkHtlcForwardResult
|
2018-04-04 05:09:51 +02:00
|
|
|
}
|
2017-06-17 00:08:19 +02:00
|
|
|
|
2019-09-27 16:21:34 +02:00
|
|
|
func (f *mockChannelLink) CheckHtlcTransit(payHash [32]byte,
|
2019-04-19 11:11:16 +02:00
|
|
|
amt lnwire.MilliSatoshi, timeout uint32,
|
2020-01-14 14:07:42 +01:00
|
|
|
heightNow uint32) *LinkError {
|
2019-04-19 11:11:16 +02:00
|
|
|
|
2019-10-09 16:58:51 +02:00
|
|
|
return f.checkHtlcTransitResult
|
2019-04-19 11:11:16 +02:00
|
|
|
}
|
|
|
|
|
2022-11-18 12:15:22 +01:00
|
|
|
func (f *mockChannelLink) Stats() (
|
|
|
|
uint64, lnwire.MilliSatoshi, lnwire.MilliSatoshi) {
|
|
|
|
|
2017-05-01 18:58:08 +02:00
|
|
|
return 0, 0, 0
|
|
|
|
}
|
|
|
|
|
2017-12-11 00:38:17 +01:00
|
|
|
func (f *mockChannelLink) AttachMailBox(mailBox MailBox) {
|
|
|
|
f.mailBox = mailBox
|
|
|
|
f.packets = mailBox.PacketOutBox()
|
2021-09-28 17:43:51 +02:00
|
|
|
mailBox.SetDustClosure(f.getDustClosure())
|
2017-12-11 00:38:17 +01:00
|
|
|
}
|
|
|
|
|
server+htlcswitch: prevent privacy leaks, allow alias routing
This intent of this change is to prevent privacy leaks when routing
with aliases and also to allow routing when using an alias. The
aliases are our aliases.
Introduces are two maps:
* aliasToReal:
This is an N->1 mapping for a channel. The keys are the set of
aliases and the value is the confirmed, on-chain SCID.
* baseIndex:
This is also an N->1 mapping for a channel. The keys are the set
of aliases and the value is the "base" SCID (whatever is in the
OpenChannel.ShortChannelID field). There is also a base->base
mapping, so not all keys are aliases.
The above maps are populated when a link is added to the switch and
when the channel has confirmed on-chain. The maps are not removed
from if the link is removed, but this is fine since forwarding won't
occur.
* getLinkByMapping
This function is introduced to adhere to the spec requirements that
using the confirmed SCID of a private, scid-alias-feature-bit
channel does not work. Lnd implements a stricter version of the spec
and disallows this behavior if the feature-bit was negotiated, rather
than just the channel type. The old, privacy-leak behavior is
preserved.
The spec also requires that if we must fail back an HTLC, the
ChannelUpdate must use the SCID of whatever was in the onion, to avoid
a privacy leak. This is also done by passing in the relevant SCID to
the mailbox and link. Lnd will also cancel back on the "incoming" side
if the InterceptableSwitch was used or if the link failed to decrypt
the onion. In this case, we are cautious and replace the SCID if an
alias exists.
2022-04-04 22:44:51 +02:00
|
|
|
func (f *mockChannelLink) attachFailAliasUpdate(closure func(
|
2024-08-21 08:39:37 +02:00
|
|
|
sid lnwire.ShortChannelID, incoming bool) *lnwire.ChannelUpdate1) {
|
server+htlcswitch: prevent privacy leaks, allow alias routing
This intent of this change is to prevent privacy leaks when routing
with aliases and also to allow routing when using an alias. The
aliases are our aliases.
Introduces are two maps:
* aliasToReal:
This is an N->1 mapping for a channel. The keys are the set of
aliases and the value is the confirmed, on-chain SCID.
* baseIndex:
This is also an N->1 mapping for a channel. The keys are the set
of aliases and the value is the "base" SCID (whatever is in the
OpenChannel.ShortChannelID field). There is also a base->base
mapping, so not all keys are aliases.
The above maps are populated when a link is added to the switch and
when the channel has confirmed on-chain. The maps are not removed
from if the link is removed, but this is fine since forwarding won't
occur.
* getLinkByMapping
This function is introduced to adhere to the spec requirements that
using the confirmed SCID of a private, scid-alias-feature-bit
channel does not work. Lnd implements a stricter version of the spec
and disallows this behavior if the feature-bit was negotiated, rather
than just the channel type. The old, privacy-leak behavior is
preserved.
The spec also requires that if we must fail back an HTLC, the
ChannelUpdate must use the SCID of whatever was in the onion, to avoid
a privacy leak. This is also done by passing in the relevant SCID to
the mailbox and link. Lnd will also cancel back on the "incoming" side
if the InterceptableSwitch was used or if the link failed to decrypt
the onion. In this case, we are cautious and replace the SCID if an
alias exists.
2022-04-04 22:44:51 +02:00
|
|
|
|
|
|
|
f.failAliasUpdate = closure
|
|
|
|
}
|
|
|
|
|
|
|
|
func (f *mockChannelLink) getAliases() []lnwire.ShortChannelID {
|
|
|
|
return f.aliases
|
|
|
|
}
|
|
|
|
|
|
|
|
func (f *mockChannelLink) isZeroConf() bool {
|
|
|
|
return f.zeroConf
|
|
|
|
}
|
|
|
|
|
|
|
|
func (f *mockChannelLink) negotiatedAliasFeature() bool {
|
|
|
|
return f.optionFeature
|
|
|
|
}
|
|
|
|
|
|
|
|
func (f *mockChannelLink) confirmedScid() lnwire.ShortChannelID {
|
|
|
|
return f.realScid
|
|
|
|
}
|
|
|
|
|
|
|
|
func (f *mockChannelLink) zeroConfConfirmed() bool {
|
|
|
|
return f.confirmedZC
|
|
|
|
}
|
|
|
|
|
2017-12-11 00:38:17 +01:00
|
|
|
func (f *mockChannelLink) Start() error {
|
|
|
|
f.mailBox.ResetMessages()
|
|
|
|
f.mailBox.ResetPackets()
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2024-02-26 22:10:22 +01:00
|
|
|
func (f *mockChannelLink) ChanID() lnwire.ChannelID {
|
|
|
|
return f.chanID
|
|
|
|
}
|
|
|
|
|
|
|
|
func (f *mockChannelLink) ShortChanID() lnwire.ShortChannelID {
|
|
|
|
return f.shortChanID
|
|
|
|
}
|
|
|
|
|
|
|
|
func (f *mockChannelLink) Bandwidth() lnwire.MilliSatoshi {
|
|
|
|
return 99999999
|
|
|
|
}
|
|
|
|
|
|
|
|
func (f *mockChannelLink) PeerPubKey() [33]byte {
|
|
|
|
return f.peer.PubKey()
|
|
|
|
}
|
|
|
|
|
2024-01-29 22:55:20 +01:00
|
|
|
func (f *mockChannelLink) ChannelPoint() wire.OutPoint {
|
|
|
|
return wire.OutPoint{}
|
|
|
|
}
|
|
|
|
|
2018-05-02 01:30:12 +02:00
|
|
|
func (f *mockChannelLink) Stop() {}
|
|
|
|
func (f *mockChannelLink) EligibleToForward() bool { return f.eligible }
|
2021-10-19 09:37:47 +02:00
|
|
|
func (f *mockChannelLink) MayAddOutgoingHtlc(lnwire.MilliSatoshi) error { return nil }
|
2018-05-02 01:30:12 +02:00
|
|
|
func (f *mockChannelLink) setLiveShortChanID(sid lnwire.ShortChannelID) { f.shortChanID = sid }
|
server+htlcswitch: prevent privacy leaks, allow alias routing
This intent of this change is to prevent privacy leaks when routing
with aliases and also to allow routing when using an alias. The
aliases are our aliases.
Introduces are two maps:
* aliasToReal:
This is an N->1 mapping for a channel. The keys are the set of
aliases and the value is the confirmed, on-chain SCID.
* baseIndex:
This is also an N->1 mapping for a channel. The keys are the set
of aliases and the value is the "base" SCID (whatever is in the
OpenChannel.ShortChannelID field). There is also a base->base
mapping, so not all keys are aliases.
The above maps are populated when a link is added to the switch and
when the channel has confirmed on-chain. The maps are not removed
from if the link is removed, but this is fine since forwarding won't
occur.
* getLinkByMapping
This function is introduced to adhere to the spec requirements that
using the confirmed SCID of a private, scid-alias-feature-bit
channel does not work. Lnd implements a stricter version of the spec
and disallows this behavior if the feature-bit was negotiated, rather
than just the channel type. The old, privacy-leak behavior is
preserved.
The spec also requires that if we must fail back an HTLC, the
ChannelUpdate must use the SCID of whatever was in the onion, to avoid
a privacy leak. This is also done by passing in the relevant SCID to
the mailbox and link. Lnd will also cancel back on the "incoming" side
if the InterceptableSwitch was used or if the link failed to decrypt
the onion. In this case, we are cautious and replace the SCID if an
alias exists.
2022-04-04 22:44:51 +02:00
|
|
|
func (f *mockChannelLink) IsUnadvertised() bool { return f.unadvertised }
|
2018-05-02 01:30:12 +02:00
|
|
|
func (f *mockChannelLink) UpdateShortChanID() (lnwire.ShortChannelID, error) {
|
|
|
|
f.eligible = true
|
|
|
|
return f.shortChanID, nil
|
|
|
|
}
|
2017-05-01 18:58:08 +02:00
|
|
|
|
2024-02-07 11:39:37 +01:00
|
|
|
func (f *mockChannelLink) EnableAdds(linkDirection LinkDirection) bool {
|
2023-11-21 22:20:53 +01:00
|
|
|
// TODO(proofofkeags): Implement
|
2024-02-07 11:39:37 +01:00
|
|
|
return true
|
2023-11-21 22:20:53 +01:00
|
|
|
}
|
2024-02-07 11:39:37 +01:00
|
|
|
|
|
|
|
func (f *mockChannelLink) DisableAdds(linkDirection LinkDirection) bool {
|
2023-11-21 22:20:53 +01:00
|
|
|
// TODO(proofofkeags): Implement
|
2024-02-07 11:39:37 +01:00
|
|
|
return true
|
2023-11-21 22:20:53 +01:00
|
|
|
}
|
|
|
|
func (f *mockChannelLink) IsFlushing(linkDirection LinkDirection) bool {
|
|
|
|
// TODO(proofofkeags): Implement
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
func (f *mockChannelLink) OnFlushedOnce(func()) {
|
|
|
|
// TODO(proofofkeags): Implement
|
|
|
|
}
|
|
|
|
func (f *mockChannelLink) OnCommitOnce(LinkDirection, func()) {
|
|
|
|
// TODO(proofofkeags): Implement
|
|
|
|
}
|
|
|
|
|
2024-05-02 16:52:47 +02:00
|
|
|
func (f *mockChannelLink) FundingCustomBlob() fn.Option[tlv.Blob] {
|
|
|
|
return fn.None[tlv.Blob]()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (f *mockChannelLink) CommitmentCustomBlob() fn.Option[tlv.Blob] {
|
|
|
|
return fn.None[tlv.Blob]()
|
|
|
|
}
|
|
|
|
|
2017-05-01 18:58:08 +02:00
|
|
|
var _ ChannelLink = (*mockChannelLink)(nil)
|
2017-05-02 01:29:30 +02:00
|
|
|
|
2019-02-21 14:52:13 +01:00
|
|
|
func newDB() (*channeldb.DB, func(), error) {
|
|
|
|
// First, create a temporary directory to be used for the duration of
|
|
|
|
// this test.
|
2023-06-14 11:45:56 +02:00
|
|
|
tempDirName, err := os.MkdirTemp("", "channeldb")
|
2019-02-21 14:52:13 +01:00
|
|
|
if err != nil {
|
|
|
|
return nil, nil, err
|
2017-05-02 01:29:30 +02:00
|
|
|
}
|
|
|
|
|
2019-02-21 14:52:13 +01:00
|
|
|
// Next, create channeldb for the first time.
|
|
|
|
cdb, err := channeldb.Open(tempDirName)
|
|
|
|
if err != nil {
|
|
|
|
os.RemoveAll(tempDirName)
|
|
|
|
return nil, nil, err
|
|
|
|
}
|
2017-05-02 01:29:30 +02:00
|
|
|
|
2019-02-21 14:52:13 +01:00
|
|
|
cleanUp := func() {
|
|
|
|
cdb.Close()
|
|
|
|
os.RemoveAll(tempDirName)
|
2017-05-02 01:29:30 +02:00
|
|
|
}
|
|
|
|
|
2019-02-21 14:52:13 +01:00
|
|
|
return cdb, cleanUp, nil
|
2017-05-02 01:29:30 +02:00
|
|
|
}
|
|
|
|
|
2019-04-19 11:11:16 +02:00
|
|
|
const testInvoiceCltvExpiry = 6
|
2019-04-05 11:13:52 +02:00
|
|
|
|
2019-02-21 14:52:13 +01:00
|
|
|
type mockInvoiceRegistry struct {
|
|
|
|
settleChan chan lntypes.Hash
|
2018-04-25 05:43:55 +02:00
|
|
|
|
2019-02-21 14:52:13 +01:00
|
|
|
registry *invoices.InvoiceRegistry
|
2017-05-02 01:29:30 +02:00
|
|
|
|
2019-02-21 14:52:13 +01:00
|
|
|
cleanup func()
|
|
|
|
}
|
|
|
|
|
2021-05-11 08:45:29 +02:00
|
|
|
type mockChainNotifier struct {
|
|
|
|
chainntnfs.ChainNotifier
|
|
|
|
}
|
|
|
|
|
|
|
|
// RegisterBlockEpochNtfn mocks a successful call to register block
|
|
|
|
// notifications.
|
|
|
|
func (m *mockChainNotifier) RegisterBlockEpochNtfn(*chainntnfs.BlockEpoch) (
|
|
|
|
*chainntnfs.BlockEpochEvent, error) {
|
|
|
|
|
|
|
|
return &chainntnfs.BlockEpochEvent{
|
|
|
|
Cancel: func() {},
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
2019-02-21 14:52:13 +01:00
|
|
|
func newMockRegistry(minDelta uint32) *mockInvoiceRegistry {
|
|
|
|
cdb, cleanup, err := newDB()
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
2017-05-02 01:29:30 +02:00
|
|
|
}
|
|
|
|
|
2024-04-23 15:33:31 +02:00
|
|
|
modifierMock := &invoices.MockHtlcModifier{}
|
2019-12-04 18:47:53 +01:00
|
|
|
registry := invoices.NewRegistry(
|
|
|
|
cdb,
|
2021-05-11 08:45:29 +02:00
|
|
|
invoices.NewInvoiceExpiryWatcher(
|
|
|
|
clock.NewDefaultClock(), 0, 0, nil,
|
|
|
|
&mockChainNotifier{},
|
|
|
|
),
|
2019-12-04 18:47:53 +01:00
|
|
|
&invoices.RegistryConfig{
|
|
|
|
FinalCltvRejectDelta: 5,
|
2024-04-23 15:33:31 +02:00
|
|
|
HtlcInterceptor: modifierMock,
|
2019-12-04 18:47:53 +01:00
|
|
|
},
|
|
|
|
)
|
2019-02-21 14:52:13 +01:00
|
|
|
registry.Start()
|
2017-05-02 01:29:30 +02:00
|
|
|
|
2019-02-21 14:52:13 +01:00
|
|
|
return &mockInvoiceRegistry{
|
|
|
|
registry: registry,
|
|
|
|
cleanup: cleanup,
|
|
|
|
}
|
2017-05-02 01:29:30 +02:00
|
|
|
}
|
|
|
|
|
2023-10-11 13:42:59 +02:00
|
|
|
func (i *mockInvoiceRegistry) LookupInvoice(ctx context.Context,
|
|
|
|
rHash lntypes.Hash) (invoices.Invoice, error) {
|
2019-08-20 14:54:39 +02:00
|
|
|
|
2023-10-11 13:42:59 +02:00
|
|
|
return i.registry.LookupInvoice(ctx, rHash)
|
2019-02-21 14:52:13 +01:00
|
|
|
}
|
2019-01-11 11:19:16 +01:00
|
|
|
|
2022-11-18 12:15:22 +01:00
|
|
|
func (i *mockInvoiceRegistry) SettleHodlInvoice(
|
2023-10-11 13:42:59 +02:00
|
|
|
ctx context.Context, preimage lntypes.Preimage) error {
|
2022-11-18 12:15:22 +01:00
|
|
|
|
2023-10-11 13:42:59 +02:00
|
|
|
return i.registry.SettleHodlInvoice(ctx, preimage)
|
2019-02-11 12:01:05 +01:00
|
|
|
}
|
|
|
|
|
2019-02-20 12:11:15 +01:00
|
|
|
func (i *mockInvoiceRegistry) NotifyExitHopHtlc(rhash lntypes.Hash,
|
2019-04-16 12:11:20 +02:00
|
|
|
amt lnwire.MilliSatoshi, expiry uint32, currentHeight int32,
|
2022-11-18 12:15:22 +01:00
|
|
|
circuitKey models.CircuitKey, hodlChan chan<- interface{},
|
2024-05-08 19:17:05 +02:00
|
|
|
wireCustomRecords lnwire.CustomRecords,
|
2020-02-06 18:35:10 +01:00
|
|
|
payload invoices.Payload) (invoices.HtlcResolution, error) {
|
2019-01-11 11:19:16 +01:00
|
|
|
|
2019-04-16 12:11:20 +02:00
|
|
|
event, err := i.registry.NotifyExitHopHtlc(
|
2024-05-08 19:17:05 +02:00
|
|
|
rhash, amt, expiry, currentHeight, circuitKey,
|
|
|
|
hodlChan, wireCustomRecords, payload,
|
2019-04-16 12:11:20 +02:00
|
|
|
)
|
2019-02-21 14:52:13 +01:00
|
|
|
if err != nil {
|
2019-02-11 12:01:05 +01:00
|
|
|
return nil, err
|
2019-02-21 14:52:13 +01:00
|
|
|
}
|
|
|
|
if i.settleChan != nil {
|
|
|
|
i.settleChan <- rhash
|
2019-01-11 11:19:16 +01:00
|
|
|
}
|
|
|
|
|
2019-02-11 12:01:05 +01:00
|
|
|
return event, nil
|
2019-01-11 11:19:16 +01:00
|
|
|
}
|
|
|
|
|
2023-10-11 13:42:59 +02:00
|
|
|
func (i *mockInvoiceRegistry) CancelInvoice(ctx context.Context,
|
|
|
|
payHash lntypes.Hash) error {
|
|
|
|
|
|
|
|
return i.registry.CancelInvoice(ctx, payHash)
|
2019-02-21 14:52:13 +01:00
|
|
|
}
|
2017-05-02 01:29:30 +02:00
|
|
|
|
2023-10-11 13:42:59 +02:00
|
|
|
func (i *mockInvoiceRegistry) AddInvoice(ctx context.Context,
|
|
|
|
invoice invoices.Invoice, paymentHash lntypes.Hash) error {
|
2018-01-09 03:57:11 +01:00
|
|
|
|
2023-10-11 13:42:59 +02:00
|
|
|
_, err := i.registry.AddInvoice(ctx, &invoice, paymentHash)
|
2019-02-21 14:52:13 +01:00
|
|
|
return err
|
2017-05-02 01:29:30 +02:00
|
|
|
}
|
|
|
|
|
2022-11-18 12:15:22 +01:00
|
|
|
func (i *mockInvoiceRegistry) HodlUnsubscribeAll(
|
|
|
|
subscriber chan<- interface{}) {
|
|
|
|
|
2019-02-11 12:01:05 +01:00
|
|
|
i.registry.HodlUnsubscribeAll(subscriber)
|
|
|
|
}
|
|
|
|
|
2017-05-02 01:29:30 +02:00
|
|
|
var _ InvoiceDatabase = (*mockInvoiceRegistry)(nil)
|
|
|
|
|
2019-06-07 16:42:26 +02:00
|
|
|
type mockCircuitMap struct {
|
|
|
|
lookup chan *PaymentCircuit
|
|
|
|
}
|
|
|
|
|
|
|
|
var _ CircuitMap = (*mockCircuitMap)(nil)
|
|
|
|
|
|
|
|
func (m *mockCircuitMap) OpenCircuits(...Keystone) error {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *mockCircuitMap) TrimOpenCircuits(chanID lnwire.ShortChannelID,
|
|
|
|
start uint64) error {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *mockCircuitMap) DeleteCircuits(inKeys ...CircuitKey) error {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *mockCircuitMap) CommitCircuits(
|
|
|
|
circuit ...*PaymentCircuit) (*CircuitFwdActions, error) {
|
|
|
|
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *mockCircuitMap) CloseCircuit(outKey CircuitKey) (*PaymentCircuit,
|
|
|
|
error) {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *mockCircuitMap) FailCircuit(inKey CircuitKey) (*PaymentCircuit,
|
|
|
|
error) {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *mockCircuitMap) LookupCircuit(inKey CircuitKey) *PaymentCircuit {
|
|
|
|
return <-m.lookup
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *mockCircuitMap) LookupOpenCircuit(outKey CircuitKey) *PaymentCircuit {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *mockCircuitMap) LookupByPaymentHash(hash [32]byte) []*PaymentCircuit {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *mockCircuitMap) NumPending() int {
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *mockCircuitMap) NumOpen() int {
|
|
|
|
return 0
|
|
|
|
}
|
2019-06-19 11:12:10 +02:00
|
|
|
|
|
|
|
type mockOnionErrorDecryptor struct {
|
|
|
|
sourceIdx int
|
|
|
|
message []byte
|
|
|
|
err error
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *mockOnionErrorDecryptor) DecryptError(encryptedData []byte) (
|
|
|
|
*sphinx.DecryptedError, error) {
|
|
|
|
|
|
|
|
return &sphinx.DecryptedError{
|
|
|
|
SenderIdx: m.sourceIdx,
|
|
|
|
Message: m.message,
|
|
|
|
}, m.err
|
|
|
|
}
|
2020-02-19 16:34:47 +01:00
|
|
|
|
|
|
|
var _ htlcNotifier = (*mockHTLCNotifier)(nil)
|
|
|
|
|
2022-08-29 13:28:17 +02:00
|
|
|
type mockHTLCNotifier struct {
|
2023-05-12 10:09:56 +02:00
|
|
|
htlcNotifier //nolint:unused
|
2022-08-29 13:28:17 +02:00
|
|
|
}
|
2020-02-19 16:34:47 +01:00
|
|
|
|
|
|
|
func (h *mockHTLCNotifier) NotifyForwardingEvent(key HtlcKey, info HtlcInfo,
|
2024-08-20 12:46:24 +02:00
|
|
|
eventType HtlcEventType) {
|
|
|
|
|
2020-02-19 16:34:47 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func (h *mockHTLCNotifier) NotifyLinkFailEvent(key HtlcKey, info HtlcInfo,
|
2022-02-07 13:58:28 +01:00
|
|
|
eventType HtlcEventType, linkErr *LinkError,
|
2024-08-20 12:46:24 +02:00
|
|
|
incoming bool) {
|
|
|
|
|
2020-02-19 16:34:47 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func (h *mockHTLCNotifier) NotifyForwardingFailEvent(key HtlcKey,
|
2024-08-20 12:46:24 +02:00
|
|
|
eventType HtlcEventType) {
|
|
|
|
|
2020-02-19 16:34:47 +01:00
|
|
|
}
|
|
|
|
|
2021-06-15 21:01:24 +02:00
|
|
|
func (h *mockHTLCNotifier) NotifySettleEvent(key HtlcKey,
|
2024-08-20 12:46:24 +02:00
|
|
|
preimage lntypes.Preimage, eventType HtlcEventType) {
|
|
|
|
|
2020-02-19 16:34:47 +01:00
|
|
|
}
|
2022-08-29 13:28:17 +02:00
|
|
|
|
2022-11-18 12:15:22 +01:00
|
|
|
func (h *mockHTLCNotifier) NotifyFinalHtlcEvent(key models.CircuitKey,
|
2024-08-20 12:46:24 +02:00
|
|
|
info channeldb.FinalHtlcInfo) {
|
|
|
|
|
2022-08-29 13:28:17 +02:00
|
|
|
}
|