mirror of
https://github.com/basicswap/basicswap.git
synced 2026-04-29 11:12:12 +02:00
Fix: Segfault + log spam and various fixes.
This commit is contained in:
@@ -3099,7 +3099,10 @@ class BTCInterface(Secp256k1Interface):
|
|||||||
}
|
}
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
error_msg = str(e).lower()
|
error_msg = str(e).lower()
|
||||||
if "no such mempool or blockchain transaction" not in error_msg:
|
if (
|
||||||
|
"no such mempool or blockchain transaction" not in error_msg
|
||||||
|
and "missing transaction" not in error_msg
|
||||||
|
):
|
||||||
self._log.debug(
|
self._log.debug(
|
||||||
f"checkWatchedOutput exception for {txid_hex}:{vout}: {e}"
|
f"checkWatchedOutput exception for {txid_hex}:{vout}: {e}"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -82,9 +82,24 @@ class ElectrumConnection:
|
|||||||
self._proxy_host = proxy_host
|
self._proxy_host = proxy_host
|
||||||
self._proxy_port = proxy_port
|
self._proxy_port = proxy_port
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _is_private_address(host: str) -> bool:
|
||||||
|
try:
|
||||||
|
import ipaddress
|
||||||
|
|
||||||
|
addr = ipaddress.ip_address(host)
|
||||||
|
return addr.is_private or addr.is_loopback or addr.is_link_local
|
||||||
|
except ValueError:
|
||||||
|
return host == "localhost"
|
||||||
|
|
||||||
def connect(self):
|
def connect(self):
|
||||||
try:
|
try:
|
||||||
if self._proxy_host and self._proxy_port:
|
use_proxy = (
|
||||||
|
self._proxy_host
|
||||||
|
and self._proxy_port
|
||||||
|
and not self._is_private_address(self._host)
|
||||||
|
)
|
||||||
|
if use_proxy:
|
||||||
import socks
|
import socks
|
||||||
|
|
||||||
sock = socks.socksocket()
|
sock = socks.socksocket()
|
||||||
@@ -101,6 +116,10 @@ class ElectrumConnection:
|
|||||||
sock = socket.create_connection(
|
sock = socket.create_connection(
|
||||||
(self._host, self._port), timeout=self._timeout
|
(self._host, self._port), timeout=self._timeout
|
||||||
)
|
)
|
||||||
|
if self._log and self._proxy_host and self._proxy_port:
|
||||||
|
self._log.debug(
|
||||||
|
f"Electrum connecting directly to LAN server {self._host}:{self._port} (bypassing proxy)"
|
||||||
|
)
|
||||||
if self._use_ssl:
|
if self._use_ssl:
|
||||||
context = ssl.create_default_context()
|
context = ssl.create_default_context()
|
||||||
context.check_hostname = False
|
context.check_hostname = False
|
||||||
@@ -546,11 +565,6 @@ class ElectrumServer:
|
|||||||
elif isinstance(srv, dict):
|
elif isinstance(srv, dict):
|
||||||
user_onion.append(srv)
|
user_onion.append(srv)
|
||||||
|
|
||||||
final_clearnet = (
|
|
||||||
user_clearnet
|
|
||||||
if user_clearnet
|
|
||||||
else DEFAULT_ELECTRUM_SERVERS.get(coin_name, [])
|
|
||||||
)
|
|
||||||
final_onion = (
|
final_onion = (
|
||||||
user_onion if user_onion else DEFAULT_ONION_SERVERS.get(coin_name, [])
|
user_onion if user_onion else DEFAULT_ONION_SERVERS.get(coin_name, [])
|
||||||
)
|
)
|
||||||
@@ -558,13 +572,26 @@ class ElectrumServer:
|
|||||||
self._using_default_servers = not user_clearnet and not user_onion
|
self._using_default_servers = not user_clearnet and not user_onion
|
||||||
|
|
||||||
if use_tor:
|
if use_tor:
|
||||||
|
if user_onion and not user_clearnet:
|
||||||
|
final_clearnet = []
|
||||||
|
else:
|
||||||
|
final_clearnet = (
|
||||||
|
user_clearnet
|
||||||
|
if user_clearnet
|
||||||
|
else DEFAULT_ELECTRUM_SERVERS.get(coin_name, [])
|
||||||
|
)
|
||||||
self._servers = list(final_onion) + list(final_clearnet)
|
self._servers = list(final_onion) + list(final_clearnet)
|
||||||
if self._log and final_onion:
|
if self._log:
|
||||||
self._log.info(
|
self._log.info(
|
||||||
f"ElectrumServer {coin_name}: TOR enabled - "
|
f"ElectrumServer {coin_name}: TOR enabled - "
|
||||||
f"{len(final_onion)} .onion + {len(final_clearnet)} clearnet servers"
|
f"{len(final_onion)} .onion + {len(final_clearnet)} clearnet servers"
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
|
final_clearnet = (
|
||||||
|
user_clearnet
|
||||||
|
if user_clearnet
|
||||||
|
else DEFAULT_ELECTRUM_SERVERS.get(coin_name, [])
|
||||||
|
)
|
||||||
self._servers = list(final_clearnet)
|
self._servers = list(final_clearnet)
|
||||||
if self._log:
|
if self._log:
|
||||||
self._log.info(
|
self._log.info(
|
||||||
@@ -983,19 +1010,21 @@ class ElectrumServer:
|
|||||||
def call_background(self, method, params=None, timeout=20):
|
def call_background(self, method, params=None, timeout=20):
|
||||||
if self._stopping:
|
if self._stopping:
|
||||||
raise TemporaryError("Electrum server is shutting down")
|
raise TemporaryError("Electrum server is shutting down")
|
||||||
conn = self._connection
|
lock_acquired = self._lock.acquire(timeout=timeout + 5)
|
||||||
if conn is None or not conn.is_connected():
|
if not lock_acquired:
|
||||||
|
raise TemporaryError(
|
||||||
|
f"Electrum background call timed out waiting for lock: {method}"
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
for attempt in range(2):
|
||||||
if self._stopping:
|
if self._stopping:
|
||||||
raise TemporaryError("Electrum server is shutting down")
|
raise TemporaryError("Electrum server is shutting down")
|
||||||
try:
|
if self._connection is None or not self._connection.is_connected():
|
||||||
self.connect()
|
self.connect()
|
||||||
conn = self._connection
|
if self._connection is None:
|
||||||
except Exception:
|
|
||||||
raise TemporaryError("Electrum call failed: no connection")
|
|
||||||
if conn is None or not conn.is_connected():
|
|
||||||
raise TemporaryError("Electrum call failed: no connection")
|
raise TemporaryError("Electrum call failed: no connection")
|
||||||
try:
|
try:
|
||||||
result = conn.call(method, params, timeout=timeout)
|
result = self._connection.call(method, params, timeout=timeout)
|
||||||
self._last_activity = time.time()
|
self._last_activity = time.time()
|
||||||
return result
|
return result
|
||||||
except TemporaryError as e:
|
except TemporaryError as e:
|
||||||
@@ -1003,27 +1032,41 @@ class ElectrumServer:
|
|||||||
raise TemporaryError("Electrum server is shutting down")
|
raise TemporaryError("Electrum server is shutting down")
|
||||||
if "timed out" in str(e).lower():
|
if "timed out" in str(e).lower():
|
||||||
self._record_timeout()
|
self._record_timeout()
|
||||||
|
if attempt == 0:
|
||||||
|
self._retry_on_failure()
|
||||||
|
else:
|
||||||
raise
|
raise
|
||||||
|
except Exception as e:
|
||||||
|
if self._is_rate_limit_error(str(e)):
|
||||||
|
server = self._get_server(self._current_server_idx)
|
||||||
|
self._blacklist_server(server, str(e))
|
||||||
|
if attempt == 0:
|
||||||
|
self._retry_on_failure()
|
||||||
|
else:
|
||||||
|
raise
|
||||||
|
finally:
|
||||||
|
self._lock.release()
|
||||||
|
|
||||||
def call_batch_background(self, requests, timeout=30):
|
def call_batch_background(self, requests, timeout=30):
|
||||||
if self._stopping:
|
if self._stopping:
|
||||||
raise TemporaryError("Electrum server is shutting down")
|
raise TemporaryError("Electrum server is shutting down")
|
||||||
conn = self._connection
|
lock_acquired = self._lock.acquire(timeout=timeout + 5)
|
||||||
if conn is None or not conn.is_connected():
|
if not lock_acquired:
|
||||||
|
raise TemporaryError(
|
||||||
|
"Electrum background batch call timed out waiting for lock"
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
for attempt in range(2):
|
||||||
if self._stopping:
|
if self._stopping:
|
||||||
raise TemporaryError("Electrum server is shutting down")
|
raise TemporaryError("Electrum server is shutting down")
|
||||||
self._record_timeout()
|
if self._connection is None or not self._connection.is_connected():
|
||||||
conn = self._connection
|
|
||||||
if conn is None or not conn.is_connected():
|
|
||||||
try:
|
|
||||||
self.connect()
|
self.connect()
|
||||||
conn = self._connection
|
if self._connection is None:
|
||||||
except Exception:
|
raise TemporaryError(
|
||||||
raise TemporaryError("Electrum batch call failed: no connection")
|
"Electrum batch call failed: no connection"
|
||||||
if conn is None or not conn.is_connected():
|
)
|
||||||
raise TemporaryError("Electrum batch call failed: no connection")
|
|
||||||
try:
|
try:
|
||||||
result = conn.call_batch(requests)
|
result = self._connection.call_batch(requests)
|
||||||
self._last_activity = time.time()
|
self._last_activity = time.time()
|
||||||
return result
|
return result
|
||||||
except TemporaryError as e:
|
except TemporaryError as e:
|
||||||
@@ -1031,7 +1074,20 @@ class ElectrumServer:
|
|||||||
raise TemporaryError("Electrum server is shutting down")
|
raise TemporaryError("Electrum server is shutting down")
|
||||||
if "timed out" in str(e).lower():
|
if "timed out" in str(e).lower():
|
||||||
self._record_timeout()
|
self._record_timeout()
|
||||||
|
if attempt == 0:
|
||||||
|
self._retry_on_failure()
|
||||||
|
else:
|
||||||
raise
|
raise
|
||||||
|
except Exception as e:
|
||||||
|
if self._is_rate_limit_error(str(e)):
|
||||||
|
server = self._get_server(self._current_server_idx)
|
||||||
|
self._blacklist_server(server, str(e))
|
||||||
|
if attempt == 0:
|
||||||
|
self._retry_on_failure()
|
||||||
|
else:
|
||||||
|
raise
|
||||||
|
finally:
|
||||||
|
self._lock.release()
|
||||||
|
|
||||||
def call_user(self, method, params=None, timeout=10):
|
def call_user(self, method, params=None, timeout=10):
|
||||||
if self._stopping:
|
if self._stopping:
|
||||||
|
|||||||
@@ -1631,7 +1631,10 @@ def js_wallettransactions(self, url_split, post_string, is_json) -> bytes:
|
|||||||
or (current_time - cache_entry["time"]) > TX_CACHE_DURATION
|
or (current_time - cache_entry["time"]) > TX_CACHE_DURATION
|
||||||
):
|
):
|
||||||
all_txs = ci.listWalletTransactions(count=10000, skip=0)
|
all_txs = ci.listWalletTransactions(count=10000, skip=0)
|
||||||
all_txs = list(reversed(all_txs)) if all_txs else []
|
if all_txs and coin_id not in (Coins.XMR, Coins.WOW):
|
||||||
|
all_txs = list(reversed(all_txs))
|
||||||
|
elif not all_txs:
|
||||||
|
all_txs = []
|
||||||
swap_client._tx_cache[coin_id] = {"txs": all_txs, "time": current_time}
|
swap_client._tx_cache[coin_id] = {"txs": all_txs, "time": current_time}
|
||||||
else:
|
else:
|
||||||
all_txs = cache_entry["txs"]
|
all_txs = cache_entry["txs"]
|
||||||
|
|||||||
@@ -1,3 +1,22 @@
|
|||||||
|
(function() {
|
||||||
|
const originalFetch = window.fetch;
|
||||||
|
window.fetch = function(url, options) {
|
||||||
|
return originalFetch.apply(this, arguments).then(function(response) {
|
||||||
|
if (response.status === 401) {
|
||||||
|
const urlStr = typeof url === 'string' ? url : (url && url.url) || '';
|
||||||
|
if (urlStr.startsWith('/json/') || urlStr.startsWith('/json')) {
|
||||||
|
window.location.href = '/login';
|
||||||
|
return new Response(JSON.stringify({error: 'Session expired'}), {
|
||||||
|
status: 401,
|
||||||
|
headers: {'Content-Type': 'application/json'}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
const burger = document.querySelectorAll('.navbar-burger');
|
const burger = document.querySelectorAll('.navbar-burger');
|
||||||
const menu = document.querySelectorAll('.navbar-menu');
|
const menu = document.querySelectorAll('.navbar-menu');
|
||||||
|
|||||||
@@ -559,7 +559,10 @@ def page_wallet(self, url_split, post_string):
|
|||||||
skip = tx_filters.get("offset", 0)
|
skip = tx_filters.get("offset", 0)
|
||||||
|
|
||||||
all_txs = ci.listWalletTransactions(count=10000, skip=0)
|
all_txs = ci.listWalletTransactions(count=10000, skip=0)
|
||||||
all_txs = list(reversed(all_txs)) if all_txs else []
|
if all_txs and coin_id not in (Coins.XMR, Coins.WOW):
|
||||||
|
all_txs = list(reversed(all_txs))
|
||||||
|
elif not all_txs:
|
||||||
|
all_txs = []
|
||||||
total_transactions = len(all_txs)
|
total_transactions = len(all_txs)
|
||||||
|
|
||||||
raw_txs = all_txs[skip : skip + count] if all_txs else []
|
raw_txs = all_txs[skip : skip + count] if all_txs else []
|
||||||
|
|||||||
Reference in New Issue
Block a user