Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions .github/workflows/python-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ jobs:
matrix:
python-version: ['3.12']
os: [ ubuntu-22.04 ] # [macos-latest, ubuntu-22.04, windows-latest]
backend: [fulcrum, cbf]
env:
DISPLAY: ":99.0" # Display setting for Xvfb on Linux
QT_SELECT: "qt6" # Environment variable to select Qt6
Expand Down Expand Up @@ -74,15 +75,15 @@ jobs:

- name: Run General Tests
run: |
poetry run pytest -m 'not marker_qt_1 and not marker_qt_2' -vvv --log-cli-level=DEBUG --setup-show --maxfail=1
poetry run pytest -m 'not marker_qt_1 and not marker_qt_2' -vvv --log-cli-level=DEBUG --setup-show --maxfail=1 --${{ matrix.backend }}

- name: Run Tests for marker_qt_1
run: |
poetry run pytest -m 'marker_qt_1' -vvv --log-cli-level=DEBUG --setup-show --maxfail=1
poetry run pytest -m 'marker_qt_1' -vvv --log-cli-level=DEBUG --setup-show --maxfail=1 --${{ matrix.backend }}

- name: Run Tests for marker_qt_2
run: |
poetry run pytest -m 'marker_qt_2' -vvv --log-cli-level=DEBUG --setup-show --maxfail=1
poetry run pytest -m 'marker_qt_2' -vvv --log-cli-level=DEBUG --setup-show --maxfail=1 --${{ matrix.backend }}



Expand All @@ -91,5 +92,5 @@ jobs:
if: always() # This ensures the step runs regardless of previous failures
uses: actions/upload-artifact@v4
with:
name: test-output
path: tests/output
name: test-output-${{ matrix.python-version }}-${{ matrix.os }}-${{ matrix.backend }}
path: tests/output
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,8 @@ test-seed
*.wallet
bitcoin_core
fulcrum
tests/bitcoin_data/
tests/cbf_data/
tools-my/


