1 from __future__ import division
8 from twisted.internet import defer, reactor
9 from twisted.python import failure
10 from twisted.web import resource, server
12 class DeferredResource(resource.Resource):
13 def render(self, request):
19 def finish_error(fail):
20 request.setResponseCode(500) # won't do anything if already written to
21 request.write('---ERROR---')
25 defer.maybeDeferred(resource.Resource.render, self, request).addCallbacks(finish, finish_error)
26 return server.NOT_DONE_YET
31 self.one_time_observers = {}
32 self.id_generator = itertools.count()
34 def watch(self, func):
35 id = self.id_generator.next()
36 self.observers[id] = func
38 def unwatch(self, id):
39 self.observers.pop(id)
41 def watch_one_time(self, func):
42 id = self.id_generator.next()
43 self.one_time_observers[id] = func
45 def unwatch_one_time(self, id):
46 self.one_time_observers.pop(id)
48 def happened(self, event=None):
49 for func in self.observers.itervalues():
52 one_time_observers = self.one_time_observers
53 self.one_time_observers = {}
54 for func in one_time_observers.itervalues():
57 def get_deferred(self):
59 self.watch_one_time(df.callback)
62 class Variable(object):
63 def __init__(self, value):
65 self.changed = Event()
68 if value == self.value:
72 self.changed.happened(value)
76 reactor.callLater(t, d.callback, None)
80 # don't really need a complex algorithm here
82 left = (len(y) - 1)//2
84 return (y[left] + y[right])/2
86 class StringBuffer(object):
87 'Buffer manager with great worst-case behavior'
89 def __init__(self, data=''):
90 self.buf = collections.deque([data])
91 self.buf_len = len(data)
95 return self.buf_len - self.pos
99 self.buf_len += len(data)
101 def get(self, wants):
102 if self.buf_len - self.pos < wants:
103 raise IndexError('not enough data')
106 seg = self.buf[0][self.pos:self.pos+wants]
108 while self.buf and self.pos >= len(self.buf[0]):
109 x = self.buf.popleft()
110 self.buf_len -= len(x)
117 def _DataChunker(receiver):
118 wants = receiver.next()
122 if len(buf) >= wants:
123 wants = receiver.send(buf.get(wants))
126 def DataChunker(receiver):
128 Produces a function that accepts data that is input into a generator
129 (receiver) in response to the receiver yielding the size of data to wait on
131 x = _DataChunker(receiver)
135 class ReplyMatcher(object):
136 def __init__(self, func, timeout=5):
138 self.timeout = timeout
141 def __call__(self, id):
144 uniq = random.randrange(2**256)
145 df = defer.Deferred()
147 df, timer = self.map[id].pop(uniq)
148 df.errback(failure.Failure(defer.TimeoutError()))
151 self.map.setdefault(id, {})[uniq] = (df, reactor.callLater(self.timeout, timeout))
155 traceback.print_exc()
157 def got_response(self, id, resp):
158 if id not in self.map:
160 for df, timer in self.map.pop(id).itervalues():
164 class GenericDeferrer(object):
165 def __init__(self, max_id, func, timeout=5):
168 self.timeout = timeout
171 def __call__(self, *args, **kwargs):
173 id = random.randrange(self.max_id)
174 if id not in self.map:
176 df = defer.Deferred()
179 df.errback(failure.Failure(defer.TimeoutError()))
180 timer = reactor.callLater(self.timeout, timeout)
181 self.func(id, *args, **kwargs)
182 self.map[id] = df, timer
185 def got_response(self, id, resp):
186 if id not in self.map:
188 df, timer = self.map.pop(id)
192 class DeferredCacher(object):
193 def __init__(self, func, backing=None):
198 self.backing = backing
201 @defer.inlineCallbacks
202 def __call__(self, key):
203 if key in self.waiting:
204 yield self.waiting[key]
206 if key in self.backing:
207 defer.returnValue(self.backing[key])
209 self.waiting[key] = defer.Deferred()
211 value = yield self.func(key)
213 self.waiting.pop(key).callback(None)
215 self.backing[key] = value
216 defer.returnValue(value)
218 def pubkey_to_address(pubkey, testnet):
219 if len(pubkey) != 65:
220 raise ValueError('invalid pubkey')
221 version = 111 if testnet else 0
222 key_hash = chr(version) + hashlib.new('ripemd160', hashlib.sha256(pubkey).digest()).digest()
223 checksum = hashlib.sha256(hashlib.sha256(key_hash).digest()).digest()[:4]
224 return base58_encode(key_hash + checksum)
226 def base58_encode(data):
227 return '1'*(len(data) - len(data.lstrip(chr(0)))) + natural_to_string(string_to_natural(data), '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz')
229 def natural_to_string(n, alphabet=None, min_width=1):
234 return s.decode('hex').rjust(min_width, '\x00')
237 n, x = divmod(n, len(alphabet))
238 res.append(alphabet[x])
240 return ''.join(res).rjust(min_width, '\x00')
242 def string_to_natural(s, alphabet=None):
246 if not s or (s != alphabet[0] and s.startswith(alphabet[0])):
248 return sum(alphabet.index(char) * len(alphabet)**i for i, char in enumerate(reversed(s)))
251 class DictWrapper(object):
252 def encode_key(self, key):
254 def decode_key(self, encoded_key):
256 def encode_value(self, value):
258 def decode_value(self, encoded_value):
261 def __init__(self, inner):
265 return len(self.inner)
267 def __contains__(self, key):
268 return self.encode_key(key) in self.inner
270 def __getitem__(self, key):
271 return self.decode_value(self.inner[self.encode_key(key)])
273 def __setitem__(self, key, value):
274 self.inner[self.encode_key(key)] = self.encode_value(value)
276 def __delitem__(self, key):
277 del self.inner[self.encode_key(key)]
280 return map(self.decode_key, self.inner.keys())