itest: test channel policy update in private channels
This commit is contained in:
parent
319cc533a6
commit
193d149d48
@ -860,7 +860,7 @@ func testPrivateChannels(net *lntest.NetworkHarness, t *harnessTest) {
|
|||||||
// Alice of 100k.
|
// Alice of 100k.
|
||||||
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
|
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
|
||||||
if err := net.ConnectNodes(ctxt, carol, net.Alice); err != nil {
|
if err := net.ConnectNodes(ctxt, carol, net.Alice); err != nil {
|
||||||
t.Fatalf("unable to connect dave to alice: %v", err)
|
t.Fatalf("unable to connect carol to alice: %v", err)
|
||||||
}
|
}
|
||||||
ctxt, _ = context.WithTimeout(ctxb, channelOpenTimeout)
|
ctxt, _ = context.WithTimeout(ctxb, channelOpenTimeout)
|
||||||
chanOpenUpdate := openChannelStream(
|
chanOpenUpdate := openChannelStream(
|
||||||
@ -1068,6 +1068,156 @@ func testPrivateChannels(net *lntest.NetworkHarness, t *harnessTest) {
|
|||||||
closeChannelAndAssert(ctxt, t, net, carol, chanPointPrivate, false)
|
closeChannelAndAssert(ctxt, t, net, carol, chanPointPrivate, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// testUpdateChannelPolicyForPrivateChannel tests when a private channel
|
||||||
|
// updates its channel edge policy, we will use the updated policy to send our
|
||||||
|
// payment.
|
||||||
|
// The topology is created as: Alice -> Bob -> Carol, where Alice -> Bob is
|
||||||
|
// public and Bob -> Carol is private. After an invoice is created by Carol,
|
||||||
|
// Bob will update the base fee via UpdateChannelPolicy, we will test that
|
||||||
|
// Alice will not fail the payment and send it using the updated channel
|
||||||
|
// policy.
|
||||||
|
func testUpdateChannelPolicyForPrivateChannel(net *lntest.NetworkHarness,
|
||||||
|
t *harnessTest) {
|
||||||
|
|
||||||
|
ctxb := context.Background()
|
||||||
|
defer ctxb.Done()
|
||||||
|
|
||||||
|
// We'll create the following topology first,
|
||||||
|
// Alice <--public:100k--> Bob <--private:100k--> Carol
|
||||||
|
const chanAmt = btcutil.Amount(100000)
|
||||||
|
|
||||||
|
// Open a channel with 100k satoshis between Alice and Bob.
|
||||||
|
ctxt, _ := context.WithTimeout(ctxb, channelOpenTimeout)
|
||||||
|
chanPointAliceBob := openChannelAndAssert(
|
||||||
|
ctxt, t, net, net.Alice, net.Bob,
|
||||||
|
lntest.OpenChannelParams{
|
||||||
|
Amt: chanAmt,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
defer closeChannelAndAssert(
|
||||||
|
ctxt, t, net, net.Alice, chanPointAliceBob, false,
|
||||||
|
)
|
||||||
|
|
||||||
|
// Get Alice's funding point.
|
||||||
|
aliceChanTXID, err := lnrpc.GetChanPointFundingTxid(chanPointAliceBob)
|
||||||
|
require.NoError(t.t, err, "unable to get txid")
|
||||||
|
aliceFundPoint := wire.OutPoint{
|
||||||
|
Hash: *aliceChanTXID,
|
||||||
|
Index: chanPointAliceBob.OutputIndex,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new node Carol.
|
||||||
|
carol := net.NewNode(t.t, "Carol", nil)
|
||||||
|
defer shutdownAndAssert(net, t, carol)
|
||||||
|
|
||||||
|
// Connect Carol to Bob.
|
||||||
|
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
|
||||||
|
require.NoError(t.t,
|
||||||
|
net.ConnectNodes(ctxt, carol, net.Bob),
|
||||||
|
"unable to connect carol to bob",
|
||||||
|
)
|
||||||
|
|
||||||
|
// Open a channel with 100k satoshis between Bob and Carol.
|
||||||
|
ctxt, _ = context.WithTimeout(ctxb, channelOpenTimeout)
|
||||||
|
chanPointBobCarol := openChannelAndAssert(
|
||||||
|
ctxt, t, net, net.Bob, carol,
|
||||||
|
lntest.OpenChannelParams{
|
||||||
|
Amt: chanAmt,
|
||||||
|
Private: true,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
defer closeChannelAndAssert(
|
||||||
|
ctxt, t, net, net.Bob, chanPointBobCarol, false,
|
||||||
|
)
|
||||||
|
|
||||||
|
// Get Bob's funding point.
|
||||||
|
bobChanTXID, err := lnrpc.GetChanPointFundingTxid(chanPointBobCarol)
|
||||||
|
require.NoError(t.t, err, "unable to get txid")
|
||||||
|
bobFundPoint := wire.OutPoint{
|
||||||
|
Hash: *bobChanTXID,
|
||||||
|
Index: chanPointBobCarol.OutputIndex,
|
||||||
|
}
|
||||||
|
|
||||||
|
// We should have the following topology now,
|
||||||
|
// Alice <--public:100k--> Bob <--private:100k--> Carol
|
||||||
|
//
|
||||||
|
// Now we will create an invoice for Carol.
|
||||||
|
const paymentAmt = 20000
|
||||||
|
invoice := &lnrpc.Invoice{
|
||||||
|
Memo: "routing hints",
|
||||||
|
Value: paymentAmt,
|
||||||
|
Private: true,
|
||||||
|
}
|
||||||
|
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
|
||||||
|
resp, err := carol.AddInvoice(ctxt, invoice)
|
||||||
|
require.NoError(t.t, err, "unable to create invoice for carol")
|
||||||
|
|
||||||
|
// Bob now updates the channel edge policy for the private channel.
|
||||||
|
const (
|
||||||
|
baseFeeMSat = 33000
|
||||||
|
)
|
||||||
|
timeLockDelta := uint32(chainreg.DefaultBitcoinTimeLockDelta)
|
||||||
|
updateFeeReq := &lnrpc.PolicyUpdateRequest{
|
||||||
|
BaseFeeMsat: baseFeeMSat,
|
||||||
|
TimeLockDelta: timeLockDelta,
|
||||||
|
Scope: &lnrpc.PolicyUpdateRequest_ChanPoint{
|
||||||
|
ChanPoint: chanPointBobCarol,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
|
||||||
|
_, err = net.Bob.UpdateChannelPolicy(ctxt, updateFeeReq)
|
||||||
|
require.NoError(t.t, err, "unable to update chan policy")
|
||||||
|
|
||||||
|
// Alice pays the invoices. She will use the updated baseFeeMSat in the
|
||||||
|
// payment
|
||||||
|
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
|
||||||
|
payReqs := []string{resp.PaymentRequest}
|
||||||
|
require.NoError(t.t,
|
||||||
|
completePaymentRequests(
|
||||||
|
ctxt, net.Alice, net.Alice.RouterClient, payReqs, true,
|
||||||
|
), "unable to send payment",
|
||||||
|
)
|
||||||
|
|
||||||
|
// Check that Alice did make the payment with two HTLCs, one failed and
|
||||||
|
// one succeeded.
|
||||||
|
ctxt, _ = context.WithTimeout(ctxt, defaultTimeout)
|
||||||
|
paymentsResp, err := net.Alice.ListPayments(
|
||||||
|
ctxt, &lnrpc.ListPaymentsRequest{},
|
||||||
|
)
|
||||||
|
require.NoError(t.t, err, "failed to obtain payments for Alice")
|
||||||
|
require.Equal(t.t, 1, len(paymentsResp.Payments), "expected 1 payment")
|
||||||
|
|
||||||
|
htlcs := paymentsResp.Payments[0].Htlcs
|
||||||
|
require.Equal(t.t, 2, len(htlcs), "expected to have 2 HTLCs")
|
||||||
|
require.Equal(
|
||||||
|
t.t, lnrpc.HTLCAttempt_FAILED, htlcs[0].Status,
|
||||||
|
"the first HTLC attempt should fail",
|
||||||
|
)
|
||||||
|
require.Equal(
|
||||||
|
t.t, lnrpc.HTLCAttempt_SUCCEEDED, htlcs[1].Status,
|
||||||
|
"the second HTLC attempt should succeed",
|
||||||
|
)
|
||||||
|
|
||||||
|
// Carol should have received 20k satoshis from Bob.
|
||||||
|
assertAmountPaid(t, "Carol(remote) [<=private] Bob(local)",
|
||||||
|
carol, bobFundPoint, 0, paymentAmt)
|
||||||
|
|
||||||
|
// Bob should have sent 20k satoshis to Carol.
|
||||||
|
assertAmountPaid(t, "Bob(local) [private=>] Carol(remote)",
|
||||||
|
net.Bob, bobFundPoint, paymentAmt, 0)
|
||||||
|
|
||||||
|
// Calcuate the amount in satoshis.
|
||||||
|
amtExpected := int64(paymentAmt + baseFeeMSat/1000)
|
||||||
|
|
||||||
|
// Bob should have received 20k satoshis + fee from Alice.
|
||||||
|
assertAmountPaid(t, "Bob(remote) <= Alice(local)",
|
||||||
|
net.Bob, aliceFundPoint, 0, amtExpected)
|
||||||
|
|
||||||
|
// Alice should have sent 20k satoshis + fee to Bob.
|
||||||
|
assertAmountPaid(t, "Alice(local) => Bob(remote)",
|
||||||
|
net.Alice, aliceFundPoint, amtExpected, 0)
|
||||||
|
}
|
||||||
|
|
||||||
// testInvoiceRoutingHints tests that the routing hints for an invoice are
|
// testInvoiceRoutingHints tests that the routing hints for an invoice are
|
||||||
// created properly.
|
// created properly.
|
||||||
func testInvoiceRoutingHints(net *lntest.NetworkHarness, t *harnessTest) {
|
func testInvoiceRoutingHints(net *lntest.NetworkHarness, t *harnessTest) {
|
||||||
|
@ -107,6 +107,11 @@ var allTestCases = []*testCase{
|
|||||||
name: "private channels",
|
name: "private channels",
|
||||||
test: testPrivateChannels,
|
test: testPrivateChannels,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "private channel update policy",
|
||||||
|
test: testUpdateChannelPolicyForPrivateChannel,
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
name: "invoice routing hints",
|
name: "invoice routing hints",
|
||||||
test: testInvoiceRoutingHints,
|
test: testInvoiceRoutingHints,
|
||||||
|
@ -283,3 +283,4 @@
|
|||||||
<time> [ERR] HSWC: ChannelLink(<chan>): failing link: process hodl queue: unable to update commitment: link shutting down with error: internal error
|
<time> [ERR] HSWC: ChannelLink(<chan>): failing link: process hodl queue: unable to update commitment: link shutting down with error: internal error
|
||||||
<time> [ERR] INVC: SettleHodlInvoice with preimage <hex>: invoice already canceled
|
<time> [ERR] INVC: SettleHodlInvoice with preimage <hex>: invoice already canceled
|
||||||
<time> [ERR] RPCS: [/invoicesrpc.Invoices/SettleInvoice]: invoice already canceled
|
<time> [ERR] RPCS: [/invoicesrpc.Invoices/SettleInvoice]: invoice already canceled
|
||||||
|
<time> [ERR] HSWC: ChannelLink(<chan>): outgoing htlc(<hex>) has insufficient fee: expected 33000, got 1020
|
||||||
|
Loading…
Reference in New Issue
Block a user