diff --git a/examples/halving-calculator.py b/examples/halving-calculator.py index c66e13f9..bf757fd6 100755 --- a/examples/halving-calculator.py +++ b/examples/halving-calculator.py @@ -9,7 +9,7 @@ from mmgen.common import * opts.init({ 'text': { - 'desc': 'Estimate date of next Bitcoin halving', + 'desc': 'Estimate date of next block subsidy halving', 'usage':'[opts]', 'options': """ -h, --help Print this help message @@ -18,20 +18,20 @@ opts.init({ estimate """, 'notes': """ -Requires a running Bitcoin Core node +Requires a running coin daemon +Specify coin with --coin=btc (default)/--coin=bch/--coin=ltc If necessary, invoke with --rpc-host/--rpc-port/--rpc-user/--rpc-password Specify aiohttp backend with --rpc-backend=aiohttp (Linux only) """ } }) -HalvingInterval = 210000 # src/chainparams.cpp - def date(t): return '{}-{:02}-{:02} {:02}:{:02}:{:02}'.format(*time.gmtime(t)[:6]) def dhms(t): - return f'{t//60//60//24} days, {t//60//60%24:02}:{t//60%60:02}:{t%60:02} h/m/s' + t,neg = (-t,'-') if t < 0 else (t,' ') + return f'{neg}{t//60//60//24} days, {t//60//60%24:02}:{t//60%60:02}:{t%60:02} h/m/s' def time_diff_warning(t_diff): if abs(t_diff) > 60*60: @@ -48,8 +48,9 @@ async def main(): c = await rpc_init(proto) tip = await c.call('getblockcount') - remaining = HalvingInterval - tip % HalvingInterval - sample_size = int(opt.sample_size) if opt.sample_size else max(remaining,144) + assert tip > 1, 'block tip must be > 1' + remaining = proto.halving_interval - tip % proto.halving_interval + sample_size = int(opt.sample_size) if opt.sample_size else min(tip-1,max(remaining,144)) # aiohttp backend will perform these two calls concurrently: cur,old = await c.gathered_call('getblockstats',((tip,),(tip - sample_size,))) @@ -64,10 +65,10 @@ async def main(): print(f'Current block: {tip}') print(f'Next halving block: {tip + remaining}') print(f'Blocks until halving: {remaining}') - print('Current block subsidy: {} BTC'.format(str(sub).rstrip('0'))) + print('Current block subsidy: {} {}'.format(str(sub).rstrip('0'),proto.coin)) print(f'Current block discovery rate (over last {sample_size} blocks): {bdr/60:0.1f} minutes') print(f'Current clock time (UTC): {date(clock_time)}') print(f'Est. halving date (UTC): {date(cur["time"] + t_rem)}') - print(f'Est. time until halving: {dhms(cur["time"] + t_rem - clock_time)}') + print(f'Est. time until halving: {dhms(cur["time"] + t_rem - clock_time)}') run_session(main()) diff --git a/mmgen/daemon.py b/mmgen/daemon.py index 8742f493..c141bfaa 100755 --- a/mmgen/daemon.py +++ b/mmgen/daemon.py @@ -457,7 +457,7 @@ class BitcoinDaemon(CoinDaemon): elif self.daemon_id == 'bch': self.coin_specific_coind_args = ['--usecashaddr=0'] elif self.daemon_id == 'ltc': - self.coin_specific_coind_args = ['--mempoolreplacement=1'] + self.coin_specific_coind_args = ['--mempoolreplacement=1','--txindex=1'] if self.network == 'testnet': self.lockfile = os.path.join(self.datadir,self.testnet_dir,'.cookie') diff --git a/mmgen/protocol.py b/mmgen/protocol.py index 3083b2a1..a3e683a7 100755 --- a/mmgen/protocol.py +++ b/mmgen/protocol.py @@ -231,6 +231,7 @@ class CoinProtocol(MMGenObject): bech32_hrp = 'bc' sign_mode = 'daemon' avg_bdi = int(9.7 * 60) # average block discovery interval (historical) + halving_interval = 210000 def hex2wif(self,hexpriv,pubkey_type,compressed): # input is preprocessed hex sec = bytes.fromhex(hexpriv) @@ -366,6 +367,7 @@ class CoinProtocol(MMGenObject): forks = [] bech32_hrp = 'ltc' avg_bdi = 150 + halving_interval = 840000 class LitecoinTestnet(Litecoin): # addr ver nums same as Bitcoin testnet, except for 'p2sh' diff --git a/mmgen/rpc.py b/mmgen/rpc.py index 43a16c84..52721345 100755 --- a/mmgen/rpc.py +++ b/mmgen/rpc.py @@ -329,7 +329,7 @@ class BitcoinRPCClient(RPCClient,metaclass=aInitMeta): async def __ainit__(self,proto,daemon,backend): self.proto = proto - self.daemon_data_dir = daemon.datadir + self.daemon = daemon super().__init__( host = 'localhost' if g.test_suite else (g.rpc_host or 'localhost'), @@ -387,14 +387,13 @@ class BitcoinRPCClient(RPCClient,metaclass=aInitMeta): def get_daemon_cfg_fn(self): # Use dirname() to remove 'bob' or 'alice' component - cfg_dir = os.path.dirname(g.data_dir) if self.proto.regtest else self.daemon_data_dir return os.path.join( - cfg_dir, - (self.proto.is_fork_of or self.proto.name).lower() + '.conf' ) + (os.path.dirname(g.data_dir) if self.proto.regtest else self.daemon.datadir), + self.daemon.cfg_file ) def get_daemon_auth_cookie_fn(self): return os.path.join( - self.daemon_data_dir, + self.daemon.datadir, self.proto.daemon_data_subdir, '.cookie' ) @@ -482,7 +481,7 @@ class EthereumRPCClient(RPCClient,metaclass=aInitMeta): async def __ainit__(self,proto,daemon,backend): self.proto = proto - self.daemon_data_dir = daemon.datadir + self.daemon = daemon super().__init__( host = 'localhost' if g.test_suite else (g.rpc_host or 'localhost'), diff --git a/test/test_py_d/ts_regtest.py b/test/test_py_d/ts_regtest.py index 8ab0e502..4ea02852 100755 --- a/test/test_py_d/ts_regtest.py +++ b/test/test_py_d/ts_regtest.py @@ -285,7 +285,7 @@ class TestSuiteRegtest(TestSuiteBase,TestSuiteShared): return t def halving_calculator_bob(self): - t = self.spawn('halving-calculator.py',['--bob','--sample-size=144'],cmd_dir='examples') + t = self.spawn('halving-calculator.py',['--bob'],cmd_dir='examples') t.expect('time until halving') t.read() return t diff --git a/test/unit_tests_d/ut_rpc.py b/test/unit_tests_d/ut_rpc.py index 7b406966..8a0e7368 100755 --- a/test/unit_tests_d/ut_rpc.py +++ b/test/unit_tests_d/ut_rpc.py @@ -13,11 +13,11 @@ from mmgen.daemon import CoinDaemon,MoneroWalletDaemon def auth_test(proto,d): d.stop() if g.platform != 'win': - qmsg(f'\n Testing authentication with credentials from bitcoin.conf:') + qmsg(f'\n Testing authentication with credentials from {d.cfg_file}:') d.remove_datadir() os.makedirs(d.datadir) - cf = os.path.join(d.datadir,'bitcoin.conf') + cf = os.path.join(d.datadir,d.cfg_file) open(cf,'a').write('\nrpcuser = ut_rpc\nrpcpassword = ut_rpc_passw0rd\n') d.add_flag('keep_cfg_file') @@ -25,7 +25,7 @@ def auth_test(proto,d): async def do(): rpc = await rpc_init(proto) - assert rpc.auth.user == 'ut_rpc', 'user is not ut_rpc!' + assert rpc.auth.user == 'ut_rpc', f'{rpc.auth.user}: user is not ut_rpc!' run_session(do()) d.stop() @@ -54,6 +54,8 @@ class init_test: rpc = await rpc_init(proto,backend) do_msg(rpc) + ltc = bch + async def eth(proto,backend): rpc = await rpc_init(proto,backend) do_msg(rpc) @@ -76,14 +78,17 @@ def run_test(coin,auth): class unit_tests: - altcoin_deps = ('bch','eth','xmr_wallet') - - def bch(self,name,ut): - return run_test('bch',auth=True) + altcoin_deps = ('ltc','bch','eth','xmr_wallet') def btc(self,name,ut): return run_test('btc',auth=True) + def ltc(self,name,ut): + return run_test('ltc',auth=True) + + def bch(self,name,ut): + return run_test('bch',auth=True) + def eth(self,name,ut): return run_test('eth',auth=False)