forked from bitcoinafterlife/bal-electrum-plugin
135 lines
4.9 KiB
Python
135 lines
4.9 KiB
Python
"""
|
|
Shared test fixtures for the BAL plugin test-suite.
|
|
|
|
This module centralises the "plausible data" used by the mock tests:
|
|
|
|
* Valid Bitcoin (regtest) addresses are read **read-only** from the
|
|
``giovanna7`` wallet so the heirs / change / will-executor addresses are
|
|
genuine, well-formed addresses for the active network.
|
|
* A lightweight fake wallet and a fake ``bal_plugin`` are provided so the
|
|
core inheritance logic (``Heirs.buildTransactions`` / ``get_transactions``)
|
|
can be exercised without a running Electrum daemon or any network access.
|
|
|
|
Nothing here touches the real wallet file other than reading it; the file is
|
|
opened read-only and never written back.
|
|
"""
|
|
|
|
import json
|
|
import os
|
|
from unittest.mock import MagicMock
|
|
|
|
from electrum.transaction import PartialTxInput, TxOutpoint
|
|
from electrum.util import bfh
|
|
|
|
# Read-only path to the giovanna7 regtest wallet used to source valid addresses.
|
|
GIOVANNA7_WALLET = (
|
|
"/home/steal/devel/bal/electrum2/.electrum2222/regtest/wallets.old/giovanna7"
|
|
)
|
|
|
|
# Fallback regtest addresses (used if the wallet file is not available, e.g. on
|
|
# CI), so the address-dependent tests can still run. These are valid regtest
|
|
# bech32 addresses taken from the giovanna7 wallet.
|
|
_FALLBACK_RECEIVING = [
|
|
"bcrt1qpm5utekdtmzwnlkh7jq5497vwwf6sm38tljan5",
|
|
"bcrt1qazle627r46apscly8lj4q5cxfxgrtuew879jde",
|
|
"bcrt1qh2c83yulvs7kgw0g6q3lkxqws4cnf0uxpcgcpt",
|
|
"bcrt1qsprcgaldcn6v6l6jw0w6annv7hgkpw7ycxu6mu",
|
|
"bcrt1qy02pnw9lulnnwg6m77yghn6v7ndgnjph3hrdmy",
|
|
"bcrt1qrmjaxllejgqu6azftsfu2cdjyrz8wjxzsv7wvp",
|
|
]
|
|
_FALLBACK_CHANGE = [
|
|
"bcrt1qzu5u0fgpxq5v42r62aefc2xjn6mehgzhtj4pld",
|
|
"bcrt1qs9ya5hserz44elcpt992r0ycrmh3w3chzffawc",
|
|
"bcrt1q28qtj5ugfcm4psqenq54sh55uryealeeprk6ju",
|
|
]
|
|
|
|
|
|
def load_addresses():
|
|
"""Return ``(receiving, change)`` address lists from the giovanna7 wallet.
|
|
|
|
Falls back to a small hard-coded set of valid regtest addresses when the
|
|
wallet file cannot be read, so the tests remain runnable everywhere.
|
|
"""
|
|
try:
|
|
with open(GIOVANNA7_WALLET, "r") as f:
|
|
data = json.load(f)
|
|
receiving = data["addresses"]["receiving"]
|
|
change = data["addresses"]["change"]
|
|
if receiving and change:
|
|
return receiving, change
|
|
except Exception:
|
|
pass
|
|
return list(_FALLBACK_RECEIVING), list(_FALLBACK_CHANGE)
|
|
|
|
|
|
# Module-level cached address pools.
|
|
RECEIVING_ADDRESSES, CHANGE_ADDRESSES = load_addresses()
|
|
|
|
|
|
def heir_addresses(n):
|
|
"""Return ``n`` distinct valid heir addresses from the giovanna7 wallet."""
|
|
# Use addresses further into the list so they do not collide with the
|
|
# change address used by the fake wallet.
|
|
return RECEIVING_ADDRESSES[10 : 10 + n]
|
|
|
|
|
|
def willexecutor_addresses(n):
|
|
"""Return ``n`` distinct valid will-executor payout addresses."""
|
|
return RECEIVING_ADDRESSES[100 : 100 + n]
|
|
|
|
|
|
def change_address():
|
|
"""Return a single valid change address."""
|
|
return CHANGE_ADDRESSES[0]
|
|
|
|
|
|
def make_utxo(txid_hex, value, out_idx=0):
|
|
"""Build a minimal spendable ``PartialTxInput`` with the given value.
|
|
|
|
Only the fields required by the inheritance transaction builder are set
|
|
(trusted value + ``is_mine``); this mirrors how Electrum hands UTXOs to the
|
|
plugin without needing a real wallet.
|
|
"""
|
|
txin = PartialTxInput(prevout=TxOutpoint(txid=bfh(txid_hex), out_idx=out_idx))
|
|
txin._trusted_value_sats = value
|
|
txin._TxInput__value_sats = value
|
|
txin.is_mine = True
|
|
return txin
|
|
|
|
|
|
def make_utxos(n, value=1_000_000, prefix="a1"):
|
|
"""Return ``n`` synthetic UTXOs of ``value`` satoshis each."""
|
|
return [make_utxo(f"{prefix}{i:062x}", value) for i in range(n)]
|
|
|
|
|
|
def fake_wallet(dust_threshold=546):
|
|
"""Return a MagicMock wallet sufficient for the inheritance builder.
|
|
|
|
The change address comes from the real giovanna7 wallet so generated
|
|
transactions carry a valid change output address.
|
|
"""
|
|
w = MagicMock()
|
|
w.dust_threshold.return_value = dust_threshold
|
|
w.get_change_addresses_for_new_transaction.return_value = [change_address()]
|
|
w.get_utxos.return_value = []
|
|
w.db.get.return_value = {}
|
|
w.db.get_transaction.return_value = None
|
|
return w
|
|
|
|
|
|
def fake_bal_plugin(willexecutors=None, no_willexecutor=False, decimal_point=8):
|
|
"""Return a fake ``bal_plugin`` exposing only what the builder reads.
|
|
|
|
Args:
|
|
willexecutors: ``{url: we_dict}`` mapping returned by
|
|
``Willexecutors.get_willexecutors`` (patched in the tests).
|
|
no_willexecutor: value of the ``NO_WILLEXECUTOR`` toggle (whether a
|
|
local backup transaction without will-executor is also produced).
|
|
decimal_point: BTC decimal point (8 for satoshi precision).
|
|
"""
|
|
plugin = MagicMock()
|
|
plugin.get_decimal_point.return_value = decimal_point
|
|
plugin.NO_WILLEXECUTOR.get.return_value = no_willexecutor
|
|
plugin._willexecutors = willexecutors or {}
|
|
return plugin
|