commit 2d05e7d891f13dc07dacb57b11a32ff14d3500b4
parent 4d6a0f29ee99969585294a2a22bc45385659a3c3
Author: Neil Booth <kyuupichan@gmail.com>
Date: Sun, 30 Aug 2015 21:18:10 +0900
Merge the network and network_proxy
Diffstat:
14 files changed, 160 insertions(+), 321 deletions(-)
diff --git a/electrum b/electrum
@@ -77,7 +77,7 @@ if is_bundle or is_local or is_android:
from electrum import util
-from electrum import SimpleConfig, Network, Wallet, WalletStorage, NetworkProxy
+from electrum import SimpleConfig, Network, Wallet, WalletStorage
from electrum.util import print_msg, print_error, print_stderr, print_json, set_verbosity, InvalidPassword
from electrum.plugins import init_plugins, run_hook, always_hook
from electrum.commands import get_parser, known_commands, Commands, config_variables
@@ -97,12 +97,12 @@ def prompt_password(prompt, confirm=True):
-def init_gui(config, network_proxy):
+def init_gui(config, network):
gui_name = config.get('gui', 'qt')
if gui_name in ['lite', 'classic']:
gui_name = 'qt'
gui = __import__('electrum_gui.' + gui_name, fromlist=['electrum_gui'])
- gui = gui.ElectrumGui(config, network_proxy)
+ gui = gui.ElectrumGui(config, network)
return gui
@@ -157,8 +157,7 @@ def init_cmdline(config):
wallet = Wallet.from_seed(seed, password, storage)
if not config.get('offline'):
- s = get_daemon(config, False)
- network = NetworkProxy(s, config)
+ network = Network(config)
network.start()
wallet.start_threads(network)
print_msg("Recovering wallet...")
@@ -326,19 +325,18 @@ class ClientThread(util.DaemonThread):
# send response and exit
self.client_pipe.send(response)
self.server.remove_client(self)
-
+
class NetworkServer(util.DaemonThread):
- def __init__(self, config, network_proxy):
+ def __init__(self, config, network):
util.DaemonThread.__init__(self)
self.debug = False
self.config = config
self.pipe = util.QueuePipe()
- self.network_proxy = network_proxy
- self.network = self.network_proxy.network
+ self.network = network
self.lock = threading.RLock()
# each GUI is a client of the daemon
self.clients = []
@@ -516,11 +514,11 @@ if __name__ == '__main__':
# daemon is not running
if cmd_name == 'gui':
- network_proxy = NetworkProxy(None, config)
- network_proxy.start()
- server = NetworkServer(config, network_proxy)
+ network = Network(config)
+ network.start()
+ server = NetworkServer(config, network)
server.start()
- server.gui = init_gui(config, network_proxy)
+ server.gui = init_gui(config, network)
server.gui.main()
elif cmd_name == 'daemon':
subcommand = config.get('subcommand')
@@ -530,9 +528,9 @@ if __name__ == '__main__':
elif subcommand == 'start':
p = os.fork()
if p == 0:
- network_proxy = NetworkProxy(None, config)
- network_proxy.start()
- server = NetworkServer(config, network_proxy)
+ network = Network(config)
+ network.start()
+ server = NetworkServer(config, network)
if config.get('websocket_server'):
import websockets
websockets.WebSocketServer(config, server).start()
diff --git a/gui/qt/main_window.py b/gui/qt/main_window.py
@@ -2357,7 +2357,7 @@ class ElectrumWindow(QMainWindow):
txid, ok = QInputDialog.getText(self, _('Lookup transaction'), _('Transaction ID') + ':')
if ok and txid:
try:
- r = self.network.synchronous_get([('blockchain.transaction.get',[str(txid)])])[0]
+ r = self.network.synchronous_get(('blockchain.transaction.get',[str(txid)]))
except BaseException as e:
self.show_message(str(e))
return
diff --git a/lib/__init__.py b/lib/__init__.py
@@ -11,4 +11,3 @@ import transaction
from transaction import Transaction
from plugins import BasePlugin
from commands import Commands, known_commands
-from network_proxy import NetworkProxy
diff --git a/lib/commands.py b/lib/commands.py
@@ -148,7 +148,7 @@ class Commands:
"""Return the transaction history of any address. Note: This is a
walletless server query, results are not checked by SPV.
"""
- return self.network.synchronous_get([('blockchain.address.get_history', [address])])[0]
+ return self.network.synchronous_get(('blockchain.address.get_history', [address]))
@command('nw')
def listunspent(self):
@@ -165,16 +165,15 @@ class Commands:
"""Returns the UTXO list of any address. Note: This
is a walletless server query, results are not checked by SPV.
"""
- return self.network.synchronous_get([('blockchain.address.listunspent', [address])])[0]
+ return self.network.synchronous_get(('blockchain.address.listunspent', [address]))
@command('n')
def getutxoaddress(self, txid, pos):
"""Get the address of a UTXO. Note: This is a walletless server query, results are
not checked by SPV.
"""
- r = self.network.synchronous_get([('blockchain.utxo.get_address', [txid, pos])])
- if r:
- return {'address':r[0]}
+ r = self.network.synchronous_get(('blockchain.utxo.get_address', [txid, pos]))
+ return {'address': r}
@command('wp')
def createrawtx(self, inputs, outputs, unsigned=False):
@@ -219,7 +218,7 @@ class Commands:
def broadcast(self, tx):
"""Broadcast a transaction to the network. """
t = Transaction(tx)
- return self.network.synchronous_get([('blockchain.transaction.broadcast', [str(t)])])[0]
+ return self.network.synchronous_get(('blockchain.transaction.broadcast', [str(t)]))
@command('')
def createmultisig(self, num, pubkeys):
@@ -287,7 +286,7 @@ class Commands:
"""Return the balance of any address. Note: This is a walletless
server query, results are not checked by SPV.
"""
- out = self.network.synchronous_get([('blockchain.address.get_balance', [address])])[0]
+ out = self.network.synchronous_get(('blockchain.address.get_balance', [address]))
out["confirmed"] = str(Decimal(out["confirmed"])/COIN)
out["unconfirmed"] = str(Decimal(out["unconfirmed"])/COIN)
return out
@@ -295,7 +294,7 @@ class Commands:
@command('n')
def getproof(self, address):
"""Get Merkle branch of an address in the UTXO set"""
- p = self.network.synchronous_get([('blockchain.address.get_proof', [address])])[0]
+ p = self.network.synchronous_get(('blockchain.address.get_proof', [address]))
out = []
for i,s in p:
out.append(i)
@@ -305,7 +304,7 @@ class Commands:
def getmerkle(self, txid, height):
"""Get Merkle branch of a transaction included in a block. Electrum
uses this to verify transactions (Simple Payment Verification)."""
- return self.network.synchronous_get([('blockchain.transaction.get_merkle', [txid, int(height)])])[0]
+ return self.network.synchronous_get(('blockchain.transaction.get_merkle', [txid, int(height)]))
@command('n')
def getservers(self):
@@ -522,7 +521,7 @@ class Commands:
"""Retrieve a transaction. """
tx = self.wallet.transactions.get(txid) if self.wallet else None
if tx is None and self.network:
- raw = self.network.synchronous_get([('blockchain.transaction.get', [txid])])[0]
+ raw = self.network.synchronous_get(('blockchain.transaction.get', [txid]))
if raw:
tx = Transaction(raw)
else:
diff --git a/lib/network.py b/lib/network.py
@@ -5,7 +5,8 @@ import sys
import random
import select
import traceback
-from collections import deque
+from collections import defaultdict, deque
+from threading import Lock
import socks
import socket
@@ -129,20 +130,19 @@ class Network(util.DaemonThread):
Our external API:
- - Member functions get_header(), get_parameters(), get_status_value(),
- new_blockchain_height(), set_parameters(), start(),
- stop()
+ - Member functions get_header(), get_interfaces(), get_local_height(),
+ get_parameters(), get_server_height(), get_status_value(),
+ is_connected(), new_blockchain_height(), set_parameters(), start(),
+ stop()
"""
- def __init__(self, pipe, config=None):
+ def __init__(self, config=None):
if config is None:
config = {} # Do not use mutables as default values!
util.DaemonThread.__init__(self)
self.config = SimpleConfig(config) if type(config) == type({}) else config
self.num_server = 8 if not self.config.get('oneserver') else 0
self.blockchain = Blockchain(self.config, self)
- self.requests_queue = pipe.send_queue
- self.response_queue = pipe.get_queue
# A deque of interface header requests, processed left-to-right
self.bc_requests = deque()
# Server for addresses and transactions
@@ -155,6 +155,10 @@ class Network(util.DaemonThread):
if not self.default_server:
self.default_server = pick_random_server()
+ self.lock = Lock()
+ self.pending_sends = []
+ self.message_id = 0
+ self.debug = False
self.irc_servers = {} # returned by interface (list from irc)
self.recent_servers = self.read_recent_servers()
@@ -163,6 +167,8 @@ class Network(util.DaemonThread):
self.heights = {}
self.merkle_roots = {}
self.utxo_roots = {}
+ self.subscriptions = defaultdict(list)
+ self.callbacks = defaultdict(list)
dir_path = os.path.join( self.config.path, 'certs')
if not os.path.exists(dir_path):
@@ -188,6 +194,15 @@ class Network(util.DaemonThread):
self.start_network(deserialize_server(self.default_server)[2],
deserialize_proxy(self.config.get('proxy')))
+ def register_callback(self, event, callback):
+ with self.lock:
+ self.callbacks[event].append(callback)
+
+ def trigger_callback(self, event, params=()):
+ with self.lock:
+ callbacks = self.callbacks[event][:]
+ [callback(*params) for callback in callbacks]
+
def read_recent_servers(self):
if not self.config.path:
return []
@@ -231,6 +246,12 @@ class Network(util.DaemonThread):
def is_connected(self):
return self.interface is not None
+ def is_connecting(self):
+ return self.connection_status == 'connecting'
+
+ def is_up_to_date(self):
+ return self.unanswered_requests == {}
+
def queue_request(self, method, params):
self.interface.queue_request({'method': method, 'params': params})
@@ -263,7 +284,10 @@ class Network(util.DaemonThread):
def notify(self, key):
value = self.get_status_value(key)
- self.response_queue.put({'method':'network.status', 'params':[key, value]})
+ if key in ['status', 'updated']:
+ self.trigger_callback(key)
+ else:
+ self.trigger_callback(key, (value,))
def get_parameters(self):
host, port, protocol = deserialize_server(self.default_server)
@@ -337,8 +361,16 @@ class Network(util.DaemonThread):
self.socket_queue = Queue.Queue()
def set_parameters(self, host, port, protocol, proxy, auto_connect):
- self.auto_connect = auto_connect
+ proxy_str = serialize_proxy(proxy)
server = serialize_server(host, port, protocol)
+ self.config.set_key('auto_connect', auto_connect, False)
+ self.config.set_key("proxy", proxy_str, False)
+ self.config.set_key("server", server, True)
+ # abort if changes were not allowed by config
+ if self.config.get('server') != server_str or self.config.get('proxy') != proxy_str:
+ return
+
+ self.auto_connect = auto_connect
if self.proxy != proxy or self.protocol != protocol:
# Restart the network defaulting to the given server
self.stop_network()
@@ -405,7 +437,9 @@ class Network(util.DaemonThread):
self.switch_lagging_interface(i.server)
self.notify('updated')
- def process_response(self, interface, response):
+ def process_response(self, interface, response, callback):
+ if self.debug:
+ self.print_error("<--", response)
error = response.get('error')
result = response.get('result')
method = response.get('method')
@@ -437,8 +471,19 @@ class Network(util.DaemonThread):
# Cache address subscription results
if method == 'blockchain.address.subscribe' and error is None:
addr = response['params'][0]
- self.addr_responses[addr] = result
- self.response_queue.put(response)
+ self.addr_responses[addr] = response
+ if callback is None:
+ params = response['params']
+ with self.lock:
+ for k,v in self.subscriptions.items():
+ if (method, params) in v:
+ callback = k
+ break
+ if callback is None:
+ self.print_error("received unexpected notification",
+ method, params)
+ else:
+ callback(response)
def process_responses(self, interface):
notifications, responses = interface.get_responses()
@@ -449,12 +494,14 @@ class Network(util.DaemonThread):
if client_id is not None:
if interface != self.interface:
continue
- self.unanswered_requests.pop(client_id)
+ _req, callback = self.unanswered_requests.pop(client_id)
+ else:
+ callback = None
# Copy the request method and params to the response
response['method'] = request.get('method')
response['params'] = request.get('params')
response['id'] = client_id
- self.process_response(interface, response)
+ self.process_response(interface, response, callback)
for response in notifications:
if not response: # Closed remotely
@@ -466,16 +513,42 @@ class Network(util.DaemonThread):
response['result'] = response['params'][0]
response['params'] = []
elif method == 'blockchain.address.subscribe':
- params = response['params']
response['params'] = [params[0]] # addr
response['result'] = params[1]
- self.process_response(interface, response)
-
- def handle_incoming_requests(self):
- while not self.requests_queue.empty():
- self.process_request(self.requests_queue.get())
-
- def process_request(self, request):
+ self.process_response(interface, response, None)
+
+ def send(self, messages, callback):
+ '''Messages is a list of (method, value) tuples'''
+ with self.lock:
+ self.pending_sends.append((messages, callback))
+
+ def process_pending_sends(self):
+ sends = self.pending_sends
+ self.pending_sends = []
+
+ for messages, callback in sends:
+ subs = filter(lambda (m,v): m.endswith('.subscribe'), messages)
+ with self.lock:
+ for sub in subs:
+ if sub not in self.subscriptions[callback]:
+ self.subscriptions[callback].append(sub)
+ _id = self.message_id
+ self.message_id += len(messages)
+
+ unsent = []
+ for message in messages:
+ method, params = message
+ request = {'id': _id, 'method': method, 'params': params}
+ if not self.process_request(request, callback):
+ unsent.append(message)
+ _id += 1
+
+ if unsent:
+ with self.lock:
+ self.pending_sends.append((unsent, callback))
+
+ # FIXME: inline this function
+ def process_request(self, request, callback):
'''Returns true if the request was processed.'''
method = request['method']
params = request['params']
@@ -492,14 +565,14 @@ class Network(util.DaemonThread):
out['error'] = str(e)
traceback.print_exc(file=sys.stdout)
self.print_error("network error", str(e))
- self.response_queue.put(out)
+ callback(out)
return True
if method == 'blockchain.address.subscribe':
addr = params[0]
self.subscribed_addresses.add(addr)
if addr in self.addr_responses:
- self.response_queue.put({'id':_id, 'result':self.addr_responses[addr]})
+ callback(self.addr_responses[addr])
return True
# This request needs connectivity. If we don't have an
@@ -507,7 +580,9 @@ class Network(util.DaemonThread):
if not self.interface:
return False
- self.unanswered_requests[_id] = request
+ if self.debug:
+ self.print_error("-->", request)
+ self.unanswered_requests[_id] = request, callback
self.interface.queue_request(request)
return True
@@ -679,10 +754,12 @@ class Network(util.DaemonThread):
while self.is_running():
self.maintain_sockets()
self.wait_on_sockets()
- self.handle_incoming_requests()
self.handle_bc_requests()
+ self.run_jobs() # Synchronizer and Verifier
+ self.process_pending_sends()
self.stop_network()
+ self.trigger_callback('stop')
self.print_error("stopped")
def on_header(self, i, header):
@@ -706,3 +783,11 @@ class Network(util.DaemonThread):
def get_local_height(self):
return self.blockchain.height()
+
+ def synchronous_get(self, request, timeout=100000000):
+ queue = Queue.Queue()
+ self.send([request], queue.put)
+ r = queue.get(True, timeout)
+ if r.get('error'):
+ raise BaseException(r.get('error'))
+ return r.get('result')
diff --git a/lib/network_proxy.py b/lib/network_proxy.py
@@ -1,235 +0,0 @@
-#!/usr/bin/env python
-#
-# Electrum - lightweight Bitcoin client
-# Copyright (C) 2014 Thomas Voegtlin
-#
-# 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/>.
-
-import sys
-import traceback
-import threading
-import Queue
-
-import util
-from network import Network, serialize_proxy, serialize_server
-from simple_config import SimpleConfig
-
-
-class NetworkProxy(util.DaemonThread):
-
- def __init__(self, socket, config=None):
-
- if config is None:
- config = {} # Do not use mutables as default arguments!
- util.DaemonThread.__init__(self)
- self.config = SimpleConfig(config) if type(config) == type({}) else config
- self.message_id = 0
- self.unanswered_requests = {}
- self.subscriptions = {}
- self.debug = False
- self.lock = threading.Lock()
- self.callbacks = {}
-
- if socket:
- self.pipe = util.SocketPipe(socket)
- self.network = None
- else:
- self.pipe = util.QueuePipe()
- self.network = Network(self.pipe, config)
- self.network.start()
- for key in ['fee','status','banner','updated','servers','interfaces']:
- value = self.network.get_status_value(key)
- self.pipe.get_queue.put({'method':'network.status', 'params':[key, value]})
-
- # status variables
- self.status = 'unknown'
- self.servers = {}
- self.banner = ''
- self.blockchain_height = 0
- self.server_height = 0
- self.interfaces = []
- # value returned by estimatefee
- self.fee = None
-
-
- def run(self):
- while self.is_running():
- self.run_jobs() # Synchronizer and Verifier
- try:
- response = self.pipe.get()
- except util.timeout:
- continue
- if response is None:
- break
- # Protect against ill-formed or malicious server responses
- try:
- self.process(response)
- except:
- traceback.print_exc(file=sys.stderr)
- self.trigger_callback('stop')
- if self.network:
- self.network.stop()
- self.print_error("stopped")
-
- def process(self, response):
- if self.debug:
- self.print_error("<--", response)
-
- if response.get('method') == 'network.status':
- key, value = response.get('params')
- if key == 'status':
- self.status = value
- elif key == 'banner':
- self.banner = value
- elif key == 'fee':
- self.fee = value
- elif key == 'updated':
- self.blockchain_height, self.server_height = value
- elif key == 'servers':
- self.servers = value
- elif key == 'interfaces':
- self.interfaces = value
- if key in ['status', 'updated']:
- self.trigger_callback(key)
- else:
- self.trigger_callback(key, (value,))
- return
-
- msg_id = response.get('id')
- result = response.get('result')
- error = response.get('error')
- if msg_id is not None:
- with self.lock:
- method, params, callback = self.unanswered_requests.pop(msg_id)
- else:
- method = response.get('method')
- params = response.get('params')
- with self.lock:
- for k,v in self.subscriptions.items():
- if (method, params) in v:
- callback = k
- break
- else:
- self.print_error("received unexpected notification",
- method, params)
- return
-
- r = {'method':method, 'params':params, 'result':result,
- 'id':msg_id, 'error':error}
- callback(r)
-
-
- def send(self, messages, callback):
- """return the ids of the requests that we sent"""
-
- # detect subscriptions
- sub = []
- for message in messages:
- m, v = message
- if m[-10:] == '.subscribe':
- sub.append(message)
- if sub:
- with self.lock:
- if self.subscriptions.get(callback) is None:
- self.subscriptions[callback] = []
- for message in sub:
- if message not in self.subscriptions[callback]:
- self.subscriptions[callback].append(message)
-
- with self.lock:
- requests = []
- ids = []
- for m in messages:
- method, params = m
- request = { 'id':self.message_id, 'method':method, 'params':params }
- self.unanswered_requests[self.message_id] = method, params, callback
- ids.append(self.message_id)
- requests.append(request)
- if self.debug:
- self.print_error("-->", request)
- self.message_id += 1
-
- self.pipe.send_all(requests)
- return ids
-
-
- def synchronous_get(self, requests, timeout=100000000):
- queue = Queue.Queue()
- ids = self.send(requests, queue.put)
- id2 = ids[:]
- res = {}
- while ids:
- r = queue.get(True, timeout)
- _id = r.get('id')
- ids.remove(_id)
- if r.get('error'):
- raise BaseException(r.get('error'))
- result = r.get('result')
- res[_id] = r.get('result')
- out = []
- for _id in id2:
- out.append(res[_id])
- return out
-
-
- def get_servers(self):
- return self.servers
-
- def get_interfaces(self):
- return self.interfaces
-
- def get_local_height(self):
- return self.blockchain_height
-
- def get_server_height(self):
- return self.server_height
-
- def is_connected(self):
- return self.status == 'connected'
-
- def is_connecting(self):
- return self.status == 'connecting'
-
- def is_up_to_date(self):
- return self.unanswered_requests == {}
-
- def get_parameters(self):
- return self.synchronous_get([('network.get_parameters', [])])[0]
-
- def set_parameters(self, host, port, protocol, proxy, auto_connect):
- proxy_str = serialize_proxy(proxy)
- server_str = serialize_server(host, port, protocol)
- self.config.set_key('auto_connect', auto_connect, False)
- self.config.set_key("proxy", proxy_str, False)
- self.config.set_key("server", server_str, True)
- # abort if changes were not allowed by config
- if self.config.get('server') != server_str or self.config.get('proxy') != proxy_str:
- return
-
- return self.synchronous_get([('network.set_parameters', (host, port, protocol, proxy, auto_connect))])[0]
-
- def stop_daemon(self):
- return self.send([('daemon.stop',[])], None)
-
- def register_callback(self, event, callback):
- with self.lock:
- if not self.callbacks.get(event):
- self.callbacks[event] = []
- self.callbacks[event].append(callback)
-
- def trigger_callback(self, event, params=()):
- with self.lock:
- callbacks = self.callbacks.get(event,[])[:]
- if callbacks:
- [callback(*params) for callback in callbacks]
diff --git a/lib/transaction.py b/lib/transaction.py
@@ -545,7 +545,7 @@ class Transaction:
for privkey in privkeys:
pubkey = public_key_from_private_key(privkey)
address = address_from_private_key(privkey)
- u = network.synchronous_get([ ('blockchain.address.listunspent',[address])])[0]
+ u = network.synchronous_get(('blockchain.address.listunspent',[address]))
pay_script = klass.pay_script('address', address)
for item in u:
item['scriptPubKey'] = pay_script
diff --git a/lib/verifier.py b/lib/verifier.py
@@ -40,9 +40,9 @@ class SPV(ThreadJob):
if tx_hash not in self.merkle_roots and tx_height <= lh:
request = ('blockchain.transaction.get_merkle',
[tx_hash, tx_height])
- if self.network.send([request], self.merkle_response):
- self.print_error('requested merkle', tx_hash)
- self.merkle_roots[tx_hash] = None
+ self.network.send([request], self.merkle_response)
+ self.print_error('requested merkle', tx_hash)
+ self.merkle_roots[tx_hash] = None
def merkle_response(self, r):
if r.get('error'):
diff --git a/plugins/keepkey.py b/plugins/keepkey.py
@@ -156,7 +156,7 @@ class Plugin(BasePlugin):
@hook
def installwizard_restore(self, wizard, storage):
- if storage.get('wallet_type') != 'keepkey':
+ if storage.get('wallet_type') != 'keepkey':
return
seed = wizard.enter_seed_dialog("Enter your KeepKey seed", None, func=lambda x:True)
if not seed:
@@ -478,7 +478,7 @@ class KeepKeyWallet(BIP32_HD_Wallet):
ptx = self.transactions.get(tx_hash)
if ptx is None:
- ptx = self.network.synchronous_get([('blockchain.transaction.get', [tx_hash])])[0]
+ ptx = self.network.synchronous_get(('blockchain.transaction.get', [tx_hash]))
ptx = Transaction(ptx)
prev_tx[tx_hash] = ptx
@@ -673,5 +673,5 @@ if KEEPKEY:
except ConnectionError:
self.bad = True
raise
-
+
return resp
diff --git a/plugins/trezor.py b/plugins/trezor.py
@@ -156,7 +156,7 @@ class Plugin(BasePlugin):
@hook
def installwizard_restore(self, wizard, storage):
- if storage.get('wallet_type') != 'trezor':
+ if storage.get('wallet_type') != 'trezor':
return
seed = wizard.enter_seed_dialog("Enter your Trezor seed", None, func=lambda x:True)
if not seed:
@@ -477,7 +477,7 @@ class TrezorWallet(BIP32_HD_Wallet):
ptx = self.transactions.get(tx_hash)
if ptx is None:
- ptx = self.network.synchronous_get([('blockchain.transaction.get', [tx_hash])])[0]
+ ptx = self.network.synchronous_get(('blockchain.transaction.get', [tx_hash]))
ptx = Transaction(ptx)
prev_tx[tx_hash] = ptx
@@ -665,5 +665,5 @@ if TREZOR:
except ConnectionError:
self.bad = True
raise
-
+
return resp
diff --git a/scripts/block_headers b/scripts/block_headers
@@ -7,8 +7,7 @@ import electrum
# start network
c = electrum.SimpleConfig()
-s = electrum.daemon.get_daemon(c,True)
-network = electrum.NetworkProxy(s,c)
+network = electrum.Network(c)
network.start()
# wait until connected
@@ -26,4 +25,3 @@ network.send([('blockchain.headers.subscribe',[])], callback)
# 3. wait for results
while network.is_connected():
time.sleep(1)
-
diff --git a/scripts/get_history b/scripts/get_history
@@ -1,7 +1,7 @@
#!/usr/bin/env python
import sys
-from electrum import NetworkProxy, print_json
+from electrum import Network, print_json
try:
addr = sys.argv[1]
@@ -9,8 +9,7 @@ except Exception:
print "usage: get_history <bitcoin_address>"
sys.exit(1)
-n = NetworkProxy()
-n.start(start_daemon=True)
-h = n.synchronous_get([ ('blockchain.address.get_history',[addr]) ])[0]
+n = Network()
+n.start()
+h = n.synchronous_get(('blockchain.address.get_history',[addr]))
print_json(h)
-
diff --git a/scripts/merchant/merchant.py b/scripts/merchant/merchant.py
@@ -54,7 +54,7 @@ def check_create_table(conn):
c = conn.cursor()
c.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='electrum_payments';")
data = c.fetchall()
- if not data:
+ if not data:
c.execute("""CREATE TABLE electrum_payments (address VARCHAR(40), amount FLOAT, confirmations INT(8), received_at TIMESTAMP, expires_at TIMESTAMP, paid INT(1), processed INT(1));""")
conn.commit()
@@ -95,7 +95,7 @@ def on_wallet_update():
s = (value)/1.e8
print "balance for %s:"%addr, s, requested_amount
- if s>= requested_amount:
+ if s>= requested_amount:
print "payment accepted", addr
out_queue.put( ('payment', addr))
@@ -162,7 +162,7 @@ def send_command(cmd, params):
except socket.error:
print "Server not running"
return 1
-
+
try:
out = f(*params)
except socket.error:
@@ -186,9 +186,9 @@ def db_thread():
data = cur.fetchall()
# add pending requests to the wallet
- for item in data:
+ for item in data:
addr, amount, confirmations = item
- if addr in pending_requests:
+ if addr in pending_requests:
continue
else:
with wallet.lock:
@@ -216,7 +216,7 @@ def db_thread():
print sql
cur.execute(sql)
- # set paid=0 for expired requests
+ # set paid=0 for expired requests
cur.execute("""UPDATE electrum_payments set paid=0 WHERE expires_at < CURRENT_TIMESTAMP and paid is NULL;""")
# do callback for addresses that received payment or expired
@@ -241,7 +241,7 @@ def db_thread():
except ValueError, e:
print e
print "cannot do callback", data_json
-
+
conn.commit()
conn.close()
@@ -259,8 +259,7 @@ if __name__ == '__main__':
# start network
c = electrum.SimpleConfig({'wallet_path':wallet_path})
- daemon_socket = electrum.daemon.get_daemon(c, True)
- network = electrum.NetworkProxy(daemon_socket, config)
+ network = electrum.Network(config)
network.start()
# wait until connected
@@ -284,7 +283,7 @@ if __name__ == '__main__':
network.register_callback('updated', on_wallet_update)
threading.Thread(target=db_thread, args=()).start()
-
+
out_queue = Queue.Queue()
# server thread
from jsonrpclib.SimpleJSONRPCServer import SimpleJSONRPCServer
@@ -299,4 +298,3 @@ if __name__ == '__main__':
server.handle_request()
except socket.timeout:
continue
-
diff --git a/scripts/watch_address b/scripts/watch_address
@@ -12,8 +12,7 @@ except Exception:
# start network
c = electrum.SimpleConfig()
-s = electrum.daemon.get_daemon(c,True)
-network = electrum.NetworkProxy(s,c)
+network = electrum.Network(c)
network.start()
# wait until connected
@@ -31,4 +30,3 @@ network.send([('blockchain.address.subscribe',[addr])], callback)
# 3. wait for results
while network.is_connected():
time.sleep(1)
-