Skip to content

Commit 6429cfa

Browse files
committed
Merge #8393: Support for compact blocks together with segwit
27acfc1 [qa] Update p2p-compactblocks.py for compactblocks v2 (Suhas Daftuar) 422fac6 [qa] Add support for compactblocks v2 to mininode (Suhas Daftuar) f5b9b8f [qa] Fix bug in mininode witness deserialization (Suhas Daftuar) 6aa28ab Use cmpctblock type 2 for segwit-enabled transfer (Pieter Wuille) be7555f Fix overly-prescriptive p2p-segwit test for new fetch logic (Matt Corallo) 06128da Make GetFetchFlags always request witness objects from witness peers (Matt Corallo)
2 parents 072116f + 27acfc1 commit 6429cfa

File tree

9 files changed

+489
-241
lines changed

9 files changed

+489
-241
lines changed

qa/rpc-tests/p2p-compactblocks.py

Lines changed: 389 additions & 194 deletions
Large diffs are not rendered by default.

qa/rpc-tests/p2p-segwit.py

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -912,14 +912,6 @@ def test_witness_tx_relay_before_segwit_activation(self):
912912
# But eliminating the witness should fix it
913913
self.test_node.test_transaction_acceptance(tx, with_witness=False, accepted=True)
914914

915-
# Verify that inv's to test_node come with getdata's for non-witness tx's
916-
# Just tweak the transaction, announce it, and verify we get a getdata
917-
# for a normal tx
918-
tx.vout[0].scriptPubKey = CScript([OP_TRUE, OP_TRUE])
919-
tx.rehash()
920-
self.test_node.announce_tx_and_wait_for_getdata(tx)
921-
assert(self.test_node.last_getdata.inv[0].type == 1)
922-
923915
# Cleanup: mine the first transaction and update utxo
924916
self.nodes[0].generate(1)
925917
assert_equal(len(self.nodes[0].getrawmempool()), 0)
@@ -1025,7 +1017,7 @@ def test_tx_relay_after_segwit_activation(self):
10251017
def test_block_relay(self, segwit_activated):
10261018
print("\tTesting block relay")
10271019

1028-
blocktype = 2|MSG_WITNESS_FLAG if segwit_activated else 2
1020+
blocktype = 2|MSG_WITNESS_FLAG
10291021

10301022
# test_node has set NODE_WITNESS, so all getdata requests should be for
10311023
# witness blocks.

qa/rpc-tests/test_framework/mininode.py

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -452,7 +452,7 @@ def deserialize(self, f):
452452
else:
453453
self.vout = deser_vector(f, CTxOut)
454454
if flags != 0:
455-
self.wit.vtxinwit = [CTxInWitness()]*len(self.vin)
455+
self.wit.vtxinwit = [CTxInWitness() for i in range(len(self.vin))]
456456
self.wit.deserialize(f)
457457
self.nLockTime = struct.unpack("<I", f.read(4))[0]
458458
self.sha256 = None
@@ -518,8 +518,8 @@ def is_valid(self):
518518
return True
519519

520520
def __repr__(self):
521-
return "CTransaction(nVersion=%i vin=%s vout=%s nLockTime=%i)" \
522-
% (self.nVersion, repr(self.vin), repr(self.vout), self.nLockTime)
521+
return "CTransaction(nVersion=%i vin=%s vout=%s wit=%s nLockTime=%i)" \
522+
% (self.nVersion, repr(self.vin), repr(self.vout), repr(self.wit), self.nLockTime)
523523

524524

525525
class CBlockHeader(object):
@@ -755,6 +755,9 @@ def serialize(self, with_witness=False):
755755
r += self.tx.serialize_without_witness()
756756
return r
757757

758+
def serialize_with_witness(self):
759+
return self.serialize(with_witness=True)
760+
758761
def __repr__(self):
759762
return "PrefilledTransaction(index=%d, tx=%s)" % (self.index, repr(self.tx))
760763

@@ -779,6 +782,7 @@ def deserialize(self, f):
779782
self.prefilled_txn = deser_vector(f, PrefilledTransaction)
780783
self.prefilled_txn_length = len(self.prefilled_txn)
781784

785+
# When using version 2 compact blocks, we must serialize with_witness.
782786
def serialize(self, with_witness=False):
783787
r = b""
784788
r += self.header.serialize()
@@ -787,12 +791,20 @@ def serialize(self, with_witness=False):
787791
for x in self.shortids:
788792
# We only want the first 6 bytes
789793
r += struct.pack("<Q", x)[0:6]
790-
r += ser_vector(self.prefilled_txn)
794+
if with_witness:
795+
r += ser_vector(self.prefilled_txn, "serialize_with_witness")
796+
else:
797+
r += ser_vector(self.prefilled_txn)
791798
return r
792799

793800
def __repr__(self):
794801
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))
795802

