self.request([head], None)
def heard_headers(self, headers):
- for header2 in header2s:
- self.tracker.add(HeaderWrapper(header2))
+ for header in headers:
+ self.tracker.add(HeaderWrapper(header))
self.think()
def heard_block(self, block_hash):
best, desired = tracker.think(ht)
for peer2, share_hash in desired:
print 'Requesting parent share %x' % (share_hash,)
- peer2.send_getshares(hashes=[share_hash], parents=2000, stops=list(set(tracker.heads) | set())
+ peer2.send_getshares(
+ hashes=[share_hash],
+ parents=2000,
+ stops=list(set(tracker.heads) | set(
+ tracker.get_nth_parent_hash(head, min(max(0, tracker.get_height_and_last(head)[0] - 1), 10)) for head in tracker.heads
+ )),
+ )
current_work.set(dict(
version=work.version,
previous_block=work.previous_block,
print 'Got share hash, requesting! Hash: %x' % (share_hash,)
peer.send_getshares(hashes=[share_hash], parents=0, stops=[])
- def p2p_get_to_best(chain_id_data, have, peer):
- # XXX
- chain = get_chain(chain_id_data)
- if chain.highest.value is None:
- return
-
- chain_hashes = chain.get_down(chain.highest.value)
-
- have2 = set()
- for hash_ in have:
- have2 |= set(chain.get_down(hash_))
-
- for share_hash in reversed(chain_hashes):
- if share_hash in have2:
- continue
- peer.send_share(chain.share2s[share_hash].share, full=True) # doesn't have to be full ... but does that still guarantee ordering?
-
- def p2p_get_shares(share_hashes, parents, peer):
+ def p2p_get_shares(share_hashes, parents, stops, peer):
parents = min(parents, 100//len(share_hashes))
+ stops = set(stops)
for share_hash in share_hashes:
for share in itertools.islice(tracker.get_chain_known(share_hash), parents + 1):
+ if share.hash in stops:
+ break
peer.send_share(share, full=True)
print 'Joining p2pool network using TCP port %i...' % (args.p2pool_port,)
)
p2p_node.handle_share = p2p_share
p2p_node.handle_share_hash = p2p_share_hash
- p2p_node.handle_get_to_best = p2p_get_to_best
p2p_node.handle_get_shares = p2p_get_shares
p2p_node.start()
random.sample(self.node.addr_store.keys(), min(count, len(self.node.addr_store)))
])
- message_gettobest = bitcoin_data.ComposedType([
- ('have', bitcoin_data.ListType(bitcoin_data.HashType())),
- ])
- def handle_gettobest(self, have):
- self.node.handle_get_to_best(have, self)
-
message_getshares = bitcoin_data.ComposedType([
('hashes', bitcoin_data.ListType(bitcoin_data.HashType())),
('parents', bitcoin_data.VarIntType()),
+ ('stops', bitcoin_data.ListType(bitcoin_data.HashType())),
])
- def handle_getshares(self, hashes, parents):
- self.node.handle_get_shares(hashes, parents, self)
+ def handle_getshares(self, hashes, parents, stops):
+ self.node.handle_get_shares(hashes, parents, stops, self)
message_share0s = bitcoin_data.ComposedType([
('hashes', bitcoin_data.ListType(bitcoin_data.HashType())),
def handle_share_hash(self, hash_, peer):
print 'handle_share_hash', (hash_, peer)
- def handle_get_to_best(self, have, peer):
- print 'handle_get_to_best', (have, peer)
-
- def handle_get_shares(self, hashes, parents, peer):
- print 'handle_get_shares', (hashes, parents, peer)
+ def handle_get_shares(self, hashes, parents, stops, peer):
+ print 'handle_get_shares', (hashes, parents, stops, peer)
if __name__ == '__main__':
p = random.randrange(2**15, 2**16)
--- /dev/null
+_nothing = object()
+
+def memoize_with_backing(backing, inverse_of=None):
+ def a(f):
+ def b(*args):
+ res = backing.get((f, args), _nothing)
+ if res is not _nothing:
+ return res
+
+ res = f(*args)
+
+ backing[(f, args)] = res
+ if inverse_of is not None:
+ if len(args) != 1:
+ raise ValueError('inverse_of can only be used for functions taking one argument')
+ backing[(inverse_of, (res,))] = args[0]
+
+ return res
+ return b
+ return a