Allow block announcements with headers

This replaces using inv messages to announce new blocks, when a peer requests
(via the new "sendheaders" message) that blocks be announced with headers
instead of inv's.

Since headers-first was introduced, peers send getheaders messages in response
to an inv, which requires generating a block locator that is large compared to
the size of the header being requested, and requires an extra round-trip before
a reorg can be relayed.  Save time by tracking headers that a peer is likely to
know about, and send a headers chain that would connect to a peer's known
headers, unless the chain would be too big, in which case we revert to sending
an inv instead.

Based off of @sipa's commit to announce all blocks in a reorg via inv,
which has been squashed into this commit.

Rebased-by: Pieter Wuille
This commit is contained in:
Suhas Daftuar
2014-11-18 22:16:32 +01:00
committed by Pieter Wuille
parent c894fbbb1d
commit 50262d8953
8 changed files with 781 additions and 14 deletions

View File

@@ -751,8 +751,8 @@ class msg_inv(object):
class msg_getdata(object):
command = "getdata"
def __init__(self):
self.inv = []
def __init__(self, inv=None):
self.inv = inv if inv != None else []
def deserialize(self, f):
self.inv = deser_vector(f, CInv)
@@ -905,6 +905,20 @@ class msg_mempool(object):
def __repr__(self):
return "msg_mempool()"
class msg_sendheaders(object):
command = "sendheaders"
def __init__(self):
pass
def deserialize(self, f):
pass
def serialize(self):
return ""
def __repr__(self):
return "msg_sendheaders()"
# getheaders message has
# number of entries
@@ -990,6 +1004,17 @@ class NodeConnCB(object):
def __init__(self):
self.verack_received = False
# Spin until verack message is received from the node.
# Tests may want to use this as a signal that the test can begin.
# This can be called from the testing thread, so it needs to acquire the
# global lock.
def wait_for_verack(self):
while True:
with mininode_lock:
if self.verack_received:
return
time.sleep(0.05)
# Derived classes should call this function once to set the message map
# which associates the derived classes' functions to incoming messages
def create_callback_map(self):
@@ -1084,7 +1109,7 @@ class NodeConn(asyncore.dispatcher):
"regtest": "\xfa\xbf\xb5\xda" # regtest
}
def __init__(self, dstaddr, dstport, rpc, callback, net="regtest"):
def __init__(self, dstaddr, dstport, rpc, callback, net="regtest", services=1):
asyncore.dispatcher.__init__(self, map=mininode_socket_map)
self.log = logging.getLogger("NodeConn(%s:%d)" % (dstaddr, dstport))
self.dstaddr = dstaddr
@@ -1102,6 +1127,7 @@ class NodeConn(asyncore.dispatcher):
# stuff version msg into sendbuf
vt = msg_version()
vt.nServices = services
vt.addrTo.ip = self.dstaddr
vt.addrTo.port = self.dstport
vt.addrFrom.ip = "0.0.0.0"