4 Commits db73afbae0 ... 81ece1ff3b

Author SHA1 Message Date
  The MMGen Project 81ece1ff3b support Bitcoin Core v30.0 1 month ago
  The MMGen Project 68c5f5be76 rpc: use icall mechanism for `listreceivedbylabel` and `listsinceblock` 1 month ago
  The MMGen Project 5529e7ed9f minor fixes and cleanups 1 month ago
  The MMGen Project 797912283c addr.py: support extended MMGen IDs 1 month ago

+ 13 - 2
mmgen/addr.py

@@ -23,7 +23,7 @@ addr: MMGen address-related types
 from collections import namedtuple
 from collections import namedtuple
 
 
 from .objmethods import HiliteStr, InitErrors, MMGenObject
 from .objmethods import HiliteStr, InitErrors, MMGenObject
-from .obj import ImmutableAttr, MMGenIdx, get_obj
+from .obj import ImmutableAttr, MMGenIdx, Int, get_obj
 from .seed import SeedID
 from .seed import SeedID
 from . import color as color_mod
 from . import color as color_mod
 
 
@@ -93,6 +93,10 @@ class MMGenPasswordType(MMGenAddrType):
 class AddrIdx(MMGenIdx):
 class AddrIdx(MMGenIdx):
 	max_digits = 7
 	max_digits = 7
 
 
+class MoneroIdx(Int):
+	max_digits = 5
+	min_val = 0
+
 def is_addr_idx(s):
 def is_addr_idx(s):
 	return get_obj(AddrIdx, n=s, silent=True, return_bool=True)
 	return get_obj(AddrIdx, n=s, silent=True, return_bool=True)
 
 
@@ -136,7 +140,14 @@ class MMGenID(HiliteStr, InitErrors, MMGenObject):
 					mmtype = proto.dfl_mmtype
 					mmtype = proto.dfl_mmtype
 				case _:
 				case _:
 					raise ValueError('not 2 or 3 colon-separated items')
 					raise ValueError('not 2 or 3 colon-separated items')
-			me = str.__new__(cls, f'{sid}:{mmtype}:{idx}')
+			if '-' in idx: # extended Monero ID
+				assert proto.coin == 'XMR', 'extended MMGen IDs supported for XMR only'
+				assert id_str.count(':') == 2, 'mmtype letter required for extended MMGen IDs'
+				me = str.__new__(cls, id_str)
+				idx, ext = idx.split('-', 1)
+				me.acct_num, me.acct_addr_num = [MoneroIdx(e) for e in ext.split('/', 1)]
+			else:
+				me = str.__new__(cls, f'{sid}:{mmtype}:{idx}')
 			me.sid = SeedID(sid=sid)
 			me.sid = SeedID(sid=sid)
 			me.mmtype = proto.addr_type(mmtype)
 			me.mmtype = proto.addr_type(mmtype)
 			me.idx = AddrIdx(idx)
 			me.idx = AddrIdx(idx)

+ 1 - 1
mmgen/data/version

@@ -1 +1 @@
-16.1.dev5
+16.1.dev6

+ 1 - 0
mmgen/proto/bch/params.py

@@ -29,6 +29,7 @@ class mainnet(mainnet):
 	caps = ()
 	caps = ()
 	coin_amt        = 'BCHAmt'
 	coin_amt        = 'BCHAmt'
 	max_tx_fee      = 0.1
 	max_tx_fee      = 0.1
+	max_op_return_data_len = 80
 	cashaddr_pfx    = 'bitcoincash'
 	cashaddr_pfx    = 'bitcoincash'
 	cashaddr        = True
 	cashaddr        = True
 
 

+ 1 - 1
mmgen/proto/btc/daemon.py

@@ -19,7 +19,7 @@ from ...util import list_gen
 from ...daemon import CoinDaemon, _nw, _dd
 from ...daemon import CoinDaemon, _nw, _dd
 
 
 class bitcoin_core_daemon(CoinDaemon):
 class bitcoin_core_daemon(CoinDaemon):
-	daemon_data = _dd('Bitcoin Core', 290100, '29.1.0')
+	daemon_data = _dd('Bitcoin Core', 300000, '30.0.0')
 	exec_fn = 'bitcoind'
 	exec_fn = 'bitcoind'
 	cli_fn = 'bitcoin-cli'
 	cli_fn = 'bitcoin-cli'
 	testnet_dir = 'testnet3'
 	testnet_dir = 'testnet3'

