1 from __future__ import division
5 from twisted.internet import defer, reactor
6 from twisted.trial import unittest
7 from twisted.web import resource, server
9 from p2pool import node, work
10 from p2pool.bitcoin import networks, worker_interface
11 from p2pool.util import deferral, jsonrpc, math, variable
13 class factory(object):
14 new_headers = variable.Event()
15 new_block = variable.Event()
16 new_tx = variable.Event()
17 conn = variable.Variable(None)
19 def getProtocol(self):
20 return defer.Deferred()
22 class bitcoind(object):
28 def rpc_getblock(self, block_hash_hex):
29 return dict(height=42)
32 def rpc_getmemorypool(self):
35 "previousblockhash" : "000000000000016c169477c25421250ec5d32cf9c6d38538b5de970a2355fd89",
39 "flags" : "062f503253482f"
41 "coinbasevalue" : 5044450000,
42 "target" : "0000000000000513c50000000000000000000000000000000000000000000000",
43 "mintime" : 1351655621,
49 "noncerange" : "00000000ffffffff",
51 "sizelimit" : 1000000,
52 "curtime" : 1351659940,
58 PARENT=networks.nets['litecoin_testnet'],
59 SHARE_PERIOD=3, # seconds
60 CHAIN_LENGTH=20*60//3, # shares
61 REAL_CHAIN_LENGTH=20*60//3, # shares
62 TARGET_LOOKBEHIND=200, # shares
64 IDENTIFIER='cca5e24ec6408b1e'.decode('hex'),
65 PREFIX='ad9614f6466a39cf'.decode('hex'),
67 MIN_TARGET=2**256 - 1,
68 MAX_TARGET=2**256 - 1,
71 BOOTSTRAP_ADDRS='72.14.191.28'.split(' '),
72 ANNOUNCE_CHANNEL='#p2pool-alt',
73 VERSION_CHECK=lambda v: True,
76 class MiniNode(object):
78 @defer.inlineCallbacks
79 def start(cls, net, factory, bitcoind, peer_ports):
82 self.n = node.Node(factory, bitcoind, [], [], net)
85 self.n.p2p_node = node.P2PNode(self.n, 0, 1000000, {}, [('127.0.0.1', peer_port) for peer_port in peer_ports])
86 self.n.p2p_node.start()
88 wb = work.WorkerBridge(node=self.n, my_pubkey_hash=random.randrange(2**160), donation_percentage=random.uniform(0, 10), merged_urls=[], worker_fee=3)
89 web_root = resource.Resource()
90 worker_interface.WorkerInterface(wb).attach_to(web_root)
91 self.web_port = reactor.listenTCP(0, server.Site(web_root))
93 defer.returnValue(self)
95 @defer.inlineCallbacks
97 yield self.web_port.stopListening()
98 yield self.n.p2p_node.stop()
100 del self.web_port, self.n
102 class Test(unittest.TestCase):
103 @defer.inlineCallbacks
105 n = node.Node(factory, bitcoind, [], [], mynet)
108 wb = work.WorkerBridge(node=n, my_pubkey_hash=42, donation_percentage=2, merged_urls=[], worker_fee=3)
109 web_root = resource.Resource()
110 worker_interface.WorkerInterface(wb).attach_to(web_root)
111 port = reactor.listenTCP(0, server.Site(web_root))
113 proxy = jsonrpc.Proxy('http://127.0.0.1:' + str(port.getHost().port))
115 yield deferral.sleep(3)
117 for i in xrange(100):
118 blah = yield proxy.rpc_getwork()
119 yield proxy.rpc_getwork(blah['data'])
121 yield deferral.sleep(3)
123 assert len(n.tracker.items) == 100
124 assert n.tracker.verified.get_height(n.best_share_var.value) == 100
128 yield port.stopListening()
129 del n, wb, web_root, port, proxy
135 yield deferral.sleep(20) # waiting for work_poller to exit
137 @defer.inlineCallbacks
138 def test_nodes(self):
143 nodes.append((yield MiniNode.start(mynet, factory, bitcoind, [mn.n.p2p_node.serverfactory.listen_port.getHost().port for mn in nodes])))
145 yield deferral.sleep(3)
147 for i in xrange(100):
148 proxy = jsonrpc.Proxy('http://127.0.0.1:' + str(random.choice(nodes).web_port.getHost().port))
149 blah = yield proxy.rpc_getwork()
150 yield proxy.rpc_getwork(blah['data'])
151 yield deferral.sleep(random.expovariate(1/.1))
153 yield deferral.sleep(3)
155 for i, n in enumerate(nodes):
156 assert len(n.n.tracker.items) == 100, (i, len(n.n.tracker.items))
157 assert n.n.tracker.verified.get_height(n.n.best_share_var.value) == 100, (i, n.n.tracker.verified.get_height(n.n.best_share_var.value))
168 yield deferral.sleep(20) # waiting for work_poller to exit