X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=lib%2Fnetwork.py;h=114edc62ae67a4a37ed17f3fae512c08ba5a9518;hb=HEAD;hp=81c9b96f49970202a07e8acce50bf4a45ebe1293;hpb=8140d6c78e116edef6578799c73cfce374b296c8;p=electrum-nvc.git diff --git a/lib/network.py b/lib/network.py index 81c9b96..114edc6 100644 --- a/lib/network.py +++ b/lib/network.py @@ -4,24 +4,46 @@ from bitcoin import * import interface from blockchain import Blockchain -DEFAULT_PORTS = {'t':'50001', 's':'50002', 'h':'8081', 'g':'8082'} +DEFAULT_PORTS = {'t':'40001', 's':'40002', 'h':'7081', 'g':'7082'} DEFAULT_SERVERS = { - #'electrum.coinwallet.me': {'h': '8081', 's': '50002', 't': '50001', 'g': '8082'}, - 'electrum.hachre.de': {'h': '8081', 's': '50002', 't': '50001', 'g': '8082'}, - 'electrum.novit.ro': {'h': '8081', 's': '50002', 't': '50001', 'g': '8082'}, - 'electrum.stepkrav.pw': {'h': '8081', 's': '50002', 't': '50001', 'g': '8082'}, - #'ecdsa.org': {'h': '8081', 's': '50002', 't': '50001', 'g': '8082'}, - 'electrum.no-ip.org': {'h': '80', 's': '50002', 't': '50001', 'g': '443'}, - 'electrum.drollette.com': {'h': '5000', 's': '50002', 't': '50001', 'g': '8082'}, - 'btc.it-zone.org': {'h': '80', 's': '110', 't': '50001', 'g': '443'}, - 'btc.medoix.com': {'h': '8081', 's': '50002', 't': '50001', 'g': '8082'}, - 'electrum.stupidfoot.com': {'h': '8081', 's': '50002', 't': '50001', 'g': '8082'}, - #'electrum.pdmc.net': {'h': '8081', 's': '50002', 't': '50001', 'g': '8082'}, - 'electrum.be': {'h': '8081', 's': '50002', 't': '50001', 'g': '8082'} +# '127.0.0.1': DEFAULT_PORTS, + '193.23.181.148': DEFAULT_PORTS, + '91.235.143.61': DEFAULT_PORTS, } +def parse_servers(result): + """ parse servers list into dict format""" + from version import PROTOCOL_VERSION + servers = {} + for item in result: + host = item[1] + out = {} + version = None + pruning_level = '-' + if len(item) > 2: + for v in item[2]: + if re.match("[stgh]\d*", v): + protocol, port = v[0], v[1:] + if port == '': port = DEFAULT_PORTS[protocol] + out[protocol] = port + elif re.match("v(.?)+", v): + version = v[1:] + elif re.match("p\d*", v): + pruning_level = v[1:] + if pruning_level == '': pruning_level = '0' + try: + is_recent = float(version)>=float(PROTOCOL_VERSION) + except Exception: + is_recent = False + + if out and is_recent: + out['pruning'] = pruning_level + servers[host] = out + + return servers + def filter_protocol(servers, p): @@ -39,7 +61,9 @@ from simple_config import SimpleConfig class Network(threading.Thread): - def __init__(self, config = {}): + def __init__(self, config=None): + if config is None: + config = {} # Do not use mutables as default values! threading.Thread.__init__(self) self.daemon = True self.config = SimpleConfig(config) if type(config) == type({}) else config @@ -66,6 +90,8 @@ class Network(threading.Thread): self.interface = None self.proxy = self.config.get('proxy') self.heights = {} + self.merkle_roots = {} + self.utxo_roots = {} self.server_lag = 0 dir_path = os.path.join( self.config.path, 'certs') @@ -76,12 +102,21 @@ class Network(threading.Thread): self.subscriptions = {} self.subscriptions[self.on_banner] = [('server.banner',[])] self.subscriptions[self.on_peers] = [('server.peers.subscribe',[])] + self.pending_transactions_for_notifications = [] def is_connected(self): return self.interface and self.interface.is_connected + def is_up_to_date(self): + return self.interface.is_up_to_date() + + + def main_server(self): + return self.interface.server + + def send_subscriptions(self): for cb, sub in self.subscriptions.items(): self.interface.send(sub, cb) @@ -141,11 +176,14 @@ class Network(threading.Thread): def get_servers(self): - out = self.irc_servers if self.irc_servers else DEFAULT_SERVERS - for s in self.recent_servers: - host, port, protocol = s.split(':') - if host not in out: - out[host] = { protocol:port } + if self.irc_servers: + out = self.irc_servers + else: + out = DEFAULT_SERVERS + for s in self.recent_servers: + host, port, protocol = s.split(':') + if host not in out: + out[host] = { protocol:port } return out def start_interface(self, server): @@ -232,7 +270,7 @@ class Network(threading.Thread): def stop_interface(self): self.interface.stop() - #self.interface = None + def set_server(self, server): if self.default_server == server and self.interface.is_connected: @@ -296,7 +334,9 @@ class Network(threading.Thread): self.start_random_interface() continue - self.pending_servers.remove(i.server) + if i.server in self.pending_servers: + self.pending_servers.remove(i.server) + if i.is_connected: #if i.server in self.interfaces: raise self.interfaces[i.server] = i @@ -322,9 +362,14 @@ class Network(threading.Thread): def on_header(self, i, r): result = r.get('result') - if not result: return + if not result: + return height = result.get('block_height') + if not height: + return self.heights[i.server] = height + self.merkle_roots[i.server] = result.get('merkle_root') + self.utxo_roots[i.server] = result.get('utxo_root') # notify blockchain about the new height self.blockchain.queue.put((i,result)) @@ -339,7 +384,7 @@ class Network(threading.Thread): def on_peers(self, i, r): if not r: return - self.irc_servers = self.parse_servers(r.get('result')) + self.irc_servers = parse_servers(r.get('result')) self.trigger_callback('peers') def on_banner(self, i, r): @@ -354,71 +399,35 @@ class Network(threading.Thread): def synchronous_get(self, requests, timeout=100000000): - queue = Queue.Queue() - ids = self.interface.send(requests, lambda i,r: queue.put(r)) - id2 = ids[:] - res = {} - while ids: - r = queue.get(True, timeout) - _id = r.get('id') - if _id in ids: - ids.remove(_id) - res[_id] = r.get('result') - out = [] - for _id in id2: - out.append(res[_id]) - return out + return self.interface.synchronous_get(requests) - def retrieve_transaction(self, tx_hash, tx_height=0): - import transaction - r = self.synchronous_get([ ('blockchain.transaction.get',[tx_hash, tx_height]) ])[0] - if r: - return transaction.Transaction(r) + def get_header(self, tx_height): + return self.blockchain.read_header(tx_height) + def get_local_height(self): + return self.blockchain.height() - def parse_servers(self, result): - """ parse servers list into dict format""" - from version import PROTOCOL_VERSION - servers = {} - for item in result: - host = item[1] - out = {} - version = None - pruning_level = '-' - if len(item) > 2: - for v in item[2]: - if re.match("[stgh]\d*", v): - protocol, port = v[0], v[1:] - if port == '': port = DEFAULT_PORTS[protocol] - out[protocol] = port - elif re.match("v(.?)+", v): - version = v[1:] - elif re.match("p\d*", v): - pruning_level = v[1:] - if pruning_level == '': pruning_level = '0' - try: - is_recent = float(version)>=float(PROTOCOL_VERSION) - except Exception: - is_recent = False - if out and is_recent: - out['pruning'] = pruning_level - servers[host] = out - return servers + #def retrieve_transaction(self, tx_hash, tx_height=0): + # import transaction + # r = self.synchronous_get([ ('blockchain.transaction.get',[tx_hash, tx_height]) ])[0] + # if r: + # return transaction.Transaction(r) + if __name__ == "__main__": - import simple_config - config = simple_config.SimpleConfig({'verbose':True, 'server':'ecdsa.org:50002:s'}) - network = Network(config) + network = NetworkProxy({}) network.start() + print network.get_servers() - while 1: - time.sleep(1) - - + q = Queue.Queue() + network.send([('blockchain.headers.subscribe',[])], q.put) + while True: + r = q.get(timeout=10000) + print r