1
0

add unit tests for ln_utxo_reserve

This commit is contained in:
ThomasV
2025-03-22 09:46:18 +01:00
parent 32807462b0
commit 001a1152fd
3 changed files with 72 additions and 17 deletions

View File

@@ -0,0 +1,6 @@
{
"seed": "cause carbon luggage air humble mistake melt paper supreme sense gravity void",
"funding_tx": "020000000001021798e10f8b7220c57ea0d605316a52453ca9b3eed99996b5b7bdf4699548bb520000000000fdffffff277d82678d238ca45dd3490ac9fbb49272f0980b093b9197ff70ec8eb082cfb00100000000fdffffff028c360100000000001600147a9bfd90821be827275023849dd91ee80d494957a08601000000000016001476efaaa243327bf3a2c0f5380cb3914099448cec024730440220354b2a74f5ac039cca3618f7ff98229d243b89ac40550c8b027894f2c5cb88ff022064cb5ab1539b4c5367c2e01a8362e0aa12c2732bc8d08c3fce6eab9e56b7fe19012103e0a1499cb3d8047492c60466722c435dfbcffae8da9b83e758fbd203d12728f502473044022073cef8b0cfb093aed5b8eaacbb58c2fa6a69405a8e266cd65e76b726c9151d7602204d5820b23ab96acc57c272aac96d94740a20a6b89c016aa5aed7c06d1e6b9100012102f09e50a265c6a0dcf7c87153ea73d7b12a0fbe9d7d0bbec5db626b2402c1e85c02fa2400",
"outgoing_address": "tb1qkfn0fude7z789uys2u7sf80kd4805zpvs3na0h",
"to_self_address": "tb1qyfnv3y866ufedugxxxfksyratv4pz3h78g9dad"
}

View File