+ 1 - 1
mmgen/proto/btc/params.py

@@ -52,7 +52,7 @@ class mainnet(CoinProtocol.Secp256k1): # chainparams.cpp
 	max_halvings    = 64
 	max_halvings    = 64
 	start_subsidy   = 50
 	start_subsidy   = 50
 	max_int         = 0xffffffff
 	max_int         = 0xffffffff
-	max_op_return_data_len = 80
+	max_op_return_data_len = 4096
 	address_reuse_ok = False
 	address_reuse_ok = False
 
 
 	coin_cfg_opts = (
 	coin_cfg_opts = (

+ 2 - 2
mmgen/proto/btc/regtest.py

@@ -76,7 +76,7 @@ class MMGenRegtest(MMGenObject):
 	def __init__(self, cfg, coin, *, bdb_wallet=False):
 	def __init__(self, cfg, coin, *, bdb_wallet=False):
 		self.cfg = cfg
 		self.cfg = cfg
 		self.coin = coin.lower()
 		self.coin = coin.lower()
-		self.bdb_wallet = bdb_wallet
+		self.bdb_wallet = bdb_wallet and self.coin != 'btc'
 
 
 		assert self.coin in self.coins, f'{coin!r}: invalid coin for regtest'
 		assert self.coin in self.coins, f'{coin!r}: invalid coin for regtest'
 
 
@@ -85,7 +85,7 @@ class MMGenRegtest(MMGenObject):
 			cfg,
 			cfg,
 			network_id = self.coin + '_rt',
 			network_id = self.coin + '_rt',
 			test_suite = cfg.test_suite,
 			test_suite = cfg.test_suite,
-			opts       = ['bdb_wallet'] if bdb_wallet else None)
+			opts       = ['bdb_wallet'] if self.bdb_wallet else None)
 
 
 	# Caching creates problems (broken pipe) when recreating + loading wallets,
 	# Caching creates problems (broken pipe) when recreating + loading wallets,
 	# so reinstantiate with every call:
 	# so reinstantiate with every call:

+ 94 - 6
mmgen/proto/btc/rpc/local.py

@@ -49,8 +49,9 @@ class CallSigs:
 
 
 	class bitcoin_core:
 	class bitcoin_core:
 
 
-		def __init__(self, cfg):
+		def __init__(self, cfg, rpc):
 			self.cfg = cfg
 			self.cfg = cfg
+			self.rpc = rpc
 
 
 		def createwallet(
 		def createwallet(
 				self,
 				self,
@@ -75,13 +76,84 @@ class CallSigs:
 				descriptors,     # 6. descriptors (native descriptor wallet)
 				descriptors,     # 6. descriptors (native descriptor wallet)
 				load_on_startup) # 7. load_on_startup
 				load_on_startup) # 7. load_on_startup
 
 
