itest: refactor testPsbtChanFundingSingleStep

This commit is contained in:
yyforyongyu committed 2023-01-16 16:49:18 +08:00
1 parent 4a8cf91e53
commit 83ecc6285c
3 files changed
+56 -68

No files matched your search

+4
View File
@@ -279,4 +279,8 @@ var allTestCasesTemp = []*lntemp.TestCase{
Name: "psbt channel funding external", Name: "psbt channel funding external",
TestFunc: testPsbtChanFundingExternal, TestFunc: testPsbtChanFundingExternal,
}, },
{
Name: "psbt channel funding single step",
TestFunc: testPsbtChanFundingSingleStep,
},
} }
+52 -64
View File
@@ -435,73 +435,68 @@ func testPsbtChanFundingExternal(ht *lntemp.HarnessTest) {
ht.CloseChannel(carol, chanPoint2) ht.CloseChannel(carol, chanPoint2)
} }
// testPsbtChanFundingSingleStep checks whether PSBT funding works also when the // testPsbtChanFundingSingleStep checks whether PSBT funding works also when
// wallet of both nodes are empty and one of them uses PSBT and an external // the wallet of both nodes are empty and one of them uses PSBT and an external
// wallet to fund the channel while creating reserve output in the same // wallet to fund the channel while creating reserve output in the same
// transaction. // transaction.
func testPsbtChanFundingSingleStep(net *lntest.NetworkHarness, t *harnessTest) { func testPsbtChanFundingSingleStep(ht *lntemp.HarnessTest) {
ctxb := context.Background()
const chanSize = funding.MaxBtcFundingAmount const chanSize = funding.MaxBtcFundingAmount
// Everything we do here should be done within a second or two, so we
// can just keep a single timeout context around for all calls.
ctxt, cancel := context.WithTimeout(ctxb, 2*defaultTimeout)
defer cancel()
args := nodeArgsForCommitType(lnrpc.CommitmentType_ANCHORS) args := nodeArgsForCommitType(lnrpc.CommitmentType_ANCHORS)
// First, we'll create two new nodes that we'll use to open channels // First, we'll create two new nodes that we'll use to open channels
// between for this test. But in this case both nodes have an empty // between for this test. But in this case both nodes have an empty
// wallet. // wallet.
carol := net.NewNode(t.t, "carol", args) carol := ht.NewNode("carol", args)
defer shutdownAndAssert(net, t, carol) defer ht.Shutdown(carol)
dave := net.NewNode(t.t, "dave", args) dave := ht.NewNode("dave", args)
defer shutdownAndAssert(net, t, dave) defer ht.Shutdown(dave)
net.SendCoins(t.t, btcutil.SatoshiPerBitcoin, net.Alice) alice := ht.Alice
ht.FundCoins(btcutil.SatoshiPerBitcoin, alice)
// Get new address for anchor reserve. // Get new address for anchor reserve.
reserveAddrReq := &lnrpc.NewAddressRequest{ req := &lnrpc.NewAddressRequest{
Type: lnrpc.AddressType_WITNESS_PUBKEY_HASH, Type: lnrpc.AddressType_WITNESS_PUBKEY_HASH,
} }
addrResp, err := carol.NewAddress(ctxb, reserveAddrReq) addrResp := carol.RPC.NewAddress(req)
require.NoError(t.t, err) reserveAddr, err := btcutil.DecodeAddress(
reserveAddr, err := btcutil.DecodeAddress(addrResp.Address, harnessNetParams) addrResp.Address, harnessNetParams,
require.NoError(t.t, err) )
require.NoError(ht, err)
reserveAddrScript, err := txscript.PayToAddrScript(reserveAddr) reserveAddrScript, err := txscript.PayToAddrScript(reserveAddr)
require.NoError(t.t, err) require.NoError(ht, err)
// Before we start the test, we'll ensure both sides are connected so // Before we start the test, we'll ensure both sides are connected so
// the funding flow can be properly executed. // the funding flow can be properly executed.
net.EnsureConnected(t.t, carol, dave) ht.EnsureConnected(carol, dave)
// At this point, we can begin our PSBT channel funding workflow. We'll // At this point, we can begin our PSBT channel funding workflow. We'll
// start by generating a pending channel ID externally that will be used // start by generating a pending channel ID externally that will be used
// to track this new funding type. // to track this new funding type.
var pendingChanID [32]byte pendingChanID := ht.Random32Bytes()
_, err = rand.Read(pendingChanID[:])
require.NoError(t.t, err)
// Now that we have the pending channel ID, Carol will open the channel // Now that we have the pending channel ID, Carol will open the channel
// by specifying a PSBT shim. // by specifying a PSBT shim.
chanUpdates, tempPsbt, err := openChannelPsbt( chanUpdates, tempPsbt := ht.OpenChannelPsbt(
ctxt, carol, dave, lntest.OpenChannelParams{ carol, dave, lntemp.OpenChannelParams{
Amt: chanSize, Amt: chanSize,
FundingShim: &lnrpc.FundingShim{ FundingShim: &lnrpc.FundingShim{
Shim: &lnrpc.FundingShim_PsbtShim{ Shim: &lnrpc.FundingShim_PsbtShim{
PsbtShim: &lnrpc.PsbtShim{ PsbtShim: &lnrpc.PsbtShim{
PendingChanId: pendingChanID[:], PendingChanId: pendingChanID,
NoPublish: false, NoPublish: false,
}, },
}, },
}, },
}, },
) )
require.NoError(t.t, err)
decodedPsbt, err := psbt.NewFromRawBytes(bytes.NewReader(tempPsbt), false) decodedPsbt, err := psbt.NewFromRawBytes(
require.NoError(t.t, err) bytes.NewReader(tempPsbt), false,
)
require.NoError(ht, err)
reserveTxOut := wire.TxOut{ reserveTxOut := wire.TxOut{
Value: 10000, Value: 10000,
@@ -515,7 +510,7 @@ func testPsbtChanFundingSingleStep(net *lntest.NetworkHarness, t *harnessTest) {
var psbtBytes bytes.Buffer var psbtBytes bytes.Buffer
err = decodedPsbt.Serialize(&psbtBytes) err = decodedPsbt.Serialize(&psbtBytes)
require.NoError(t.t, err) require.NoError(ht, err)
fundReq := &walletrpc.FundPsbtRequest{ fundReq := &walletrpc.FundPsbtRequest{
Template: &walletrpc.FundPsbtRequest_Psbt{ Template: &walletrpc.FundPsbtRequest_Psbt{
@@ -525,55 +520,45 @@ func testPsbtChanFundingSingleStep(net *lntest.NetworkHarness, t *harnessTest) {
SatPerVbyte: 2, SatPerVbyte: 2,
}, },
} }
fundResp, err := net.Alice.WalletKitClient.FundPsbt(ctxt, fundReq) fundResp := alice.RPC.FundPsbt(fundReq)
require.NoError(t.t, err)
// Make sure the wallets are actually empty // Make sure the wallets are actually empty
unspentCarol, err := carol.ListUnspent(ctxb, &lnrpc.ListUnspentRequest{}) ht.AssertNumUTXOsUnconfirmed(alice, 0)
require.NoError(t.t, err) ht.AssertNumUTXOsUnconfirmed(dave, 0)
require.Len(t.t, unspentCarol.Utxos, 0)
unspentDave, err := dave.ListUnspent(ctxb, &lnrpc.ListUnspentRequest{})
require.NoError(t.t, err)
require.Len(t.t, unspentDave.Utxos, 0)
// We have a PSBT that has no witness data yet, which is exactly what we // We have a PSBT that has no witness data yet, which is exactly what we
// need for the next step: Verify the PSBT with the funding intents. // need for the next step: Verify the PSBT with the funding intents.
_, err = carol.FundingStateStep(ctxb, &lnrpc.FundingTransitionMsg{ carol.RPC.FundingStateStep(&lnrpc.FundingTransitionMsg{
Trigger: &lnrpc.FundingTransitionMsg_PsbtVerify{ Trigger: &lnrpc.FundingTransitionMsg_PsbtVerify{
PsbtVerify: &lnrpc.FundingPsbtVerify{ PsbtVerify: &lnrpc.FundingPsbtVerify{
PendingChanId: pendingChanID[:], PendingChanId: pendingChanID,
FundedPsbt: fundResp.FundedPsbt, FundedPsbt: fundResp.FundedPsbt,
}, },
}, },
}) })
require.NoError(t.t, err)
// Now we'll ask Alice's wallet to sign the PSBT so we can finish the // Now we'll ask Alice's wallet to sign the PSBT so we can finish the
// funding flow. // funding flow.
finalizeReq := &walletrpc.FinalizePsbtRequest{ finalizeReq := &walletrpc.FinalizePsbtRequest{
FundedPsbt: fundResp.FundedPsbt, FundedPsbt: fundResp.FundedPsbt,
} }
finalizeRes, err := net.Alice.WalletKitClient.FinalizePsbt(ctxt, finalizeReq) finalizeRes := alice.RPC.FinalizePsbt(finalizeReq)
require.NoError(t.t, err)
// We've signed our PSBT now, let's pass it to the intent again. // We've signed our PSBT now, let's pass it to the intent again.
_, err = carol.FundingStateStep(ctxb, &lnrpc.FundingTransitionMsg{ carol.RPC.FundingStateStep(&lnrpc.FundingTransitionMsg{
Trigger: &lnrpc.FundingTransitionMsg_PsbtFinalize{ Trigger: &lnrpc.FundingTransitionMsg_PsbtFinalize{
PsbtFinalize: &lnrpc.FundingPsbtFinalize{ PsbtFinalize: &lnrpc.FundingPsbtFinalize{
PendingChanId: pendingChanID[:], PendingChanId: pendingChanID,
SignedPsbt: finalizeRes.SignedPsbt, SignedPsbt: finalizeRes.SignedPsbt,
}, },
}, },
}) })
require.NoError(t.t, err)
// Consume the "channel pending" update. This waits until the funding // Consume the "channel pending" update. This waits until the funding
// transaction was fully compiled. // transaction was fully compiled.
updateResp, err := receiveChanUpdate(ctxt, chanUpdates) updateResp := ht.ReceiveOpenChannelUpdate(chanUpdates)
require.NoError(t.t, err)
upd, ok := updateResp.Update.(*lnrpc.OpenStatusUpdate_ChanPending) upd, ok := updateResp.Update.(*lnrpc.OpenStatusUpdate_ChanPending)
require.True(t.t, ok) require.True(ht, ok)
chanPoint := &lnrpc.ChannelPoint{ chanPoint := &lnrpc.ChannelPoint{
FundingTxid: &lnrpc.ChannelPoint_FundingTxidBytes{ FundingTxid: &lnrpc.ChannelPoint_FundingTxidBytes{
FundingTxidBytes: upd.ChanPending.Txid, FundingTxidBytes: upd.ChanPending.Txid,
@@ -583,13 +568,12 @@ func testPsbtChanFundingSingleStep(net *lntest.NetworkHarness, t *harnessTest) {
var finalTx wire.MsgTx var finalTx wire.MsgTx
err = finalTx.Deserialize(bytes.NewReader(finalizeRes.RawFinalTx)) err = finalTx.Deserialize(bytes.NewReader(finalizeRes.RawFinalTx))
require.NoError(t.t, err) require.NoError(ht, err)
txHash := finalTx.TxHash() txHash := finalTx.TxHash()
block := mineBlocks(t, net, 6, 1)[0] block := ht.MineBlocksAndAssertNumTxes(6, 1)[0]
assertTxInBlock(t, block, &txHash) ht.Miner.AssertTxInBlock(block, &txHash)
err = carol.WaitForNetworkChannelOpen(chanPoint) ht.AssertTopologyChannelOpen(carol, chanPoint)
require.NoError(t.t, err)
// Next, to make sure the channel functions as normal, we'll make some // Next, to make sure the channel functions as normal, we'll make some
// payments within the channel. // payments within the channel.
@@ -598,19 +582,23 @@ func testPsbtChanFundingSingleStep(net *lntest.NetworkHarness, t *harnessTest) {
Memo: "new chans", Memo: "new chans",
Value: int64(payAmt), Value: int64(payAmt),
} }
resp, err := dave.AddInvoice(ctxt, invoice) resp := dave.RPC.AddInvoice(invoice)
require.NoError(t.t, err) ht.CompletePaymentRequests(carol, []string{resp.PaymentRequest})
err = completePaymentRequests(
carol, carol.RouterClient, []string{resp.PaymentRequest}, // TODO(yy): remove the sleep once the following bug is fixed. When the
true, // payment is reported as settled by Carol, it's expected the
) // commitment dance is finished and all subsequent states have been
require.NoError(t.t, err) // updated. Yet we'd receive the error `cannot co-op close channel with
// active htlcs` or `link failed to shutdown` if we close the channel.
// We need to investigate the order of settling the payments and
// updating commitments to understand and fix .
time.Sleep(2 * time.Second)
// To conclude, we'll close the newly created channel between Carol and // To conclude, we'll close the newly created channel between Carol and
// Dave. This function will also block until the channel is closed and // Dave. This function will also block until the channel is closed and
// will additionally assert the relevant channel closing post // will additionally assert the relevant channel closing post
// conditions. // conditions.
closeChannelAndAssert(t, net, carol, chanPoint, false) ht.CloseChannel(carol, chanPoint)
} }
// testSignPsbt tests that the SignPsbt RPC works correctly. // testSignPsbt tests that the SignPsbt RPC works correctly.
-4
View File
@@ -122,10 +122,6 @@ var allTestCases = []*testCase{
name: "sign psbt", name: "sign psbt",
test: testSignPsbt, test: testSignPsbt,
}, },
{
name: "psbt channel funding single step",
test: testPsbtChanFundingSingleStep,
},
{ {
name: "sendtoroute multi path payment", name: "sendtoroute multi path payment",
test: testSendToRouteMultiPath, test: testSendToRouteMultiPath,