Merge pull request #3402 from joostjager/remove-debug-invoice

multi: remove debug invoices
This commit is contained in:
Olaoluwa Osuntokun 2019-08-19 18:42:34 -07:00 committed by GitHub
commit 701244012a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
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