+		# Get detailed information about in-wallet transaction <txid>
+		# Arguments:
+		# 1. txid                 (string, required) The transaction id
+		# 2. include_watchonly    (boolean, optional, default=true for watch-only wallets, otherwise
+		#                         false) Whether to include watch-only addresses in balance calculation
+		#                         and details[]
+		# 3. verbose              (boolean, optional, default=false) Whether to include a `decoded`
+		#                         field containing the decoded transaction (equivalent to RPC
+		#                         decoderawtransaction)
 		def gettransaction(self, txid, include_watchonly, verbose):
 		def gettransaction(self, txid, include_watchonly, verbose):
 			return (
 			return (
 				'gettransaction',
 				'gettransaction',
-				txid,               # 1. transaction id
-				include_watchonly,  # 2. optional, default=true for watch-only wallets, otherwise false
-				verbose)            # 3. optional, default=false -- include a `decoded` field containing
-									# => the decoded transaction (equivalent to RPC decoderawtransaction)
+				txid,
+				verbose
+			) if 'descriptor_wallet_only' in self.rpc.caps else (
+				'gettransaction',
+				txid,
+				include_watchonly,
+				verbose)
+
+		# List received transactions by label.
+		# 1. minconf                      (numeric, optional, default=1) The minimum number of
+		#                                 confirmations before payments are included.
+		# 2. include_empty                (boolean, optional, default=false) Whether to include labels
+		#                                 that haven't received any payments.
+		# 3. include_watchonly            (boolean, optional, default=true for watch-only wallets,
+		#                                 otherwise false) Whether to include watch-only addresses
+		#                                 (see 'importaddress')
+		# 4. include_immature_coinbase    (boolean, optional, default=false) Include immature coinbase
+		#                                 transactions.
+		def listreceivedbylabel(
+				self,
+				*,
+				minconf = 1,
+				include_empty = False,
+				include_watchonly = True,
+				include_immature_coinbase = False):
+			return (
+				'listreceivedbylabel',
+				minconf,
+				include_empty,
+				include_immature_coinbase
+			) if 'descriptor_wallet_only' in self.rpc.caps else (
+				'listreceivedbylabel',
+				minconf,
+				include_empty,
+				include_watchonly,
+				include_immature_coinbase)
+
+		# Get all transactions in blocks since block [blockhash], or all transactions if omitted.
+		# 1. blockhash            (string, optional) If set, the block hash to list transactions since,
+		#                         otherwise list all transactions.
+		# 2. target_confirmations (numeric, optional, default=1) Return the nth block hash from the main
+		#                         chain. e.g. 1 would mean the best block hash. Note: this is not used
+		#                         as a filter, but only affects [lastblock] in the return value
+		# 3. include_watchonly    (boolean, optional, default=true for watch-only wallets, otherwise
+		#                         false) Include transactions to watch-only addresses
+		# 4. include_removed      (boolean, optional, default=true) Show transactions that were removed
+		#                         due to a reorg in the "removed" array (not guaranteed to work on
+		#                         pruned nodes)
+		def listsinceblock(
+				self,
+				*,
+				blockhash = '',
+				target_confirmations = 1,
+				include_watchonly = True,
+				include_removed = True):
+			return (
+				'listsinceblock',
+				blockhash,
+				target_confirmations,
+				include_removed
+			) if 'descriptor_wallet_only' in self.rpc.caps else (
+				'listsinceblock',
+				blockhash,
+				target_confirmations,
+				include_watchonly,
+				include_removed)
 
 
 	class litecoin_core(bitcoin_core):
 	class litecoin_core(bitcoin_core):
 
 
@@ -106,6 +178,19 @@ class CallSigs:
 				txid,               # 1. transaction id
 				txid,               # 1. transaction id
 				include_watchonly)  # 2. optional, default=true for watch-only wallets, otherwise false
 				include_watchonly)  # 2. optional, default=true for watch-only wallets, otherwise false
 
 
+		def listreceivedbylabel(
+				self,
+				*,
+				minconf = 1,
+				include_empty = False,
+				include_watchonly = True,
+				include_immature_coinbase = False):
+			return (
+				'listreceivedbylabel',
+				minconf,
+				include_empty,
+				include_watchonly)
+
 	class bitcoin_cash_node(litecoin_core):
 	class bitcoin_cash_node(litecoin_core):
 		pass
 		pass
 
 
@@ -127,7 +212,7 @@ class BitcoinRPCClient(RPCClient, metaclass=AsyncInit):
 
 
 		self.proto = proto
 		self.proto = proto
 		self.daemon = daemon
 		self.daemon = daemon
