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 data, node, work
10 from p2pool.bitcoin import data as bitcoin_data, networks, worker_interface
11 from p2pool.util import deferral, jsonrpc, math, variable
14 class bitcoinp2p(object):
15 def send_block(self, block):
18 def get_block_header(self, hash):
19 if hash == 0x16c169477c25421250ec5d32cf9c6d38538b5de970a2355fd89:
20 return defer.succeed({
22 'timestamp': 1351658517,
23 'merkle_root': 2282849479936278423916707524932131168473430114569971665822757638339486597658L,
25 'previous_block': 1048610514577342396345362905164852351970507722694242579238530L,
26 'bits': bitcoin_data.FloatingInteger(bits=0x1a0513c5, target=0x513c50000000000000000000000000000000000000000000000L),
29 return defer.fail('blah')
31 class factory(object):
32 new_headers = variable.Event()
33 new_block = variable.Event()
34 new_tx = variable.Event()
35 conn = variable.Variable(bitcoinp2p)
37 def getProtocol(self):
40 class bitcoind(object):
46 def rpc_getblock(self, block_hash_hex):
47 return dict(height=42)
50 def rpc_getmemorypool(self, result=None):
51 if result is not None:
55 "previousblockhash" : "000000000000016c169477c25421250ec5d32cf9c6d38538b5de970a2355fd89",
59 "flags" : "062f503253482f"
61 "coinbasevalue" : 5044450000,
62 "target" : "0000000000000513c50000000000000000000000000000000000000000000000",
63 "mintime" : 1351655621,
69 "noncerange" : "00000000ffffffff",
71 "sizelimit" : 1000000,
72 "curtime" : 1351659940,
78 PARENT=networks.nets['litecoin_testnet'],
79 SHARE_PERIOD=3, # seconds
80 CHAIN_LENGTH=20*60//3, # shares
81 REAL_CHAIN_LENGTH=20*60//3, # shares
82 TARGET_LOOKBEHIND=200, # shares
84 IDENTIFIER='cca5e24ec6408b1e'.decode('hex'),
85 PREFIX='ad9614f6466a39cf'.decode('hex'),
87 MIN_TARGET=2**256 - 1,
88 MAX_TARGET=2**256 - 1,
91 BOOTSTRAP_ADDRS='72.14.191.28'.split(' '),
92 ANNOUNCE_CHANNEL='#p2pool-alt',
93 VERSION_CHECK=lambda v: True,
96 class MiniNode(object):
98 @defer.inlineCallbacks
99 def start(cls, net, factory, bitcoind, peer_ports):
102 self.n = node.Node(factory, bitcoind, [], [], net)
105 self.n.p2p_node = node.P2PNode(self.n, 0, 1000000, {}, [('127.0.0.1', peer_port) for peer_port in peer_ports])
106 self.n.p2p_node.start()
108 wb = work.WorkerBridge(node=self.n, my_pubkey_hash=random.randrange(2**160), donation_percentage=random.uniform(0, 10), merged_urls=[], worker_fee=3)
109 web_root = resource.Resource()
110 worker_interface.WorkerInterface(wb).attach_to(web_root)
111 self.web_port = reactor.listenTCP(0, server.Site(web_root))
113 defer.returnValue(self)
115 @defer.inlineCallbacks
117 yield self.web_port.stopListening()
118 yield self.n.p2p_node.stop()
120 del self.web_port, self.n
122 class Test(unittest.TestCase):
123 @defer.inlineCallbacks
125 n = node.Node(factory, bitcoind, [], [], mynet)
128 wb = work.WorkerBridge(node=n, my_pubkey_hash=42, donation_percentage=2, merged_urls=[], worker_fee=3)
129 web_root = resource.Resource()
130 worker_interface.WorkerInterface(wb).attach_to(web_root)
131 port = reactor.listenTCP(0, server.Site(web_root))
133 proxy = jsonrpc.Proxy('http://127.0.0.1:' + str(port.getHost().port))
135 yield deferral.sleep(3)
137 for i in xrange(100):
138 blah = yield proxy.rpc_getwork()
139 yield proxy.rpc_getwork(blah['data'])
141 yield deferral.sleep(3)
143 assert len(n.tracker.items) == 100
144 assert n.tracker.verified.get_height(n.best_share_var.value) == 100
148 yield port.stopListening()
149 del n, wb, web_root, port, proxy
155 yield deferral.sleep(20) # waiting for work_poller to exit
156 #test_node.timeout = 15
158 @defer.inlineCallbacks
159 def test_nodes(self):
161 old_successor = data.Share.SUCCESSOR
162 data.Share.SUCCESSOR = data.NewShare
169 nodes.append((yield MiniNode.start(mynet, factory, bitcoind, [mn.n.p2p_node.serverfactory.listen_port.getHost().port for mn in nodes])))
171 yield deferral.sleep(3)
173 for i in xrange(SHARES):
174 proxy = jsonrpc.Proxy('http://127.0.0.1:' + str(random.choice(nodes).web_port.getHost().port))
175 blah = yield proxy.rpc_getwork()
176 yield proxy.rpc_getwork(blah['data'])
177 yield deferral.sleep(random.expovariate(1/.1))
179 print type(nodes[0].n.tracker.items[nodes[0].n.best_share_var.value])
181 yield deferral.sleep(3)
183 for i, n in enumerate(nodes):
184 assert len(n.n.tracker.items) == SHARES, (i, len(n.n.tracker.items))
185 assert n.n.tracker.verified.get_height(n.n.best_share_var.value) == SHARES, (i, n.n.tracker.verified.get_height(n.n.best_share_var.value))
186 assert type(n.n.tracker.items[nodes[0].n.best_share_var.value]) is data.NewShare
187 assert type(n.n.tracker.items[n.n.tracker.get_nth_parent_hash(nodes[0].n.best_share_var.value, SHARES - 5)]) is data.Share
198 yield deferral.sleep(20) # waiting for work_poller to exit
200 data.Share.SUCCESSOR = old_successor