diff --git a/go.mod b/go.mod index 173a796..a6b6cf9 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.19 require ( github.com/aws/aws-sdk-go v1.30.20 - github.com/breez/lntest v0.0.3 + github.com/breez/lntest v0.0.6 github.com/btcsuite/btcd v0.23.1 github.com/btcsuite/btcd/btcec/v2 v2.2.1 github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 @@ -176,4 +176,4 @@ require ( replace github.com/lightningnetwork/lnd v0.15.1-beta => github.com/breez/lnd v0.15.0-beta.rc6.0.20220831104847-00b86a81e57a -replace github.com/niftynei/glightning v0.8.2 => github.com/breez/glightning v0.0.0-20221124075140-383be4672b47 +replace github.com/niftynei/glightning v0.8.2 => github.com/breez/glightning v0.0.0-20221201092709-02feadd1d0ad diff --git a/itest/intercept_zero_conf_test.go b/itest/intercept_zero_conf_test.go index 2318e56..d6312c1 100644 --- a/itest/intercept_zero_conf_test.go +++ b/itest/intercept_zero_conf_test.go @@ -2,7 +2,6 @@ package itest import ( "log" - "testing" "time" "github.com/breez/lntest" @@ -10,24 +9,18 @@ import ( "gotest.tools/assert" ) -func TestOpenZeroConfChannelOnReceive(t *testing.T) { - harness := lntest.NewTestHarness(t) - defer harness.TearDown() - - timeout := time.Now().Add(time.Minute) - - miner := lntest.NewMiner(harness) - alice := lntest.NewCoreLightningNode(harness, miner, "Alice", timeout) - bob := NewZeroConfNode(harness, miner, "Bob", timeout) - lsp := NewLspdNode(harness, miner, "Lsp", timeout) +func testOpenZeroConfChannelOnReceive(h *lntest.TestHarness, lsp LspNode, miner *lntest.Miner, timeout time.Time) { + alice := lntest.NewCoreLightningNode(h, miner, "Alice", timeout) + bob := NewZeroConfNode(h, miner, "Bob", timeout) alice.Fund(10000000, timeout) - lsp.lightningNode.Fund(10000000, timeout) + lsp.LightningNode().Fund(10000000, timeout) log.Print("Opening channel between Alice and the lsp") - alice.OpenChannelAndWait(lsp.lightningNode, &lntest.OpenChannelOptions{ + channel := alice.OpenChannel(lsp.LightningNode(), &lntest.OpenChannelOptions{ AmountSat: 1000000, - }, timeout) + }) + alice.WaitForChannelReady(channel, timeout) log.Printf("Adding bob's invoices") outerAmountMsat := uint64(2100000) @@ -41,12 +34,12 @@ func TestOpenZeroConfChannelOnReceive(t *testing.T) { }) log.Print("Connecting bob to lspd") - bob.lightningNode.ConnectPeer(lsp.lightningNode) + bob.lightningNode.ConnectPeer(lsp.LightningNode()) // NOTE: We pretend to be paying fees to the lsp, but actually we won't. log.Printf("Registering payment with lsp") pretendAmount := outerAmountMsat - 2000000 - lsp.RegisterPayment(&lspd.PaymentInformation{ + RegisterPayment(lsp, &lspd.PaymentInformation{ PaymentHash: innerInvoice.paymentHash, PaymentSecret: innerInvoice.paymentSecret, Destination: bob.lightningNode.NodeId(), @@ -58,28 +51,22 @@ func TestOpenZeroConfChannelOnReceive(t *testing.T) { payResp := alice.Pay(outerInvoice.bolt11, timeout) bobInvoice := bob.lightningNode.GetInvoice(payResp.PaymentHash) - assert.DeepEqual(t, payResp.PaymentPreimage, bobInvoice.PaymentPreimage) - assert.Equal(t, outerAmountMsat, bobInvoice.AmountReceivedMsat) + assert.DeepEqual(h.T, payResp.PaymentPreimage, bobInvoice.PaymentPreimage) + assert.Equal(h.T, outerAmountMsat, bobInvoice.AmountReceivedMsat) } -func TestOpenZeroConfSingleHtlc(t *testing.T) { - harness := lntest.NewTestHarness(t) - defer harness.TearDown() - - timeout := time.Now().Add(time.Minute) - - miner := lntest.NewMiner(harness) - alice := lntest.NewCoreLightningNode(harness, miner, "Alice", timeout) - bob := NewZeroConfNode(harness, miner, "Bob", timeout) - lsp := NewLspdNode(harness, miner, "Lsp", timeout) +func testOpenZeroConfSingleHtlc(h *lntest.TestHarness, lsp LspNode, miner *lntest.Miner, timeout time.Time) { + alice := lntest.NewCoreLightningNode(h, miner, "Alice", timeout) + bob := NewZeroConfNode(h, miner, "Bob", timeout) alice.Fund(10000000, timeout) - lsp.lightningNode.Fund(10000000, timeout) + lsp.LightningNode().Fund(10000000, timeout) log.Print("Opening channel between Alice and the lsp") - channel := alice.OpenChannelAndWait(lsp.lightningNode, &lntest.OpenChannelOptions{ + channel := alice.OpenChannel(lsp.LightningNode(), &lntest.OpenChannelOptions{ AmountSat: 1000000, - }, timeout) + }) + channelId := alice.WaitForChannelReady(channel, timeout) log.Printf("Adding bob's invoices") outerAmountMsat := uint64(2100000) @@ -93,12 +80,12 @@ func TestOpenZeroConfSingleHtlc(t *testing.T) { }) log.Print("Connecting bob to lspd") - bob.lightningNode.ConnectPeer(lsp.lightningNode) + bob.lightningNode.ConnectPeer(lsp.LightningNode()) // NOTE: We pretend to be paying fees to the lsp, but actually we won't. log.Printf("Registering payment with lsp") pretendAmount := outerAmountMsat - 2000000 - lsp.RegisterPayment(&lspd.PaymentInformation{ + RegisterPayment(lsp, &lspd.PaymentInformation{ PaymentHash: innerInvoice.paymentHash, PaymentSecret: innerInvoice.paymentSecret, Destination: bob.lightningNode.NodeId(), @@ -107,23 +94,23 @@ func TestOpenZeroConfSingleHtlc(t *testing.T) { }) log.Printf("Alice paying") - route := constructRoute(lsp.lightningNode, bob.lightningNode, channel.ChannelId, "1x0x0", outerAmountMsat) - alice.StartPayPartViaRoute(outerAmountMsat, outerInvoice.paymentHash, outerInvoice.paymentSecret, 0, route) - payResp := alice.WaitForPaymentPart(outerInvoice.paymentHash, timeout, 0) + route := constructRoute(lsp.LightningNode(), bob.lightningNode, channelId, lntest.NewShortChanIDFromString("1x0x0"), outerAmountMsat) + payResp := alice.PayViaRoute(outerAmountMsat, outerInvoice.paymentHash, outerInvoice.paymentSecret, route, timeout) bobInvoice := bob.lightningNode.GetInvoice(payResp.PaymentHash) - assert.DeepEqual(t, payResp.PaymentPreimage, bobInvoice.PaymentPreimage) - assert.Equal(t, outerAmountMsat, bobInvoice.AmountReceivedMsat) + assert.DeepEqual(h.T, payResp.PaymentPreimage, bobInvoice.PaymentPreimage) + assert.Equal(h.T, outerAmountMsat, bobInvoice.AmountReceivedMsat) } func constructRoute( - lsp *lntest.CoreLightningNode, - bob *lntest.CoreLightningNode, - aliceLspChannel string, - lspBobChannel string, - amountMsat uint64) *lntest.Route { + lsp lntest.LightningNode, + bob lntest.LightningNode, + aliceLspChannel lntest.ShortChannelID, + lspBobChannel lntest.ShortChannelID, + amountMsat uint64, +) *lntest.Route { return &lntest.Route{ - Route: []*lntest.Hop{ + Hops: []*lntest.Hop{ { Id: lsp.NodeId(), Channel: aliceLspChannel, diff --git a/itest/lspd_node.go b/itest/lspd_node.go index dc76539..73c024d 100644 --- a/itest/lspd_node.go +++ b/itest/lspd_node.go @@ -9,12 +9,14 @@ import ( "os" "os/exec" "path/filepath" + "strings" "time" "github.com/breez/lntest" "github.com/breez/lspd/btceclegacy" lspd "github.com/breez/lspd/rpc" "github.com/btcsuite/btcd/btcec/v2" + "github.com/decred/dcrd/dcrec/secp256k1/v4" "github.com/golang/protobuf/proto" grpc "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" @@ -35,28 +37,208 @@ var ( lspCltvDelta uint16 = 40 ) -type LspNode struct { +type LspNode interface { + Harness() *lntest.TestHarness + PublicKey() *btcec.PublicKey + Rpc() lspd.ChannelOpenerClient + NodeId() []byte + LightningNode() lntest.LightningNode +} + +type ClnLspNode struct { harness *lntest.TestHarness lightningNode *lntest.CoreLightningNode rpc lspd.ChannelOpenerClient - rpcPort uint32 - rpcHost string - privateKey btcec.PrivateKey publicKey btcec.PublicKey postgresBackend *PostgresContainer - scriptDir string } -func NewLspdNode(h *lntest.TestHarness, m *lntest.Miner, name string, timeout time.Time) *LspNode { +func (c *ClnLspNode) Harness() *lntest.TestHarness { + return c.harness +} + +func (c *ClnLspNode) PublicKey() *btcec.PublicKey { + return &c.publicKey +} + +func (c *ClnLspNode) Rpc() lspd.ChannelOpenerClient { + return c.rpc +} + +func (l *ClnLspNode) TearDown() error { + // NOTE: The lightningnode will be torn down on its own. + return l.postgresBackend.Shutdown(l.harness.Ctx) +} + +func (l *ClnLspNode) Cleanup() error { + return l.postgresBackend.Cleanup(l.harness.Ctx) +} + +func (l *ClnLspNode) NodeId() []byte { + return l.lightningNode.NodeId() +} + +func (l *ClnLspNode) LightningNode() lntest.LightningNode { + return l.lightningNode +} + +type LndLspNode struct { + harness *lntest.TestHarness + lightningNode *lntest.LndNode + rpc lspd.ChannelOpenerClient + publicKey btcec.PublicKey + postgresBackend *PostgresContainer + logFile *os.File + lspdCmd *exec.Cmd +} + +func (c *LndLspNode) Harness() *lntest.TestHarness { + return c.harness +} + +func (c *LndLspNode) PublicKey() *btcec.PublicKey { + return &c.publicKey +} + +func (c *LndLspNode) Rpc() lspd.ChannelOpenerClient { + return c.rpc +} + +func (l *LndLspNode) TearDown() error { + // NOTE: The lightningnode will be torn down on its own. + if l.lspdCmd != nil && l.lspdCmd.Process != nil { + err := l.lspdCmd.Process.Kill() + if err != nil { + log.Printf("error stopping lspd process: %v", err) + } + } + + if l.logFile != nil { + err := l.logFile.Close() + if err != nil { + log.Printf("error closing logfile: %v", err) + } + } + + return l.postgresBackend.Shutdown(l.harness.Ctx) +} + +func (l *LndLspNode) Cleanup() error { + return l.postgresBackend.Cleanup(l.harness.Ctx) +} + +func (l *LndLspNode) NodeId() []byte { + return l.lightningNode.NodeId() +} + +func (l *LndLspNode) LightningNode() lntest.LightningNode { + return l.lightningNode +} + +func NewClnLspdNode(h *lntest.TestHarness, m *lntest.Miner, name string, timeout time.Time) LspNode { + scriptFilePath, grpcAddress, publ, postgresBackend := setupLspd(h, name, "RUN_CLN=true") + args := []string{ + fmt.Sprintf("--plugin=%s", scriptFilePath), + fmt.Sprintf("--fee-base=%d", lspBaseFeeMsat), + fmt.Sprintf("--fee-per-satoshi=%d", lspFeeRatePpm), + fmt.Sprintf("--cltv-delta=%d", lspCltvDelta), + } + + lightningNode := lntest.NewCoreLightningNode(h, m, name, timeout, args...) + + conn, err := grpc.Dial( + grpcAddress, + grpc.WithTransportCredentials(insecure.NewCredentials()), + grpc.WithPerRPCCredentials(&token{token: "hello"}), + ) + lntest.CheckError(h.T, err) + + client := lspd.NewChannelOpenerClient(conn) + + lspNode := &ClnLspNode{ + harness: h, + lightningNode: lightningNode, + rpc: client, + publicKey: *publ, + postgresBackend: postgresBackend, + } + + h.AddStoppable(lspNode) + h.AddCleanable(lspNode) + return lspNode +} + +func NewLndLspdNode(h *lntest.TestHarness, m *lntest.Miner, name string, timeout time.Time) LspNode { + args := []string{ + "--protocol.zero-conf", + "--protocol.option-scid-alias", + "--requireinterceptor", + "--bitcoin.defaultchanconfs=0", + "--bitcoin.chanreservescript=\"0\"", + fmt.Sprintf("--bitcoin.basefee=%d", lspBaseFeeMsat), + fmt.Sprintf("--bitcoin.feerate=%d", lspFeeRatePpm), + fmt.Sprintf("--bitcoin.timelockdelta=%d", lspCltvDelta), + } + + lightningNode := lntest.NewLndNode(h, m, name, timeout, args...) + tlsCert := strings.Replace(string(lightningNode.TlsCert()), "\n", "\\n", -1) + scriptFilePath, grpcAddress, publ, postgresBackend := setupLspd(h, name, + "RUN_LND=true", + fmt.Sprintf("LND_CERT=\"%s\"", tlsCert), + fmt.Sprintf("LND_ADDRESS=%s", lightningNode.GrpcHost()), + fmt.Sprintf("LND_MACAROON_HEX=%x", lightningNode.Macaroon()), + ) + scriptDir := filepath.Dir(scriptFilePath) + logFilePath := filepath.Join(scriptDir, "lspd.log") + h.RegisterLogfile(logFilePath, fmt.Sprintf("lspd-%s", name)) + + lspdCmd := exec.CommandContext(h.Ctx, scriptFilePath) + logFile, err := os.Create(logFilePath) + lntest.CheckError(h.T, err) + + lspdCmd.Stdout = logFile + lspdCmd.Stderr = logFile + + log.Printf("%s: starting lspd %s", name, scriptFilePath) + err = lspdCmd.Start() + lntest.CheckError(h.T, err) + + conn, err := grpc.Dial( + grpcAddress, + grpc.WithTransportCredentials(insecure.NewCredentials()), + grpc.WithPerRPCCredentials(&token{token: "hello"}), + ) + lntest.CheckError(h.T, err) + + client := lspd.NewChannelOpenerClient(conn) + + lspNode := &LndLspNode{ + harness: h, + lightningNode: lightningNode, + rpc: client, + publicKey: *publ, + postgresBackend: postgresBackend, + logFile: logFile, + lspdCmd: lspdCmd, + } + + h.AddStoppable(lspNode) + h.AddCleanable(lspNode) + return lspNode +} + +func setupLspd(h *lntest.TestHarness, name string, envExt ...string) (string, string, *secp256k1.PublicKey, *PostgresContainer) { scriptDir := h.GetDirectory(fmt.Sprintf("lspd-%s", name)) - migrationsDir, err := GetMigrationsDir() + log.Printf("%s: Creating LSPD in dir %s", name, scriptDir) + migrationsDir, err := getMigrationsDir() lntest.CheckError(h.T, err) pgLogfile := filepath.Join(scriptDir, "postgres.log") + h.RegisterLogfile(pgLogfile, fmt.Sprintf("%s-postgres", name)) postgresBackend := StartPostgresContainer(h.T, h.Ctx, pgLogfile) postgresBackend.RunMigrations(h.T, h.Ctx, migrationsDir) - lspdBinary, err := GetLspdBinary() + lspdBinary, err := getLspdBinary() lntest.CheckError(h.T, err) lspdPort, err := lntest.GetPort() @@ -65,23 +247,23 @@ func NewLspdNode(h *lntest.TestHarness, m *lntest.Miner, name string, timeout ti lspdPrivateKeyBytes, err := GenerateRandomBytes(32) lntest.CheckError(h.T, err) - priv, publ := btcec.PrivKeyFromBytes(lspdPrivateKeyBytes) - + _, publ := btcec.PrivKeyFromBytes(lspdPrivateKeyBytes) host := "localhost" grpcAddress := fmt.Sprintf("%s:%d", host, lspdPort) env := []string{ "NODE_NAME=lsp", "NODE_PUBKEY=dunno", "NODE_HOST=host:port", - "RUN_CLN=true", "TOKEN=hello", fmt.Sprintf("DATABASE_URL=%s", postgresBackend.ConnectionString()), fmt.Sprintf("LISTEN_ADDRESS=%s", grpcAddress), fmt.Sprintf("LSPD_PRIVATE_KEY=%x", lspdPrivateKeyBytes), } + env = append(env, envExt...) + scriptFilePath := filepath.Join(scriptDir, "start-lspd.sh") - log.Printf("Creating lspd startup script at %s", scriptFilePath) + log.Printf("%s: Creating lspd startup script at %s", name, scriptFilePath) scriptFile, err := os.OpenFile(scriptFilePath, os.O_CREATE|os.O_WRONLY, 0755) lntest.CheckError(h.T, err) @@ -101,73 +283,27 @@ func NewLspdNode(h *lntest.TestHarness, m *lntest.Miner, name string, timeout ti lntest.CheckError(h.T, err) scriptFile.Close() - args := []string{ - fmt.Sprintf("--plugin=%s", scriptFilePath), - fmt.Sprintf("--fee-base=%d", lspBaseFeeMsat), - fmt.Sprintf("--fee-per-satoshi=%d", lspFeeRatePpm), - fmt.Sprintf("--cltv-delta=%d", lspCltvDelta), - } - - lightningNode := lntest.NewCoreLightningNode(h, m, name, timeout, args...) - - conn, err := grpc.Dial( - grpcAddress, - grpc.WithTransportCredentials(insecure.NewCredentials()), - grpc.WithPerRPCCredentials(&token{token: "hello"}), - ) - lntest.CheckError(h.T, err) - - client := lspd.NewChannelOpenerClient(conn) - - lspNode := &LspNode{ - harness: h, - lightningNode: lightningNode, - rpc: client, - rpcPort: lspdPort, - rpcHost: host, - privateKey: *priv, - publicKey: *publ, - postgresBackend: postgresBackend, - scriptDir: scriptDir, - } - - h.AddStoppable(lspNode) - h.AddCleanable(lspNode) - h.RegisterLogfile(pgLogfile, fmt.Sprintf("%s-postgres", name)) - return lspNode + return scriptFilePath, grpcAddress, publ, postgresBackend } -func (l *LspNode) RegisterPayment(paymentInfo *lspd.PaymentInformation) { +func RegisterPayment(l LspNode, paymentInfo *lspd.PaymentInformation) { serialized, err := proto.Marshal(paymentInfo) - lntest.CheckError(l.harness.T, err) + lntest.CheckError(l.Harness().T, err) - encrypted, err := btceclegacy.Encrypt(&l.publicKey, serialized) - lntest.CheckError(l.harness.T, err) + encrypted, err := btceclegacy.Encrypt(l.PublicKey(), serialized) + lntest.CheckError(l.Harness().T, err) log.Printf("Registering payment") - _, err = l.rpc.RegisterPayment( - l.harness.Ctx, + _, err = l.Rpc().RegisterPayment( + l.Harness().Ctx, &lspd.RegisterPaymentRequest{ Blob: encrypted, }, ) - lntest.CheckError(l.harness.T, err) + lntest.CheckError(l.Harness().T, err) } -func (l *LspNode) TearDown() error { - // NOTE: The lightningnode will be torn down on its own. - return l.postgresBackend.Shutdown(l.harness.Ctx) -} - -func (l *LspNode) Cleanup() error { - return l.postgresBackend.Cleanup(l.harness.Ctx) -} - -func (l *LspNode) NodeId() []byte { - return l.lightningNode.NodeId() -} - -func GetLspdBinary() (string, error) { +func getLspdBinary() (string, error) { if lspdExecutable != nil { return *lspdExecutable, nil } @@ -175,7 +311,7 @@ func GetLspdBinary() (string, error) { return exec.LookPath("lspd") } -func GetMigrationsDir() (string, error) { +func getMigrationsDir() (string, error) { if lspdMigrationsDir != nil { return *lspdMigrationsDir, nil } diff --git a/itest/lspd_test.go b/itest/lspd_test.go new file mode 100644 index 0000000..5c0cb7d --- /dev/null +++ b/itest/lspd_test.go @@ -0,0 +1,70 @@ +package itest + +import ( + "fmt" + "log" + "testing" + "time" + + "github.com/breez/lntest" +) + +var defaultTimeout time.Duration = time.Second * 120 + +func TestLspd(t *testing.T) { + testCases := allTestCases + // runTests(t, testCases, "LND-lspd", func(h *lntest.TestHarness, m *lntest.Miner, t time.Time) LspNode { + // return NewLndLspdNode(h, m, "lsp", t) + // }) + + runTests(t, testCases, "CLN-lspd", func(h *lntest.TestHarness, m *lntest.Miner, t time.Time) LspNode { + return NewClnLspdNode(h, m, "lsp", t) + }) +} + +func runTests(t *testing.T, testCases []*testCase, prefix string, lspFunc func(h *lntest.TestHarness, m *lntest.Miner, t time.Time) LspNode) { + for _, testCase := range testCases { + testCase := testCase + t.Run(fmt.Sprintf("%s: %s", prefix, testCase.name), func(t *testing.T) { + runTest(t, testCase, prefix, lspFunc) + }) + } +} + +func runTest(t *testing.T, testCase *testCase, prefix string, lspFunc func(h *lntest.TestHarness, m *lntest.Miner, t time.Time) LspNode) { + log.Printf("%s: Running test case '%s'", prefix, testCase.name) + harness := lntest.NewTestHarness(t) + defer harness.TearDown() + + var dd time.Duration + to := testCase.timeout + if to == dd { + to = defaultTimeout + } + + timeout := time.Now().Add(to) + log.Printf("Using timeout %v", timeout.String()) + log.Printf("Creating miner") + miner := lntest.NewMiner(harness) + log.Printf("Creating lsp") + lsp := lspFunc(harness, miner, timeout) + log.Printf("Run testcase") + testCase.test(harness, lsp, miner, timeout) +} + +type testCase struct { + name string + test func(h *lntest.TestHarness, lsp LspNode, miner *lntest.Miner, timeout time.Time) + timeout time.Duration +} + +var allTestCases = []*testCase{ + { + name: "testOpenZeroConfChannelOnReceive", + test: testOpenZeroConfChannelOnReceive, + }, + { + name: "testOpenZeroConfSingleHtlc", + test: testOpenZeroConfSingleHtlc, + }, +} diff --git a/itest/postgres.go b/itest/postgres.go index 91539e0..1d4fbfd 100644 --- a/itest/postgres.go +++ b/itest/postgres.go @@ -83,6 +83,13 @@ func StartPostgresContainer(t *testing.T, ctx context.Context, logfile string) * err = cli.ContainerStart(ctx, createResp.ID, types.ContainerStartOptions{}) lntest.CheckError(t, err) + ct := &PostgresContainer{ + id: createResp.ID, + password: "pgpassword", + port: port, + cli: cli, + } + HealthCheck: for { inspect, err := cli.ContainerInspect(ctx, createResp.ID) @@ -93,17 +100,18 @@ HealthCheck: case "unhealthy": lntest.CheckError(t, errors.New("container unhealthy")) case "healthy": - break HealthCheck - default: - time.Sleep(500 * time.Millisecond) - } - } + for { + pgxPool, err := pgxpool.Connect(context.Background(), ct.ConnectionString()) + if err == nil { + pgxPool.Close() + break HealthCheck + } - ct := &PostgresContainer{ - id: createResp.ID, - password: "pgpassword", - port: port, - cli: cli, + time.Sleep(50 * time.Millisecond) + } + default: + time.Sleep(200 * time.Millisecond) + } } go ct.monitorLogs(logfile) diff --git a/itest/zero_conf_node.go b/itest/zero_conf_node.go index ef7c1db..e90c7f6 100644 --- a/itest/zero_conf_node.go +++ b/itest/zero_conf_node.go @@ -4,7 +4,6 @@ import ( "bufio" "crypto/sha256" "fmt" - "log" "os" "path/filepath" "time" @@ -108,7 +107,7 @@ type generateInvoicesRequest struct { innerAmountMsat uint64 outerAmountMsat uint64 description string - lsp *LspNode + lsp LspNode } type invoice struct { @@ -116,17 +115,15 @@ type invoice struct { paymentHash []byte paymentSecret []byte paymentPreimage []byte - expiresAt uint64 } func (n *ZeroConfNode) GenerateInvoices(req generateInvoicesRequest) (invoice, invoice) { preimage, err := GenerateRandomBytes(32) lntest.CheckError(n.harness.T, err) - lspNodeId, err := btcec.ParsePubKey(req.lsp.lightningNode.NodeId()) + lspNodeId, err := btcec.ParsePubKey(req.lsp.NodeId()) lntest.CheckError(n.harness.T, err) - log.Printf("Adding bob's invoices") innerInvoice := n.lightningNode.CreateBolt11Invoice(&lntest.CreateInvoiceOptions{ AmountMsat: req.innerAmountMsat, Description: &req.description, @@ -161,14 +158,12 @@ func (n *ZeroConfNode) GenerateInvoices(req generateInvoicesRequest) (invoice, i paymentHash: innerInvoice.PaymentHash, paymentSecret: innerInvoice.PaymentSecret, paymentPreimage: preimage, - expiresAt: innerInvoice.ExpiresAt, } outer := invoice{ bolt11: outerInvoice, paymentHash: outerInvoiceRaw.PaymentHash[:], paymentSecret: innerInvoice.PaymentSecret, paymentPreimage: preimage, - expiresAt: innerInvoice.ExpiresAt, } return inner, outer