mmgen-node-tools/mmnode-peerblocks

118 lines
3.4 KiB
Python
Executable file

#!/usr/bin/env python3
#
# mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
# Copyright (C)2013-2017 Philemon <mmgen-py@yandex.com>
#
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# this program. If not, see <http://www.gnu.org/licenses/>.
"""
mmgen-peerblocks: List blocks in flight, disconnect stalling nodes
"""
import time,threading
from mmgen.common import *
opts_data = {
'text': {
'desc': 'List blocks in flight, disconnect stalling nodes',
'usage': '[opts]',
'options': """
-h, --help Print this help message
--, --longhelp Print help message for long options (common options)
"""
}
}
cmd_args = opts.init(opts_data)
colors = ['\033[38;5;%s;1m' % c for c in (238,240,242,244,246,247,249,251,253,255)]
_red,_reset = '\033[31m','\033[0m'
ERASE_ALL,ERASE_LINE,CUR_HOME,CUR_HIDE,CUR_SHOW = \
'\033[J','\033[K','\033[H','\033[?25l','\033[?25h'
import atexit
def at_exit():
import os
os.system('stty sane')
sys.stderr.write('\n')
atexit.register(at_exit)
bc = rpc_init()
msg_r(CUR_HOME+ERASE_ALL)
def do_display():
from mmgen.term import get_terminal_size
global data
count = 1
while True:
twid = get_terminal_size()[0]
data = bc.getpeerinfo()
min_t = None
lines = []
with lock:
msg('{}{}{}ACTIVE PEERS ({}) - poll {}'.format(
CUR_HOME,ERASE_ALL,CUR_HOME,len(data),count))
for d in data:
line = { 'id': d['id'], 'data': [] }
if 'inflight' in d and d['inflight']:
blks = [str(e) for e in d['inflight']]
min_p = min(e for e in d['inflight'])
if not min_t or min_t > min_p: min_t = min_p
line_d = ' '.join(blks)[:twid-6]
blks = blks[:len(line_d) - len(line_d.replace(' ','')) + 1]
blks[-1] = blks[-1][:len(line_d.split(' ')[-1])]
line['data'] = [[colors[int(i)%10],i,_reset] for i in blks if i]
else:
line['data'] = []
lines.append(line)
for line in lines:
d = ' '.join([(a,_red)[int(b)==min_t]+b+c for a,b,c in line['data']])
sys.stderr.write('\r{} {:>3}: {}\n'.format(ERASE_LINE,line['id'],d))
msg_r(ERASE_ALL+'Hit ENTER for disconnect prompt: ')
time.sleep(2)
count += 1
lock = threading.Lock()
data = {}
t = threading.Thread(target=do_display,name='display')
t.daemon = True
t.start()
def do_loop():
global data
while True:
input()
with lock:
ids = [str(d['id']) for d in data]
msg('{}{}{}ACTIVE PEERS ({})'.format(CUR_HOME,ERASE_ALL,CUR_HOME,len(data)))
msg(' '+'\n '.join(['{:>3}: {:30} {}'.format(*[d[k] for k in ('id','addr','subver')]) for d in data]))
reply = input('Enter a peer number to disconnect> ')
if reply == '':
pass
elif reply in ids:
idx = ids.index(reply)
msg("Disconnecting peer {} ('{}')".format(reply,data[idx]['addr']))
bc.disconnectnode(data[idx]['addr'])
time.sleep(1.5)
else:
msg("'{}': invalid peer number".format(reply))
time.sleep(0.5)
try:
do_loop()
except KeyboardInterrupt:
pass