-		self.call_sigs = getattr(CallSigs, daemon.id)(cfg)
+		self.call_sigs = getattr(CallSigs, daemon.id)(cfg, self)
 		self.twname = TrackingWalletName(cfg.regtest_user or proto.tw_name or cfg.tw_name or self.dfl_twname)
 		self.twname = TrackingWalletName(cfg.regtest_user or proto.tw_name or cfg.tw_name or self.dfl_twname)
 
 
 		super().__init__(
 		super().__init__(
@@ -174,6 +259,9 @@ class BitcoinRPCClient(RPCClient, metaclass=AsyncInit):
 		self.daemon_version_str = self.cached['networkinfo']['subversion']
 		self.daemon_version_str = self.cached['networkinfo']['subversion']
 		self.chain = self.cached['blockchaininfo']['chain']
 		self.chain = self.cached['blockchaininfo']['chain']
 
 
+		if self.daemon.id == 'bitcoin_core' and self.daemon_version >= 300000:
+			self.caps += ('descriptor_wallet_only',)
+
 		tip = await self.call('getblockhash', self.blockcount)
 		tip = await self.call('getblockhash', self.blockcount)
 		self.cur_date = (await self.call('getblockheader', tip))['time']
 		self.cur_date = (await self.call('getblockheader', tip))['time']
 		if self.chain != 'regtest':
 		if self.chain != 'regtest':

+ 1 - 2
mmgen/proto/btc/tw/addresses.py

@@ -62,8 +62,7 @@ class BitcoinTwAddresses(BitcoinTwView, TwAddresses, BitcoinTwRPC):
 		qmsg('done')
 		qmsg('done')
 
 
 		qmsg_r('Getting received funds data...')
 		qmsg_r('Getting received funds data...')
-		# args: 1:minconf, 2:include_empty, 3:include_watchonly, 4:include_immature_coinbase (>=v23.0.0)
-		for d in await self.rpc.call('listreceivedbylabel', 1, True, True):
+		for d in await self.rpc.icall('listreceivedbylabel', include_empty=True):
 			label = get_obj(TwLabel, proto=self.proto, text=d['label'])
 			label = get_obj(TwLabel, proto=self.proto, text=d['label'])
 			if label:
 			if label:
 				assert label.mmid in addrs, f'{label.mmid!r} not found in addrlist!'
 				assert label.mmid in addrs, f'{label.mmid!r} not found in addrlist!'

+ 4 - 13
mmgen/proto/btc/tw/txhistory.py

@@ -275,19 +275,10 @@ class BitcoinTwTxHistory(BitcoinTwView, TwTxHistory, BitcoinTwRPC):
 		blockhash = (
 		blockhash = (
 			await self.rpc.call('getblockhash', self.sinceblock)
 			await self.rpc.call('getblockhash', self.sinceblock)
 				if self.sinceblock else '')
 				if self.sinceblock else '')
-		# bitcoin-cli help listsinceblock:
-		# Arguments:
-		# 1. blockhash            (string, optional) If set, the block hash to list transactions since,
-		#                         otherwise list all transactions.
-		# 2. target_confirmations (numeric, optional, default=1) Return the nth block hash from the main
-		#                         chain. e.g. 1 would mean the best block hash. Note: this is not used
-		#                         as a filter, but only affects [lastblock] in the return value
-		# 3. include_watchonly    (boolean, optional, default=true for watch-only wallets, otherwise
-		#                         false) Include transactions to watch-only addresses
-		# 4. include_removed      (boolean, optional, default=true) Show transactions that were removed
-		#                         due to a reorg in the "removed" array (not guaranteed to work on
-		#                         pruned nodes)
-		return (await self.rpc.call('listsinceblock', blockhash, 1, True, False))['transactions']
+		return (await self.rpc.icall(
+			'listsinceblock',
+			blockhash = blockhash,
+			include_removed = False))['transactions']
 
 
 	async def gen_data(self, rpc_data, lbl_id):
 	async def gen_data(self, rpc_data, lbl_id):
 
 

+ 1 - 1
mmgen/proto/eth/daemon.py

@@ -130,7 +130,7 @@ class geth_daemon(ethereum_daemon):
 		)
 		)
 
 
 class reth_daemon(geth_daemon):
 class reth_daemon(geth_daemon):
-	daemon_data = _dd('Reth', 1008020, '1.8.2')
+	daemon_data = _dd('Reth', 1008002, '1.8.2')
 	version_pat = r'reth/v(\d+)\.(\d+)\.(\d+)'
 	version_pat = r'reth/v(\d+)\.(\d+)\.(\d+)'
 	exec_fn = 'reth'
 	exec_fn = 'reth'
 	version_info_arg = '--version'
 	version_info_arg = '--version'

+ 1 - 0
mmgen/proto/ltc/params.py

@@ -21,6 +21,7 @@ class mainnet(mainnet):
 	mmtypes         = ('L', 'C', 'S', 'B')
 	mmtypes         = ('L', 'C', 'S', 'B')
 	coin_amt        = 'LTCAmt'
 	coin_amt        = 'LTCAmt'
 	max_tx_fee      = 0.3
 	max_tx_fee      = 0.3
+	max_op_return_data_len = 80
 	base_coin       = 'LTC'
 	base_coin       = 'LTC'
 	forks           = []
 	forks           = []
 	bech32_hrp      = 'ltc'
 	bech32_hrp      = 'ltc'

+ 1 - 1
test/cmdtest_d/base.py

