Add safe_logs option to anonymise logs. (#264)

* Add safe_logs option to anonymise logs.

* Extend logger class.
This commit is contained in:
tecnovert
2025-02-22 15:54:13 +00:00
committed by GitHub
parent 8d317e4b67
commit f1c2b41714
13 changed files with 735 additions and 805 deletions

View File

@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (c) 2019-2024 tecnovert # Copyright (c) 2019-2024 tecnovert
# Copyright (c) 2024 The Basicswap developers # Copyright (c) 2024-2025 The Basicswap developers
# Distributed under the MIT software license, see the accompanying # Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php. # file LICENSE or http://www.opensource.org/licenses/mit-license.php.
@@ -28,6 +28,9 @@ from .rpc import (
from .util import ( from .util import (
TemporaryError, TemporaryError,
) )
from .util.logging import (
BSXLogger,
)
from .chainparams import ( from .chainparams import (
Coins, Coins,
chainparams, chainparams,
@@ -75,6 +78,7 @@ class BaseApp(DBMethods):
self.delay_event.set() self.delay_event.set()
def prepareLogging(self): def prepareLogging(self):
logging.setLoggerClass(BSXLogger)
self.log = logging.getLogger(self.log_name) self.log = logging.getLogger(self.log_name)
self.log.propagate = False self.log.propagate = False

File diff suppressed because it is too large Load Diff

View File

@@ -1,13 +1,13 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (c) 2024 The Basicswap developers # Copyright (c) 2024-2025 The Basicswap developers
# Distributed under the MIT software license, see the accompanying # Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php. # file LICENSE or http://www.opensource.org/licenses/mit-license.php.
from typing import Union from typing import Union
from basicswap.contrib.test_framework.messages import COutPoint, CTransaction, CTxIn from basicswap.contrib.test_framework.messages import COutPoint, CTransaction, CTxIn
from basicswap.util import b2h, b2i, ensure, i2h from basicswap.util import b2i, ensure, i2b
from basicswap.util.script import decodePushData, decodeScriptNum from basicswap.util.script import decodePushData, decodeScriptNum
from .btc import BTCInterface, ensure_op, findOutput from .btc import BTCInterface, ensure_op, findOutput
from basicswap.rpc import make_rpc_func from basicswap.rpc import make_rpc_func
@@ -454,11 +454,14 @@ class BCHInterface(BTCInterface):
tx.rehash() tx.rehash()
self._log.info( self._log.info(
"createSCLockSpendTx %s:\n fee_rate, size, fee: %ld, %ld, %ld.", "createSCLockSpendTx {}{}.".format(
i2h(tx.sha256), self._log.id(i2b(tx.sha256)),
tx_fee_rate, (
size, ""
pay_fee, if self._log.safe_logs
else f":\n fee_rate, vsize, fee: {tx_fee_rate}, {size}, {pay_fee}"
),
)
) )
return tx.serialize_without_witness() return tx.serialize_without_witness()
@@ -506,11 +509,14 @@ class BCHInterface(BTCInterface):
tx.rehash() tx.rehash()
self._log.info( self._log.info(
"createSCLockRefundTx %s:\n fee_rate, vsize, fee: %ld, %ld, %ld.", "createSCLockRefundTx {}{}.".format(
i2h(tx.sha256), self._log.id(i2b(tx.sha256)),
tx_fee_rate, (
vsize, ""
pay_fee, if self._log.safe_logs
else f":\n fee_rate, vsize, fee: {tx_fee_rate}, {vsize}, {pay_fee}"
),
)
) )
return tx.serialize_without_witness(), refund_script, tx.vout[0].nValue return tx.serialize_without_witness(), refund_script, tx.vout[0].nValue
@@ -582,11 +588,14 @@ class BCHInterface(BTCInterface):
tx.rehash() tx.rehash()
self._log.info( self._log.info(
"createSCLockRefundSpendToFTx %s:\n fee_rate, vsize, fee: %ld, %ld, %ld.", "createSCLockRefundSpendToFTx {}{}.".format(
i2h(tx.sha256), self._log.id(i2b(tx.sha256)),
tx_fee_rate, (
vsize, ""
pay_fee, if self._log.safe_logs
else f":\n fee_rate, vsize, fee: {tx_fee_rate}, {vsize}, {pay_fee}"
),
)
) )
return tx.serialize_without_witness() return tx.serialize_without_witness()
@@ -780,7 +789,7 @@ class BCHInterface(BTCInterface):
tx = self.loadTx(tx_bytes) tx = self.loadTx(tx_bytes)
txid = self.getTxid(tx) txid = self.getTxid(tx)
self._log.info("Verifying lock tx: {}.".format(b2h(txid))) self._log.info("Verifying lock tx: {}.".format(self._log.id(txid)))
ensure(tx.nVersion == self.txVersion(), "Bad version") ensure(tx.nVersion == self.txVersion(), "Bad version")
ensure(tx.nLockTime == 0, "Bad nLockTime") # TODO match txns created by cores ensure(tx.nLockTime == 0, "Bad nLockTime") # TODO match txns created by cores
@@ -835,7 +844,7 @@ class BCHInterface(BTCInterface):
tx = self.loadTx(tx_bytes) tx = self.loadTx(tx_bytes)
txid = self.getTxid(tx) txid = self.getTxid(tx)
self._log.info("Verifying lock refund tx: {}.".format(b2h(txid))) self._log.info("Verifying lock refund tx: {}.".format(self._log.id(txid)))
ensure(tx.nVersion == self.txVersion(), "Bad version") ensure(tx.nVersion == self.txVersion(), "Bad version")
ensure(tx.nLockTime == 0, "nLockTime not 0") ensure(tx.nLockTime == 0, "nLockTime not 0")
@@ -881,7 +890,7 @@ class BCHInterface(BTCInterface):
size = self.getTxSize(tx) size = self.getTxSize(tx)
vsize = size vsize = size
self._log.info( self._log.info_s(
"tx amount, vsize, fee: %ld, %ld, %ld", locked_coin, vsize, fee_paid "tx amount, vsize, fee: %ld, %ld, %ld", locked_coin, vsize, fee_paid
) )
@@ -905,7 +914,7 @@ class BCHInterface(BTCInterface):
# Must have only one output sending lock refund tx value - fee to leader's address, TODO: follower shouldn't need to verify destination addr # Must have only one output sending lock refund tx value - fee to leader's address, TODO: follower shouldn't need to verify destination addr
tx = self.loadTx(tx_bytes) tx = self.loadTx(tx_bytes)
txid = self.getTxid(tx) txid = self.getTxid(tx)
self._log.info("Verifying lock refund spend tx: {}.".format(b2h(txid))) self._log.info("Verifying lock refund spend tx: {}.".format(self._log.id(txid)))
ensure(tx.nVersion == self.txVersion(), "Bad version") ensure(tx.nVersion == self.txVersion(), "Bad version")
ensure(tx.nLockTime == 0, "nLockTime not 0") ensure(tx.nLockTime == 0, "nLockTime not 0")
@@ -947,9 +956,7 @@ class BCHInterface(BTCInterface):
size = self.getTxSize(tx) size = self.getTxSize(tx)
vsize = size vsize = size
self._log.info( self._log.info_s(f"tx amount, vsize, fee: {tx_value}, {vsize}, {fee_paid}")
"tx amount, vsize, fee: %ld, %ld, %ld", tx_value, vsize, fee_paid
)
return True return True
@@ -962,7 +969,7 @@ class BCHInterface(BTCInterface):
tx = self.loadTx(tx_bytes) tx = self.loadTx(tx_bytes)
txid = self.getTxid(tx) txid = self.getTxid(tx)
self._log.info("Verifying lock spend tx: {}.".format(b2h(txid))) self._log.info("Verifying lock spend tx: {}.".format(self._log.id(txid)))
ensure(tx.nVersion == self.txVersion(), "Bad version") ensure(tx.nVersion == self.txVersion(), "Bad version")
ensure(tx.nLockTime == 0, "nLockTime not 0") ensure(tx.nLockTime == 0, "nLockTime not 0")
@@ -995,7 +1002,7 @@ class BCHInterface(BTCInterface):
size = self.getTxSize(tx) size = self.getTxSize(tx)
vsize = size vsize = size
self._log.info( self._log.info_s(
"tx amount, vsize, fee: %ld, %ld, %ld", tx.vout[0].nValue, vsize, fee_paid "tx amount, vsize, fee: %ld, %ld, %ld", tx.vout[0].nValue, vsize, fee_paid
) )
@@ -1115,11 +1122,14 @@ class BCHInterface(BTCInterface):
tx.rehash() tx.rehash()
self._log.info( self._log.info(
"createMercyTx %s:\n fee_rate, vsize, fee: %ld, %ld, %ld.", "createMercyTx {}{}.".format(
i2h(tx.sha256), self._log.id(i2b(tx.sha256)),
1, (
vsize, ""
pay_fee, if self._log.safe_logs
else f":\n fee_rate, vsize, fee: {1}, {vsize}, {pay_fee}"
),
)
) )
txHex = tx.serialize_without_witness() txHex = tx.serialize_without_witness()

View File

@@ -21,7 +21,6 @@ from basicswap.basicswap_util import (
from basicswap.interface.base import Secp256k1Interface from basicswap.interface.base import Secp256k1Interface
from basicswap.util import ( from basicswap.util import (
ensure, ensure,
b2h,
i2b, i2b,
b2i, b2i,
i2h, i2h,
@@ -319,7 +318,9 @@ class BTCInterface(Secp256k1Interface):
if wallet_name in ("mweb",): if wallet_name in ("mweb",):
continue continue
change_watchonly_wallet: bool = self._rpc_wallet_watch == self._rpc_wallet change_watchonly_wallet: bool = (
self._rpc_wallet_watch == self._rpc_wallet
)
self._rpc_wallet = wallet_name self._rpc_wallet = wallet_name
self._log.info( self._log.info(
@@ -733,11 +734,14 @@ class BTCInterface(Secp256k1Interface):
tx.rehash() tx.rehash()
self._log.info( self._log.info(
"createSCLockRefundTx %s:\n fee_rate, vsize, fee: %ld, %ld, %ld.", "createSCLockRefundTx {}{}.".format(
i2h(tx.sha256), self._log.id(i2b(tx.sha256)),
tx_fee_rate, (
vsize, ""
pay_fee, if self._log.safe_logs
else f":\n fee_rate, vsize, fee: {tx_fee_rate}, {vsize}, {pay_fee}"
),
)
) )
return tx.serialize(), refund_script, tx.vout[0].nValue return tx.serialize(), refund_script, tx.vout[0].nValue
@@ -788,11 +792,14 @@ class BTCInterface(Secp256k1Interface):
tx.rehash() tx.rehash()
self._log.info( self._log.info(
"createSCLockRefundSpendTx %s:\n fee_rate, vsize, fee: %ld, %ld, %ld.", "createSCLockRefundSpendTx {}{}.".format(
i2h(tx.sha256), self._log.id(i2b(tx.sha256)),
tx_fee_rate, (
vsize, ""
pay_fee, if self._log.safe_logs
else f":\n fee_rate, vsize, fee: {tx_fee_rate}, {vsize}, {pay_fee}"
),
)
) )
return tx.serialize() return tx.serialize()
@@ -855,11 +862,14 @@ class BTCInterface(Secp256k1Interface):
tx.rehash() tx.rehash()
self._log.info( self._log.info(
"createSCLockRefundSpendToFTx %s:\n fee_rate, vsize, fee: %ld, %ld, %ld.", "createSCLockRefundSpendToFTx {}{}.".format(
i2h(tx.sha256), self._log.id(i2b(tx.sha256)),
tx_fee_rate, (
vsize, ""
pay_fee, if self._log.safe_logs
else f":\n fee_rate, vsize, fee: {tx_fee_rate}, {vsize}, {pay_fee}"
),
)
) )
return tx.serialize() return tx.serialize()
@@ -902,11 +912,14 @@ class BTCInterface(Secp256k1Interface):
tx.rehash() tx.rehash()
self._log.info( self._log.info(
"createSCLockSpendTx %s:\n fee_rate, vsize, fee: %ld, %ld, %ld.", "createSCLockSpendTx {}{}.".format(
i2h(tx.sha256), self._log.id(i2b(tx.sha256)),
tx_fee_rate, (
vsize, ""
pay_fee, if self._log.safe_logs
else f":\n fee_rate, vsize, fee: {tx_fee_rate}, {vsize}, {pay_fee}"
),
)
) )
return tx.serialize() return tx.serialize()
@@ -931,7 +944,7 @@ class BTCInterface(Secp256k1Interface):
tx = self.loadTx(tx_bytes) tx = self.loadTx(tx_bytes)
txid = self.getTxid(tx) txid = self.getTxid(tx)
self._log.info("Verifying lock tx: {}.".format(b2h(txid))) self._log.info("Verifying lock tx: {}.".format(self._log.id(txid)))
ensure(tx.nVersion == self.txVersion(), "Bad version") ensure(tx.nVersion == self.txVersion(), "Bad version")
ensure(tx.nLockTime == 0, "Bad nLockTime") # TODO match txns created by cores ensure(tx.nLockTime == 0, "Bad nLockTime") # TODO match txns created by cores
@@ -1019,7 +1032,7 @@ class BTCInterface(Secp256k1Interface):
tx = self.loadTx(tx_bytes) tx = self.loadTx(tx_bytes)
txid = self.getTxid(tx) txid = self.getTxid(tx)
self._log.info("Verifying lock refund tx: {}.".format(b2h(txid))) self._log.info("Verifying lock refund tx: {}.".format(self._log.id(txid)))
ensure(tx.nVersion == self.txVersion(), "Bad version") ensure(tx.nVersion == self.txVersion(), "Bad version")
ensure(tx.nLockTime == 0, "nLockTime not 0") ensure(tx.nLockTime == 0, "nLockTime not 0")
@@ -1058,7 +1071,7 @@ class BTCInterface(Secp256k1Interface):
vsize = self.getTxVSize(tx, add_witness_bytes=witness_bytes) vsize = self.getTxVSize(tx, add_witness_bytes=witness_bytes)
fee_rate_paid = fee_paid * 1000 // vsize fee_rate_paid = fee_paid * 1000 // vsize
self._log.info( self._log.info_s(
"tx amount, vsize, feerate: %ld, %ld, %ld", "tx amount, vsize, feerate: %ld, %ld, %ld",
locked_coin, locked_coin,
vsize, vsize,
@@ -1087,7 +1100,7 @@ class BTCInterface(Secp256k1Interface):
# Must have only one output sending lock refund tx value - fee to leader's address, TODO: follower shouldn't need to verify destination addr # Must have only one output sending lock refund tx value - fee to leader's address, TODO: follower shouldn't need to verify destination addr
tx = self.loadTx(tx_bytes) tx = self.loadTx(tx_bytes)
txid = self.getTxid(tx) txid = self.getTxid(tx)
self._log.info("Verifying lock refund spend tx: {}.".format(b2h(txid))) self._log.info("Verifying lock refund spend tx: {}.".format(self._log.id(txid)))
ensure(tx.nVersion == self.txVersion(), "Bad version") ensure(tx.nVersion == self.txVersion(), "Bad version")
ensure(tx.nLockTime == 0, "nLockTime not 0") ensure(tx.nLockTime == 0, "nLockTime not 0")
@@ -1124,7 +1137,7 @@ class BTCInterface(Secp256k1Interface):
vsize = self.getTxVSize(tx, add_witness_bytes=witness_bytes) vsize = self.getTxVSize(tx, add_witness_bytes=witness_bytes)
fee_rate_paid = fee_paid * 1000 // vsize fee_rate_paid = fee_paid * 1000 // vsize
self._log.info( self._log.info_s(
"tx amount, vsize, feerate: %ld, %ld, %ld", tx_value, vsize, fee_rate_paid "tx amount, vsize, feerate: %ld, %ld, %ld", tx_value, vsize, fee_rate_paid
) )
@@ -1142,7 +1155,7 @@ class BTCInterface(Secp256k1Interface):
tx = self.loadTx(tx_bytes) tx = self.loadTx(tx_bytes)
txid = self.getTxid(tx) txid = self.getTxid(tx)
self._log.info("Verifying lock spend tx: {}.".format(b2h(txid))) self._log.info("Verifying lock spend tx: {}.".format(self._log.id(txid)))
ensure(tx.nVersion == self.txVersion(), "Bad version") ensure(tx.nVersion == self.txVersion(), "Bad version")
ensure(tx.nLockTime == 0, "nLockTime not 0") ensure(tx.nLockTime == 0, "nLockTime not 0")
@@ -1180,7 +1193,7 @@ class BTCInterface(Secp256k1Interface):
vsize = self.getTxVSize(tx, add_witness_bytes=witness_bytes) vsize = self.getTxVSize(tx, add_witness_bytes=witness_bytes)
fee_rate_paid = fee_paid * 1000 // vsize fee_rate_paid = fee_paid * 1000 // vsize
self._log.info( self._log.info_s(
"tx amount, vsize, feerate: %ld, %ld, %ld", "tx amount, vsize, feerate: %ld, %ld, %ld",
tx.vout[0].nValue, tx.vout[0].nValue,
vsize, vsize,
@@ -1490,7 +1503,7 @@ class BTCInterface(Secp256k1Interface):
witness_bytes = 109 witness_bytes = 109
vsize = self.getTxVSize(tx, add_witness_bytes=witness_bytes) vsize = self.getTxVSize(tx, add_witness_bytes=witness_bytes)
pay_fee = round(fee_rate * vsize / 1000) pay_fee = round(fee_rate * vsize / 1000)
self._log.info( self._log.info_s(
f"BLockSpendTx fee_rate, vsize, fee: {fee_rate}, {vsize}, {pay_fee}." f"BLockSpendTx fee_rate, vsize, fee: {fee_rate}, {vsize}, {pay_fee}."
) )
return pay_fee return pay_fee
@@ -1508,7 +1521,9 @@ class BTCInterface(Secp256k1Interface):
lock_tx_vout=None, lock_tx_vout=None,
) -> bytes: ) -> bytes:
self._log.info( self._log.info(
"spendBLockTx: {} {}\n".format(chain_b_lock_txid.hex(), lock_tx_vout) "spendBLockTx: {} {}\n".format(
self._log.id(chain_b_lock_txid), lock_tx_vout
)
) )
locked_n = lock_tx_vout locked_n = lock_tx_vout
@@ -1589,7 +1604,9 @@ class BTCInterface(Secp256k1Interface):
# Add watchonly address and rescan if required # Add watchonly address and rescan if required
if not self.isAddressMine(dest_address, or_watch_only=True): if not self.isAddressMine(dest_address, or_watch_only=True):
self.importWatchOnlyAddress(dest_address, "bid") self.importWatchOnlyAddress(dest_address, "bid")
self._log.info("Imported watch-only addr: {}".format(dest_address)) self._log.info(
"Imported watch-only addr: {}".format(self._log.addr(dest_address))
)
self._log.info( self._log.info(
"Rescanning {} chain from height: {}".format( "Rescanning {} chain from height: {}".format(
self.coin_name(), rescan_from self.coin_name(), rescan_from

View File

@@ -27,7 +27,6 @@ from basicswap.interface.btc import (
) )
from basicswap.util import ( from basicswap.util import (
ensure, ensure,
b2h,
b2i, b2i,
i2b, i2b,
i2h, i2h,
@@ -1130,11 +1129,14 @@ class DCRInterface(Secp256k1Interface):
fee_info["size"] = size fee_info["size"] = size
self._log.info( self._log.info(
"createSCLockSpendTx %s:\n fee_rate, size, fee: %ld, %ld, %ld.", "createSCLockSpendTx {}{}.".format(
tx.TxHash().hex(), self._log.id(tx.TxHash()),
tx_fee_rate, (
size, ""
pay_fee, if self._log.safe_logs
else f":\n fee_rate, size, fee: {tx_fee_rate}, {size}, {pay_fee}"
),
)
) )
return tx.serialize(TxSerializeType.NoWitness) return tx.serialize(TxSerializeType.NoWitness)
@@ -1174,11 +1176,14 @@ class DCRInterface(Secp256k1Interface):
tx.vout[0].value = locked_coin - pay_fee tx.vout[0].value = locked_coin - pay_fee
self._log.info( self._log.info(
"createSCLockRefundTx %s:\n fee_rate, size, fee: %ld, %ld, %ld.", "createSCLockRefundTx {}{}.".format(
tx.TxHash().hex(), self._log.id(tx.TxHash()),
tx_fee_rate, (
size, ""
pay_fee, if self._log.safe_logs
else f":\n fee_rate, size, fee: {tx_fee_rate}, {size}, {pay_fee}"
),
)
) )
return tx.serialize(TxSerializeType.NoWitness), refund_script, tx.vout[0].value return tx.serialize(TxSerializeType.NoWitness), refund_script, tx.vout[0].value
@@ -1222,11 +1227,14 @@ class DCRInterface(Secp256k1Interface):
tx.vout[0].value = locked_coin - pay_fee tx.vout[0].value = locked_coin - pay_fee
self._log.info( self._log.info(
"createSCLockRefundSpendTx %s:\n fee_rate, size, fee: %ld, %ld, %ld.", "createSCLockRefundSpendTx {}{}.".format(
tx.TxHash().hex(), self._log.id(tx.TxHash()),
tx_fee_rate, (
size, ""
pay_fee, if self._log.safe_logs
else f":\n fee_rate, size, fee: {tx_fee_rate}, {size}, {pay_fee}"
),
)
) )
return tx.serialize(TxSerializeType.NoWitness) return tx.serialize(TxSerializeType.NoWitness)
@@ -1251,7 +1259,7 @@ class DCRInterface(Secp256k1Interface):
tx = self.loadTx(tx_bytes) tx = self.loadTx(tx_bytes)
txid = self.getTxid(tx) txid = self.getTxid(tx)
self._log.info("Verifying lock tx: {}.".format(b2h(txid))) self._log.info("Verifying lock tx: {}.".format(self._log.id(txid)))
ensure(tx.version == self.txVersion(), "Bad version") ensure(tx.version == self.txVersion(), "Bad version")
ensure(tx.locktime == 0, "Bad locktime") ensure(tx.locktime == 0, "Bad locktime")
@@ -1327,7 +1335,7 @@ class DCRInterface(Secp256k1Interface):
tx = self.loadTx(tx_bytes) tx = self.loadTx(tx_bytes)
txid = self.getTxid(tx) txid = self.getTxid(tx)
self._log.info("Verifying lock spend tx: {}.".format(b2h(txid))) self._log.info("Verifying lock spend tx: {}.".format(self._log.id(txid)))
ensure(tx.version == self.txVersion(), "Bad version") ensure(tx.version == self.txVersion(), "Bad version")
ensure(tx.locktime == 0, "Bad locktime") ensure(tx.locktime == 0, "Bad locktime")
@@ -1397,7 +1405,7 @@ class DCRInterface(Secp256k1Interface):
tx = self.loadTx(tx_bytes) tx = self.loadTx(tx_bytes)
txid = self.getTxid(tx) txid = self.getTxid(tx)
self._log.info("Verifying lock refund tx: {}.".format(b2h(txid))) self._log.info("Verifying lock refund tx: {}.".format(self._log.id(txid)))
ensure(tx.version == self.txVersion(), "Bad version") ensure(tx.version == self.txVersion(), "Bad version")
ensure(tx.locktime == 0, "locktime not 0") ensure(tx.locktime == 0, "locktime not 0")
@@ -1460,7 +1468,7 @@ class DCRInterface(Secp256k1Interface):
# Must have only one output sending lock refund tx value - fee to leader's address, TODO: follower shouldn't need to verify destination addr # Must have only one output sending lock refund tx value - fee to leader's address, TODO: follower shouldn't need to verify destination addr
tx = self.loadTx(tx_bytes) tx = self.loadTx(tx_bytes)
txid = self.getTxid(tx) txid = self.getTxid(tx)
self._log.info("Verifying lock refund spend tx: {}.".format(b2h(txid))) self._log.info("Verifying lock refund spend tx: {}.".format(self._log.id(txid)))
ensure(tx.version == self.txVersion(), "Bad version") ensure(tx.version == self.txVersion(), "Bad version")
ensure(tx.locktime == 0, "locktime not 0") ensure(tx.locktime == 0, "locktime not 0")
@@ -1546,11 +1554,14 @@ class DCRInterface(Secp256k1Interface):
tx.vout[0].value = locked_amount - pay_fee tx.vout[0].value = locked_amount - pay_fee
self._log.info( self._log.info(
"createSCLockRefundSpendToFTx %s:\n fee_rate, size, fee: %ld, %ld, %ld.", "createSCLockRefundSpendToFTx {}{}.".format(
tx.TxHash().hex(), self._log.id(tx.TxHash()),
tx_fee_rate, (
size, ""
pay_fee, if self._log.safe_logs
else f":\n fee_rate, size, fee: {tx_fee_rate}, {size}, {pay_fee}"
),
)
) )
return tx.serialize(TxSerializeType.NoWitness) return tx.serialize(TxSerializeType.NoWitness)
@@ -1719,7 +1730,7 @@ class DCRInterface(Secp256k1Interface):
witness_bytes = 115 witness_bytes = 115
size = len(tx.serialize()) + witness_bytes size = len(tx.serialize()) + witness_bytes
pay_fee = round(fee_rate * size / 1000) pay_fee = round(fee_rate * size / 1000)
self._log.info( self._log.info_s(
f"BLockSpendTx fee_rate, vsize, fee: {fee_rate}, {size}, {pay_fee}." f"BLockSpendTx fee_rate, vsize, fee: {fee_rate}, {size}, {pay_fee}."
) )
return pay_fee return pay_fee

View File

@@ -105,7 +105,9 @@ class FIROInterface(BTCInterface):
if not self.isAddressMine(dest_address, or_watch_only=True): if not self.isAddressMine(dest_address, or_watch_only=True):
self.importWatchOnlyAddress(dest_address, "bid") self.importWatchOnlyAddress(dest_address, "bid")
self._log.info("Imported watch-only addr: {}".format(dest_address)) self._log.info(
"Imported watch-only addr: {}".format(self._log.addr(dest_address))
)
self._log.info( self._log.info(
"Rescanning {} chain from height: {}".format( "Rescanning {} chain from height: {}".format(
self.coin_name(), rescan_from self.coin_name(), rescan_from

View File

@@ -41,7 +41,6 @@ from basicswap.util.address import (
from basicswap.util import ( from basicswap.util import (
b2i, b2i,
i2b, i2b,
i2h,
ensure, ensure,
) )
from basicswap.basicswap_util import ( from basicswap.basicswap_util import (
@@ -552,7 +551,9 @@ class NAVInterface(BTCInterface):
if not self.isAddressMine(dest_address, or_watch_only=True): if not self.isAddressMine(dest_address, or_watch_only=True):
self.importWatchOnlyAddress(dest_address, "bid") self.importWatchOnlyAddress(dest_address, "bid")
self._log.info("Imported watch-only addr: {}".format(dest_address)) self._log.info(
"Imported watch-only addr: {}".format(self._log.addr(dest_address))
)
self._log.info( self._log.info(
"Rescanning {} chain from height: {}".format( "Rescanning {} chain from height: {}".format(
self.coin_name(), rescan_from self.coin_name(), rescan_from
@@ -816,11 +817,14 @@ class NAVInterface(BTCInterface):
tx.rehash() tx.rehash()
self._log.info( self._log.info(
"createSCLockRefundTx %s:\n fee_rate, vsize, fee: %ld, %ld, %ld.", "createSCLockRefundTx {}{}.".format(
i2h(tx.sha256), self._log.id(i2b(tx.sha256)),
tx_fee_rate, (
vsize, ""
pay_fee, if self._log.safe_logs
else f":\n fee_rate, vsize, fee: {tx_fee_rate}, {vsize}, {pay_fee}"
),
)
) )
return tx.serialize(), refund_script, tx.vout[0].nValue return tx.serialize(), refund_script, tx.vout[0].nValue
@@ -871,11 +875,14 @@ class NAVInterface(BTCInterface):
tx.rehash() tx.rehash()
self._log.info( self._log.info(
"createSCLockRefundSpendTx %s:\n fee_rate, vsize, fee: %ld, %ld, %ld.", "createSCLockRefundSpendTx {}{}.".format(
i2h(tx.sha256), self._log.id(i2b(tx.sha256)),
tx_fee_rate, (
vsize, ""
pay_fee, if self._log.safe_logs
else f":\n fee_rate, vsize, fee: {tx_fee_rate}, {vsize}, {pay_fee}"
),
)
) )
return tx.serialize() return tx.serialize()
@@ -928,11 +935,14 @@ class NAVInterface(BTCInterface):
tx.rehash() tx.rehash()
self._log.info( self._log.info(
"createSCLockRefundSpendToFTx %s:\n fee_rate, vsize, fee: %ld, %ld, %ld.", "createSCLockRefundSpendToFTx {}{}.".format(
i2h(tx.sha256), self._log.id(i2b(tx.sha256)),
tx_fee_rate, (
vsize, ""
pay_fee, if self._log.safe_logs
else f":\n fee_rate, vsize, fee: {tx_fee_rate}, {vsize}, {pay_fee}"
),
)
) )
return tx.serialize() return tx.serialize()
@@ -975,11 +985,14 @@ class NAVInterface(BTCInterface):
tx.rehash() tx.rehash()
self._log.info( self._log.info(
"createSCLockSpendTx %s:\n fee_rate, vsize, fee: %ld, %ld, %ld.", "createSCLockSpendTx {}{}.".format(
i2h(tx.sha256), self._log.id(i2b(tx.sha256)),
tx_fee_rate, (
vsize, ""
pay_fee, if self._log.safe_logs
else f":\n fee_rate, vsize, fee: {tx_fee_rate}, {vsize}, {pay_fee}"
),
)
) )
return tx.serialize() return tx.serialize()

View File

@@ -477,7 +477,7 @@ class PARTInterfaceBlind(PARTInterface):
): ):
lock_tx_obj = self.rpc("decoderawtransaction", [tx_bytes.hex()]) lock_tx_obj = self.rpc("decoderawtransaction", [tx_bytes.hex()])
lock_txid_hex = lock_tx_obj["txid"] lock_txid_hex = lock_tx_obj["txid"]
self._log.info("Verifying lock tx: {}.".format(lock_txid_hex)) self._log.info("Verifying lock tx: {}.".format(self._log.id(lock_txid_hex)))
ensure(lock_tx_obj["version"] == self.txVersion(), "Bad version") ensure(lock_tx_obj["version"] == self.txVersion(), "Bad version")
ensure(lock_tx_obj["locktime"] == 0, "Bad nLockTime") ensure(lock_tx_obj["locktime"] == 0, "Bad nLockTime")
@@ -541,7 +541,9 @@ class PARTInterfaceBlind(PARTInterface):
): ):
lock_refund_tx_obj = self.rpc("decoderawtransaction", [tx_bytes.hex()]) lock_refund_tx_obj = self.rpc("decoderawtransaction", [tx_bytes.hex()])
lock_refund_txid_hex = lock_refund_tx_obj["txid"] lock_refund_txid_hex = lock_refund_tx_obj["txid"]
self._log.info("Verifying lock refund tx: {}.".format(lock_refund_txid_hex)) self._log.info(
"Verifying lock refund tx: {}.".format(self._log.id(lock_refund_txid_hex))
)
ensure(lock_refund_tx_obj["version"] == self.txVersion(), "Bad version") ensure(lock_refund_tx_obj["version"] == self.txVersion(), "Bad version")
ensure(lock_refund_tx_obj["locktime"] == 0, "Bad nLockTime") ensure(lock_refund_tx_obj["locktime"] == 0, "Bad nLockTime")
@@ -630,7 +632,9 @@ class PARTInterfaceBlind(PARTInterface):
lock_refund_spend_tx_obj = self.rpc("decoderawtransaction", [tx_bytes.hex()]) lock_refund_spend_tx_obj = self.rpc("decoderawtransaction", [tx_bytes.hex()])
lock_refund_spend_txid_hex = lock_refund_spend_tx_obj["txid"] lock_refund_spend_txid_hex = lock_refund_spend_tx_obj["txid"]
self._log.info( self._log.info(
"Verifying lock refund spend tx: {}.".format(lock_refund_spend_txid_hex) "Verifying lock refund spend tx: {}.".format(
self._log.id(lock_refund_spend_txid_hex)
)
) )
ensure(lock_refund_spend_tx_obj["version"] == self.txVersion(), "Bad version") ensure(lock_refund_spend_tx_obj["version"] == self.txVersion(), "Bad version")
@@ -789,11 +793,14 @@ class PARTInterfaceBlind(PARTInterface):
) )
actual_tx_fee_rate = pay_fee * 1000 // vsize actual_tx_fee_rate = pay_fee * 1000 // vsize
self._log.info( self._log.info(
"createSCLockSpendTx %s:\n fee_rate, vsize, fee: %ld, %ld, %ld.", "createSCLockSpendTx {}{}.".format(
lock_spend_tx_obj["txid"], self._log.id(lock_spend_tx_obj["txid"]),
actual_tx_fee_rate, (
vsize, ""
pay_fee, if self._log.safe_logs
else f":\n fee_rate, vsize, fee: {actual_tx_fee_rate}, {vsize}, {pay_fee}"
),
)
) )
fee_info["vsize"] = vsize fee_info["vsize"] = vsize
@@ -808,7 +815,9 @@ class PARTInterfaceBlind(PARTInterface):
): ):
lock_spend_tx_obj = self.rpc("decoderawtransaction", [tx_bytes.hex()]) lock_spend_tx_obj = self.rpc("decoderawtransaction", [tx_bytes.hex()])
lock_spend_txid_hex = lock_spend_tx_obj["txid"] lock_spend_txid_hex = lock_spend_tx_obj["txid"]
self._log.info("Verifying lock spend tx: {}.".format(lock_spend_txid_hex)) self._log.info(
"Verifying lock spend tx: {}.".format(self._log.id(lock_spend_txid_hex))
)
ensure(lock_spend_tx_obj["version"] == self.txVersion(), "Bad version") ensure(lock_spend_tx_obj["version"] == self.txVersion(), "Bad version")
ensure(lock_spend_tx_obj["locktime"] == 0, "Bad nLockTime") ensure(lock_spend_tx_obj["locktime"] == 0, "Bad nLockTime")

View File

@@ -180,7 +180,19 @@ class XMRInterface(CoinInterface):
if self._wallet_password is not None: if self._wallet_password is not None:
params["password"] = self._wallet_password params["password"] = self._wallet_password
rv = self.rpc_wallet("generate_from_keys", params) rv = self.rpc_wallet("generate_from_keys", params)
self._log.info("generate_from_keys %s", dumpj(rv)) if "address" in rv:
new_address: str = rv["address"]
is_watch_only: bool = "Watch-only" in rv.get("info", "")
self._log.info(
"Generated{} {} wallet: {}".format(
" watch-only" if is_watch_only else "",
self.coin_name(),
self._log.addr(new_address),
)
)
else:
self._log.debug("generate_from_keys %s", dumpj(rv))
raise ValueError("generate_from_keys failed")
def openWallet(self, filename): def openWallet(self, filename):
params = {"filename": filename} params = {"filename": filename}
@@ -406,7 +418,9 @@ class XMRInterface(CoinInterface):
params["priority"] = self._fee_priority params["priority"] = self._fee_priority
rv = self.rpc_wallet("transfer", params) rv = self.rpc_wallet("transfer", params)
self._log.info( self._log.info(
"publishBLockTx %s to address_b58 %s", rv["tx_hash"], shared_addr "publishBLockTx %s to address_b58 %s",
self._log.id(rv["tx_hash"]),
self._log.addr(shared_addr),
) )
tx_hash = bytes.fromhex(rv["tx_hash"]) tx_hash = bytes.fromhex(rv["tx_hash"])

View File

@@ -44,7 +44,7 @@ def addLockRefundSigs(self, xmr_swap, ci):
def recoverNoScriptTxnWithKey(self, bid_id: bytes, encoded_key, cursor=None): def recoverNoScriptTxnWithKey(self, bid_id: bytes, encoded_key, cursor=None):
self.log.info(f"Manually recovering {bid_id.hex()}") self.log.info(f"Manually recovering {self.log.id(bid_id)}")
# Manually recover txn if other key is known # Manually recover txn if other key is known
try: try:
use_cursor = self.openDB(cursor) use_cursor = self.openDB(cursor)
@@ -119,10 +119,7 @@ def recoverNoScriptTxnWithKey(self, bid_id: bytes, encoded_key, cursor=None):
lock_tx_vout=lock_tx_vout, lock_tx_vout=lock_tx_vout,
) )
self.log.debug( self.log.debug(
"Submitted lock B spend txn %s to %s chain for bid %s", f"Submitted lock B spend txn {self.log.id(txid)} to {ci_follower.coin_name()} chain for bid {self.log.id(bid_id)}."
txid.hex(),
ci_follower.coin_name(),
bid_id.hex(),
) )
self.logBidEvent( self.logBidEvent(
bid.bid_id, bid.bid_id,

View File

@@ -1,16 +1,16 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (c) 2022-2024 tecnovert # Copyright (c) 2022-2025 tecnovert
# Distributed under the MIT software license, see the accompanying # Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php. # file LICENSE or http://www.opensource.org/licenses/mit-license.php.
from hashlib import sha256 as hashlib_sha256 # hashlib is faster than pycryptodome
from basicswap.contrib.blake256.blake256 import blake_hash from basicswap.contrib.blake256.blake256 import blake_hash
from Crypto.Hash import HMAC, RIPEMD160, SHA512 # pycryptodome
from Crypto.Hash import HMAC, RIPEMD160, SHA256, SHA512 # pycryptodome
def sha256(data: bytes) -> bytes: def sha256(data: bytes) -> bytes:
h = SHA256.new() h = hashlib_sha256()
h.update(data) h.update(data)
return h.digest() return h.digest()

42
basicswap/util/logging.py Normal file
View File

@@ -0,0 +1,42 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2025 The Basicswap developers
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
import logging
from basicswap.util.crypto import (
sha256,
)
class BSXLogger(logging.Logger):
def __init__(self, name):
super().__init__(name)
self.safe_logs = False
self.safe_logs_prefix = b""
def addr(self, addr: str) -> str:
if self.safe_logs:
return (
"A_"
+ sha256(self.safe_logs_prefix + addr.encode(encoding="utf-8"))[
:8
].hex()
)
return addr
def id(self, concept_id: bytes, prefix: str = "") -> str:
if concept_id is None:
return prefix + "None"
if isinstance(concept_id, str):
concept_id = bytes.fromhex(concept_id)
if self.safe_logs:
return (prefix if len(prefix) > 0 else "_") + sha256(
self.safe_logs_prefix + concept_id
)[:8].hex()
return prefix + concept_id.hex()
def info_s(self, msg, *args, **kwargs):
if self.safe_logs is False:
self.info(msg, *args, **kwargs)

View File

@@ -770,6 +770,14 @@ class TestFunctions(BaseTest):
class BasicSwapTest(TestFunctions): class BasicSwapTest(TestFunctions):
@classmethod
def setUpClass(cls):
super(BasicSwapTest, cls).setUpClass()
if False:
for client in cls.swap_clients:
client.log.safe_logs = True
client.log.safe_logs_prefix = b"tests"
def test_001_nested_segwit(self): def test_001_nested_segwit(self):
# p2sh-p2wpkh # p2sh-p2wpkh
logging.info( logging.info(
@@ -2141,6 +2149,14 @@ class TestBTC_PARTB(TestFunctions):
start_ltc_nodes = False start_ltc_nodes = False
base_rpc_port = BTC_BASE_RPC_PORT base_rpc_port = BTC_BASE_RPC_PORT
@classmethod
def setUpClass(cls):
super(TestBTC_PARTB, cls).setUpClass()
if False:
for client in cls.swap_clients:
client.log.safe_logs = True
client.log.safe_logs_prefix = b"tests"
def test_01_a_full_swap(self): def test_01_a_full_swap(self):
self.prepare_balance(self.test_coin_to, 100.0, 1801, 1800) self.prepare_balance(self.test_coin_to, 100.0, 1801, 1800)
self.do_test_01_full_swap(self.test_coin_from, self.test_coin_to) self.do_test_01_full_swap(self.test_coin_from, self.test_coin_to)