Implementing a better print_error routine
[electrum-nvc.git] / remote_wallet.py
1 #!/usr/bin/env python
2 #
3 # Electrum - lightweight Bitcoin client
4 # Copyright (C) 2011 thomasv@gitorious
5 #
6 # This program is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation, either version 3 of the License, or
9 # (at your option) any later version.
10 #
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
19 import time, thread, sys, socket
20
21 # see http://code.google.com/p/jsonrpclib/
22 import jsonrpclib
23 from wallet import Wallet
24 from lib.util import print_error
25
26 """
27 Simple wallet daemon for webservers.
28 - generates new addresses on request
29 - private keys are not needed in order to generate new addresses. A neutralized wallet can be used (seed removed)
30 - no gap limit: use 'getnum' to know how many addresses have been created.
31
32 todo:
33 - return the max gap
34 - add expiration date
35
36 """
37
38
39 host = 'ecdsa.org'
40 port = 8444
41 wallet_path = 'wallet_path'
42 username = 'foo'
43 password = 'bar'
44 wallet = Wallet()
45 stopping = False
46
47
48
49 from jsonrpclib.SimpleJSONRPCServer import SimpleJSONRPCRequestHandler
50 import SimpleXMLRPCServer
51
52 class authHandler(SimpleJSONRPCRequestHandler):
53     def parse_request(self):
54         if SimpleXMLRPCServer.SimpleXMLRPCRequestHandler.parse_request(self):
55             if self.authenticate(self.headers):
56                 return True
57             else:
58                 self.send_error(401, 'Authentication failed')
59             return False
60
61     def authenticate(self, headers):
62         from base64 import b64decode
63         basic, _, encoded = headers.get('Authorization').partition(' ')
64         assert basic == 'Basic', 'Only basic authentication supported'
65         x_username, _, x_password = b64decode(encoded).partition(':')
66         return username == x_username and password == x_password
67
68
69 def do_stop():
70     global stopping
71     stopping = True
72
73 def get_new_address():
74     a = wallet.create_new_address(False)
75     wallet.save()
76     return a
77
78 def get_num():
79     return len(wallet.addresses)
80
81 def get_mpk():
82     return wallet.master_public_key.encode('hex')
83
84
85
86 if __name__ == '__main__':
87
88     if len(sys.argv)>1:
89         import jsonrpclib
90         server = jsonrpclib.Server('http://%s:%s@%s:%d'%(username, password, host, port))
91         cmd = sys.argv[1]
92
93         try:
94             if cmd == 'getnum':
95                 out = server.getnum()
96             elif cmd == 'getkey':
97                 out = server.getkey()
98             elif cmd == 'getnewaddress':
99                 out = server.getnewaddress()
100             elif cmd == 'stop':
101                 out = server.stop()
102         except socket.error:
103             print_error("Server not running")
104             sys.exit(1)
105         print out
106         sys.exit(0)
107
108     else:
109
110         wallet.set_path(wallet_path)
111         wallet.read()
112
113         def server_thread():
114             from SocketServer import ThreadingMixIn
115             from jsonrpclib.SimpleJSONRPCServer import SimpleJSONRPCServer
116             server = SimpleJSONRPCServer(( host, port), requestHandler=authHandler)
117             server.register_function(get_new_address, 'getnewaddress')
118             server.register_function(get_num, 'getnum')
119             server.register_function(get_mpk, 'getkey')
120             server.register_function(do_stop, 'stop')
121             server.serve_forever()
122
123         thread.start_new_thread(server_thread, ())
124         while not stopping: time.sleep(0.1)
125
126
127
128