Daemon version checking

- abort RPC initialization if version of running coin daemon is greater
  than latest tested version

- version checking may be overridden with --ignore-daemon-version option
This commit is contained in:
The MMGen Project 2021-02-19 20:22:42 +03:00
commit a4eee3ef4b
Signed by: mmgen
GPG key ID: 3F8B1861E32B7DA2
6 changed files with 113 additions and 12 deletions

View file

@ -293,16 +293,74 @@ class CoinDaemon(Daemon):
network_ids = ('btc','btc_tn','btc_rt','bch','bch_tn','bch_rt','ltc','ltc_tn','ltc_rt','xmr','eth','etc')
cd = namedtuple('daemon_data',
['coin','cls_pfx','coind_exec','cli_exec','cfg_file','testnet_dir','dfl_rpc','dfl_rpc_tn','dfl_rpc_rt'])
cd = namedtuple('daemon_data', [
'coin',
'cls_pfx',
'coind_name',
'coind_exec',
'coind_version', 'coind_version_str', # latest tested version
'cli_exec',
'cfg_file',
'testnet_dir',
'dfl_rpc',
'dfl_rpc_tn',
'dfl_rpc_rt' ])
daemon_ids = { # for BCH we use non-standard RPC ports
'btc': cd('Bitcoin', 'Bitcoin', 'bitcoind', 'bitcoin-cli', 'bitcoin.conf', 'testnet3',8332,18332,18444),
'bch': cd('BitcoinCashNode', 'Bitcoin', 'bitcoind-bchn','bitcoin-cli-bchn','bitcoin.conf','testnet3',8442,18442,18553),
'ltc': cd('Litecoin', 'Bitcoin', 'litecoind', 'litecoin-cli','litecoin.conf','testnet4',9332,19332,19444),
'xmr': cd('Monero', 'Monero', 'monerod', 'monerod', 'bitmonero.conf',None, 18081,None,None),
'eth': cd('Ethereum', 'Ethereum','openethereum','openethereum','parity.conf', None, 8545, 8545,8545),
'etc': cd('Ethereum Classic','Ethereum','openethereum','openethereum','parity.conf', None, 8545, 8545,8545)
daemon_ids = {
'btc': cd(
'Bitcoin',
'Bitcoin',
'Bitcoin Core',
'bitcoind', 200100, '0.20.1',
'bitcoin-cli',
'bitcoin.conf',
'testnet3',
8332, 18332, 18444),
'bch': cd(
'BitcoinCashNode',
'Bitcoin',
'Bitcoin Cash Node',
'bitcoind-bchn', 22020000, '22.2.0',
'bitcoin-cli-bchn',
'bitcoin.conf',
'testnet3',
8442, 18442, 18553), # for BCH we use non-standard RPC ports
'ltc': cd(
'Litecoin',
'Bitcoin',
'Litecoin Core',
'litecoind', 180100, '0.18.1',
'litecoin-cli',
'litecoin.conf',
'testnet4',
9332, 19332, 19444),
'xmr': cd(
'Monero',
'Monero',
'Monero',
'monerod', 'N/A', 'N/A',
'monerod',
'bitmonero.conf',
None,
18081, None, None),
'eth': cd(
'Ethereum',
'Ethereum',
'OpenEthereum',
'openethereum', 3000001, '3.0.1',
'openethereum',
'parity.conf',
None,
8545, 8545, 8545),
'etc': cd(
'Ethereum Classic',
'Ethereum',
'OpenEthereum',
'openethereum', 3000001, '3.0.1',
'openethereum',
'parity.conf',
None,
8545, 8545, 8545)
}
def __new__(cls,network_id=None,test_suite=False,flags=None,proto=None):

View file

@ -197,6 +197,7 @@ common_opts_data = {
--, --force-256-color Force 256-color output when color is enabled
--, --data-dir=path Specify {pnm} data directory location
--, --daemon-data-dir=path Specify {dn} data directory location
--, --ignore-daemon-version Ignore {dn} version check
--, --no-license Suppress the GPL license prompt
--, --rpc-host=host Communicate with {dn} running on host 'host'
--, --rpc-port=port Communicate with {dn} listening on port 'port'

View file

@ -355,6 +355,7 @@ class BitcoinRPCClient(RPCClient,metaclass=aInitMeta):
('getblockhash',(0,)),
))
self.daemon_version = self.cached['networkinfo']['version']
self.daemon_version_str = self.cached['networkinfo']['subversion']
self.chain = self.cached['blockchaininfo']['chain']
tip = await self.call('getblockhash',self.blockcount)
@ -505,7 +506,12 @@ class EthereumRPCClient(RPCClient,metaclass=aInitMeta):
('parity_nodeKind',()),
))
self.daemon_version = vi['version']
self.daemon_version = int((
lambda v: '{:d}{:03d}{:03d}'.format(v['major'],v['minor'],v['patch'])
)(vi['version']))
self.daemon_version_str = (
lambda v: '{}.{}.{}'.format(v['major'],v['minor'],v['patch'])
)(vi['version'])
self.cur_date = int(bh['timestamp'],16)
self.chain = ch.replace(' ','_')
self.caps = ('full_node',) if nk['capability'] == 'full' else ()
@ -590,7 +596,7 @@ class MoneroWalletRPCClient(RPCClient):
'refresh', # start_height
)
async def rpc_init(proto,backend=None):
async def rpc_init(proto,backend=None,ignore_daemon_version=False):
if not 'rpc' in proto.mmcaps:
die(1,f'Coin daemon operations not supported for {proto.name} protocol!')
@ -604,6 +610,24 @@ async def rpc_init(proto,backend=None):
daemon = CoinDaemon(proto=proto,test_suite=g.test_suite),
backend = backend or opt.rpc_backend )
if not (ignore_daemon_version or opt.ignore_daemon_version):
if rpc.daemon_version > rpc.daemon.coind_version:
rdie(1,fmt(
"""
The running {} daemon has version {}.
This version of MMGen is tested only on {} v{} and below.
To avoid this error, downgrade your daemon to a supported version.
Alternatively, you may invoke the command with the --ignore-daemon-version
option, in which case you proceed at your own risk.
""".format(
rpc.daemon.coind_name,
rpc.daemon_version_str,
rpc.daemon.coind_name,
rpc.daemon.coind_version_str,
),indent=' ').rstrip())
if proto.chain_name != rpc.chain:
raise RPCChainMismatch(
'{} protocol chain is {}, but coin daemon chain is {}'.format(

View file

@ -901,6 +901,12 @@ from .tw import TwAddrList,TwUnspentOutputs
class MMGenToolCmdRPC(MMGenToolCmds):
"tracking wallet commands using the JSON-RPC interface"
async def daemon_version(self):
"print coin daemon version"
from .rpc import rpc_init
r = await rpc_init(self.proto,ignore_daemon_version=True)
return f'{r.daemon.coind_name} version {r.daemon_version} ({r.daemon_version_str})'
async def getbalance(self,minconf=1,quiet=False,pager=False):
"list confirmed/unconfirmed, spendable/unspendable balances in tracking wallet"
from .tw import TwGetBalance

View file

@ -146,6 +146,7 @@ class TestSuiteEthdev(TestSuiteBase,TestSuiteShared):
color = True
cmd_group = (
('setup', 'OpenEthereum dev mode tests for coin {} (start openethereum)'.format(coin)),
('daemon_version', 'mmgen-tool daemon_version'),
('wallet_upgrade1', 'upgrading the tracking wallet (v1 -> v2)'),
('wallet_upgrade2', 'upgrading the tracking wallet (v2 -> v3)'),
('addrgen', 'generating addresses'),
@ -349,6 +350,11 @@ class TestSuiteEthdev(TestSuiteBase,TestSuiteShared):
os.unlink(w_to)
return t
def daemon_version(self):
t = self.spawn('mmgen-tool', self.eth_args + ['daemon_version'])
t.expect('version')
return t
def wallet_upgrade1(self): return self.wallet_upgrade('tracking-wallet-v1.json')
def wallet_upgrade2(self): return self.wallet_upgrade('tracking-wallet-v2.json')

View file

@ -143,6 +143,7 @@ class TestSuiteRegtest(TestSuiteBase,TestSuiteShared):
color = True
cmd_group = (
('setup', 'regtest (Bob and Alice) mode setup'),
('daemon_version', 'mmgen-tool daemon_version'),
('current_user', 'current user'),
('halving_calculator_bob', 'halving calculator (Bob)'),
('walletgen_bob', 'wallet generation (Bob)'),
@ -279,6 +280,11 @@ class TestSuiteRegtest(TestSuiteBase,TestSuiteShared):
t.expect(s)
return t
def daemon_version(self):
t = self.spawn('mmgen-tool', ['--bob','daemon_version'])
t.expect('version')
return t
def current_user(self):
t = self.spawn('mmgen-regtest', ['user'])
t.expect('Bob')