@@ -14,7 +14,9 @@ from electrum.lnsweep import SweepInfo
from electrum.fee_policy import FeeTimeEstimates from electrum.fee_policy import FeeTimeEstimates
from . import ElectrumTestCase from . import ElectrumTestCase
from .test_wallet_vertical import WalletIntegrityHelper from .test_wallet_vertical import WalletIntegrityHelper, read_test_vector
WALLET_DATA = read_test_vector('cause_carbon_wallet.json')
class MockNetwork(Logger): class MockNetwork(Logger):
@@ -49,8 +51,6 @@ class MockNetwork(Logger):
return tx return tx
WALLET_SEED = 'cause carbon luggage air humble mistake melt paper supreme sense gravity void'
FUNDING_TX = '020000000001021798e10f8b7220c57ea0d605316a52453ca9b3eed99996b5b7bdf4699548bb520000000000fdffffff277d82678d238ca45dd3490ac9fbb49272f0980b093b9197ff70ec8eb082cfb00100000000fdffffff028c360100000000001600147a9bfd90821be827275023849dd91ee80d494957a08601000000000016001476efaaa243327bf3a2c0f5380cb3914099448cec024730440220354b2a74f5ac039cca3618f7ff98229d243b89ac40550c8b027894f2c5cb88ff022064cb5ab1539b4c5367c2e01a8362e0aa12c2732bc8d08c3fce6eab9e56b7fe19012103e0a1499cb3d8047492c60466722c435dfbcffae8da9b83e758fbd203d12728f502473044022073cef8b0cfb093aed5b8eaacbb58c2fa6a69405a8e266cd65e76b726c9151d7602204d5820b23ab96acc57c272aac96d94740a20a6b89c016aa5aed7c06d1e6b9100012102f09e50a265c6a0dcf7c87153ea73d7b12a0fbe9d7d0bbec5db626b2402c1e85c02fa2400'
SWAP_FUNDING_TX = "01000000000101500e9d67647481864edfb020b5c45e1c40d90f06b0130f9faed1a5149c6d26450000000000ffffffff0226080300000000002200205059c44bf57534303ab8f090f06b7bde58f5d2522440247a1ff6b41bdca9348df312c20100000000160014021d4f3b17921d790e1c022367a5bb078ce4deb402483045022100d41331089a2031396a1db8e4dec6dda9cacefe1288644b92f8e08a23325aa19b02204159230691601f7d726e4e6e0b7124d3377620f400d699a01095f0b0a09ee26a012102d60315c72c0cefd41c6d07883c20b88be3fc37aac7912f0052722a95de0de71600000000" SWAP_FUNDING_TX = "01000000000101500e9d67647481864edfb020b5c45e1c40d90f06b0130f9faed1a5149c6d26450000000000ffffffff0226080300000000002200205059c44bf57534303ab8f090f06b7bde58f5d2522440247a1ff6b41bdca9348df312c20100000000160014021d4f3b17921d790e1c022367a5bb078ce4deb402483045022100d41331089a2031396a1db8e4dec6dda9cacefe1288644b92f8e08a23325aa19b02204159230691601f7d726e4e6e0b7124d3377620f400d699a01095f0b0a09ee26a012102d60315c72c0cefd41c6d07883c20b88be3fc37aac7912f0052722a95de0de71600000000"
SWAP_CLAIM_TX = "02000000000101f9db8580febd5c0f85b6f1576c83f7739109e3a2d772743e3217e9537fea7e890000000000fdffffff017005030000000000160014b113a47f3718da3fd161339a6681c150fef2cfe30347304402206736066ce15d34eed20951a9d974a100a72dc034f9c878769ddf27f9a584dcb1022042b14d627b8e8465a3a129bb43c0bd8369f49bbcf473879b9a477263655f1f930120f1939b5723155713855d7ebea6e174f77d41d669269e7f138856c3de190e7a366a8201208763a914d7a62ef0270960fe23f0f351b28caadab62c21838821030bfd61153816df786036ea293edce851d3a4b9f4a1c66bdc1a17f00ffef3d6b167750334ef24b1752102fc8128f17f9e666ea281c702171ab16c1dd2a4337b71f08970f5aa10c608a93268ac00000000" SWAP_CLAIM_TX = "02000000000101f9db8580febd5c0f85b6f1576c83f7739109e3a2d772743e3217e9537fea7e890000000000fdffffff017005030000000000160014b113a47f3718da3fd161339a6681c150fef2cfe30347304402206736066ce15d34eed20951a9d974a100a72dc034f9c878769ddf27f9a584dcb1022042b14d627b8e8465a3a129bb43c0bd8369f49bbcf473879b9a477263655f1f930120f1939b5723155713855d7ebea6e174f77d41d669269e7f138856c3de190e7a366a8201208763a914d7a62ef0270960fe23f0f351b28caadab62c21838821030bfd61153816df786036ea293edce851d3a4b9f4a1c66bdc1a17f00ffef3d6b167750334ef24b1752102fc8128f17f9e666ea281c702171ab16c1dd2a4337b71f08970f5aa10c608a93268ac00000000"
@@ -80,7 +80,7 @@ class TestTxBatcher(ElectrumTestCase):
return WalletIntegrityHelper.create_standard_wallet(ks, gap_limit=gap_limit, config=config) return WalletIntegrityHelper.create_standard_wallet(ks, gap_limit=gap_limit, config=config)
def _create_wallet(self): def _create_wallet(self):
wallet = self.create_standard_wallet_from_seed(WALLET_SEED) wallet = self.create_standard_wallet_from_seed(WALLET_DATA["seed"])
wallet.start_network(self.network) wallet.start_network(self.network)
wallet.txbatcher.SLEEP_INTERVAL = 0.01 wallet.txbatcher.SLEEP_INTERVAL = 0.01
self.network.wallets.append(wallet) self.network.wallets.append(wallet)
@@ -99,7 +99,7 @@ class TestTxBatcher(ElectrumTestCase):
OUTGOING_ADDRESS = 'tb1q7rl9cxr85962ztnsze089zs8ycv52hk43f3m9n' OUTGOING_ADDRESS = 'tb1q7rl9cxr85962ztnsze089zs8ycv52hk43f3m9n'
wallet = self._create_wallet() wallet = self._create_wallet()
# fund wallet # fund wallet
funding_tx = Transaction(FUNDING_TX) funding_tx = Transaction(WALLET_DATA["funding_tx"])
await self.network.try_broadcasting(funding_tx, 'funding') await self.network.try_broadcasting(funding_tx, 'funding')
await self.network.next_tx() await self.network.next_tx()
assert wallet.adb.get_transaction(funding_tx.txid()) is not None assert wallet.adb.get_transaction(funding_tx.txid()) is not None
@@ -140,9 +140,8 @@ class TestTxBatcher(ElectrumTestCase):
The tx batcher fails to batch, and should create a child transaction The tx batcher fails to batch, and should create a child transaction
""" """
wallet = self._create_wallet() wallet = self._create_wallet()
# fund wallet # fund wallet
funding_tx = Transaction(FUNDING_TX) funding_tx = Transaction(WALLET_DATA['funding_tx'])
await self.network.try_broadcasting(funding_tx, 'funding') await self.network.try_broadcasting(funding_tx, 'funding')
await self.network.next_tx() await self.network.next_tx()
assert wallet.adb.get_transaction(funding_tx.txid()) is not None assert wallet.adb.get_transaction(funding_tx.txid()) is not None

