itest: refactor testSingleHopInvoice
This commit is contained in:
3 files changed
+66
-164
No files matched your search
@@ -361,4 +361,8 @@ var allTestCasesTemp = []*lntemp.TestCase{
|
|||||||
Name: "stateless init",
|
Name: "stateless init",
|
||||||
TestFunc: testStatelessInit,
|
TestFunc: testStatelessInit,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: "single hop invoice",
|
||||||
|
TestFunc: testSingleHopInvoice,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
@@ -2,35 +2,34 @@ package itest
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/btcutil"
|
"github.com/btcsuite/btcd/btcutil"
|
||||||
"github.com/davecgh/go-spew/spew"
|
|
||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
||||||
"github.com/lightningnetwork/lnd/lntest"
|
"github.com/lightningnetwork/lnd/lntemp"
|
||||||
"github.com/lightningnetwork/lnd/lntest/wait"
|
|
||||||
"github.com/lightningnetwork/lnd/lntypes"
|
"github.com/lightningnetwork/lnd/lntypes"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
"github.com/lightningnetwork/lnd/record"
|
"github.com/lightningnetwork/lnd/record"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func testSingleHopInvoice(net *lntest.NetworkHarness, t *harnessTest) {
|
func testSingleHopInvoice(ht *lntemp.HarnessTest) {
|
||||||
ctxb := context.Background()
|
// Open a channel with 100k satoshis between Alice and Bob with Alice
|
||||||
|
// being the sole funder of the channel.
|
||||||
// Open a channel with 100k satoshis between Alice and Bob with Alice being
|
|
||||||
// the sole funder of the channel.
|
|
||||||
chanAmt := btcutil.Amount(100000)
|
chanAmt := btcutil.Amount(100000)
|
||||||
chanPoint := openChannelAndAssert(
|
alice, bob := ht.Alice, ht.Bob
|
||||||
t, net, net.Alice, net.Bob,
|
cp := ht.OpenChannel(
|
||||||
lntest.OpenChannelParams{
|
alice, bob, lntemp.OpenChannelParams{Amt: chanAmt},
|
||||||
Amt: chanAmt,
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// assertAmountPaid is a helper closure that asserts the amount paid by
|
||||||
|
// Alice and received by Bob are expected.
|
||||||
|
assertAmountPaid := func(expected int64) {
|
||||||
|
ht.AssertAmountPaid("alice -> bob", alice, cp, expected, 0)
|
||||||
|
ht.AssertAmountPaid("bob <- alice", bob, cp, 0, expected)
|
||||||
|
}
|
||||||
|
|
||||||
// Now that the channel is open, create an invoice for Bob which
|
// Now that the channel is open, create an invoice for Bob which
|
||||||
// expects a payment of 1000 satoshis from Alice paid via a particular
|
// expects a payment of 1000 satoshis from Alice paid via a particular
|
||||||
// preimage.
|
// preimage.
|
||||||
@@ -41,61 +40,20 @@ func testSingleHopInvoice(net *lntest.NetworkHarness, t *harnessTest) {
|
|||||||
RPreimage: preimage,
|
RPreimage: preimage,
|
||||||
Value: paymentAmt,
|
Value: paymentAmt,
|
||||||
}
|
}
|
||||||
invoiceResp, err := net.Bob.AddInvoice(ctxb, invoice)
|
invoiceResp := bob.RPC.AddInvoice(invoice)
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unable to add invoice: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait for Alice to recognize and advertise the new channel generated
|
|
||||||
// above.
|
|
||||||
err = net.Alice.WaitForNetworkChannelOpen(chanPoint)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("alice didn't advertise channel before "+
|
|
||||||
"timeout: %v", err)
|
|
||||||
}
|
|
||||||
err = net.Bob.WaitForNetworkChannelOpen(chanPoint)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("bob didn't advertise channel before "+
|
|
||||||
"timeout: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// With the invoice for Bob added, send a payment towards Alice paying
|
// With the invoice for Bob added, send a payment towards Alice paying
|
||||||
// to the above generated invoice.
|
// to the above generated invoice.
|
||||||
resp := sendAndAssertSuccess(
|
ht.CompletePaymentRequests(alice, []string{invoiceResp.PaymentRequest})
|
||||||
t, net.Alice, &routerrpc.SendPaymentRequest{
|
|
||||||
PaymentRequest: invoiceResp.PaymentRequest,
|
|
||||||
TimeoutSeconds: 60,
|
|
||||||
FeeLimitMsat: noFeeLimitMsat,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
if hex.EncodeToString(preimage) != resp.PaymentPreimage {
|
|
||||||
t.Fatalf("preimage mismatch: expected %v, got %v", preimage,
|
|
||||||
resp.PaymentPreimage)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bob's invoice should now be found and marked as settled.
|
// Bob's invoice should now be found and marked as settled.
|
||||||
payHash := &lnrpc.PaymentHash{
|
dbInvoice := bob.RPC.LookupInvoice(invoiceResp.RHash)
|
||||||
RHash: invoiceResp.RHash,
|
require.Equal(ht, lnrpc.Invoice_SETTLED, dbInvoice.State,
|
||||||
}
|
"bob's invoice should be marked as settled")
|
||||||
ctxt, _ := context.WithTimeout(ctxb, defaultTimeout)
|
|
||||||
dbInvoice, err := net.Bob.LookupInvoice(ctxt, payHash)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unable to lookup invoice: %v", err)
|
|
||||||
}
|
|
||||||
if !dbInvoice.Settled { // nolint:staticcheck
|
|
||||||
t.Fatalf("bob's invoice should be marked as settled: %v",
|
|
||||||
spew.Sdump(dbInvoice))
|
|
||||||
}
|
|
||||||
|
|
||||||
// With the payment completed all balance related stats should be
|
// With the payment completed all balance related stats should be
|
||||||
// properly updated.
|
// properly updated.
|
||||||
err = wait.NoError(
|
assertAmountPaid(paymentAmt)
|
||||||
assertAmountSent(paymentAmt, net.Alice, net.Bob),
|
|
||||||
3*time.Second,
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf(err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create another invoice for Bob, this time leaving off the preimage
|
// Create another invoice for Bob, this time leaving off the preimage
|
||||||
// to one will be randomly generated. We'll test the proper
|
// to one will be randomly generated. We'll test the proper
|
||||||
@@ -104,92 +62,58 @@ func testSingleHopInvoice(net *lntest.NetworkHarness, t *harnessTest) {
|
|||||||
Memo: "test3",
|
Memo: "test3",
|
||||||
Value: paymentAmt,
|
Value: paymentAmt,
|
||||||
}
|
}
|
||||||
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
|
invoiceResp = bob.RPC.AddInvoice(invoice)
|
||||||
invoiceResp, err = net.Bob.AddInvoice(ctxt, invoice)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unable to add invoice: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Next send another payment, but this time using a zpay32 encoded
|
// Next send another payment, but this time using a zpay32 encoded
|
||||||
// invoice rather than manually specifying the payment details.
|
// invoice rather than manually specifying the payment details.
|
||||||
sendAndAssertSuccess(
|
ht.CompletePaymentRequests(alice, []string{invoiceResp.PaymentRequest})
|
||||||
t, net.Alice, &routerrpc.SendPaymentRequest{
|
|
||||||
PaymentRequest: invoiceResp.PaymentRequest,
|
|
||||||
TimeoutSeconds: 60,
|
|
||||||
FeeLimitMsat: noFeeLimitMsat,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
// The second payment should also have succeeded, with the balances
|
// The second payment should also have succeeded, with the balances
|
||||||
// being update accordingly.
|
// being update accordingly.
|
||||||
err = wait.NoError(
|
assertAmountPaid(paymentAmt * 2)
|
||||||
assertAmountSent(2*paymentAmt, net.Alice, net.Bob),
|
|
||||||
3*time.Second,
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf(err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Next send a keysend payment.
|
// Next send a keysend payment.
|
||||||
keySendPreimage := lntypes.Preimage{3, 4, 5, 11}
|
keySendPreimage := lntypes.Preimage{3, 4, 5, 11}
|
||||||
keySendHash := keySendPreimage.Hash()
|
keySendHash := keySendPreimage.Hash()
|
||||||
|
|
||||||
sendAndAssertSuccess(
|
req := &routerrpc.SendPaymentRequest{
|
||||||
t, net.Alice, &routerrpc.SendPaymentRequest{
|
Dest: bob.PubKey[:],
|
||||||
Dest: net.Bob.PubKey[:],
|
Amt: paymentAmt,
|
||||||
Amt: paymentAmt,
|
FinalCltvDelta: 40,
|
||||||
FinalCltvDelta: 40,
|
PaymentHash: keySendHash[:],
|
||||||
PaymentHash: keySendHash[:],
|
DestCustomRecords: map[uint64][]byte{
|
||||||
DestCustomRecords: map[uint64][]byte{
|
record.KeySendType: keySendPreimage[:],
|
||||||
record.KeySendType: keySendPreimage[:],
|
|
||||||
},
|
|
||||||
TimeoutSeconds: 60,
|
|
||||||
FeeLimitMsat: noFeeLimitMsat,
|
|
||||||
},
|
},
|
||||||
)
|
TimeoutSeconds: 60,
|
||||||
|
FeeLimitMsat: noFeeLimitMsat,
|
||||||
|
}
|
||||||
|
ht.SendPaymentAssertSettled(alice, req)
|
||||||
|
|
||||||
// The keysend payment should also have succeeded, with the balances
|
// The keysend payment should also have succeeded, with the balances
|
||||||
// being update accordingly.
|
// being update accordingly.
|
||||||
err = wait.NoError(
|
assertAmountPaid(paymentAmt * 3)
|
||||||
assertAmountSent(3*paymentAmt, net.Alice, net.Bob),
|
|
||||||
3*time.Second,
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf(err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Assert that the invoice has the proper AMP fields set, since the
|
// Assert that the invoice has the proper AMP fields set, since the
|
||||||
// legacy keysend payment should have been promoted into an AMP payment
|
// legacy keysend payment should have been promoted into an AMP payment
|
||||||
// internally.
|
// internally.
|
||||||
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
|
keysendInvoice := bob.RPC.LookupInvoice(keySendHash[:])
|
||||||
keysendInvoice, err := net.Bob.LookupInvoice(
|
require.Len(ht, keysendInvoice.Htlcs, 1)
|
||||||
ctxt, &lnrpc.PaymentHash{
|
|
||||||
RHash: keySendHash[:],
|
|
||||||
},
|
|
||||||
)
|
|
||||||
require.NoError(t.t, err)
|
|
||||||
require.Equal(t.t, 1, len(keysendInvoice.Htlcs))
|
|
||||||
htlc := keysendInvoice.Htlcs[0]
|
htlc := keysendInvoice.Htlcs[0]
|
||||||
require.Equal(t.t, uint64(0), htlc.MppTotalAmtMsat)
|
require.Zero(ht, htlc.MppTotalAmtMsat)
|
||||||
require.Nil(t.t, htlc.Amp)
|
require.Nil(ht, htlc.Amp)
|
||||||
|
|
||||||
// Now create an invoice and specify routing hints.
|
// Now create an invoice and specify routing hints.
|
||||||
// We will test that the routing hints are encoded properly.
|
// We will test that the routing hints are encoded properly.
|
||||||
hintChannel := lnwire.ShortChannelID{BlockHeight: 10}
|
hintChannel := lnwire.ShortChannelID{BlockHeight: 10}
|
||||||
bobPubKey := hex.EncodeToString(net.Bob.PubKey[:])
|
bobPubKey := hex.EncodeToString(bob.PubKey[:])
|
||||||
hints := []*lnrpc.RouteHint{
|
hint := &lnrpc.HopHint{
|
||||||
{
|
NodeId: bobPubKey,
|
||||||
HopHints: []*lnrpc.HopHint{
|
ChanId: hintChannel.ToUint64(),
|
||||||
{
|
FeeBaseMsat: 1,
|
||||||
NodeId: bobPubKey,
|
FeeProportionalMillionths: 1000000,
|
||||||
ChanId: hintChannel.ToUint64(),
|
CltvExpiryDelta: 20,
|
||||||
FeeBaseMsat: 1,
|
|
||||||
FeeProportionalMillionths: 1000000,
|
|
||||||
CltvExpiryDelta: 20,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
hints := []*lnrpc.RouteHint{{HopHints: []*lnrpc.HopHint{hint}}}
|
||||||
|
|
||||||
invoice = &lnrpc.Invoice{
|
invoice = &lnrpc.Invoice{
|
||||||
Memo: "hints",
|
Memo: "hints",
|
||||||
@@ -197,43 +121,21 @@ func testSingleHopInvoice(net *lntest.NetworkHarness, t *harnessTest) {
|
|||||||
RouteHints: hints,
|
RouteHints: hints,
|
||||||
}
|
}
|
||||||
|
|
||||||
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
|
invoiceResp = bob.RPC.AddInvoice(invoice)
|
||||||
invoiceResp, err = net.Bob.AddInvoice(ctxt, invoice)
|
payreq := bob.RPC.DecodePayReq(invoiceResp.PaymentRequest)
|
||||||
if err != nil {
|
require.Len(ht, payreq.RouteHints, 1, "expected one routing hint")
|
||||||
t.Fatalf("unable to add invoice: %v", err)
|
|
||||||
}
|
|
||||||
payreq, err := net.Bob.DecodePayReq(ctxt, &lnrpc.PayReqString{PayReq: invoiceResp.PaymentRequest})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("failed to decode payment request %v", err)
|
|
||||||
}
|
|
||||||
if len(payreq.RouteHints) != 1 {
|
|
||||||
t.Fatalf("expected one routing hint")
|
|
||||||
}
|
|
||||||
routingHint := payreq.RouteHints[0]
|
routingHint := payreq.RouteHints[0]
|
||||||
if len(routingHint.HopHints) != 1 {
|
require.Len(ht, routingHint.HopHints, 1, "expected one hop hint")
|
||||||
t.Fatalf("expected one hop hint")
|
|
||||||
}
|
|
||||||
hopHint := routingHint.HopHints[0]
|
|
||||||
if hopHint.FeeProportionalMillionths != 1000000 {
|
|
||||||
t.Fatalf("wrong FeeProportionalMillionths %v",
|
|
||||||
hopHint.FeeProportionalMillionths)
|
|
||||||
}
|
|
||||||
if hopHint.NodeId != bobPubKey {
|
|
||||||
t.Fatalf("wrong NodeId %v",
|
|
||||||
hopHint.NodeId)
|
|
||||||
}
|
|
||||||
if hopHint.ChanId != hintChannel.ToUint64() {
|
|
||||||
t.Fatalf("wrong ChanId %v",
|
|
||||||
hopHint.ChanId)
|
|
||||||
}
|
|
||||||
if hopHint.FeeBaseMsat != 1 {
|
|
||||||
t.Fatalf("wrong FeeBaseMsat %v",
|
|
||||||
hopHint.FeeBaseMsat)
|
|
||||||
}
|
|
||||||
if hopHint.CltvExpiryDelta != 20 {
|
|
||||||
t.Fatalf("wrong CltvExpiryDelta %v",
|
|
||||||
hopHint.CltvExpiryDelta)
|
|
||||||
}
|
|
||||||
|
|
||||||
closeChannelAndAssert(t, net, net.Alice, chanPoint, false)
|
hopHint := routingHint.HopHints[0]
|
||||||
|
require.EqualValues(ht, 1000000, hopHint.FeeProportionalMillionths,
|
||||||
|
"wrong FeeProportionalMillionths")
|
||||||
|
require.Equal(ht, bobPubKey, hopHint.NodeId, "wrong NodeId")
|
||||||
|
require.Equal(ht, hintChannel.ToUint64(), hopHint.ChanId,
|
||||||
|
"wrong ChanId")
|
||||||
|
require.EqualValues(ht, 1, hopHint.FeeBaseMsat, "wrong FeeBaseMsat")
|
||||||
|
require.EqualValues(ht, 20, hopHint.CltvExpiryDelta,
|
||||||
|
"wrong CltvExpiryDelta")
|
||||||
|
|
||||||
|
ht.CloseChannel(alice, cp)
|
||||||
}
|
}
|
||||||
@@ -4,10 +4,6 @@
|
|||||||
package itest
|
package itest
|
||||||
|
|
||||||
var allTestCases = []*testCase{
|
var allTestCases = []*testCase{
|
||||||
{
|
|
||||||
name: "single hop invoice",
|
|
||||||
test: testSingleHopInvoice,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: "multiple channel creation and update subscription",
|
name: "multiple channel creation and update subscription",
|
||||||
test: testBasicChannelCreationAndUpdates,
|
test: testBasicChannelCreationAndUpdates,
|
||||||
|
|||||||
Reference in new issue
Block a user