@@ -43,7 +43,7 @@ class CmdTestBase:
 	is_helper = False
 	is_helper = False
 
 
 	def __init__(self, cfg, trunner, cfgs, spawn):
 	def __init__(self, cfg, trunner, cfgs, spawn):
-		if hasattr(self, 'name'): # init will be called multiple times for classes with multiple inheritance
+		if hasattr(self, 'name'): # init may called multiple times
 			return
 			return
 		self.name = type(self).__name__
 		self.name = type(self).__name__
 		self.cfg = cfg
 		self.cfg = cfg

+ 9 - 3
test/cmdtest_d/main.py

@@ -379,7 +379,7 @@ class CmdTestMain(CmdTestBase, CmdTestShared):
 		if trunner is None or self.coin not in self.networks:
 		if trunner is None or self.coin not in self.networks:
 			return
 			return
 		if self.coin in ('btc', 'bch', 'ltc'):
 		if self.coin in ('btc', 'bch', 'ltc'):
-			self.tx_fee     = {'btc':'0.0001', 'bch':'0.001', 'ltc':'0.01'}[self.coin]
+			self.tx_fee     = {'btc':'90s', 'bch':'0.001', 'ltc':'0.01'}[self.coin]
 			self.txbump_fee = {'btc':'123s', 'bch':'567s', 'ltc':'12345s'}[self.coin]
 			self.txbump_fee = {'btc':'123s', 'bch':'567s', 'ltc':'12345s'}[self.coin]
 
 
 		self.unspent_data_file = joinpath('test', 'trash', 'unspent.json')
 		self.unspent_data_file = joinpath('test', 'trash', 'unspent.json')
@@ -417,6 +417,7 @@ class CmdTestMain(CmdTestBase, CmdTestShared):
 	def txcreate_dfl_wallet(self, addrfile):
 	def txcreate_dfl_wallet(self, addrfile):
 		return self.txcreate_common(
 		return self.txcreate_common(
 			sources = ['15'],
 			sources = ['15'],
+			add_opts = ['--btc-max-tx-fee=0.005'],
 			add_output_args = ['data:' + 'z' * self.proto.max_op_return_data_len])
 			add_output_args = ['data:' + 'z' * self.proto.max_op_return_data_len])
 
 
 	def txsign_dfl_wallet(self, txfile, pf='', save=True, has_label=False):
 	def txsign_dfl_wallet(self, txfile, pf='', save=True, has_label=False):
@@ -771,14 +772,19 @@ class CmdTestMain(CmdTestBase, CmdTestShared):
 	def txcreate(self, addrfile):
 	def txcreate(self, addrfile):
 		return self.txcreate_common(
 		return self.txcreate_common(
 			sources = ['1'],
 			sources = ['1'],
-			add_opts = ['--vsize-adj=1.01'],
+			add_opts = ['--vsize-adj=1.01', '--btc-max-tx-fee=0.005'],
 			add_output_args = ['hexdata:' + 'ee' * self.proto.max_op_return_data_len])
 			add_output_args = ['hexdata:' + 'ee' * self.proto.max_op_return_data_len])
 
 
 	def txbump(self, txfile, prepend_args=[], seed_args=[]):
 	def txbump(self, txfile, prepend_args=[], seed_args=[]):
 		if not self.proto.cap('rbf'):
 		if not self.proto.cap('rbf'):
 			msg(gray('Skipping RBF'))
 			msg(gray('Skipping RBF'))
 			return 'skip'
 			return 'skip'
-		args = prepend_args + ['--quiet', '--outdir='+self.tmpdir, txfile] + seed_args
+		args = prepend_args + [
+			'--quiet',
+			'--btc-max-tx-fee=0.006',
+			'--outdir='+self.tmpdir,
+			txfile
+			] + seed_args
 		t = self.spawn('mmgen-txbump', args)
 		t = self.spawn('mmgen-txbump', args)
 		if seed_args:
 		if seed_args:
 			t.do_decrypt_ka_data(pw=self.cfgs['14']['kapasswd'])
 			t.do_decrypt_ka_data(pw=self.cfgs['14']['kapasswd'])

+ 1 - 1
test/modtest_d/tx.py

@@ -146,7 +146,7 @@ class unit_tests:
 			'data:',
 			'data:',
 			'hexdata:',
 			'hexdata:',
 			'data:' + 'x' * (max_len + 1),
 			'data:' + 'x' * (max_len + 1),