803+
# P2P version of the above that will use witness serialization (for compact
804+
# block version 2)
805+
class P2PHeaderAndShortWitnessIDs(P2PHeaderAndShortIDs):
806+
def serialize(self):
807+
return super(P2PHeaderAndShortWitnessIDs, self).serialize(with_witness=True)
796808

797809
# Calculate the BIP 152-compact blocks shortid for a given transaction hash
798810
def calculate_shortid(k0, k1, tx_hash):
@@ -808,6 +820,7 @@ def __init__(self, p2pheaders_and_shortids = None):
808820
self.nonce = 0
809821
self.shortids = []
810822
self.prefilled_txn = []
823+
self.use_witness = False
811824

812825
if p2pheaders_and_shortids != None:
813826
self.header = p2pheaders_and_shortids.header
@@ -819,7 +832,10 @@ def __init__(self, p2pheaders_and_shortids = None):
819832
last_index = self.prefilled_txn[-1].index
820833

821834
def to_p2p(self):
822-
ret = P2PHeaderAndShortIDs()
835+
if self.use_witness:
836+
ret = P2PHeaderAndShortWitnessIDs()
837+
else:
838+
ret = P2PHeaderAndShortIDs()
823839
ret.header = self.header
824840
ret.nonce = self.nonce
825841
ret.shortids_length = len(self.shortids)
@@ -840,15 +856,20 @@ def get_siphash_keys(self):
840856
key1 = struct.unpack("<Q", hash_header_nonce_as_str[8:16])[0]
841857
return [ key0, key1 ]
842858

843-
def initialize_from_block(self, block, nonce=0, prefill_list = [0]):
859+
# Version 2 compact blocks use wtxid in shortids (rather than txid)
860+
def initialize_from_block(self, block, nonce=0, prefill_list = [0], use_witness = False):
844861
self.header = CBlockHeader(block)
845862
self.nonce = nonce
846863
self.prefilled_txn = [ PrefilledTransaction(i, block.vtx[i]) for i in prefill_list ]
847864
self.shortids = []
865+
self.use_witness = use_witness
848866
[k0, k1] = self.get_siphash_keys()
849867
for i in range(len(block.vtx)):
850868
if i not in prefill_list:
851-
self.shortids.append(calculate_shortid(k0, k1, block.vtx[i].sha256))
869+
tx_hash = block.vtx[i].sha256
870+
if use_witness:
871+
tx_hash = block.vtx[i].calc_sha256(with_witness=True)
872+
self.shortids.append(calculate_shortid(k0, k1, tx_hash))
852873

853874
def __repr__(self):
854875
return "HeaderAndShortIDs(header=%s, nonce=%d, shortids=%s, prefilledtxn=%s" % (repr(self.header), self.nonce, repr(self.shortids), repr(self.prefilled_txn))
@@ -1424,6 +1445,12 @@ def serialize(self):
14241445
def __repr__(self):
14251446
return "msg_blocktxn(block_transactions=%s)" % (repr(self.block_transactions))
14261447

1448+
class msg_witness_blocktxn(msg_blocktxn):
1449+
def serialize(self):
1450+
r = b""
1451+
r += self.block_transactions.serialize(with_witness=True)
1452+
return r
1453+
14271454
# This is what a callback should look like for NodeConn
14281455
# Reimplement the on_* functions to provide handling for events
14291456
class NodeConnCB(object):

src/blockencodings.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,15 @@
1717

1818
#define MIN_TRANSACTION_BASE_SIZE (::GetSerializeSize(CTransaction(), SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS))
1919

20-
CBlockHeaderAndShortTxIDs::CBlockHeaderAndShortTxIDs(const CBlock& block) :
20+
CBlockHeaderAndShortTxIDs::CBlockHeaderAndShortTxIDs(const CBlock& block, bool fUseWTXID) :
2121
nonce(GetRand(std::numeric_limits<uint64_t>::max())),
2222
shorttxids(block.vtx.size() - 1), prefilledtxn(1), header(block) {
2323
FillShortTxIDSelector();
2424
//TODO: Use our mempool prior to block acceptance to predictively fill more than just the coinbase
2525
prefilledtxn[0] = {0, block.vtx[0]};
2626
for (size_t i = 1; i < block.vtx.size(); i++) {
2727
const CTransaction& tx = block.vtx[i];
28-
shorttxids[i - 1] = GetShortID(tx.GetHash());
28+
shorttxids[i - 1] = GetShortID(fUseWTXID ? tx.GetWitnessHash() : tx.GetHash());
2929
}
3030
}
3131

src/blockencodings.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ class CBlockHeaderAndShortTxIDs {
146146
// Dummy for deserialization
147147
CBlockHeaderAndShortTxIDs() {}
148148

149-
CBlockHeaderAndShortTxIDs(const CBlock& block);
149+
CBlockHeaderAndShortTxIDs(const CBlock& block, bool fUseWTXID);
150150

151151
uint64_t GetShortID(const uint256& txhash) const;
152152

0 commit comments

Comments
 (0)