Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
f4d49bc
Merge #8068: Compact Blocks
laanwj Jun 22, 2016
91d0bd9
Merge #8408: Prevent fingerprinting, disk-DoS with compact blocks
laanwj Jul 29, 2016
c0c8d8b
Merge #8418: Add tests for compact blocks
laanwj Aug 2, 2016
5debadc
Merge #8505: Trivial: Fix typos in various files
laanwj Aug 17, 2016
63c33e2
Merge #8449: [Trivial] Do not shadow local variable, cleanup
laanwj Sep 2, 2016
caae165
Merge #8739: [qa] Fix broken sendcmpct test in p2p-compactblocks.py
laanwj Sep 20, 2016
3d1804f
Merge #8854: [qa] Fix race condition in p2p-compactblocks test
Oct 1, 2016
f4b6ddb
Merge #8393: Support for compact blocks together with segwit
sipa Oct 10, 2016
50858ef
Merge #8882: [qa] Fix race conditions in p2p-compactblocks.py and sen…
Oct 11, 2016
c31fde0
Merge #8904: [qa] Fix compact block shortids for a test case
laanwj Oct 13, 2016
cd2c4c6
Merge #8637: Compact Block Tweaks (rebase of #8235)
laanwj Oct 18, 2016
08ec624
Merge #8975: Chainparams: Trivial: In AppInit2(), s/Params()/chainpar…
laanwj Oct 21, 2016
ca64365
Merge #8968: Don't hold cs_main when calling ProcessNewBlock from a c…
laanwj Oct 21, 2016
8f3f638
Merge #8995: Add missing cs_main lock to ::GETBLOCKTXN processing
laanwj Oct 24, 2016
bc47ef3
Merge #8515: A few mempool removal optimizations
laanwj Oct 25, 2016
0f3ea35
Merge #9026: Fix handling of invalid compact blocks
sipa Nov 8, 2016
a526e9b
Merge #9039: Various serialization simplifcations and optimizations
laanwj Nov 9, 2016
ac2cd34
Merge #9058: Fixes for p2p-compactblocks.py test timeouts on travis (…
laanwj Nov 11, 2016
64393ed
Merge #9160: [trivial] Fix hungarian variable name
laanwj Nov 15, 2016
629ddc3
Merge #9159: [qa] Wait for specific block announcement in p2p-compact…
Nov 19, 2016
a96ed58
Merge #9125: Make CBlock a vector of shared_ptr of CTransactions
laanwj Nov 21, 2016
8fdfa6e
Merge #8872: Remove block-request logic from INV message processing
laanwj Nov 21, 2016
7773173
Merge #9199: Always drop the least preferred HB peer when adding a ne…
sipa Nov 24, 2016
b77ff6c
Merge #9233: Fix some typos
Nov 29, 2016
1fc226d
Merge #9260: Mrs Peacock in The Library with The Candlestick (killed …
sipa Dec 3, 2016
ca694e8
Merge #9014: Fix block-connection performance regression
laanwj Dec 5, 2016
5af46ee
Merge #9240: Remove txConflicted
sipa Dec 10, 2016
c7a4fc9
Merge #9344: Do not run functions with necessary side-effects in asse…
laanwj Dec 14, 2016
4be3fd7
Merge #9273: Remove unused CDiskBlockPos* argument from ProcessNewBlock
laanwj Dec 14, 2016
36415f8
Merge #9352: Attempt reconstruction from all compact block announcements
laanwj Dec 19, 2016
085e9ce
Merge #9252: Release cs_main before calling ProcessNewBlock, or proce…
sipa Jan 3, 2017
385fb8d
Merge #9283: A few more CTransactionRef optimizations
laanwj Jan 4, 2017
e7ae1ec
Merge #9375: Relay compact block messages prior to full block connection
sipa Jan 13, 2017
22553a0
Merge #9486: Make peer=%d log prints consistent
laanwj Jan 15, 2017
2f8f475
Merge #9400: Set peers as HB peers upon full block validation
sipa Jan 15, 2017
4ab5e6e
Merge #9499: Use recent-rejects, orphans, and recently-replaced txn f…
laanwj Jan 19, 2017
c728f7d
Fix using of AcceptToMemoryPool in PrivateSend code
Mar 14, 2018
39256a7
Merge #9587: Do not shadow local variable named `tx`.
laanwj Jan 26, 2017
8e04e55
Merge #9510: [trivial] Fix typos in comments
Jan 29, 2017
519187c
Merge #9604: [Trivial] add comment about setting peer as HB peer.
laanwj Feb 7, 2017
0400258
bring back tx ressurection in DisconnectTip
UdjinM6 Mar 25, 2018
da49fce
fSupportsDesiredCmpctVersion
UdjinM6 Mar 25, 2018
ba27cde
add `override`
UdjinM6 Mar 24, 2018
1a070be
Fix delayed headers
UdjinM6 Mar 28, 2018
c093912
Remove unused CConnman::FindNode overload
Mar 30, 2018
89b65bd
Fix typos and comments
Mar 30, 2018
4e24f73
Fix minor code differences
codablock Apr 4, 2018
6791059
Don't use rejection cache for corrupted transactions
codablock Apr 4, 2018
fcbfaa6
Backport missed cs_main locking changes
codablock Apr 4, 2018
3a51596
Backport missed comments and mapBlockSource.emplace call
codablock Apr 4, 2018
0bf93ce
Add CheckPeerHeaders() helper and check in (nCount == 0) too
UdjinM6 Apr 4, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/bips.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,4 @@ BIPs that are implemented by Bitcoin Core (up-to-date up to **v0.13.0**):
* [`BIP 130`](https://github.com/bitcoin/bips/blob/master/bip-0130.mediawiki): direct headers announcement is negotiated with peer versions `>=70012` as of **v0.12.0** ([PR 6494](https://github.com/bitcoin/bitcoin/pull/6494)).
* [`BIP 133`](https://github.com/bitcoin/bips/blob/master/bip-0133.mediawiki): feefilter messages are respected and sent for peer versions `>=70013` as of **v0.13.0** ([PR 7542](https://github.com/bitcoin/bitcoin/pull/7542)).
* [`BIP 147`](https://github.com/bitcoin/bips/blob/master/bip-0147.mediawiki): NULLDUMMY softfork as of **v0.13.1** ([PR 8636](https://github.com/bitcoin/bitcoin/pull/8636) and [PR 8937](https://github.com/bitcoin/bitcoin/pull/8937)).
* [`BIP 152`](https://github.com/bitcoin/bips/blob/master/bip-0152.mediawiki): Compact block transfer and related optimizations are used as of **v0.13.0** ([PR 8068](https://github.com/bitcoin/bitcoin/pull/8068)).
1 change: 1 addition & 0 deletions qa/pull-tester/rpc-tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@
'rpcnamedargs.py',
'listsinceblock.py',
'p2p-leaktests.py',
'p2p-compactblocks.py',
]
if ENABLE_ZMQ:
testScripts.append('zmq_test.py')
Expand Down
847 changes: 847 additions & 0 deletions qa/rpc-tests/p2p-compactblocks.py

Large diffs are not rendered by default.

271 changes: 267 additions & 4 deletions qa/rpc-tests/test_framework/mininode.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,12 @@
from threading import Thread
import logging
import copy
from test_framework.siphash import siphash256

import dash_hash

BIP0031_VERSION = 60000
MY_VERSION = 70208 # current MIN_PEER_PROTO_VERSION
MY_VERSION = 70209 # SHORT_IDS_BLOCKS_VERSION to support cmpct blocks
MY_SUBVERSION = b"/python-mininode-tester:0.0.3/"
MY_RELAY = 1 # from version 70001 onwards, fRelay should be appended to version messages (BIP37)

Expand All @@ -54,7 +55,7 @@
NODE_BLOOM = (1 << 2)

# Keep our own socket map for asyncore, so that we can track disconnects
# ourselves (to workaround an issue with closing an asyncore socket when
# ourselves (to workaround an issue with closing an asyncore socket when
# using select)
mininode_socket_map = dict()

Expand Down Expand Up @@ -241,7 +242,9 @@ class CInv(object):
typemap = {
0: "Error",
1: "TX",
2: "Block"}
2: "Block",
20: "CompactBlock"
}

def __init__(self, t=0, h=0):
self.type = t
Expand Down Expand Up @@ -604,6 +607,181 @@ def __repr__(self):
% (len(self.vchMsg), len(self.vchSig))


class PrefilledTransaction(object):
def __init__(self, index=0, tx = None):
self.index = index
self.tx = tx

def deserialize(self, f):
self.index = deser_compact_size(f)
self.tx = CTransaction()
self.tx.deserialize(f)

def serialize(self):
r = b""
r += ser_compact_size(self.index)
r += self.tx.serialize()
return r

def __repr__(self):
return "PrefilledTransaction(index=%d, tx=%s)" % (self.index, repr(self.tx))

# This is what we send on the wire, in a cmpctblock message.
class P2PHeaderAndShortIDs(object):
def __init__(self):
self.header = CBlockHeader()
self.nonce = 0
self.shortids_length = 0
self.shortids = []
self.prefilled_txn_length = 0
self.prefilled_txn = []

def deserialize(self, f):
self.header.deserialize(f)
self.nonce = struct.unpack("<Q", f.read(8))[0]
self.shortids_length = deser_compact_size(f)
for i in range(self.shortids_length):
# shortids are defined to be 6 bytes in the spec, so append
# two zero bytes and read it in as an 8-byte number
self.shortids.append(struct.unpack("<Q", f.read(6) + b'\x00\x00')[0])
self.prefilled_txn = deser_vector(f, PrefilledTransaction)
self.prefilled_txn_length = len(self.prefilled_txn)

def serialize(self):
r = b""
r += self.header.serialize()
r += struct.pack("<Q", self.nonce)
r += ser_compact_size(self.shortids_length)
for x in self.shortids:
# We only want the first 6 bytes
r += struct.pack("<Q", x)[0:6]
r += ser_vector(self.prefilled_txn)
return r

def __repr__(self):
return "P2PHeaderAndShortIDs(header=%s, nonce=%d, shortids_length=%d, shortids=%s, prefilled_txn_length=%d, prefilledtxn=%s" % (repr(self.header), self.nonce, self.shortids_length, repr(self.shortids), self.prefilled_txn_length, repr(self.prefilled_txn))


# Calculate the BIP 152-compact blocks shortid for a given transaction hash
def calculate_shortid(k0, k1, tx_hash):
expected_shortid = siphash256(k0, k1, tx_hash)
expected_shortid &= 0x0000ffffffffffff
return expected_shortid

# This version gets rid of the array lengths, and reinterprets the differential
# encoding into indices that can be used for lookup.
class HeaderAndShortIDs(object):
def __init__(self, p2pheaders_and_shortids = None):
self.header = CBlockHeader()
self.nonce = 0
self.shortids = []
self.prefilled_txn = []

if p2pheaders_and_shortids != None:
self.header = p2pheaders_and_shortids.header
self.nonce = p2pheaders_and_shortids.nonce
self.shortids = p2pheaders_and_shortids.shortids
last_index = -1
for x in p2pheaders_and_shortids.prefilled_txn:
self.prefilled_txn.append(PrefilledTransaction(x.index + last_index + 1, x.tx))
last_index = self.prefilled_txn[-1].index

def to_p2p(self):
ret = P2PHeaderAndShortIDs()
ret.header = self.header
ret.nonce = self.nonce
ret.shortids_length = len(self.shortids)
ret.shortids = self.shortids
ret.prefilled_txn_length = len(self.prefilled_txn)
ret.prefilled_txn = []
last_index = -1
for x in self.prefilled_txn:
ret.prefilled_txn.append(PrefilledTransaction(x.index - last_index - 1, x.tx))
last_index = x.index
return ret

def get_siphash_keys(self):
header_nonce = self.header.serialize()
header_nonce += struct.pack("<Q", self.nonce)
hash_header_nonce_as_str = sha256(header_nonce)
key0 = struct.unpack("<Q", hash_header_nonce_as_str[0:8])[0]
key1 = struct.unpack("<Q", hash_header_nonce_as_str[8:16])[0]
return [ key0, key1 ]

def initialize_from_block(self, block, nonce=0, prefill_list = [0]):
self.header = CBlockHeader(block)
self.nonce = nonce
self.prefilled_txn = [ PrefilledTransaction(i, block.vtx[i]) for i in prefill_list ]
self.shortids = []
[k0, k1] = self.get_siphash_keys()
for i in range(len(block.vtx)):
if i not in prefill_list:
self.shortids.append(calculate_shortid(k0, k1, block.vtx[i].sha256))

def __repr__(self):
return "HeaderAndShortIDs(header=%s, nonce=%d, shortids=%s, prefilledtxn=%s" % (repr(self.header), self.nonce, repr(self.shortids), repr(self.prefilled_txn))


class BlockTransactionsRequest(object):

def __init__(self, blockhash=0, indexes = None):
self.blockhash = blockhash
self.indexes = indexes if indexes != None else []

def deserialize(self, f):
self.blockhash = deser_uint256(f)
indexes_length = deser_compact_size(f)
for i in range(indexes_length):
self.indexes.append(deser_compact_size(f))

def serialize(self):
r = b""
r += ser_uint256(self.blockhash)
r += ser_compact_size(len(self.indexes))
for x in self.indexes:
r += ser_compact_size(x)
return r

# helper to set the differentially encoded indexes from absolute ones
def from_absolute(self, absolute_indexes):
self.indexes = []
last_index = -1
for x in absolute_indexes:
self.indexes.append(x-last_index-1)
last_index = x

def to_absolute(self):
absolute_indexes = []
last_index = -1
for x in self.indexes:
absolute_indexes.append(x+last_index+1)
last_index = absolute_indexes[-1]
return absolute_indexes

def __repr__(self):
return "BlockTransactionsRequest(hash=%064x indexes=%s)" % (self.blockhash, repr(self.indexes))


class BlockTransactions(object):

def __init__(self, blockhash=0, transactions = None):
self.blockhash = blockhash
self.transactions = transactions if transactions != None else []

def deserialize(self, f):
self.blockhash = deser_uint256(f)
self.transactions = deser_vector(f, CTransaction)

def serialize(self):
r = b""
r += ser_uint256(self.blockhash)
r += ser_vector(self.transactions)
return r

def __repr__(self):
return "BlockTransactions(hash=%064x transactions=%s)" % (self.blockhash, repr(self.transactions))


# Objects that correspond to messages on the wire
class msg_version(object):
command = b"version"
Expand Down Expand Up @@ -1040,6 +1218,79 @@ def serialize(self):
def __repr__(self):
return "msg_feefilter(feerate=%08x)" % self.feerate

class msg_sendcmpct(object):
command = b"sendcmpct"

def __init__(self):
self.announce = False
self.version = 1

def deserialize(self, f):
self.announce = struct.unpack("<?", f.read(1))[0]
self.version = struct.unpack("<Q", f.read(8))[0]

def serialize(self):
r = b""
r += struct.pack("<?", self.announce)
r += struct.pack("<Q", self.version)
return r

def __repr__(self):
return "msg_sendcmpct(announce=%s, version=%lu)" % (self.announce, self.version)

class msg_cmpctblock(object):
command = b"cmpctblock"

def __init__(self, header_and_shortids = None):
self.header_and_shortids = header_and_shortids

def deserialize(self, f):
self.header_and_shortids = P2PHeaderAndShortIDs()
self.header_and_shortids.deserialize(f)

def serialize(self):
r = b""
r += self.header_and_shortids.serialize()
return r

def __repr__(self):
return "msg_cmpctblock(HeaderAndShortIDs=%s)" % repr(self.header_and_shortids)

class msg_getblocktxn(object):
command = b"getblocktxn"

def __init__(self):
self.block_txn_request = None

def deserialize(self, f):
self.block_txn_request = BlockTransactionsRequest()
self.block_txn_request.deserialize(f)

def serialize(self):
r = b""
r += self.block_txn_request.serialize()
return r

def __repr__(self):
return "msg_getblocktxn(block_txn_request=%s)" % (repr(self.block_txn_request))

class msg_blocktxn(object):
command = b"blocktxn"

def __init__(self):
self.block_transactions = BlockTransactions()

def deserialize(self, f):
self.block_transactions.deserialize(f)

def serialize(self):
r = b""
r += self.block_transactions.serialize()
return r

def __repr__(self):
return "msg_blocktxn(block_transactions=%s)" % (repr(self.block_transactions))

# This is what a callback should look like for NodeConn
# Reimplement the on_* functions to provide handling for events
class NodeConnCB(object):
Expand Down Expand Up @@ -1121,6 +1372,10 @@ def on_mempool(self, conn): pass
def on_pong(self, conn, message): pass
def on_feefilter(self, conn, message): pass
def on_sendheaders(self, conn, message): pass
def on_sendcmpct(self, conn, message): pass
def on_cmpctblock(self, conn, message): pass
def on_getblocktxn(self, conn, message): pass
def on_blocktxn(self, conn, message): pass

# More useful callbacks and functions for NodeConnCB's which have a single NodeConn
class SingleNodeConnCB(NodeConnCB):
Expand All @@ -1137,6 +1392,10 @@ def add_connection(self, conn):
def send_message(self, message):
self.connection.send_message(message)

def send_and_ping(self, message):
self.send_message(message)
self.sync_with_ping()

def on_pong(self, conn, message):
self.last_pong = message

Expand Down Expand Up @@ -1170,7 +1429,11 @@ class NodeConn(asyncore.dispatcher):
b"reject": msg_reject,
b"mempool": msg_mempool,
b"feefilter": msg_feefilter,
b"sendheaders": msg_sendheaders
b"sendheaders": msg_sendheaders,
b"sendcmpct": msg_sendcmpct,
b"cmpctblock": msg_cmpctblock,
b"getblocktxn": msg_getblocktxn,
b"blocktxn": msg_blocktxn
}
MAGIC_BYTES = {
"mainnet": b"\xbf\x0c\x6b\xbd", # mainnet
Expand Down
2 changes: 2 additions & 0 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ BITCOIN_CORE_H = \
base58.h \
bip39.h \
bip39_english.h \
blockencodings.h \
bloom.h \
cachemap.h \
cachemultimap.h \
Expand Down Expand Up @@ -211,6 +212,7 @@ libbitcoin_server_a_SOURCES = \
addrdb.cpp \
alert.cpp \
bloom.cpp \
blockencodings.cpp \
chain.cpp \
checkpoints.cpp \
dsnotificationinterface.cpp \
Expand Down
1 change: 1 addition & 0 deletions src/Makefile.test.include
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ BITCOIN_TESTS =\
test/base64_tests.cpp \
test/bip32_tests.cpp \
test/bip39_tests.cpp \
test/blockencodings_tests.cpp \
test/bloom_tests.cpp \
test/bswap_tests.cpp \
test/checkqueue_tests.cpp \
Expand Down
Loading