support Bitcoin Core v30.0

As of Core v30, legacy BDB wallets are no longer supported.  Users with legacy
tracking wallets must convert them to descriptor wallets.  See `bitcoin-cli
migratewallet` for details.

The maximum OP_RETURN data size has been increased to 4096 bytes, while the one
data output per transaction limitation has been retained.  This seems like a
reasonable compromise.  The MMGen Project discourages the use of MMGen Wallet
to spam the blockchain.
This commit is contained in:
The MMGen Project 2025-10-26 10:35:54 +00:00
commit 81ece1ff3b
Signed by: mmgen
GPG key ID: 3F8B1861E32B7DA2
9 changed files with 31 additions and 11 deletions

View file

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

View file

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

View file

@ -19,7 +19,7 @@ from ...util import list_gen
from ...daemon import CoinDaemon, _nw, _dd
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'
cli_fn = 'bitcoin-cli'
testnet_dir = 'testnet3'

View file

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

View file

@ -76,7 +76,7 @@ class MMGenRegtest(MMGenObject):
def __init__(self, cfg, coin, *, bdb_wallet=False):
self.cfg = cfg
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'
@ -85,7 +85,7 @@ class MMGenRegtest(MMGenObject):
cfg,
network_id = self.coin + '_rt',
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,
# so reinstantiate with every call:

View file

@ -49,8 +49,9 @@ class CallSigs:
class bitcoin_core:
def __init__(self, cfg):
def __init__(self, cfg, rpc):
self.cfg = cfg
self.rpc = rpc
def createwallet(
self,
@ -86,6 +87,10 @@ class CallSigs:
# decoderawtransaction)
def gettransaction(self, txid, include_watchonly, verbose):
return (
'gettransaction',
txid,
verbose
) if 'descriptor_wallet_only' in self.rpc.caps else (
'gettransaction',
txid,
include_watchonly,
@ -109,6 +114,11 @@ class CallSigs:
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,
@ -134,6 +144,11 @@ class CallSigs:
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,
@ -197,7 +212,7 @@ class BitcoinRPCClient(RPCClient, metaclass=AsyncInit):
self.proto = proto
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)
super().__init__(
@ -244,6 +259,9 @@ class BitcoinRPCClient(RPCClient, metaclass=AsyncInit):
self.daemon_version_str = self.cached['networkinfo']['subversion']
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)
self.cur_date = (await self.call('getblockheader', tip))['time']
if self.chain != 'regtest':

View file

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

View file

@ -379,7 +379,7 @@ class CmdTestMain(CmdTestBase, CmdTestShared):
if trunner is None or self.coin not in self.networks:
return
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.unspent_data_file = joinpath('test', 'trash', 'unspent.json')
@ -417,6 +417,7 @@ class CmdTestMain(CmdTestBase, CmdTestShared):
def txcreate_dfl_wallet(self, addrfile):
return self.txcreate_common(
sources = ['15'],
add_opts = ['--btc-max-tx-fee=0.005'],
add_output_args = ['data:' + 'z' * self.proto.max_op_return_data_len])
def txsign_dfl_wallet(self, txfile, pf='', save=True, has_label=False):
@ -771,7 +772,7 @@ class CmdTestMain(CmdTestBase, CmdTestShared):
def txcreate(self, addrfile):
return self.txcreate_common(
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])
def txbump(self, txfile, prepend_args=[], seed_args=[]):
@ -780,6 +781,7 @@ class CmdTestMain(CmdTestBase, CmdTestShared):
return 'skip'
args = prepend_args + [
'--quiet',
'--btc-max-tx-fee=0.006',
'--outdir='+self.tmpdir,
txfile
] + seed_args

View file

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