-			'hexdata:' + ('deadbeef' * 20) + 'ee',
+			'hexdata:' + ('deadbeef' * (max_len // 4)) + 'ee',
 			'hex:0abc',
 			'hex:0abc',
 			'da:xyz',
 			'da:xyz',
 			'hexdata:xyz',
 			'hexdata:xyz',

+ 1 - 0
test/objtest_d/btc_mainnet.py

@@ -176,6 +176,7 @@ tests = {
 			{'id_str': 'x:L:3',         'proto': proto},
 			{'id_str': 'x:L:3',         'proto': proto},
 			{'id_str': 'F00BAA12',      'proto': proto},
 			{'id_str': 'F00BAA12',      'proto': proto},
 			{'id_str': 'F00BAA12:Z:99', 'proto': proto},
 			{'id_str': 'F00BAA12:Z:99', 'proto': proto},
+			{'id_str': 'F00BAA12:B:1-0/0', 'proto': proto},
 		),
 		),
 		'good': (
 		'good': (
 			{'id_str': 'F00BAA12:99',   'proto': proto, 'ret': 'F00BAA12:L:99'},
 			{'id_str': 'F00BAA12:99',   'proto': proto, 'ret': 'F00BAA12:L:99'},

+ 41 - 0
test/objtest_d/xmr_mainnet.py

@@ -0,0 +1,41 @@
+#!/usr/bin/env python3
+#
+# MMGen Wallet, a terminal-based cryptocurrency wallet
+# Copyright (C)2013-2025 The MMGen Project <mmgen@tuta.io>
+
+"""
+test.objtest_d.xmr_mainnet: XMR mainnet test vectors for MMGen data objects
+"""
+
+from mmgen.protocol import init_proto
+
+from mmgen.addr import MMGenID
+
+from ..include.common import cfg
+
+proto = init_proto(cfg, 'xmr', need_amt=True)
+
+tests = {
+	'MMGenID': {
+		'arg1': 'id_str',
+		'bad': (
+			{'id_str': 'F00BAA12',          'proto': proto},
+			{'id_str': 'F00BAA12:C:99',     'proto': proto},
+			{'id_str': 'F00BAA12:M',        'proto': proto},
+			{'id_str': 'F00BAA12:M:',       'proto': proto},
+			{'id_str': 'F00BAA12:M:99-FOO', 'proto': proto},
+			{'id_str': 'F00BAA12:M:99-1',   'proto': proto},
+			{'id_str': 'F00BAA12:M:99-x/y', 'proto': proto},
+			{'id_str': 'F00BAA12:M:99-1/y', 'proto': proto},
+			{'id_str': 'F00BAA12:M:0-1/1',  'proto': proto},
+			{'id_str': 'F00BAA12:M:1-0/-1', 'proto': proto},
+			{'id_str': 'F00BAA12:1-0/0',    'proto': proto},
+			{'id_str': 'F00BAA12:M:1-111111/3', 'proto': proto},
+		),
+		'good': (
+			{'id_str': 'F00BAA12:M:1', 'proto': proto},
+			{'id_str': 'F00BAA12:M:1-0/0', 'proto': proto},
+			{'id_str': 'F00BAA12:M:9999999-99999/99999', 'proto': proto},
+		),
+	},
+}

+ 0 - 2
test/test-release.d/cfg.sh

@@ -218,10 +218,8 @@ init_tests() {
 	d_btc_rt="overall operations using the regtest network (Bitcoin, multicoin)"
 	d_btc_rt="overall operations using the regtest network (Bitcoin, multicoin)"
 	t_btc_rt="
 	t_btc_rt="
 		- $cmdtest_py regtest
 		- $cmdtest_py regtest
-		x $cmdtest_py regtest_legacy
 		a $cmdtest_py swap
 		a $cmdtest_py swap
 	"
 	"
-	[ "$FAST" ] && t_btc_rt_skip='x'
 	[ "$SKIP_ALT_DEP" ] && t_btc_rt_skip+=' a'
 	[ "$SKIP_ALT_DEP" ] && t_btc_rt_skip+=' a'
 
 
 	d_bch="overall operations with emulated RPC data (Bitcoin Cash Node)"
 	d_bch="overall operations with emulated RPC data (Bitcoin Cash Node)"