Skip to content

Commit 50262d8

Browse files
sdaftuarsipa
authored andcommitted
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
1 parent c894fbb commit 50262d8

File tree

8 files changed

+781
-14
lines changed

8 files changed

+781
-14
lines changed

qa/pull-tester/rpc-tests.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@
9191
'p2p-fullblocktest.py',
9292
'blockchain.py',
9393
'disablewallet.py',
94+
'sendheaders.py',
9495
]
9596
testScriptsExt = [
9697
'bip65-cltv.py',

qa/rpc-tests/sendheaders.py

Lines changed: 519 additions & 0 deletions
Large diffs are not rendered by default.

qa/rpc-tests/test_framework/mininode.py

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -751,8 +751,8 @@ def __repr__(self):
751751
class msg_getdata(object):
752752
command = "getdata"
753753

754-
def __init__(self):
755-
self.inv = []
754+
def __init__(self, inv=None):
755+
self.inv = inv if inv != None else []
756756

757757
def deserialize(self, f):
758758
self.inv = deser_vector(f, CInv)
@@ -905,6 +905,20 @@ def serialize(self):
905905
def __repr__(self):
906906
return "msg_mempool()"
907907

908+
class msg_sendheaders(object):
909+
command = "sendheaders"
910+
911+
def __init__(self):
912+
pass
913+
914+
def deserialize(self, f):
915+
pass
916+
917+
def serialize(self):
918+
return ""
919+
920+
def __repr__(self):
921+
return "msg_sendheaders()"
908922

909923
# getheaders message has
910924
# number of entries
@@ -990,6 +1004,17 @@ class NodeConnCB(object):
9901004
def __init__(self):
9911005
self.verack_received = False
9921006

1007+
# Spin until verack message is received from the node.
1008+
# Tests may want to use this as a signal that the test can begin.
1009+
# This can be called from the testing thread, so it needs to acquire the
1010+
# global lock.
1011+
def wait_for_verack(self):
1012+
while True:
1013+
with mininode_lock:
1014+
if self.verack_received:
1015+
return
1016+
time.sleep(0.05)
1017+
9931018
# Derived classes should call this function once to set the message map
9941019
# which associates the derived classes' functions to incoming messages
9951020
def create_callback_map(self):
@@ -1084,7 +1109,7 @@ class NodeConn(asyncore.dispatcher):
10841109
"regtest": "\xfa\xbf\xb5\xda" # regtest
10851110
}
10861111

1087-
def __init__(self, dstaddr, dstport, rpc, callback, net="regtest"):
1112+
def __init__(self, dstaddr, dstport, rpc, callback, net="regtest", services=1):
10881113
asyncore.dispatcher.__init__(self, map=mininode_socket_map)
10891114
self.log = logging.getLogger("NodeConn(%s:%d)" % (dstaddr, dstport))
10901115
self.dstaddr = dstaddr
@@ -1102,6 +1127,7 @@ def __init__(self, dstaddr, dstport, rpc, callback, net="regtest"):
11021127

11031128
# stuff version msg into sendbuf
11041129
vt = msg_version()
1130+
vt.nServices = services
11051131
vt.addrTo.ip = self.dstaddr
11061132
vt.addrTo.port = self.dstport
11071133
vt.addrFrom.ip = "0.0.0.0"

src/chain.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ CBlockLocator CChain::GetLocator(const CBlockIndex *pindex) const {
5151
}
5252

5353
const CBlockIndex *CChain::FindFork(const CBlockIndex *pindex) const {
54+
if (pindex == NULL) {
55+
return NULL;
56+
}
5457
if (pindex->nHeight > Height())
5558
pindex = pindex->GetAncestor(Height());
5659
while (pindex && !Contains(pindex))

0 commit comments

Comments
 (0)