Expand Down
49 changes: 45 additions & 4 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
{
"version": "0.1.0",
"configurations": [
{
"configurations": [{
"name": "Python: Module",
"type": "python",
"request": "launch",
Expand All @@ -14,15 +13,35 @@
// "justMyCode": false
},
{
"name": "Pytest",
"name": "Pytest cbf backend",
"type": "python",
"request": "launch",
"module": "pytest",
"args": [
"-vvv",
"--cbf",
"--ignore=coding_tests",
"--ignore=tools",
"--maxfail=1",
],

"console": "integratedTerminal",
"preLaunchTask": "Poetry Install",
// "justMyCode": false
},
{
"name": "Pytest fulcrum",
"type": "python",
"request": "launch",
"module": "pytest",
"args": [
"-vvv",
"--fulcrum",
"--ignore=coding_tests",
"--ignore=tools",
"--maxfail=1",
],

"console": "integratedTerminal",
"preLaunchTask": "Poetry Install",
// "justMyCode": false
Expand All @@ -34,9 +53,11 @@
"module": "pytest",
"args": [
// "-vvv",
"--cbf",
"tests/gui",
"--ignore=coding_tests",
"--ignore=tools",
"--maxfail=1",
// "-s", // Disable all capturing of outputs
],
"console": "integratedTerminal",
Expand All @@ -50,23 +71,43 @@
"module": "pytest",
"args": [
"-vvv",
"--cbf",
"--ignore=tests/gui",
"--ignore=tools",
"--maxfail=1",
"-s", // Disable all capturing of outputs
],
"console": "integratedTerminal",
"justMyCode": false,
"preLaunchTask": "Poetry Install",
}, {
"name": "Pytest: Current File [fulcrum]",
"type": "python",
"request": "launch",
"module": "pytest",
"args": [
"-vvv",
"--fulcrum",
"${file}",
"-s", // Disable all capturing of outputs
"--ignore=tools",
"--maxfail=1",
],
"console": "integratedTerminal",
"justMyCode": false,
"preLaunchTask": "Poetry Install",
}, {
"name": "Pytest: Current File",
"name": "Pytest: Current File [cbf]",
"type": "python",
"request": "launch",
"module": "pytest",
"args": [
"-vvv",
"--cbf",
"${file}",
"-s", // Disable all capturing of outputs
"--ignore=tools",
"--maxfail=1",
],
"console": "integratedTerminal",
"justMyCode": false,
Expand Down
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@
"tests"
],
"python.testing.unittestEnabled": false,
"python.testing.pytestEnabled": true
"python.testing.pytestEnabled": true,
"python.defaultInterpreterPath": "${workspaceFolder}/.venv/bin/python"
}
5 changes: 4 additions & 1 deletion bitcoin_safe/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

import asyncio
import logging
import time
from concurrent.futures import Future
from datetime import datetime, timedelta
from pathlib import Path
Expand All @@ -49,6 +50,7 @@

class Client:
MAX_PROGRESS_WHILE_SYNC = 0.99
BROADCAST_TIMEOUT = 3

def __init__(
self,
Expand Down Expand Up @@ -232,6 +234,7 @@ def from_cbf(
)

client.build_node()
time.sleep(0.1) # this prevents an ifinite loop of getting info messages from cbf client
return cls(client=client, proxy_info=proxy_info, electrum_config=None, loop_in_thread=loop_in_thread)

def broadcast(self, tx: bdk.Transaction):
Expand All @@ -244,7 +247,7 @@ def broadcast(self, tx: bdk.Transaction):
assert self.client.client, "Not initialized"
try:
return self.loop_in_thread.run_foreground(
asyncio.wait_for(self.client.client.broadcast(tx), timeout=3)
asyncio.wait_for(self.client.client.broadcast(tx), timeout=self.BROADCAST_TIMEOUT)
)
except asyncio.TimeoutError:
logger.error("Broadcast timed out after 3 seconds")
Expand Down
42 changes: 26 additions & 16 deletions bitcoin_safe/gui/qt/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@
from bitcoin_safe.keystore import KeyStoreImporterTypes
from bitcoin_safe.logging_handlers import mail_contact, mail_feedback
from bitcoin_safe.logging_setup import get_log_file
from bitcoin_safe.network_config import P2pListenerType
from bitcoin_safe.network_config import P2pListenerType, Peers
from bitcoin_safe.network_utils import ProxyInfo
from bitcoin_safe.p2p.p2p_client import ConnectionInfo
from bitcoin_safe.p2p.p2p_listener import P2pListener
Expand Down Expand Up @@ -626,15 +626,19 @@ def init_p2p_listening(self):
if self.config.network_config.p2p_listener_type == P2pListenerType.deactive:
return
initial_peer = self.config.network_config.get_p2p_initial_peer()
discovered_peers = Peers(self.config.network_config.discovered_peers)
if initial_peer and initial_peer not in discovered_peers:
discovered_peers.append(initial_peer)
self.p2p_listener = P2pListener(
network=self.config.network,
discovered_peers=self.config.network_config.discovered_peers,
discovered_peers=discovered_peers,
loop_in_thread=self.loop_in_thread,
autodiscover_additional_peers=self.config.network_config.p2p_autodiscover_additional_peers,
)
self.p2p_listener.signal_tx.connect(self.p2p_listening_on_tx)
self.p2p_listener.signal_block.connect(self.p2p_listening_on_block)
self.p2p_listener.start(
initial_peer=initial_peer,
preferred_peers=[initial_peer] if initial_peer else None,
proxy_info=(
ProxyInfo.parse(self.config.network_config.proxy_url)
if self.config.network_config.proxy_url
Expand Down Expand Up @@ -2105,17 +2109,20 @@ def new_wallet_id(self) -> str:
"""New wallet id."""
return f"{self.tr('new')}{len(self.qt_wallets)}"

def _ask_if_full_scan(self) -> bool | None:
return question_dialog(
text=self.tr("Was this wallet ever used before?"),
true_button=self.tr("Yes, full scan for transactions"),
false_button=self.tr("No, quick scan"),
)

def create_qtwallet_from_protowallet(
self, protowallet: ProtoWallet, tutorial_index: int | None
) -> QTWallet:
"""Create qtwallet from protowallet."""
is_new_wallet = False
if self.config.network_config.server_type == BlockchainType.CompactBlockFilter:
answer = question_dialog(
text=self.tr("Was this wallet ever used before?"),
true_button=self.tr("Yes, full scan for transactions"),
false_button=self.tr("No, quick scan"),
)
answer = self._ask_if_full_scan()
if answer is False:
is_new_wallet = True
else:
Expand Down Expand Up @@ -2497,21 +2504,24 @@ def remove_all_qt_wallet(self) -> None:
for qt_wallet in self.qt_wallets.copy().values():
self._remove_qt_wallet(qt_wallet)

def _ask_if_wallet_should_remain_open(self) -> bool | None:
return question_dialog(
text=self.tr(
"This wallet is still syncing and syncing would need to start from scratch if you close it.\nDo you want to keep the wallet open?",
),
title=self.tr("Wallet syncing"),
true_button=self.tr("Keep open"),
false_button=self.tr("Close anyway"),
)

def close_tab(self, node: SidebarNode[TT]) -> None:
"""Close tab."""
if not node.closable and not node.widget == self.welcome_screen:
return
tab_data = node.data
if isinstance(tab_data, QTWallet):
if tab_data.is_in_cbf_ibd():
res = question_dialog(
text=self.tr(
"This wallet is still syncing and syncing would need to start from scratch if you close it.\nDo you want to keep the wallet open?",
),
title=self.tr("Wallet syncing"),
true_button=self.tr("Keep open"),
false_button=self.tr("Close anyway"),
)
res = self._ask_if_wallet_should_remain_open()
if res is None:
return
elif res is True:
Expand Down
2 changes: 1 addition & 1 deletion bitcoin_safe/gui/qt/ui_tx/recipients.py
Original file line number Diff line number Diff line change
Expand Up @@ -660,7 +660,7 @@ def export_csv(self, recipients: list[Recipient], file_path: str | Path | None =
return None

table = self.as_list(recipients)
with open(str(file_path), "w") as file:
with open(str(file_path), "w", newline="") as file:
writer = csv.writer(file)
writer.writerows(table)

Expand Down
3 changes: 2 additions & 1 deletion bitcoin_safe/network_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -433,7 +433,7 @@ class P2pListenerType(enum.Enum):


class NetworkConfig(BaseSaveableClass):
VERSION = "0.2.3"
VERSION = "0.2.5"
known_classes = {
**BaseSaveableClass.known_classes,
BlockchainType.__name__: BlockchainType,
Expand Down Expand Up @@ -466,6 +466,7 @@ def __init__(
self.proxy_url: str | None = None
self.p2p_listener_type: P2pListenerType = P2pListenerType.automatic
self.p2p_inital_url: str = get_default_p2p_node_urls(network=network)["default"]
self.p2p_autodiscover_additional_peers: bool = True
self.discovered_peers: Peers | list[Peer] = discovered_peers if discovered_peers else Peers()
self.mempool_data: MempoolData = mempool_data if mempool_data else MempoolData()

Expand Down
5 changes: 3 additions & 2 deletions bitcoin_safe/p2p/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import bdkpython as bdk
from PyQt6.QtCore import QCoreApplication

from bitcoin_safe.network_config import Peers
from bitcoin_safe.network_utils import ProxyInfo

from .p2p_client import Peer
Expand All @@ -58,7 +59,7 @@
proxy_info = ProxyInfo.parse("socks5h://127.0.0.1:9050")


client = P2pListener(network=network, loop_in_thread=None)
client = P2pListener(network=network, loop_in_thread=None, discovered_peers=Peers([initial_peer]))
# client.set_address_filter(None)


Expand All @@ -68,7 +69,7 @@ def on_tx(tx: bdk.Transaction):


client.signal_tx.connect(on_tx)
client.start(proxy_info=proxy_info)
client.start(proxy_info=proxy_info, preferred_peers=[initial_peer])


while input("type q") != "q":
Expand Down
Loading
Loading