Skip to content

Commit 8f62efb

Browse files
itest: add test for ConfirmationsUntilActive and ConfirmationHeight
Signed-off-by: Nishant Bansal <[email protected]>
1 parent 5fd42ac commit 8f62efb

File tree

2 files changed

+238
-0
lines changed

2 files changed

+238
-0
lines changed

itest/list_on_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,14 @@ var allTestCases = []*lntest.TestCase{
6262
Name: "funding expiry blocks on pending",
6363
TestFunc: testFundingExpiryBlocksOnPending,
6464
},
65+
{
66+
Name: "pending channel confirmation until active",
67+
TestFunc: testPendingChannelConfirmationUntilActive,
68+
},
69+
{
70+
Name: "pending channel reorg test",
71+
TestFunc: testPendingChannelAfterReorg,
72+
},
6573
{
6674
Name: "list channels",
6775
TestFunc: testListChannels,

itest/lnd_open_channel_test.go

Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -877,6 +877,236 @@ func testFundingExpiryBlocksOnPending(ht *lntest.HarnessTest) {
877877
ht.MineBlocksAndAssertNumTxes(1, 1)
878878
}
879879

880+
// assertConfirmation is a helper to assert the ConfirmationsUntilActive and
881+
// ConfirmationHeight has been updated to the expected value.
882+
func assertConfirmation(ht *lntest.HarnessTest, hn *node.HarnessNode,
883+
expConfLeft, expConfHeight uint32) {
884+
885+
ht.Helper()
886+
887+
err := wait.NoError(func() error {
888+
// Node should have one pending open channel.
889+
pendingChan := ht.AssertNumPendingOpenChannels(hn, 1)[0]
890+
891+
// Check if the ConfirmationsUntilActive is updated to the
892+
// expected value.
893+
if expConfLeft != pendingChan.ConfirmationsUntilActive {
894+
return fmt.Errorf("remaining confirmations mismatch, "+
895+
"want %v, got %v", expConfLeft,
896+
pendingChan.ConfirmationsUntilActive)
897+
}
898+
899+
// Check if the ConfirmationHeight is updated to the expected
900+
// value.
901+
if expConfHeight != pendingChan.ConfirmationHeight {
902+
return fmt.Errorf("confirmation height mismatch, want "+
903+
"%v, got %v", expConfHeight,
904+
pendingChan.ConfirmationHeight)
905+
}
906+
907+
return nil
908+
}, defaultTimeout)
909+
910+
require.NoError(ht, err)
911+
}
912+
913+
// testPendingChannelConfirmationUntilActive verifies the value for the rpc
914+
// field ConfirmationUntilActive updates correctly as soon as blocks are
915+
// confirmed.
916+
func testPendingChannelConfirmationUntilActive(ht *lntest.HarnessTest) {
917+
var (
918+
numConfs uint32 = 5
919+
chanAmt btcutil.Amount = 100000
920+
)
921+
922+
// Since we want Bob's channels to require more than 1 on-chain
923+
// confirmation before becoming active, we will launch Bob with the
924+
// custom defaultchanconfs flag.
925+
alice := ht.NewNodeWithCoins("Alice", nil)
926+
bob := ht.NewNode("Bob", []string{
927+
fmt.Sprintf("--bitcoin.defaultchanconfs=%v", numConfs),
928+
})
929+
930+
// Ensure Alice and Bob are connected.
931+
ht.EnsureConnected(alice, bob)
932+
933+
// Alice initiates a channel opening to Bob.
934+
param := lntest.OpenChannelParams{Amt: chanAmt}
935+
ht.OpenChannelAssertPending(alice, bob, param)
936+
937+
// Both Alice and Bob have one pending open channel.
938+
ht.AssertNumPendingOpenChannels(alice, 1)
939+
ht.AssertNumPendingOpenChannels(bob, 1)
940+
941+
// Since the funding transaction is not confirmed yet,
942+
// ConfirmationsUntilActive will always be numConfs, and confirmation
943+
// height will be 0.
944+
assertConfirmation(ht, alice, numConfs, 0)
945+
assertConfirmation(ht, bob, numConfs, 0)
946+
947+
// Mine the first block containing the funding transaction, This
948+
// confirms the funding transaction but the channel should still remain
949+
// pending.
950+
ht.MineBlocksAndAssertNumTxes(1, 1)
951+
952+
// Decrement numConfs to reflect that one confirmation has been
953+
// received.
954+
numConfs--
955+
956+
// Since the funding transaction has been mined, the best block height
957+
// corresponds to the confirmation height of the channel's opening tx.
958+
_, expConfHeight := ht.GetBestBlock()
959+
960+
// Channel remains pending after the first confirmation.
961+
ht.AssertNumPendingOpenChannels(alice, 1)
962+
ht.AssertNumPendingOpenChannels(bob, 1)
963+
964+
// Make sure the ConfirmationsUntilActive and ConfirmationHeight
965+
// fields have been updated to the expected values before restarting the
966+
// nodes.
967+
assertConfirmation(ht, alice, numConfs, uint32(expConfHeight))
968+
assertConfirmation(ht, bob, numConfs, uint32(expConfHeight))
969+
970+
// Restart both nodes to test that the appropriate state has been
971+
// persisted and that both nodes recover gracefully.
972+
ht.RestartNode(alice)
973+
ht.RestartNode(bob)
974+
ht.EnsureConnected(alice, bob)
975+
976+
// ConfirmationsUntilActive field should decrease as each block is
977+
// mined until the required number of confirmations is reached. Let's
978+
// mine a few blocks and verify the value of ConfirmationsUntilActive at
979+
// each step.
980+
for i := numConfs; i > 0; i-- {
981+
expConfLeft := i
982+
983+
// Retrieve pending channels for both Alice and Bob and verify
984+
// the remaining confirmations and confirmation height.
985+
assertConfirmation(
986+
ht, alice, expConfLeft, uint32(expConfHeight),
987+
)
988+
assertConfirmation(ht, bob, expConfLeft, uint32(expConfHeight))
989+
990+
// Mine the next block.
991+
ht.MineBlocks(1)
992+
}
993+
994+
// After the required number of confirmations, the channel should be
995+
// marked as active.
996+
ht.AssertNumPendingOpenChannels(alice, 0)
997+
ht.AssertNumPendingOpenChannels(bob, 0)
998+
}
999+
1000+
// testPendingChannelAfterReorg verifies the value for the rpc field
1001+
// ConfirmationUntilActive updates correctly as blocks are confirmed and after
1002+
// chain reorgs.
1003+
func testPendingChannelAfterReorg(ht *lntest.HarnessTest) {
1004+
// Skip test for neutrino, as we cannot disconnect the miner at will.
1005+
if ht.IsNeutrinoBackend() {
1006+
ht.Skipf("skipping reorg test for neutrino backend")
1007+
}
1008+
1009+
var numConfs uint32 = 3
1010+
1011+
// Since we want Bob's channels to require more than 1 on-chain
1012+
// confirmation before becoming active, we will launch Bob with the
1013+
// custom defaultchanconfs flag.
1014+
miner := ht.Miner()
1015+
alice := ht.NewNodeWithCoins("Alice", nil)
1016+
bob := ht.NewNode("Bob", []string{
1017+
fmt.Sprintf("--bitcoin.defaultchanconfs=%v", numConfs),
1018+
})
1019+
ht.EnsureConnected(alice, bob)
1020+
1021+
// Spawn a temporary miner to simulate a chain reorg with a longer
1022+
// chain.
1023+
tempMiner := ht.SpawnTempMiner()
1024+
1025+
// Alice initiates a channel opening to Bob.
1026+
params := lntest.OpenChannelParams{Amt: funding.MaxBtcFundingAmount}
1027+
ht.OpenChannelAssertPending(alice, bob, params)
1028+
1029+
// Mine the first block containing the funding transaction.
1030+
ht.MineBlocksAndAssertNumTxes(1, 1)
1031+
1032+
// Channel remains pending after the first confirmation.
1033+
ht.AssertNumPendingOpenChannels(alice, 1)
1034+
ht.AssertNumPendingOpenChannels(bob, 1)
1035+
1036+
// Since the funding transaction has been mined, the best block height
1037+
// corresponds to the confirmation height of the channel's opening tx.
1038+
_, expConfHeight := ht.GetBestBlock()
1039+
1040+
// Make sure the ConfirmationsUntilActive and ConfirmationHeight
1041+
// fields have been updated to the expected values before reorg.
1042+
//
1043+
// Decrement numConfs to reflect one confirmation received.
1044+
assertConfirmation(ht, alice, numConfs-1, uint32(expConfHeight))
1045+
assertConfirmation(ht, bob, numConfs-1, uint32(expConfHeight))
1046+
1047+
// We now cause a fork, by letting our original miner mine 1 blocks,
1048+
// and our new miner mine 3.
1049+
_, err := tempMiner.Client.Generate(3)
1050+
require.NoError(ht, err, "unable to generate blocks on temp miner")
1051+
1052+
// Ensure the chain lengths are what we expect, with the temp miner
1053+
// being 2 blocks ahead.
1054+
miner.AssertMinerBlockHeightDelta(tempMiner, 2)
1055+
1056+
// Now we disconnect Alice's chain backend from the original miner, and
1057+
// connect the two miners together. Since the temporary miner knows
1058+
// about a longer chain, both miners should sync to that chain.
1059+
ht.DisconnectMiner()
1060+
1061+
// Connecting to the temporary miner should now cause our original
1062+
// chain to be re-orged out.
1063+
miner.ConnectMiner(tempMiner)
1064+
1065+
// Once again they should be on the same chain.
1066+
miner.AssertMinerBlockHeightDelta(tempMiner, 0)
1067+
1068+
// Now we disconnect the two miners, and connect our original miner to
1069+
// our chain backend once again.
1070+
miner.DisconnectMiner(tempMiner)
1071+
ht.ConnectMiner()
1072+
1073+
// This should have caused a reorg, and Alice should sync to the longer
1074+
// chain, where the funding transaction is not confirmed.
1075+
_, tempMinerHeight, err := tempMiner.Client.GetBestBlock()
1076+
require.NoError(ht, err, "unable to get current blockheight")
1077+
ht.WaitForNodeBlockHeight(alice, tempMinerHeight)
1078+
1079+
// After the reorg, the funding transaction's confirmation is removed,
1080+
// so the pending channel should again require the original number of
1081+
// confirmations and have a confirmation height of 0.
1082+
assertConfirmation(ht, alice, numConfs, 0)
1083+
assertConfirmation(ht, bob, numConfs, 0)
1084+
1085+
// Mine the first block containing the funding transaction again.
1086+
ht.MineBlocksAndAssertNumTxes(1, 1)
1087+
1088+
// Decrement numConfs to reflect one confirmation received.
1089+
numConfs--
1090+
1091+
// Since the funding transaction has been mined, the best block height
1092+
// corresponds to the confirmation height of the channel's opening tx.
1093+
_, expConfHeight = ht.GetBestBlock()
1094+
1095+
// Make sure the ConfirmationsUntilActive and ConfirmationHeight
1096+
// fields have been updated to the expected values after reorg.
1097+
assertConfirmation(ht, alice, numConfs, uint32(expConfHeight))
1098+
assertConfirmation(ht, bob, numConfs, uint32(expConfHeight))
1099+
1100+
// Cleanup by mining the remaining blocks to reach the required number
1101+
// of confirmations.
1102+
ht.MineBlocks(int(numConfs))
1103+
1104+
// After the required number of confirmations, the channel should be
1105+
// marked as active.
1106+
ht.AssertNumPendingOpenChannels(alice, 0)
1107+
ht.AssertNumPendingOpenChannels(bob, 0)
1108+
}
1109+
8801110
// testSimpleTaprootChannelActivation ensures that a simple taproot channel is
8811111
// active if the initiator disconnects and reconnects in between channel opening
8821112
// and channel confirmation.

0 commit comments

Comments
 (0)