itest: assert P2TR on-chain fund recovery

This commit is contained in:
Oliver Gugger
2022-03-18 18:37:48 +01:00
parent 108f49f23b
commit 5109c55721
3 changed files with 46 additions and 19 deletions

View File

@@ -1452,6 +1452,17 @@ func (n *NetworkHarness) SendCoinsNP2WKH(t *testing.T, amt btcutil.Amount,
) )
} }
// SendCoinsP2TR attempts to send amt satoshis from the internal mining node
// to the targeted lightning node using a P2TR address.
func (n *NetworkHarness) SendCoinsP2TR(t *testing.T, amt btcutil.Amount,
target *HarnessNode) {
err := n.sendCoins(amt, target, lnrpc.AddressType_TAPROOT_PUBKEY, true)
require.NoErrorf(
t, err, "unable to send P2TR coins for %s", target.Cfg.Name,
)
}
// sendCoins attempts to send amt satoshis from the internal mining node to the // sendCoins attempts to send amt satoshis from the internal mining node to the
// targeted lightning node. The confirmed boolean indicates whether the // targeted lightning node. The confirmed boolean indicates whether the
// transaction that pays to the target should confirm. // transaction that pays to the target should confirm.

View File

@@ -220,15 +220,24 @@ func testOnchainFundRecovery(net *lntest.NetworkHarness, t *harnessTest) {
Type: AddrTypeNestedPubkeyHash, Type: AddrTypeNestedPubkeyHash,
} }
newP2TRAddrReq := &lnrpc.NewAddressRequest{
Type: AddrTypeTaprootPubkey,
}
// Generate and skip the number of addresses requested. // Generate and skip the number of addresses requested.
ctxt, cancel := context.WithTimeout(
ctxb, defaultTimeout,
)
defer cancel()
for i := 0; i < nskip; i++ { for i := 0; i < nskip; i++ {
ctxt, _ := context.WithTimeout(ctxb, defaultTimeout)
_, err = node.NewAddress(ctxt, newP2WKHAddrReq) _, err = node.NewAddress(ctxt, newP2WKHAddrReq)
require.NoError(t.t, err) require.NoError(t.t, err)
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
_, err = node.NewAddress(ctxt, newNP2WKHAddrReq) _, err = node.NewAddress(ctxt, newNP2WKHAddrReq)
require.NoError(t.t, err) require.NoError(t.t, err)
_, err = node.NewAddress(ctxt, newP2TRAddrReq)
require.NoError(t.t, err)
} }
// Send one BTC to the next P2WKH address. // Send one BTC to the next P2WKH address.
@@ -238,6 +247,11 @@ func testOnchainFundRecovery(net *lntest.NetworkHarness, t *harnessTest) {
net.SendCoinsNP2WKH( net.SendCoinsNP2WKH(
t.t, btcutil.SatoshiPerBitcoin, node, t.t, btcutil.SatoshiPerBitcoin, node,
) )
// Add another whole coin to the P2TR address.
net.SendCoinsP2TR(
t.t, btcutil.SatoshiPerBitcoin, node,
)
} }
} }
@@ -256,26 +270,26 @@ func testOnchainFundRecovery(net *lntest.NetworkHarness, t *harnessTest) {
// the two transactions above. We should also now have 2 UTXOs in the // the two transactions above. We should also now have 2 UTXOs in the
// wallet at the end of the recovery attempt. // wallet at the end of the recovery attempt.
// //
// After, we will generate and skip 9 P2WKH and NP2WKH addresses, and // After, we will generate and skip 9 P2WKH, NP2WKH and P2TR addresses,
// send another BTC to the subsequent 10th address in each derivation // and send another BTC to the subsequent 10th address in each
// path. // derivation path.
restoreCheckBalance(2*btcutil.SatoshiPerBitcoin, 2, 1, skipAndSend(9)) restoreCheckBalance(3*btcutil.SatoshiPerBitcoin, 3, 1, skipAndSend(9))
// Check that using a recovery window of 9 does not find the two most // Check that using a recovery window of 9 does not find the two most
// recent txns. // recent txns.
restoreCheckBalance(2*btcutil.SatoshiPerBitcoin, 2, 9, nil) restoreCheckBalance(3*btcutil.SatoshiPerBitcoin, 3, 9, nil)
// Extending our recovery window to 10 should find the most recent // Extending our recovery window to 10 should find the most recent
// transactions, leaving the wallet with 4 BTC total. We should also // transactions, leaving the wallet with 6 BTC total. We should also
// learn of the two additional UTXOs created above. // learn of the two additional UTXOs created above.
// //
// After, we will skip 19 more addrs, sending to the 20th address past // After, we will skip 19 more addrs, sending to the 20th address past
// our last found address, and repeat the same checks. // our last found address, and repeat the same checks.
restoreCheckBalance(4*btcutil.SatoshiPerBitcoin, 4, 10, skipAndSend(19)) restoreCheckBalance(6*btcutil.SatoshiPerBitcoin, 6, 10, skipAndSend(19))
// Check that recovering with a recovery window of 19 fails to find the // Check that recovering with a recovery window of 19 fails to find the
// most recent transactions. // most recent transactions.
restoreCheckBalance(4*btcutil.SatoshiPerBitcoin, 4, 19, nil) restoreCheckBalance(6*btcutil.SatoshiPerBitcoin, 6, 19, nil)
// Ensure that using a recovery window of 20 succeeds with all UTXOs // Ensure that using a recovery window of 20 succeeds with all UTXOs
// found and the final balance reflected. // found and the final balance reflected.
@@ -285,11 +299,11 @@ func testOnchainFundRecovery(net *lntest.NetworkHarness, t *harnessTest) {
// fixed bug in the wallet in which change addresses could at times be // fixed bug in the wallet in which change addresses could at times be
// created outside of the default key scopes. Recovery only used to be // created outside of the default key scopes. Recovery only used to be
// performed on the default key scopes, so ideally this test case // performed on the default key scopes, so ideally this test case
// would've caught the bug earlier. Carol has received 6 BTC so far from // would've caught the bug earlier. Carol has received 9 BTC so far from
// the miner, we'll send 5 back to ensure all of her UTXOs get spent to // the miner, we'll send 8 back to ensure all of her UTXOs get spent to
// avoid fee discrepancies and a change output is formed. // avoid fee discrepancies and a change output is formed.
const minerAmt = 5 * btcutil.SatoshiPerBitcoin const minerAmt = 8 * btcutil.SatoshiPerBitcoin
const finalBalance = 6 * btcutil.SatoshiPerBitcoin const finalBalance = 9 * btcutil.SatoshiPerBitcoin
promptChangeAddr := func(node *lntest.HarnessNode) { promptChangeAddr := func(node *lntest.HarnessNode) {
t.t.Helper() t.t.Helper()
@@ -310,12 +324,13 @@ func testOnchainFundRecovery(net *lntest.NetworkHarness, t *harnessTest) {
block := mineBlocks(t, net, 1, 1)[0] block := mineBlocks(t, net, 1, 1)[0]
assertTxInBlock(t, block, txid) assertTxInBlock(t, block, txid)
} }
restoreCheckBalance(finalBalance, 6, 20, promptChangeAddr) restoreCheckBalance(finalBalance, 9, 20, promptChangeAddr)
// We should expect a static fee of 27750 satoshis for spending 6 inputs // We should expect a static fee of 50100 satoshis for spending 9 inputs
// (3 P2WPKH, 3 NP2WPKH) to two P2WPKH outputs. Carol should therefore // (3 P2WPKH, 3 NP2WPKH, 3 P2TR) to two P2WPKH outputs. Carol should
// only have one UTXO present (the change output) of 6 - 5 - fee BTC. // therefore only have one UTXO present (the change output) of
const fee = 27750 // 9 - 8 - fee BTC.
const fee = 50100
restoreCheckBalance(finalBalance-minerAmt-fee, 1, 21, nil) restoreCheckBalance(finalBalance-minerAmt-fee, 1, 21, nil)
// Last of all, make sure we can also restore a node from the extended // Last of all, make sure we can also restore a node from the extended

View File

@@ -46,6 +46,7 @@ const (
AddrTypeWitnessPubkeyHash = lnrpc.AddressType_WITNESS_PUBKEY_HASH AddrTypeWitnessPubkeyHash = lnrpc.AddressType_WITNESS_PUBKEY_HASH
AddrTypeNestedPubkeyHash = lnrpc.AddressType_NESTED_PUBKEY_HASH AddrTypeNestedPubkeyHash = lnrpc.AddressType_NESTED_PUBKEY_HASH
AddrTypeTaprootPubkey = lnrpc.AddressType_TAPROOT_PUBKEY
) )
// harnessTest wraps a regular testing.T providing enhanced error detection // harnessTest wraps a regular testing.T providing enhanced error detection