multi: remove debug invoices

Debug invoices are rarely used nowadays, but keep asking for maintenance
every time refactoring in primarily the invoice registry occurs. We have
passed the cost/benefit tipping point, so therefore the debug invoice
concept is removed in this commit.

Previously the debughtlc flag also controlled whether hodl masks were
active. It is safe to remove that additional condition because the hodl
masks are still guarded by the dev build tag.
This commit is contained in:
Joost Jager 2019-08-14 19:57:31 +02:00
parent d134e0362e
commit 4dd054ae90
No known key found for this signature in database
GPG Key ID: A61B9D4C393C59C7
8 changed files with 30 additions and 151 deletions

@ -269,7 +269,6 @@ type config struct {
Profile string `long:"profile" description:"Enable HTTP profiling on given port -- NOTE port must be between 1024 and 65535"`
DebugHTLC bool `long:"debughtlc" description:"Activate the debug htlc mode. With the debug HTLC mode, all payments sent use a pre-determined R-Hash. Additionally, all HTLCs sent to a node with the debug HTLC R-Hash are immediately settled in the next available state transition."`
UnsafeDisconnect bool `long:"unsafe-disconnect" description:"Allows the rpcserver to intentionally disconnect from peers with open channels. USED FOR TESTING ONLY."`
UnsafeReplay bool `long:"unsafe-replay" description:"Causes a link to replay the adds on its commitment txn after starting up, this enables testing of the sphinx replay logic."`
MaxPendingChannels int `long:"maxpendingchannels" description:"The maximum number of incoming pending channels permitted per peer."`
@ -718,13 +717,6 @@ func loadConfig() (*config, error) {
return nil, err
}
if cfg.Litecoin.MainNet && cfg.DebugHTLC {
str := "%s: debug-htlc mode cannot be used " +
"on litecoin mainnet"
err := fmt.Errorf(str, funcName)
return nil, err
}
// The litecoin chain is the current active chain. However
// throughout the codebase we required chaincfg.Params. So as a
// temporary hack, we'll mutate the default net params for
@ -807,13 +799,6 @@ func loadConfig() (*config, error) {
return nil, err
}
if cfg.Bitcoin.MainNet && cfg.DebugHTLC {
str := "%s: debug-htlc mode cannot be used " +
"on bitcoin mainnet"
err := fmt.Errorf(str, funcName)
return nil, err
}
if cfg.Bitcoin.Node == "neutrino" && cfg.Bitcoin.MainNet {
str := "%s: neutrino isn't yet supported for " +
"bitcoin's mainnet"

@ -191,16 +191,10 @@ type ChannelLinkConfig struct {
// transaction to ensure timely confirmation.
FeeEstimator lnwallet.FeeEstimator
// DebugHTLC should be turned on if you want all HTLCs sent to a node
// with the debug htlc R-Hash are immediately settled in the next
// available state transition.
DebugHTLC bool
// hodl.Mask is a bitvector composed of hodl.Flags, specifying breakpoints
// for HTLC forwarding internal to the switch.
//
// NOTE: This should only be used for testing, and should only be used
// simultaneously with DebugHTLC.
// NOTE: This should only be used for testing.
HodlMask hodl.Mask
// SyncStates is used to indicate that we need send the channel
@ -1256,7 +1250,7 @@ func (l *channelLink) handleDownStreamPkt(pkt *htlcPacket, isReProcess bool) {
// If hodl.AddOutgoing mode is active, we exit early to simulate
// arbitrary delays between the switch adding an ADD to the
// mailbox, and the HTLC being added to the commitment state.
if l.cfg.DebugHTLC && l.cfg.HodlMask.Active(hodl.AddOutgoing) {
if l.cfg.HodlMask.Active(hodl.AddOutgoing) {
l.warnf(hodl.AddOutgoing.Warning())
l.mailBox.AckPacket(pkt.inKey())
return
@ -1378,7 +1372,7 @@ func (l *channelLink) handleDownStreamPkt(pkt *htlcPacket, isReProcess bool) {
// simulate arbitrary delays between the switch adding the
// SETTLE to the mailbox, and the HTLC being added to the
// commitment state.
if l.cfg.DebugHTLC && l.cfg.HodlMask.Active(hodl.SettleOutgoing) {
if l.cfg.HodlMask.Active(hodl.SettleOutgoing) {
l.warnf(hodl.SettleOutgoing.Warning())
l.mailBox.AckPacket(pkt.inKey())
return
@ -1436,7 +1430,7 @@ func (l *channelLink) handleDownStreamPkt(pkt *htlcPacket, isReProcess bool) {
// simulate arbitrary delays between the switch adding a FAIL to
// the mailbox, and the HTLC being added to the commitment
// state.
if l.cfg.DebugHTLC && l.cfg.HodlMask.Active(hodl.FailOutgoing) {
if l.cfg.HodlMask.Active(hodl.FailOutgoing) {
l.warnf(hodl.FailOutgoing.Warning())
l.mailBox.AckPacket(pkt.inKey())
return
@ -1948,7 +1942,7 @@ func (l *channelLink) updateCommitTx() error {
// commit any in-memory modifications to the channel state. Exiting here
// permits testing of either the switch or link's ability to trim
// circuits that have been opened, but unsuccessfully committed.
if l.cfg.DebugHTLC && l.cfg.HodlMask.Active(hodl.Commit) {
if l.cfg.HodlMask.Active(hodl.Commit) {
l.warnf(hodl.Commit.Warning())
return nil
}
@ -2445,7 +2439,7 @@ func (l *channelLink) processRemoteSettleFails(fwdPkg *channeldb.FwdPkg,
// If hodl.SettleIncoming is requested, we will not
// forward the SETTLE to the switch and will not signal
// a free slot on the commitment transaction.
if l.cfg.DebugHTLC && l.cfg.HodlMask.Active(hodl.SettleIncoming) {
if l.cfg.HodlMask.Active(hodl.SettleIncoming) {
l.warnf(hodl.SettleIncoming.Warning())
continue
}
@ -2473,7 +2467,7 @@ func (l *channelLink) processRemoteSettleFails(fwdPkg *channeldb.FwdPkg,
// If hodl.SettleIncoming is requested, we will not
// forward the FAIL to the switch and will not signal a
// free slot on the commitment transaction.
if l.cfg.DebugHTLC && l.cfg.HodlMask.Active(hodl.FailIncoming) {
if l.cfg.HodlMask.Active(hodl.FailIncoming) {
l.warnf(hodl.FailIncoming.Warning())
continue
}
@ -2654,8 +2648,7 @@ func (l *channelLink) processRemoteAdds(fwdPkg *channeldb.FwdPkg,
// If hodl.AddIncoming is requested, we will not
// validate the forwarded ADD, nor will we send the
// packet to the htlc switch.
if l.cfg.DebugHTLC &&
l.cfg.HodlMask.Active(hodl.AddIncoming) {
if l.cfg.HodlMask.Active(hodl.AddIncoming) {
l.warnf(hodl.AddIncoming.Warning())
continue
}
@ -2814,7 +2807,7 @@ func (l *channelLink) processExitHop(pd *lnwallet.PaymentDescriptor,
// If hodl.ExitSettle is requested, we will not validate the final hop's
// ADD, nor will we settle the corresponding invoice or respond with the
// preimage.
if l.cfg.DebugHTLC && l.cfg.HodlMask.Active(hodl.ExitSettle) {
if l.cfg.HodlMask.Active(hodl.ExitSettle) {
l.warnf(hodl.ExitSettle.Warning())
return false, nil
@ -2823,7 +2816,7 @@ func (l *channelLink) processExitHop(pd *lnwallet.PaymentDescriptor,
// As we're the exit hop, we'll double check the hop-payload included in
// the HTLC to ensure that it was crafted correctly by the sender and
// matches the HTLC we were extended.
if !l.cfg.DebugHTLC && pd.Amount != fwdInfo.AmountToForward {
if pd.Amount != fwdInfo.AmountToForward {
log.Errorf("Onion payload of incoming htlc(%x) has incorrect "+
"value: expected %v, got %v", pd.RHash,
@ -2837,7 +2830,7 @@ func (l *channelLink) processExitHop(pd *lnwallet.PaymentDescriptor,
// We'll also ensure that our time-lock value has been computed
// correctly.
if !l.cfg.DebugHTLC && pd.Timeout != fwdInfo.OutgoingCTLV {
if pd.Timeout != fwdInfo.OutgoingCTLV {
log.Errorf("Onion payload of incoming htlc(%x) has incorrect "+
"time-lock: expected %v, got %v",
pd.RHash[:], pd.Timeout, fwdInfo.OutgoingCTLV)
@ -2914,7 +2907,7 @@ func (l *channelLink) settleHTLC(preimage lntypes.Preimage, htlcIndex uint64,
// If the link is in hodl.BogusSettle mode, replace the preimage with a
// fake one before sending it to the peer.
if l.cfg.DebugHTLC && l.cfg.HodlMask.Active(hodl.BogusSettle) {
if l.cfg.HodlMask.Active(hodl.BogusSettle) {
l.warnf(hodl.BogusSettle.Warning())
preimage = [32]byte{}
copy(preimage[:], bytes.Repeat([]byte{2}, 32))

@ -1908,7 +1908,6 @@ func TestChannelLinkBandwidthConsistency(t *testing.T) {
// We put Alice into hodl.ExitSettle mode, such that she won't settle
// incoming HTLCs automatically.
coreLink.cfg.HodlMask = hodl.MaskFromFlags(hodl.ExitSettle)
coreLink.cfg.DebugHTLC = true
estimator := lnwallet.NewStaticFeeEstimator(6000, 0)
feePerKw, err := estimator.EstimateFeePerKW(1)
@ -2857,7 +2856,6 @@ func TestChannelLinkTrimCircuitsNoCommit(t *testing.T) {
// outgoing ADDs are opened, but the changes are not committed in the
// channel state.
alice.coreLink.cfg.HodlMask = hodl.Commit.Mask()
alice.coreLink.cfg.DebugHTLC = true
// Compute the static fees that will be used to determine the
// correctness of Alice's bandwidth when forwarding HTLCs.
@ -4233,7 +4231,6 @@ func (h *persistentLinkHarness) restartLink(
MaxFeeUpdateTimeout: 40 * time.Minute,
// Set any hodl flags requested for the new link.
HodlMask: hodl.MaskFromFlags(hodlFlags...),
DebugHTLC: len(hodlFlags) > 0,
MaxOutgoingCltvExpiry: DefaultMaxOutgoingCltvExpiry,
}
@ -4934,7 +4931,6 @@ func TestChannelLinkCleanupSpuriousResponses(t *testing.T) {
// Settle Alice in hodl ExitSettle mode so that she won't respond
// immediately to the htlc's meant for her. This allows us to control
// the responses she gives back to Bob.
coreLink.cfg.DebugHTLC = true
coreLink.cfg.HodlMask = hodl.ExitSettle.Mask()
// Add two HTLCs to Alice's registry, that Bob can pay.

@ -1,14 +1,11 @@
package invoices
import (
"bytes"
"errors"
"fmt"
"sync"
"sync/atomic"
"time"
"github.com/btcsuite/btcutil"
"github.com/davecgh/go-spew/spew"
"github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/lntypes"
@ -16,18 +13,6 @@ import (
"github.com/lightningnetwork/lnd/queue"
)
var (
// DebugPre is the default debug preimage which is inserted into the
// invoice registry if the --debughtlc flag is activated on start up.
// All nodes initialized with the flag active will immediately settle
// any incoming HTLC whose rHash corresponds with the debug
// preimage.
DebugPre, _ = lntypes.MakePreimage(bytes.Repeat([]byte{1}, 32))
// DebugHash is the hash of the default preimage.
DebugHash = DebugPre.Hash()
)
var (
// ErrInvoiceExpiryTooSoon is returned when an invoice is attempted to be
// accepted or settled with not enough blocks remaining.
@ -73,11 +58,6 @@ type InvoiceRegistry struct {
// new single invoice subscriptions are carried.
invoiceEvents chan interface{}
// debugInvoices is a map which stores special "debug" invoices which
// should be only created/used when manual tests require an invoice
// that *all* nodes are able to fully settle.
debugInvoices map[lntypes.Hash]*channeldb.Invoice
// decodeFinalCltvExpiry is a function used to decode the final expiry
// value from the payment request.
decodeFinalCltvExpiry func(invoice string) (uint32, error)
@ -110,7 +90,6 @@ func NewRegistry(cdb *channeldb.DB, decodeFinalCltvExpiry func(invoice string) (
return &InvoiceRegistry{
cdb: cdb,
debugInvoices: make(map[lntypes.Hash]*channeldb.Invoice),
notificationClients: make(map[uint32]*InvoiceSubscription),
singleNotificationClients: make(map[uint32]*SingleInvoiceSubscription),
newSubscriptions: make(chan *InvoiceSubscription),
@ -392,32 +371,6 @@ func (i *InvoiceRegistry) deliverSingleBacklogEvents(
return nil
}
// AddDebugInvoice adds a debug invoice for the specified amount, identified
// by the passed preimage. Once this invoice is added, subsystems within the
// daemon add/forward HTLCs that are able to obtain the proper preimage
// required for redemption in the case that we're the final destination.
func (i *InvoiceRegistry) AddDebugInvoice(amt btcutil.Amount,
preimage lntypes.Preimage) {
paymentHash := preimage.Hash()
invoice := &channeldb.Invoice{
CreationDate: time.Now(),
Terms: channeldb.ContractTerm{
Value: lnwire.NewMSatFromSatoshis(amt),
PaymentPreimage: preimage,
},
}
i.Lock()
i.debugInvoices[paymentHash] = invoice
i.Unlock()
log.Debugf("Adding debug invoice %v", newLogClosure(func() string {
return spew.Sdump(invoice)
}))
}
// AddInvoice adds a regular invoice for the specified amount, identified by
// the passed preimage. Additionally, any memo or receipt data provided will
// also be stored on-disk. Once this invoice is added, subsystems within the
@ -458,19 +411,8 @@ func (i *InvoiceRegistry) AddInvoice(invoice *channeldb.Invoice,
//
// TODO(roasbeef): ignore if settled?
func (i *InvoiceRegistry) LookupInvoice(rHash lntypes.Hash) (channeldb.Invoice, uint32, error) {
// First check the in-memory debug invoice index to see if this is an
// existing invoice added for debugging.
i.RLock()
debugInv, ok := i.debugInvoices[rHash]
i.RUnlock()
// If found, then simply return the invoice directly.
if ok {
return *debugInv, 0, nil
}
// Otherwise, we'll check the database to see if there's an existing
// matching invoice.
// We'll check the database to see if there's an existing matching
// invoice.
invoice, err := i.cdb.LookupInvoice(rHash)
if err != nil {
return channeldb.Invoice{}, 0, err
@ -556,18 +498,6 @@ func (i *InvoiceRegistry) NotifyExitHopHtlc(rHash lntypes.Hash,
log.Debugf("Invoice(%x): %v, amt=%v, expiry=%v",
rHash[:], s, amtPaid, expiry)
}
// First check the in-memory debug invoice index to see if this is an
// existing invoice added for debugging.
if invoice, ok := i.debugInvoices[rHash]; ok {
debugLog("payment to debug invoice accepted")
// Debug invoices are never fully settled, so we just settle the
// htlc in this case.
return &HodlEvent{
Hash: rHash,
Preimage: &invoice.Terms.PaymentPreimage,
}, nil
}
// If this isn't a debug invoice, then we'll attempt to settle an
// invoice matching this rHash on disk (if one exists).

@ -2372,10 +2372,7 @@ func testChannelUnsettledBalance(net *lntest.NetworkHarness, t *harnessTest) {
ctxb := context.Background()
// Create carol in hodl mode.
carol, err := net.NewNode("Carol", []string{
"--debughtlc",
"--hodl.exit-settle",
})
carol, err := net.NewNode("Carol", []string{"--hodl.exit-settle"})
if err != nil {
t.Fatalf("unable to create new nodes: %v", err)
}
@ -2642,7 +2639,7 @@ func testChannelForceClosure(net *lntest.NetworkHarness, t *harnessTest) {
// Since we'd like to test failure scenarios with outstanding htlcs,
// we'll introduce another node into our test network: Carol.
carol, err := net.NewNode("Carol", []string{"--debughtlc", "--hodl.exit-settle"})
carol, err := net.NewNode("Carol", []string{"--hodl.exit-settle"})
if err != nil {
t.Fatalf("unable to create new nodes: %v", err)
}
@ -3420,7 +3417,7 @@ func testSphinxReplayPersistence(net *lntest.NetworkHarness, t *harnessTest) {
chanAmt := btcutil.Amount(100000)
// First, we'll create Dave, the receiver, and start him in hodl mode.
dave, err := net.NewNode("Dave", []string{"--debughtlc", "--hodl.exit-settle"})
dave, err := net.NewNode("Dave", []string{"--hodl.exit-settle"})
if err != nil {
t.Fatalf("unable to create new nodes: %v", err)
}
@ -6277,8 +6274,7 @@ func testFailingChannel(net *lntest.NetworkHarness, t *harnessTest) {
// We'll introduce Carol, which will settle any incoming invoice with a
// totally unrelated preimage.
carol, err := net.NewNode("Carol",
[]string{"--debughtlc", "--hodl.bogus-settle"})
carol, err := net.NewNode("Carol", []string{"--hodl.bogus-settle"})
if err != nil {
t.Fatalf("unable to create new nodes: %v", err)
}
@ -6740,7 +6736,7 @@ func testRevokedCloseRetribution(net *lntest.NetworkHarness, t *harnessTest) {
// protection logic automatically.
carol, err := net.NewNode(
"Carol",
[]string{"--debughtlc", "--hodl.exit-settle", "--nolisten"},
[]string{"--hodl.exit-settle", "--nolisten"},
)
if err != nil {
t.Fatalf("unable to create new carol node: %v", err)
@ -6992,7 +6988,7 @@ func testRevokedCloseRetributionZeroValueRemoteOutput(net *lntest.NetworkHarness
// Since we'd like to test some multi-hop failure scenarios, we'll
// introduce another node into our test network: Carol.
carol, err := net.NewNode("Carol", []string{"--debughtlc", "--hodl.exit-settle"})
carol, err := net.NewNode("Carol", []string{"--hodl.exit-settle"})
if err != nil {
t.Fatalf("unable to create new nodes: %v", err)
}
@ -7003,7 +6999,7 @@ func testRevokedCloseRetributionZeroValueRemoteOutput(net *lntest.NetworkHarness
// protection logic automatically.
dave, err := net.NewNode(
"Dave",
[]string{"--debughtlc", "--hodl.exit-settle", "--nolisten"},
[]string{"--hodl.exit-settle", "--nolisten"},
)
if err != nil {
t.Fatalf("unable to create new node: %v", err)
@ -7240,7 +7236,7 @@ func testRevokedCloseRetributionRemoteHodl(net *lntest.NetworkHarness,
// Since this test will result in the counterparty being left in a
// weird state, we will introduce another node into our test network:
// Carol.
carol, err := net.NewNode("Carol", []string{"--debughtlc", "--hodl.exit-settle"})
carol, err := net.NewNode("Carol", []string{"--hodl.exit-settle"})
if err != nil {
t.Fatalf("unable to create new nodes: %v", err)
}
@ -7253,7 +7249,7 @@ func testRevokedCloseRetributionRemoteHodl(net *lntest.NetworkHarness,
// trigger the channel data protection logic automatically.
dave, err := net.NewNode(
"Dave",
[]string{"--debughtlc", "--hodl.exit-settle", "--nolisten"},
[]string{"--hodl.exit-settle", "--nolisten"},
)
if err != nil {
t.Fatalf("unable to create new dave node: %v", err)
@ -7657,9 +7653,7 @@ func testRevokedCloseRetributionAltruistWatchtower(net *lntest.NetworkHarness,
// Since we'd like to test some multi-hop failure scenarios, we'll
// introduce another node into our test network: Carol.
carol, err := net.NewNode("Carol", []string{
"--debughtlc", "--hodl.exit-settle",
})
carol, err := net.NewNode("Carol", []string{"--hodl.exit-settle"})
if err != nil {
t.Fatalf("unable to create new nodes: %v", err)
}
@ -9854,7 +9848,7 @@ func createThreeHopNetwork(t *harnessTest, net *lntest.NetworkHarness,
// Next, we'll create a new node "carol" and have Bob connect to her. If
// the carolHodl flag is set, we'll make carol always hold onto the
// HTLC, this way it'll force Bob to go to chain to resolve the HTLC.
carolFlags := []string{"--debughtlc"}
carolFlags := []string{}
if carolHodl {
carolFlags = append(carolFlags, "--hodl.exit-settle")
}
@ -10694,7 +10688,7 @@ func testSwitchCircuitPersistence(net *lntest.NetworkHarness, t *harnessTest) {
// Next, we'll create Carol and establish a channel to from her to
// Dave. Carol is started in htlchodl mode so that we can disconnect the
// intermediary hops before starting the settle.
carol, err := net.NewNode("Carol", []string{"--debughtlc", "--hodl.exit-settle"})
carol, err := net.NewNode("Carol", []string{"--hodl.exit-settle"})
if err != nil {
t.Fatalf("unable to create new nodes: %v", err)
}
@ -11017,7 +11011,7 @@ func testSwitchOfflineDelivery(net *lntest.NetworkHarness, t *harnessTest) {
// Next, we'll create Carol and establish a channel to from her to
// Dave. Carol is started in htlchodl mode so that we can disconnect the
// intermediary hops before starting the settle.
carol, err := net.NewNode("Carol", []string{"--debughtlc", "--hodl.exit-settle"})
carol, err := net.NewNode("Carol", []string{"--hodl.exit-settle"})
if err != nil {
t.Fatalf("unable to create new nodes: %v", err)
}
@ -11348,7 +11342,7 @@ func testSwitchOfflineDeliveryPersistence(net *lntest.NetworkHarness, t *harness
// Next, we'll create Carol and establish a channel to from her to
// Dave. Carol is started in htlchodl mode so that we can disconnect the
// intermediary hops before starting the settle.
carol, err := net.NewNode("Carol", []string{"--debughtlc", "--hodl.exit-settle"})
carol, err := net.NewNode("Carol", []string{"--hodl.exit-settle"})
if err != nil {
t.Fatalf("unable to create new nodes: %v", err)
}
@ -11684,7 +11678,7 @@ func testSwitchOfflineDeliveryOutgoingOffline(
// Next, we'll create Carol and establish a channel to from her to
// Dave. Carol is started in htlchodl mode so that we can disconnect the
// intermediary hops before starting the settle.
carol, err := net.NewNode("Carol", []string{"--debughtlc", "--hodl.exit-settle"})
carol, err := net.NewNode("Carol", []string{"--hodl.exit-settle"})
if err != nil {
t.Fatalf("unable to create new nodes: %v", err)
}

@ -560,7 +560,6 @@ func (p *peer) addLink(chanPoint *wire.OutPoint,
DecodeHopIterators: p.server.sphinx.DecodeHopIterators,
ExtractErrorEncrypter: p.server.sphinx.ExtractErrorEncrypter,
FetchLastChannelUpdate: p.server.fetchLastChanUpdate(),
DebugHTLC: cfg.DebugHTLC,
HodlMask: cfg.Hodl.Mask(),
Registry: p.server.invoices,
Switch: p.server.htlcSwitch,

@ -29,7 +29,7 @@ import (
"github.com/btcsuite/btcwallet/wallet/txauthor"
"github.com/coreos/bbolt"
"github.com/davecgh/go-spew/spew"
"github.com/grpc-ecosystem/go-grpc-middleware"
grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
proxy "github.com/grpc-ecosystem/grpc-gateway/runtime"
"github.com/lightningnetwork/lnd/autopilot"
"github.com/lightningnetwork/lnd/build"
@ -3067,14 +3067,6 @@ func extractPaymentIntent(rpcPayReq *rpcPaymentRequest) (rpcPaymentIntent, error
copy(payIntent.rHash[:], paymentHash)
// If we're in debug HTLC mode, then all outgoing HTLCs will pay to the
// same debug rHash. Otherwise, we pay to the rHash specified within
// the RPC request.
case cfg.DebugHTLC &&
bytes.Equal(payIntent.rHash[:], lntypes.ZeroHash[:]):
copy(payIntent.rHash[:], invoices.DebugHash[:])
default:
copy(payIntent.rHash[:], rpcPayReq.PaymentHash)
}

@ -396,16 +396,6 @@ func newServer(listenAddrs []net.Addr, chanDB *channeldb.DB,
subscribers: make(map[uint64]*preimageSubscriber),
}
// If the debug HTLC flag is on, then we invoice a "master debug"
// invoice which all outgoing payments will be sent and all incoming
// HTLCs with the debug R-Hash immediately settled.
if cfg.DebugHTLC {
kiloCoin := btcutil.Amount(btcutil.SatoshiPerBitcoin * 1000)
s.invoices.AddDebugInvoice(kiloCoin, invoices.DebugPre)
srvrLog.Debugf("Debug HTLC invoice inserted, preimage=%x, hash=%x",
invoices.DebugPre[:], invoices.DebugHash[:])
}
_, currentHeight, err := s.cc.chainIO.GetBestBlock()
if err != nil {
return nil, err