make LND tests work

This commit is contained in:
Jesse de Wit
2022-12-16 10:32:30 +01:00
parent 4b6eaf3773
commit 08f2f73b5d
7 changed files with 99 additions and 24 deletions

2
go.mod
View File

@@ -4,7 +4,7 @@ go 1.19
require ( require (
github.com/aws/aws-sdk-go v1.30.20 github.com/aws/aws-sdk-go v1.30.20
github.com/breez/lntest v0.0.9 github.com/breez/lntest v0.0.10
github.com/btcsuite/btcd v0.23.3 github.com/btcsuite/btcd v0.23.3
github.com/btcsuite/btcd/btcec/v2 v2.2.1 github.com/btcsuite/btcd/btcec/v2 v2.2.1
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1

View File

@@ -3,11 +3,13 @@ package itest
import ( import (
"bufio" "bufio"
"crypto/sha256" "crypto/sha256"
"flag"
"fmt" "fmt"
"os" "os"
"path/filepath" "path/filepath"
"github.com/breez/lntest" "github.com/breez/lntest"
"github.com/breez/lntest/lnd"
"github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btcd/btcec/v2/ecdsa" "github.com/btcsuite/btcd/btcec/v2/ecdsa"
"github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg"
@@ -77,7 +79,7 @@ func newClnBreezClient(h *lntest.TestHarness, m *lntest.Miner, name string) *bre
lntest.CheckError(h.T, err) lntest.CheckError(h.T, err)
pluginFile.Close() pluginFile.Close()
node := lntest.NewCoreLightningNode( node := lntest.NewClnNode(
h, h,
m, m,
name, name,
@@ -99,8 +101,19 @@ func newClnBreezClient(h *lntest.TestHarness, m *lntest.Miner, name string) *bre
} }
} }
var lndMobileExecutable = flag.String(
"lndmobileexec", "", "full path to lnd mobile binary",
)
func newLndBreezClient(h *lntest.TestHarness, m *lntest.Miner, name string) *breezClient { func newLndBreezClient(h *lntest.TestHarness, m *lntest.Miner, name string) *breezClient {
lnd := lntest.NewLndNode(h, m, name) lnd := lntest.NewLndNodeFromBinary(h, m, name, *lndMobileExecutable,
"--protocol.zero-conf",
"--protocol.option-scid-alias",
"--bitcoin.defaultchanconfs=0",
)
go startChannelAcceptor(h, lnd)
return &breezClient{ return &breezClient{
name: name, name: name,
harness: h, harness: h,
@@ -108,6 +121,31 @@ func newLndBreezClient(h *lntest.TestHarness, m *lntest.Miner, name string) *bre
} }
} }
func startChannelAcceptor(h *lntest.TestHarness, n *lntest.LndNode) error {
client, err := n.LightningClient().ChannelAcceptor(h.Ctx)
lntest.CheckError(h.T, err)
for {
request, err := client.Recv()
if err != nil {
return err
}
private := request.ChannelFlags&uint32(lnwire.FFAnnounceChannel) == 0
resp := &lnd.ChannelAcceptResponse{
PendingChanId: request.PendingChanId,
Accept: private,
}
if request.WantsZeroConf {
resp.MinAcceptDepth = 0
resp.ZeroConf = true
}
err = client.Send(resp)
lntest.CheckError(h.T, err)
}
}
type generateInvoicesRequest struct { type generateInvoicesRequest struct {
innerAmountMsat uint64 innerAmountMsat uint64
outerAmountMsat uint64 outerAmountMsat uint64

View File

@@ -2,26 +2,29 @@ package itest
import ( import (
"log" "log"
"time"
"github.com/breez/lntest" "github.com/breez/lntest"
lspd "github.com/breez/lspd/rpc" lspd "github.com/breez/lspd/rpc"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
var htlcInterceptorDelay = time.Second * 7
func testOpenZeroConfChannelOnReceive(p *testParams) { func testOpenZeroConfChannelOnReceive(p *testParams) {
alice := lntest.NewCoreLightningNode(p.h, p.m, "Alice") alice := lntest.NewClnNode(p.h, p.m, "Alice")
alice.Fund(10000000) alice.Fund(10000000)
p.lsp.LightningNode().Fund(10000000) p.lsp.LightningNode().Fund(10000000)
log.Print("Opening channel between Alice and the lsp") log.Print("Opening channel between Alice and the lsp")
channel := alice.OpenChannel(p.lsp.LightningNode(), &lntest.OpenChannelOptions{ channel := alice.OpenChannel(p.lsp.LightningNode(), &lntest.OpenChannelOptions{
AmountSat: 1000000, AmountSat: publicChanAmount,
}) })
alice.WaitForChannelReady(channel) alice.WaitForChannelReady(channel)
log.Printf("Adding bob's invoices") log.Printf("Adding bob's invoices")
outerAmountMsat := uint64(2100000) outerAmountMsat := uint64(2100000)
innerAmountMsat := uint64(2100000) innerAmountMsat := calculateInnerAmountMsat(p.lsp, outerAmountMsat)
description := "Please pay me" description := "Please pay me"
innerInvoice, outerInvoice := p.BreezClient().GenerateInvoices(generateInvoicesRequest{ innerInvoice, outerInvoice := p.BreezClient().GenerateInvoices(generateInvoicesRequest{
innerAmountMsat: innerAmountMsat, innerAmountMsat: innerAmountMsat,
@@ -44,12 +47,15 @@ func testOpenZeroConfChannelOnReceive(p *testParams) {
OutgoingAmountMsat: int64(pretendAmount), OutgoingAmountMsat: int64(pretendAmount),
}) })
// TODO: Fix race waiting for htlc interceptor.
log.Printf("Waiting %v to allow htlc interceptor to activate.", htlcInterceptorDelay)
<-time.After(htlcInterceptorDelay)
log.Printf("Alice paying") log.Printf("Alice paying")
payResp := alice.Pay(outerInvoice.bolt11) payResp := alice.Pay(outerInvoice.bolt11)
bobInvoice := p.BreezClient().lightningNode.GetInvoice(payResp.PaymentHash) bobInvoice := p.BreezClient().lightningNode.GetInvoice(payResp.PaymentHash)
assert.Equal(p.t, payResp.PaymentPreimage, bobInvoice.PaymentPreimage) assert.Equal(p.t, payResp.PaymentPreimage, bobInvoice.PaymentPreimage)
assert.Equal(p.t, outerAmountMsat, bobInvoice.AmountReceivedMsat) assert.Equal(p.t, innerAmountMsat, bobInvoice.AmountReceivedMsat)
// Make sure capacity is correct // Make sure capacity is correct
chans := p.BreezClient().lightningNode.GetChannels() chans := p.BreezClient().lightningNode.GetChannels()
@@ -59,20 +65,20 @@ func testOpenZeroConfChannelOnReceive(p *testParams) {
} }
func testOpenZeroConfSingleHtlc(p *testParams) { func testOpenZeroConfSingleHtlc(p *testParams) {
alice := lntest.NewCoreLightningNode(p.h, p.m, "Alice") alice := lntest.NewClnNode(p.h, p.m, "Alice")
alice.Fund(10000000) alice.Fund(10000000)
p.lsp.LightningNode().Fund(10000000) p.lsp.LightningNode().Fund(10000000)
log.Print("Opening channel between Alice and the lsp") log.Print("Opening channel between Alice and the lsp")
channel := alice.OpenChannel(p.lsp.LightningNode(), &lntest.OpenChannelOptions{ channel := alice.OpenChannel(p.lsp.LightningNode(), &lntest.OpenChannelOptions{
AmountSat: 1000000, AmountSat: publicChanAmount,
}) })
channelId := alice.WaitForChannelReady(channel) channelId := alice.WaitForChannelReady(channel)
log.Printf("Adding bob's invoices") log.Printf("Adding bob's invoices")
outerAmountMsat := uint64(2100000) outerAmountMsat := uint64(2100000)
innerAmountMsat := uint64(2100000) innerAmountMsat := calculateInnerAmountMsat(p.lsp, outerAmountMsat)
description := "Please pay me" description := "Please pay me"
innerInvoice, outerInvoice := p.BreezClient().GenerateInvoices(generateInvoicesRequest{ innerInvoice, outerInvoice := p.BreezClient().GenerateInvoices(generateInvoicesRequest{
innerAmountMsat: innerAmountMsat, innerAmountMsat: innerAmountMsat,
@@ -95,13 +101,16 @@ func testOpenZeroConfSingleHtlc(p *testParams) {
OutgoingAmountMsat: int64(pretendAmount), OutgoingAmountMsat: int64(pretendAmount),
}) })
// TODO: Fix race waiting for htlc interceptor.
log.Printf("Waiting %v to allow htlc interceptor to activate.", htlcInterceptorDelay)
<-time.After(htlcInterceptorDelay)
log.Printf("Alice paying") log.Printf("Alice paying")
route := constructRoute(p.lsp.LightningNode(), p.BreezClient().lightningNode, channelId, lntest.NewShortChanIDFromString("1x0x0"), outerAmountMsat) route := constructRoute(p.lsp.LightningNode(), p.BreezClient().lightningNode, channelId, lntest.NewShortChanIDFromString("1x0x0"), outerAmountMsat)
payResp := alice.PayViaRoute(outerAmountMsat, outerInvoice.paymentHash, outerInvoice.paymentSecret, route) payResp := alice.PayViaRoute(outerAmountMsat, outerInvoice.paymentHash, outerInvoice.paymentSecret, route)
bobInvoice := p.BreezClient().lightningNode.GetInvoice(payResp.PaymentHash) bobInvoice := p.BreezClient().lightningNode.GetInvoice(payResp.PaymentHash)
assert.Equal(p.t, payResp.PaymentPreimage, bobInvoice.PaymentPreimage) assert.Equal(p.t, payResp.PaymentPreimage, bobInvoice.PaymentPreimage)
assert.Equal(p.t, outerAmountMsat, bobInvoice.AmountReceivedMsat) assert.Equal(p.t, innerAmountMsat, bobInvoice.AmountReceivedMsat)
// Make sure capacity is correct // Make sure capacity is correct
chans := p.BreezClient().lightningNode.GetChannels() chans := p.BreezClient().lightningNode.GetChannels()

View File

@@ -43,11 +43,12 @@ type LspNode interface {
Rpc() lspd.ChannelOpenerClient Rpc() lspd.ChannelOpenerClient
NodeId() []byte NodeId() []byte
LightningNode() lntest.LightningNode LightningNode() lntest.LightningNode
SupportsChargingFees() bool
} }
type ClnLspNode struct { type ClnLspNode struct {
harness *lntest.TestHarness harness *lntest.TestHarness
lightningNode *lntest.CoreLightningNode lightningNode *lntest.ClnNode
rpc lspd.ChannelOpenerClient rpc lspd.ChannelOpenerClient
publicKey btcec.PublicKey publicKey btcec.PublicKey
eciesPublicKey ecies.PublicKey eciesPublicKey ecies.PublicKey
@@ -72,11 +73,11 @@ func (c *ClnLspNode) Rpc() lspd.ChannelOpenerClient {
func (l *ClnLspNode) TearDown() error { func (l *ClnLspNode) TearDown() error {
// NOTE: The lightningnode will be torn down on its own. // NOTE: The lightningnode will be torn down on its own.
return l.postgresBackend.Shutdown(l.harness.Ctx) return l.postgresBackend.Shutdown(context.Background())
} }
func (l *ClnLspNode) Cleanup() error { func (l *ClnLspNode) Cleanup() error {
return l.postgresBackend.Cleanup(l.harness.Ctx) return l.postgresBackend.Cleanup(context.Background())
} }
func (l *ClnLspNode) NodeId() []byte { func (l *ClnLspNode) NodeId() []byte {
@@ -87,6 +88,10 @@ func (l *ClnLspNode) LightningNode() lntest.LightningNode {
return l.lightningNode return l.lightningNode
} }
func (l *ClnLspNode) SupportsChargingFees() bool {
return false
}
type LndLspNode struct { type LndLspNode struct {
harness *lntest.TestHarness harness *lntest.TestHarness
lightningNode *lntest.LndNode lightningNode *lntest.LndNode
@@ -113,6 +118,9 @@ func (c *LndLspNode) EciesPublicKey() *ecies.PublicKey {
func (c *LndLspNode) Rpc() lspd.ChannelOpenerClient { func (c *LndLspNode) Rpc() lspd.ChannelOpenerClient {
return c.rpc return c.rpc
} }
func (l *LndLspNode) SupportsChargingFees() bool {
return true
}
func (l *LndLspNode) TearDown() error { func (l *LndLspNode) TearDown() error {
// NOTE: The lightningnode will be torn down on its own. // NOTE: The lightningnode will be torn down on its own.
@@ -130,11 +138,11 @@ func (l *LndLspNode) TearDown() error {
} }
} }
return l.postgresBackend.Shutdown(l.harness.Ctx) return l.postgresBackend.Shutdown(context.Background())
} }
func (l *LndLspNode) Cleanup() error { func (l *LndLspNode) Cleanup() error {
return l.postgresBackend.Cleanup(l.harness.Ctx) return l.postgresBackend.Cleanup(context.Background())
} }
func (l *LndLspNode) NodeId() []byte { func (l *LndLspNode) NodeId() []byte {
@@ -156,7 +164,7 @@ func NewClnLspdNode(h *lntest.TestHarness, m *lntest.Miner, name string) LspNode
"--dev-allowdustreserve=true", "--dev-allowdustreserve=true",
} }
lightningNode := lntest.NewCoreLightningNode(h, m, name, args...) lightningNode := lntest.NewClnNode(h, m, name, args...)
conn, err := grpc.Dial( conn, err := grpc.Dial(
grpcAddress, grpcAddress,
@@ -187,7 +195,7 @@ func NewLndLspdNode(h *lntest.TestHarness, m *lntest.Miner, name string) LspNode
"--protocol.option-scid-alias", "--protocol.option-scid-alias",
"--requireinterceptor", "--requireinterceptor",
"--bitcoin.defaultchanconfs=0", "--bitcoin.defaultchanconfs=0",
"--bitcoin.chanreservescript=\"0\"", fmt.Sprintf("--bitcoin.chanreservescript=\"0 if (chanAmt != %d) else chanAmt/100\"", publicChanAmount),
fmt.Sprintf("--bitcoin.basefee=%d", lspBaseFeeMsat), fmt.Sprintf("--bitcoin.basefee=%d", lspBaseFeeMsat),
fmt.Sprintf("--bitcoin.feerate=%d", lspFeeRatePpm), fmt.Sprintf("--bitcoin.feerate=%d", lspFeeRatePpm),
fmt.Sprintf("--bitcoin.timelockdelta=%d", lspCltvDelta), fmt.Sprintf("--bitcoin.timelockdelta=%d", lspCltvDelta),

View File

@@ -13,9 +13,9 @@ var defaultTimeout time.Duration = time.Second * 120
func TestLspd(t *testing.T) { func TestLspd(t *testing.T) {
testCases := allTestCases testCases := allTestCases
// runTests(t, testCases, "LND-lspd", func(h *lntest.TestHarness, m *lntest.Miner) (LspNode, *breezClient) { runTests(t, testCases, "LND-lspd", func(h *lntest.TestHarness, m *lntest.Miner) (LspNode, *breezClient) {
// return NewLndLspdNode(h, m, "lsp"), newLndBreezClient(h, m, "breez-client") return NewLndLspdNode(h, m, "lsp"), newLndBreezClient(h, m, "breez-client")
// }) })
runTests(t, testCases, "CLN-lspd", func(h *lntest.TestHarness, m *lntest.Miner) (LspNode, *breezClient) { runTests(t, testCases, "CLN-lspd", func(h *lntest.TestHarness, m *lntest.Miner) (LspNode, *breezClient) {
return NewClnLspdNode(h, m, "lsp"), newClnBreezClient(h, m, "breez-client") return NewClnLspdNode(h, m, "lsp"), newClnBreezClient(h, m, "breez-client")

View File

@@ -25,3 +25,18 @@ func AssertChannelCapacity(
) { ) {
assert.Equal(t, ((outerAmountMsat/1000)+100000)*1000, capacityMsat) assert.Equal(t, ((outerAmountMsat/1000)+100000)*1000, capacityMsat)
} }
func calculateInnerAmountMsat(lsp LspNode, outerAmountMsat uint64) uint64 {
if lsp.SupportsChargingFees() {
fee := outerAmountMsat * 40 / 10_000 / 1_000 * 1_000
if fee < 2000000 {
fee = 2000000
}
return outerAmountMsat - fee
} else {
return outerAmountMsat
}
}
var publicChanAmount uint64 = 1000183

View File

@@ -2,6 +2,7 @@ package itest
import ( import (
"log" "log"
"time"
"github.com/breez/lntest" "github.com/breez/lntest"
lspd "github.com/breez/lspd/rpc" lspd "github.com/breez/lspd/rpc"
@@ -9,19 +10,19 @@ import (
) )
func testZeroReserve(p *testParams) { func testZeroReserve(p *testParams) {
alice := lntest.NewCoreLightningNode(p.h, p.m, "Alice") alice := lntest.NewClnNode(p.h, p.m, "Alice")
alice.Fund(10000000) alice.Fund(10000000)
p.lsp.LightningNode().Fund(10000000) p.lsp.LightningNode().Fund(10000000)
log.Print("Opening channel between Alice and the lsp") log.Print("Opening channel between Alice and the lsp")
channel := alice.OpenChannel(p.lsp.LightningNode(), &lntest.OpenChannelOptions{ channel := alice.OpenChannel(p.lsp.LightningNode(), &lntest.OpenChannelOptions{
AmountSat: 1000000, AmountSat: publicChanAmount,
}) })
channelId := alice.WaitForChannelReady(channel) channelId := alice.WaitForChannelReady(channel)
log.Printf("Adding bob's invoices") log.Printf("Adding bob's invoices")
outerAmountMsat := uint64(2100000) outerAmountMsat := uint64(2100000)
innerAmountMsat := uint64(2100000) innerAmountMsat := calculateInnerAmountMsat(p.lsp, outerAmountMsat)
description := "Please pay me" description := "Please pay me"
innerInvoice, outerInvoice := p.BreezClient().GenerateInvoices(generateInvoicesRequest{ innerInvoice, outerInvoice := p.BreezClient().GenerateInvoices(generateInvoicesRequest{
innerAmountMsat: innerAmountMsat, innerAmountMsat: innerAmountMsat,
@@ -44,6 +45,9 @@ func testZeroReserve(p *testParams) {
OutgoingAmountMsat: int64(pretendAmount), OutgoingAmountMsat: int64(pretendAmount),
}) })
// TODO: Fix race waiting for htlc interceptor.
log.Printf("Waiting %v to allow htlc interceptor to activate.", htlcInterceptorDelay)
<-time.After(htlcInterceptorDelay)
log.Printf("Alice paying") log.Printf("Alice paying")
route := constructRoute(p.lsp.LightningNode(), p.BreezClient().lightningNode, channelId, lntest.NewShortChanIDFromString("1x0x0"), outerAmountMsat) route := constructRoute(p.lsp.LightningNode(), p.BreezClient().lightningNode, channelId, lntest.NewShortChanIDFromString("1x0x0"), outerAmountMsat)
alice.PayViaRoute(outerAmountMsat, outerInvoice.paymentHash, outerInvoice.paymentSecret, route) alice.PayViaRoute(outerAmountMsat, outerInvoice.paymentHash, outerInvoice.paymentSecret, route)
@@ -54,5 +58,6 @@ func testZeroReserve(p *testParams) {
c := chans[0] c := chans[0]
assert.Equal(p.t, c.RemoteReserveMsat, c.CapacityMsat/100) assert.Equal(p.t, c.RemoteReserveMsat, c.CapacityMsat/100)
log.Printf("local reserve: %d, remote reserve: %d", c.LocalReserveMsat, c.RemoteReserveMsat)
assert.Zero(p.t, c.LocalReserveMsat) assert.Zero(p.t, c.LocalReserveMsat)
} }