mirror of
https://github.com/aljazceru/lspd.git
synced 2026-02-03 05:14:20 +01:00
lsps2: add integration tests
This commit is contained in:
6
.github/workflows/integration_tests.yaml
vendored
6
.github/workflows/integration_tests.yaml
vendored
@@ -145,7 +145,11 @@ jobs:
|
||||
testLsps0GetProtocolVersions,
|
||||
testLsps2GetVersions,
|
||||
testLsps2GetInfo,
|
||||
testLsps2Buy
|
||||
testLsps2Buy,
|
||||
testLsps2HappyFlow,
|
||||
testLsps2Cltv,
|
||||
testLsps2NoBalance,
|
||||
testLsps2ZeroConfUtxo
|
||||
]
|
||||
implementation: [
|
||||
CLN
|
||||
|
||||
@@ -2,10 +2,16 @@ package itest
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"log"
|
||||
"math/rand"
|
||||
"testing"
|
||||
|
||||
"github.com/breez/lntest"
|
||||
"github.com/breez/lspd/lsps0"
|
||||
"github.com/breez/lspd/lsps0/jsonrpc"
|
||||
"github.com/breez/lspd/lsps2"
|
||||
"github.com/btcsuite/btcd/btcec/v2"
|
||||
"github.com/btcsuite/btcd/btcec/v2/ecdsa"
|
||||
"github.com/btcsuite/btcd/chaincfg"
|
||||
@@ -39,6 +45,18 @@ type invoice struct {
|
||||
}
|
||||
|
||||
func GenerateInvoices(n BreezClient, req generateInvoicesRequest) (invoice, invoice) {
|
||||
return generateInvoices(n, req, lntest.ShortChannelID{
|
||||
BlockHeight: 1,
|
||||
TxIndex: 0,
|
||||
OutputIndex: 0,
|
||||
}, lspCltvDelta)
|
||||
}
|
||||
|
||||
func GenerateLsps2Invoices(n BreezClient, req generateInvoicesRequest, scid string) (invoice, invoice) {
|
||||
return generateInvoices(n, req, lntest.NewShortChanIDFromString(scid), lspCltvDelta+2)
|
||||
}
|
||||
|
||||
func generateInvoices(n BreezClient, req generateInvoicesRequest, scid lntest.ShortChannelID, cltvDelta uint16) (invoice, invoice) {
|
||||
preimage, err := GenerateRandomBytes(32)
|
||||
lntest.CheckError(n.Harness().T, err)
|
||||
|
||||
@@ -47,11 +65,7 @@ func GenerateInvoices(n BreezClient, req generateInvoicesRequest) (invoice, invo
|
||||
Description: &req.description,
|
||||
Preimage: &preimage,
|
||||
})
|
||||
outerInvoice := AddHopHint(n, innerInvoice.Bolt11, req.lsp, lntest.ShortChannelID{
|
||||
BlockHeight: 1,
|
||||
TxIndex: 0,
|
||||
OutputIndex: 0,
|
||||
}, &req.outerAmountMsat)
|
||||
outerInvoice := AddHopHint(n, innerInvoice.Bolt11, req.lsp, scid, &req.outerAmountMsat, cltvDelta)
|
||||
|
||||
inner := invoice{
|
||||
bolt11: innerInvoice.Bolt11,
|
||||
@@ -76,7 +90,7 @@ func ContainsHopHint(t *testing.T, invoice string) bool {
|
||||
return len(rawInvoice.RouteHints) > 0
|
||||
}
|
||||
|
||||
func AddHopHint(n BreezClient, invoice string, lsp LspNode, chanid lntest.ShortChannelID, amountMsat *uint64) string {
|
||||
func AddHopHint(n BreezClient, invoice string, lsp LspNode, chanid lntest.ShortChannelID, amountMsat *uint64, cltvDelta uint16) string {
|
||||
rawInvoice, err := zpay32.Decode(invoice, &chaincfg.RegressionNetParams)
|
||||
lntest.CheckError(n.Harness().T, err)
|
||||
|
||||
@@ -93,7 +107,7 @@ func AddHopHint(n BreezClient, invoice string, lsp LspNode, chanid lntest.ShortC
|
||||
ChannelID: chanid.ToUint64(),
|
||||
FeeBaseMSat: lspBaseFeeMsat,
|
||||
FeeProportionalMillionths: lspFeeRatePpm,
|
||||
CLTVExpiryDelta: lspCltvDelta,
|
||||
CLTVExpiryDelta: cltvDelta,
|
||||
},
|
||||
})
|
||||
|
||||
@@ -121,3 +135,67 @@ func AddHopHint(n BreezClient, invoice string, lsp LspNode, chanid lntest.ShortC
|
||||
|
||||
return newInvoice
|
||||
}
|
||||
|
||||
func Lsps2GetInfo(c BreezClient, l LspNode, req lsps2.GetInfoRequest) lsps2.GetInfoResponse {
|
||||
req.Version = lsps2.SupportedVersion
|
||||
r := lsps2RequestResponse(c, l, "lsps2.get_info", req)
|
||||
var resp lsps2.GetInfoResponse
|
||||
err := json.Unmarshal(r, &resp)
|
||||
lntest.CheckError(c.Harness().T, err)
|
||||
|
||||
return resp
|
||||
}
|
||||
|
||||
func Lsps2Buy(c BreezClient, l LspNode, req lsps2.BuyRequest) lsps2.BuyResponse {
|
||||
req.Version = lsps2.SupportedVersion
|
||||
r := lsps2RequestResponse(c, l, "lsps2.buy", req)
|
||||
var resp lsps2.BuyResponse
|
||||
err := json.Unmarshal(r, &resp)
|
||||
lntest.CheckError(c.Harness().T, err)
|
||||
|
||||
return resp
|
||||
}
|
||||
|
||||
func lsps2RequestResponse(c BreezClient, l LspNode, method string, req interface{}) []byte {
|
||||
id := RandStringBytes(32)
|
||||
peerId := hex.EncodeToString(l.NodeId())
|
||||
inner, err := json.Marshal(req)
|
||||
lntest.CheckError(c.Harness().T, err)
|
||||
outer, err := json.Marshal(&jsonrpc.Request{
|
||||
JsonRpc: jsonrpc.Version,
|
||||
Method: method,
|
||||
Id: id,
|
||||
Params: inner,
|
||||
})
|
||||
lntest.CheckError(c.Harness().T, err)
|
||||
|
||||
log.Printf(string(outer))
|
||||
c.Node().SendCustomMessage(&lntest.CustomMsgRequest{
|
||||
PeerId: peerId,
|
||||
Type: lsps0.Lsps0MessageType,
|
||||
Data: outer,
|
||||
})
|
||||
|
||||
m := c.ReceiveCustomMessage()
|
||||
log.Printf(string(m.Data))
|
||||
|
||||
var resp jsonrpc.Response
|
||||
err = json.Unmarshal(m.Data, &resp)
|
||||
lntest.CheckError(c.Harness().T, err)
|
||||
|
||||
if resp.Id != id {
|
||||
c.Harness().T.Fatalf("Received custom message, but had different id")
|
||||
}
|
||||
|
||||
return resp.Result
|
||||
}
|
||||
|
||||
const letterBytes = "abcdefghijklmnopqrstuvwxyz"
|
||||
|
||||
func RandStringBytes(n int) string {
|
||||
b := make([]byte, n)
|
||||
for i := range b {
|
||||
b[i] = letterBytes[rand.Intn(len(letterBytes))]
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
||||
@@ -114,6 +114,8 @@ func newLspd(h *lntest.TestHarness, mem *mempoolApi, name string, nodeConfig *co
|
||||
ChannelMinimumFeeMsat: 2000000,
|
||||
AdditionalChannelCapacity: 100000,
|
||||
MaxInactiveDuration: 3888000,
|
||||
MinPaymentSizeMsat: 600,
|
||||
MaxPaymentSizeMsat: 4000000000,
|
||||
Lnd: lnd,
|
||||
Cln: cln,
|
||||
}
|
||||
|
||||
@@ -18,8 +18,14 @@ func TestLspd(t *testing.T) {
|
||||
return
|
||||
}
|
||||
testCases := allTestCases
|
||||
runTests(t, testCases, "LND-lsp-CLN-client", lndLspFunc, clnClientFunc)
|
||||
runTests(t, testCases, "LND-lsp-LND-client", legacyOnionLndLspFunc, lndClientFunc)
|
||||
var lndTestCases []*testCase
|
||||
for _, c := range testCases {
|
||||
if !c.isLsps2 {
|
||||
lndTestCases = append(lndTestCases, c)
|
||||
}
|
||||
}
|
||||
runTests(t, lndTestCases, "LND-lsp-CLN-client", lndLspFunc, clnClientFunc)
|
||||
runTests(t, lndTestCases, "LND-lsp-LND-client", legacyOnionLndLspFunc, lndClientFunc)
|
||||
runTests(t, testCases, "CLN-lsp-CLN-client", clnLspFunc, clnClientFunc)
|
||||
}
|
||||
|
||||
@@ -117,6 +123,7 @@ type testCase struct {
|
||||
name string
|
||||
test func(t *testParams)
|
||||
skipCreateLsp bool
|
||||
isLsps2 bool
|
||||
timeout time.Duration
|
||||
}
|
||||
|
||||
@@ -179,19 +186,44 @@ var allTestCases = []*testCase{
|
||||
test: testOfflineNotificationZeroConfChannel,
|
||||
},
|
||||
{
|
||||
name: "testLsps0GetProtocolVersions",
|
||||
test: testLsps0GetProtocolVersions,
|
||||
name: "testLsps0GetProtocolVersions",
|
||||
test: testLsps0GetProtocolVersions,
|
||||
isLsps2: true,
|
||||
},
|
||||
{
|
||||
name: "testLsps2GetVersions",
|
||||
test: testLsps2GetVersions,
|
||||
name: "testLsps2GetVersions",
|
||||
test: testLsps2GetVersions,
|
||||
isLsps2: true,
|
||||
},
|
||||
{
|
||||
name: "testLsps2GetInfo",
|
||||
test: testLsps2GetInfo,
|
||||
name: "testLsps2GetInfo",
|
||||
test: testLsps2GetInfo,
|
||||
isLsps2: true,
|
||||
},
|
||||
{
|
||||
name: "testLsps2Buy",
|
||||
test: testLsps2Buy,
|
||||
name: "testLsps2Buy",
|
||||
test: testLsps2Buy,
|
||||
isLsps2: true,
|
||||
},
|
||||
{
|
||||
name: "testLsps2HappyFlow",
|
||||
test: testLsps2HappyFlow,
|
||||
isLsps2: true,
|
||||
},
|
||||
{
|
||||
name: "testLsps2Cltv",
|
||||
test: testLsps2Cltv,
|
||||
isLsps2: true,
|
||||
},
|
||||
{
|
||||
name: "testLsps2NoBalance",
|
||||
test: testLsps2NoBalance,
|
||||
isLsps2: true,
|
||||
},
|
||||
{
|
||||
name: "testLsps2ZeroConfUtxo",
|
||||
test: testLsps2ZeroConfUtxo,
|
||||
isLsps2: true,
|
||||
skipCreateLsp: true,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -7,7 +7,10 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/breez/lntest"
|
||||
"github.com/breez/lspd/lightning"
|
||||
"github.com/breez/lspd/lsps0"
|
||||
"github.com/jackc/pgx/v4/pgxpool"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func testLsps2Buy(p *testParams) {
|
||||
@@ -62,12 +65,12 @@ func testLsps2Buy(p *testParams) {
|
||||
Type: lsps0.Lsps0MessageType,
|
||||
Data: append(append(
|
||||
[]byte(`{
|
||||
"method": "lsps2.get_info",
|
||||
"method": "lsps2.buy",
|
||||
"jsonrpc": "2.0",
|
||||
"id": "example#3cad6a54d302edba4c9ade2f7ffac098",
|
||||
"id": "example#3cad6a54d302edba4c9ade2f7ffac099",
|
||||
"params": {
|
||||
"version": 1,
|
||||
"payment_size_msat": "42000",
|
||||
"payment_size_msat": "42000000",
|
||||
"opening_fee_params":`),
|
||||
pr...),
|
||||
[]byte(`}}`)...,
|
||||
@@ -75,7 +78,7 @@ func testLsps2Buy(p *testParams) {
|
||||
})
|
||||
|
||||
buyResp := p.BreezClient().ReceiveCustomMessage()
|
||||
log.Print(string(resp.Data))
|
||||
log.Print(string(buyResp.Data))
|
||||
b := new(struct {
|
||||
Result struct {
|
||||
Jit_channel_scid string `json:"jit_channel_scid"`
|
||||
@@ -85,4 +88,37 @@ func testLsps2Buy(p *testParams) {
|
||||
})
|
||||
err = json.Unmarshal(buyResp.Data, b)
|
||||
lntest.CheckError(p.t, err)
|
||||
|
||||
pgxPool, err := pgxpool.Connect(p.h.Ctx, p.lsp.PostgresBackend().ConnectionString())
|
||||
if err != nil {
|
||||
p.h.T.Fatalf("Failed to connect to postgres backend: %v", err)
|
||||
}
|
||||
defer pgxPool.Close()
|
||||
|
||||
scid, err := lightning.NewShortChannelIDFromString(b.Result.Jit_channel_scid)
|
||||
lntest.CheckError(p.t, err)
|
||||
|
||||
rows, err := pgxPool.Query(
|
||||
p.h.Ctx,
|
||||
`SELECT token
|
||||
FROM lsps2.buy_registrations
|
||||
WHERE scid = $1`,
|
||||
int64(uint64(*scid)),
|
||||
)
|
||||
if err != nil {
|
||||
p.h.T.Fatalf("Failed to query token: %v", err)
|
||||
}
|
||||
|
||||
defer rows.Close()
|
||||
if !rows.Next() {
|
||||
p.h.T.Fatal("No rows found")
|
||||
}
|
||||
|
||||
var actual string
|
||||
err = rows.Scan(&actual)
|
||||
if err != nil {
|
||||
p.h.T.Fatalf("Failed to get token from row: %v", err)
|
||||
}
|
||||
|
||||
assert.Equal(p.h.T, "hello", actual)
|
||||
}
|
||||
|
||||
63
itest/lsps2_cltv_test.go
Normal file
63
itest/lsps2_cltv_test.go
Normal file
@@ -0,0 +1,63 @@
|
||||
package itest
|
||||
|
||||
import (
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/breez/lntest"
|
||||
"github.com/breez/lspd/lsps2"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func testLsps2Cltv(p *testParams) {
|
||||
alice := lntest.NewClnNode(p.h, p.m, "Alice")
|
||||
alice.Start()
|
||||
alice.Fund(10000000)
|
||||
p.lsp.LightningNode().Fund(10000000)
|
||||
|
||||
log.Print("Opening channel between Alice and the lsp")
|
||||
channel := alice.OpenChannel(p.lsp.LightningNode(), &lntest.OpenChannelOptions{
|
||||
AmountSat: publicChanAmount,
|
||||
})
|
||||
aliceLspScid := alice.WaitForChannelReady(channel)
|
||||
|
||||
log.Print("Connecting bob to lspd")
|
||||
p.BreezClient().Node().ConnectPeer(p.lsp.LightningNode())
|
||||
|
||||
log.Printf("Calling lsps2.get_info")
|
||||
info := Lsps2GetInfo(p.BreezClient(), p.Lsp(), lsps2.GetInfoRequest{
|
||||
Token: &WorkingToken,
|
||||
})
|
||||
|
||||
outerAmountMsat := uint64(2100000)
|
||||
innerAmountMsat := lsps2CalculateInnerAmountMsat(p.lsp, outerAmountMsat, info.OpeningFeeParamsMenu[0])
|
||||
p.BreezClient().SetHtlcAcceptor(innerAmountMsat)
|
||||
|
||||
log.Printf("Calling lsps2.buy")
|
||||
buyResp := Lsps2Buy(p.BreezClient(), p.Lsp(), lsps2.BuyRequest{
|
||||
OpeningFeeParams: *info.OpeningFeeParamsMenu[0],
|
||||
PaymentSizeMsat: &outerAmountMsat,
|
||||
})
|
||||
|
||||
log.Printf("Adding bob's invoices")
|
||||
description := "Please pay me"
|
||||
_, outerInvoice := GenerateLsps2Invoices(p.BreezClient(),
|
||||
generateInvoicesRequest{
|
||||
innerAmountMsat: innerAmountMsat,
|
||||
outerAmountMsat: outerAmountMsat,
|
||||
description: description,
|
||||
lsp: p.lsp,
|
||||
},
|
||||
buyResp.JitChannelScid)
|
||||
|
||||
// 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")
|
||||
route := constructRoute(p.Lsp().LightningNode(), p.BreezClient().Node(), aliceLspScid, lntest.NewShortChanIDFromString(buyResp.JitChannelScid), outerAmountMsat)
|
||||
|
||||
// Increment the delay by one (should be incremented by 2), so the cltv delta is too little.
|
||||
route.Hops[0].Delay++
|
||||
_, err := alice.PayViaRoute(outerAmountMsat, outerInvoice.paymentHash, outerInvoice.paymentSecret, route)
|
||||
assert.Contains(p.t, err.Error(), "WIRE_INCORRECT_CLTV_EXPIRY")
|
||||
}
|
||||
72
itest/lsps2_happy_flow_test.go
Normal file
72
itest/lsps2_happy_flow_test.go
Normal file
@@ -0,0 +1,72 @@
|
||||
package itest
|
||||
|
||||
import (
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/breez/lntest"
|
||||
"github.com/breez/lspd/lsps2"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func testLsps2HappyFlow(p *testParams) {
|
||||
alice := lntest.NewClnNode(p.h, p.m, "Alice")
|
||||
alice.Start()
|
||||
alice.Fund(10000000)
|
||||
p.lsp.LightningNode().Fund(10000000)
|
||||
|
||||
log.Print("Opening channel between Alice and the lsp")
|
||||
channel := alice.OpenChannel(p.lsp.LightningNode(), &lntest.OpenChannelOptions{
|
||||
AmountSat: publicChanAmount,
|
||||
})
|
||||
alice.WaitForChannelReady(channel)
|
||||
|
||||
log.Print("Connecting bob to lspd")
|
||||
p.BreezClient().Node().ConnectPeer(p.lsp.LightningNode())
|
||||
|
||||
log.Printf("Calling lsps2.get_info")
|
||||
info := Lsps2GetInfo(p.BreezClient(), p.Lsp(), lsps2.GetInfoRequest{
|
||||
Token: &WorkingToken,
|
||||
})
|
||||
|
||||
outerAmountMsat := uint64(2100000)
|
||||
innerAmountMsat := lsps2CalculateInnerAmountMsat(p.lsp, outerAmountMsat, info.OpeningFeeParamsMenu[0])
|
||||
p.BreezClient().SetHtlcAcceptor(innerAmountMsat)
|
||||
|
||||
log.Printf("Calling lsps2.buy")
|
||||
buyResp := Lsps2Buy(p.BreezClient(), p.Lsp(), lsps2.BuyRequest{
|
||||
OpeningFeeParams: *info.OpeningFeeParamsMenu[0],
|
||||
PaymentSizeMsat: &outerAmountMsat,
|
||||
})
|
||||
|
||||
log.Printf("Adding bob's invoices")
|
||||
description := "Please pay me"
|
||||
_, outerInvoice := GenerateLsps2Invoices(p.BreezClient(),
|
||||
generateInvoicesRequest{
|
||||
innerAmountMsat: innerAmountMsat,
|
||||
outerAmountMsat: outerAmountMsat,
|
||||
description: description,
|
||||
lsp: p.lsp,
|
||||
},
|
||||
buyResp.JitChannelScid)
|
||||
|
||||
// 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")
|
||||
payResp := alice.Pay(outerInvoice.bolt11)
|
||||
bobInvoice := p.BreezClient().Node().GetInvoice(payResp.PaymentHash)
|
||||
|
||||
assert.Equal(p.t, payResp.PaymentPreimage, bobInvoice.PaymentPreimage)
|
||||
assert.Equal(p.t, innerAmountMsat, bobInvoice.AmountReceivedMsat)
|
||||
|
||||
// Make sure capacity is correct
|
||||
chans := p.BreezClient().Node().GetChannels()
|
||||
assert.Equal(p.t, 1, len(chans))
|
||||
c := chans[0]
|
||||
AssertChannelCapacity(p.t, innerAmountMsat, c.CapacityMsat)
|
||||
|
||||
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)
|
||||
}
|
||||
62
itest/lsps2_no_balance_test.go
Normal file
62
itest/lsps2_no_balance_test.go
Normal file
@@ -0,0 +1,62 @@
|
||||
package itest
|
||||
|
||||
import (
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/breez/lntest"
|
||||
"github.com/breez/lspd/lsps2"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func testLsps2NoBalance(p *testParams) {
|
||||
alice := lntest.NewClnNode(p.h, p.m, "Alice")
|
||||
alice.Start()
|
||||
alice.Fund(10000000)
|
||||
|
||||
log.Print("Opening channel between Alice and the lsp")
|
||||
channel := alice.OpenChannel(p.lsp.LightningNode(), &lntest.OpenChannelOptions{
|
||||
AmountSat: publicChanAmount,
|
||||
})
|
||||
aliceLspScid := alice.WaitForChannelReady(channel)
|
||||
|
||||
log.Print("Connecting bob to lspd")
|
||||
p.BreezClient().Node().ConnectPeer(p.lsp.LightningNode())
|
||||
|
||||
log.Printf("Calling lsps2.get_info")
|
||||
info := Lsps2GetInfo(p.BreezClient(), p.Lsp(), lsps2.GetInfoRequest{
|
||||
Token: &WorkingToken,
|
||||
})
|
||||
|
||||
outerAmountMsat := uint64(2100000)
|
||||
innerAmountMsat := lsps2CalculateInnerAmountMsat(p.lsp, outerAmountMsat, info.OpeningFeeParamsMenu[0])
|
||||
p.BreezClient().SetHtlcAcceptor(innerAmountMsat)
|
||||
|
||||
log.Printf("Calling lsps2.buy")
|
||||
buyResp := Lsps2Buy(p.BreezClient(), p.Lsp(), lsps2.BuyRequest{
|
||||
OpeningFeeParams: *info.OpeningFeeParamsMenu[0],
|
||||
PaymentSizeMsat: &outerAmountMsat,
|
||||
})
|
||||
|
||||
log.Printf("Adding bob's invoices")
|
||||
description := "Please pay me"
|
||||
_, outerInvoice := GenerateLsps2Invoices(p.BreezClient(),
|
||||
generateInvoicesRequest{
|
||||
innerAmountMsat: innerAmountMsat,
|
||||
outerAmountMsat: outerAmountMsat,
|
||||
description: description,
|
||||
lsp: p.lsp,
|
||||
},
|
||||
buyResp.JitChannelScid)
|
||||
|
||||
// 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")
|
||||
route := constructRoute(p.Lsp().LightningNode(), p.BreezClient().Node(), aliceLspScid, lntest.NewShortChanIDFromString(buyResp.JitChannelScid), outerAmountMsat)
|
||||
|
||||
// Increment the delay by two to support the spec
|
||||
route.Hops[0].Delay += 2
|
||||
_, err := alice.PayViaRoute(outerAmountMsat, outerInvoice.paymentHash, outerInvoice.paymentSecret, route)
|
||||
assert.Contains(p.t, err.Error(), "WIRE_TEMPORARY_CHANNEL_FAILURE")
|
||||
}
|
||||
82
itest/lsps2_zero_conf_utxo_test.go
Normal file
82
itest/lsps2_zero_conf_utxo_test.go
Normal file
@@ -0,0 +1,82 @@
|
||||
package itest
|
||||
|
||||
import (
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/breez/lntest"
|
||||
"github.com/breez/lspd/config"
|
||||
"github.com/breez/lspd/lsps2"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func testLsps2ZeroConfUtxo(p *testParams) {
|
||||
alice := lntest.NewClnNode(p.h, p.m, "Alice")
|
||||
alice.Start()
|
||||
alice.Fund(10000000)
|
||||
|
||||
minConfs := uint32(0)
|
||||
lsp := p.lspFunc(p.h, p.m, p.mem, &config.NodeConfig{MinConfs: &minConfs})
|
||||
lsp.Start()
|
||||
|
||||
log.Print("Opening channel between Alice and the lsp")
|
||||
channel := alice.OpenChannel(lsp.LightningNode(), &lntest.OpenChannelOptions{
|
||||
AmountSat: publicChanAmount,
|
||||
})
|
||||
channelId := alice.WaitForChannelReady(channel)
|
||||
|
||||
tempaddr := lsp.LightningNode().GetNewAddress()
|
||||
p.m.SendToAddress(tempaddr, 210000)
|
||||
p.m.MineBlocks(6)
|
||||
lsp.LightningNode().WaitForSync()
|
||||
|
||||
initialHeight := p.m.GetBlockHeight()
|
||||
addr := lsp.LightningNode().GetNewAddress()
|
||||
lsp.LightningNode().SendToAddress(addr, 200000)
|
||||
|
||||
log.Print("Connecting bob to lspd")
|
||||
p.BreezClient().Node().ConnectPeer(lsp.LightningNode())
|
||||
|
||||
log.Printf("Calling lsps2.get_info")
|
||||
info := Lsps2GetInfo(p.BreezClient(), lsp, lsps2.GetInfoRequest{
|
||||
Token: &WorkingToken,
|
||||
})
|
||||
|
||||
outerAmountMsat := uint64(2100000)
|
||||
innerAmountMsat := lsps2CalculateInnerAmountMsat(lsp, outerAmountMsat, info.OpeningFeeParamsMenu[0])
|
||||
p.BreezClient().SetHtlcAcceptor(innerAmountMsat)
|
||||
|
||||
log.Printf("Calling lsps2.buy")
|
||||
buyResp := Lsps2Buy(p.BreezClient(), lsp, lsps2.BuyRequest{
|
||||
OpeningFeeParams: *info.OpeningFeeParamsMenu[0],
|
||||
PaymentSizeMsat: &outerAmountMsat,
|
||||
})
|
||||
|
||||
log.Printf("Adding bob's invoices")
|
||||
description := "Please pay me"
|
||||
_, outerInvoice := GenerateLsps2Invoices(p.BreezClient(),
|
||||
generateInvoicesRequest{
|
||||
innerAmountMsat: innerAmountMsat,
|
||||
outerAmountMsat: outerAmountMsat,
|
||||
description: description,
|
||||
lsp: lsp,
|
||||
},
|
||||
buyResp.JitChannelScid)
|
||||
|
||||
// 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")
|
||||
route := constructRoute(lsp.LightningNode(), p.BreezClient().Node(), channelId, lntest.NewShortChanIDFromString(buyResp.JitChannelScid), outerAmountMsat)
|
||||
route.Hops[0].Delay += 2
|
||||
payResp, err := alice.PayViaRoute(outerAmountMsat, outerInvoice.paymentHash, outerInvoice.paymentSecret, route)
|
||||
lntest.CheckError(p.t, err)
|
||||
bobInvoice := p.BreezClient().Node().GetInvoice(payResp.PaymentHash)
|
||||
|
||||
assert.Equal(p.t, payResp.PaymentPreimage, bobInvoice.PaymentPreimage)
|
||||
assert.Equal(p.t, innerAmountMsat, bobInvoice.AmountReceivedMsat)
|
||||
|
||||
// Make sure there's not accidently a block mined in between
|
||||
finalHeight := p.m.GetBlockHeight()
|
||||
assert.Equal(p.t, initialHeight, finalHeight)
|
||||
}
|
||||
@@ -270,7 +270,7 @@ func testOfflineNotificationZeroConfChannel(p *testParams) {
|
||||
} else {
|
||||
id = chans[0].ShortChannelID
|
||||
}
|
||||
invoiceWithHint = AddHopHint(p.BreezClient(), bobInvoice.Bolt11, p.Lsp(), id, nil)
|
||||
invoiceWithHint = AddHopHint(p.BreezClient(), bobInvoice.Bolt11, p.Lsp(), id, nil, lspCltvDelta)
|
||||
}
|
||||
|
||||
log.Printf("Invoice with hint: %s", invoiceWithHint)
|
||||
|
||||
@@ -5,10 +5,13 @@ import (
|
||||
"log"
|
||||
"testing"
|
||||
|
||||
"github.com/breez/lspd/lsps2"
|
||||
lspd "github.com/breez/lspd/rpc"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
var WorkingToken = "hello"
|
||||
|
||||
func GenerateRandomBytes(n int) ([]byte, error) {
|
||||
b := make([]byte, n)
|
||||
_, err := rand.Read(b)
|
||||
@@ -51,4 +54,14 @@ func calculateInnerAmountMsat(lsp LspNode, outerAmountMsat uint64, params *lspd.
|
||||
return outerAmountMsat - fee
|
||||
}
|
||||
|
||||
func lsps2CalculateInnerAmountMsat(lsp LspNode, outerAmountMsat uint64, params *lsps2.OpeningFeeParams) uint64 {
|
||||
fee := (outerAmountMsat*uint64(params.Proportional) + 999_999) / 1_000_000
|
||||
if fee < params.MinFeeMsat {
|
||||
fee = params.MinFeeMsat
|
||||
}
|
||||
|
||||
log.Printf("outer: %v, fee: %v", outerAmountMsat, fee)
|
||||
return outerAmountMsat - fee
|
||||
}
|
||||
|
||||
var publicChanAmount uint64 = 1000183
|
||||
|
||||
Reference in New Issue
Block a user