View File

@@ -82,6 +82,14 @@ class WalletIntegrityHelper:
return w return w
def read_test_vector(filename: str):
import os
from electrum.util import read_json_file
path = os.path.join(os.path.dirname(__file__), filename)
data = read_json_file(path)
return data
class TestWalletKeystoreAddressIntegrityForMainnet(ElectrumTestCase): class TestWalletKeystoreAddressIntegrityForMainnet(ElectrumTestCase):
def setUp(self): def setUp(self):
@@ -2005,27 +2013,69 @@ class TestWalletSending(ElectrumTestCase):
wallet.adb.receive_tx_callback(tx, TX_HEIGHT_UNCONFIRMED) wallet.adb.receive_tx_callback(tx, TX_HEIGHT_UNCONFIRMED)
self.assertEqual((0, 3_900_000, 0), wallet.get_balance()) self.assertEqual((0, 3_900_000, 0), wallet.get_balance())
def _create_cause_carbon_wallet(self):
data = read_test_vector('cause_carbon_wallet.json')
ks = keystore.from_seed(data['seed'], passphrase='', for_multisig=False)
wallet = WalletIntegrityHelper.create_standard_wallet(ks, gap_limit=2, config=self.config)
# bootstrap wallet (incoming funding_tx0)
funding_tx = Transaction(data['funding_tx'])
wallet.adb.receive_tx_callback(funding_tx, TX_HEIGHT_UNCONFIRMED)
return wallet, data['outgoing_address'], data['to_self_address']
async def test_ln_reserve_send_everything(self):
""" send all the coins, not using 'max' """
wallet, outgoing_address, to_self_address = self._create_cause_carbon_wallet()
balance = sum(wallet.get_balance())
assert balance == 100_000
fee_sats = 1000
outputs = [PartialTxOutput.from_address_and_value(outgoing_address, balance - fee_sats)]
def make_tx(b):
return wallet.make_unsigned_transaction(
outputs = outputs,
is_anchor_channel_opening = b,
fee_policy = FixedFeePolicy(fee_sats),
)
tx = make_tx(False)
self.assertEqual(1, len(tx.outputs()))
with self.assertRaises(NotEnoughFunds):
make_tx(True)
async def test_ln_reserve_spend_max(self):
""" send all the coins using 'max'. test with outgoing and to self address """
wallet, outgoing_address, to_self_address = self._create_cause_carbon_wallet()
def make_tx(address):
outputs = [PartialTxOutput.from_address_and_value(address, '!')]
return wallet.make_unsigned_transaction(
outputs = outputs,
is_anchor_channel_opening = True,
fee_policy = FixedFeePolicy(100),
)
tx = make_tx(outgoing_address)
self.assertEqual(2, len(tx.outputs()))
tx = make_tx(to_self_address)
self.assertEqual(1, len(tx.outputs()))
async def test_rbf_batching__cannot_batch_as_would_need_to_use_ismine_outputs_of_basetx(self): async def test_rbf_batching__cannot_batch_as_would_need_to_use_ismine_outputs_of_basetx(self):
"""Wallet history contains unconf tx1 that spends all its coins to two ismine outputs, """Wallet history contains unconf tx1 that spends all its coins to two ismine outputs,
one 'recv' address (20k sats) and one 'change' (80k sats). one 'recv' address (20k sats) and one 'change' (80k sats).
The user tries to create tx2, that pays an invoice for 90k sats. The user tries to create tx2, that pays an invoice for 90k sats.
Even if batch_rbf==True, no batching should be done. Instead, the outputs of tx1 should be used. Even if batch_rbf==True, no batching should be done. Instead, the outputs of tx1 should be used.
""" """
wallet = self.create_standard_wallet_from_seed('cause carbon luggage air humble mistake melt paper supreme sense gravity void', wallet, outgoing_address, to_self_address = self._create_cause_carbon_wallet()
config=self.config)
# bootstrap wallet (incoming funding_tx0)
funding_tx = Transaction('020000000001021798e10f8b7220c57ea0d605316a52453ca9b3eed99996b5b7bdf4699548bb520000000000fdffffff277d82678d238ca45dd3490ac9fbb49272f0980b093b9197ff70ec8eb082cfb00100000000fdffffff028c360100000000001600147a9bfd90821be827275023849dd91ee80d494957a08601000000000016001476efaaa243327bf3a2c0f5380cb3914099448cec024730440220354b2a74f5ac039cca3618f7ff98229d243b89ac40550c8b027894f2c5cb88ff022064cb5ab1539b4c5367c2e01a8362e0aa12c2732bc8d08c3fce6eab9e56b7fe19012103e0a1499cb3d8047492c60466722c435dfbcffae8da9b83e758fbd203d12728f502473044022073cef8b0cfb093aed5b8eaacbb58c2fa6a69405a8e266cd65e76b726c9151d7602204d5820b23ab96acc57c272aac96d94740a20a6b89c016aa5aed7c06d1e6b9100012102f09e50a265c6a0dcf7c87153ea73d7b12a0fbe9d7d0bbec5db626b2402c1e85c02fa2400')
funding_txid = funding_tx.txid()
wallet.adb.receive_tx_callback(funding_tx, TX_HEIGHT_UNCONFIRMED)
# to_self_payment tx1 # to_self_payment tx1
toself_tx = Transaction('02000000000101ce05b8ae96fe8d2875fd1efcb591b6fb5c5d924bf05d75d880a0e44498fe14b80100000000fdffffff02204e0000000000001600142266c890fad71396f106319368107d5b2a1146feb837010000000000160014b113a47f3718da3fd161339a6681c150fef2cfe3024730440220197bfea1bc5c86c35d68029422342de97c1e5d9adc12e48d99ae359940211a660220770ddb228ae75698f827e2fddc574f0c8eb2a3e109678a2a2b6bc9cbb9593b1c012102b07ca318381fcef5998f34ee4197e96c17aa19867cbe99c544d321807db95ed2f1f92400') outputs = [PartialTxOutput.from_address_and_value(to_self_address, 20_000)]
toself_tx = wallet.make_unsigned_transaction(
outputs = outputs,
fee_policy = FixedFeePolicy(200),
locktime = 2423281,
rbf = True,
)
wallet.sign_transaction(toself_tx, password=None)
toself_txid = toself_tx.txid() toself_txid = toself_tx.txid()
wallet.adb.receive_tx_callback(toself_tx, TX_HEIGHT_UNCONFIRMED) wallet.adb.receive_tx_callback(toself_tx, TX_HEIGHT_UNCONFIRMED)
# create outgoing tx2 # create outgoing tx2
outputs = [PartialTxOutput.from_address_and_value("tb1qkfn0fude7z789uys2u7sf80kd4805zpvs3na0h", 90_000)] outputs = [PartialTxOutput.from_address_and_value(outgoing_address, 90_000)]
coins = wallet.get_spendable_coins(domain=None) coins = wallet.get_spendable_coins(domain=None)
self.assertEqual(2, len(coins)) self.assertEqual(2, len(coins))