@@ -209,6 +209,20 @@ static constexpr uint64_t CMPCTBLOCKS_VERSION{2};
209209
210210// Internal stuff
211211namespace {
212+
213+ struct HeaderWithTxCount {
214+ CBlockHeader header;
215+
216+ uint256 GetHash () const { return header.GetHash (); }
217+
218+ template <typename Stream>
219+ void Serialize (Stream& s) const {
220+ s << TX_WITH_WITNESS (header);
221+ WriteCompactSize (s, 0 ); // txcount = 0
222+ }
223+ // Unserialize not needed - this is only used for sending
224+ };
225+
212226/* * Blocks that are in flight, and that are in the queue to be downloaded. */
213227struct QueuedBlock {
214228 /* * BlockIndex. We must have this since we only request blocks when we've already validated the header. */
@@ -4352,7 +4366,9 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
43524366 }
43534367
43544368 // we must use CBlocks, as CBlockHeaders won't include the 0x00 nTx count at the end
4355- std::vector<CBlock> vHeaders;
4369+ // Use HeaderWithTxCount (defined above) to serialize headers correctly for P2P.
4370+ // Our CBlock has extra fields that aren't part of the headers protocol.
4371+ std::vector<HeaderWithTxCount> vHeaders;
43564372 unsigned nCount = 0 ;
43574373 unsigned nSize = 0 ;
43584374 LogDebug (BCLog::NET, " getheaders %d to %s from peer=%d\n " , (pindex ? pindex->nHeight : -1 ), hashStop.IsNull () ? " end" : hashStop.ToString (), pfrom.GetId ());
@@ -4366,8 +4382,8 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
43664382 }
43674383
43684384 ++nCount;
4369- nSize += GetSerializeSize (header);
4370- vHeaders.emplace_back ( header);
4385+ nSize += GetSerializeSize (TX_WITH_WITNESS ( header)) + 1 ; // header + txcount byte
4386+ vHeaders.push_back (HeaderWithTxCount{ header} );
43714387 if (nCount >= m_opts.max_headers_result
43724388 || pindex->GetBlockHash () == hashStop)
43734389 break ;
@@ -4394,8 +4410,9 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
43944410 // without the new block. By resetting the BestHeaderSent, we ensure we
43954411 // will re-announce the new block via headers (or compact blocks again)
43964412 // in the SendMessages logic.
4413+
43974414 nodestate->pindexBestHeaderSent = pindex ? pindex : m_chainman.ActiveChain ().Tip ();
4398- MakeAndPushMessage (pfrom, NetMsgType::HEADERS, TX_WITH_WITNESS ( vHeaders) );
4415+ MakeAndPushMessage (pfrom, NetMsgType::HEADERS, vHeaders);
43994416 }
44004417 return ;
44014418 }
@@ -4745,15 +4762,41 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
47454762 std::vector<CBlockHeader> headers;
47464763
47474764 // Bypass the normal CBlock deserialization, as we don't want to risk deserializing 2000 full blocks.
4765+ size_t pos_before_count = vRecv.size ();
47484766 unsigned int nCount = ReadCompactSize (vRecv);
4767+ LogPrintf (" HEADERS DEBUG: nCount=%u, message_size=%zu\n " , nCount, pos_before_count);
4768+
47494769 if (nCount > m_opts.max_headers_result ) {
47504770 Misbehaving (*peer, strprintf (" headers message size = %u" , nCount));
47514771 return ;
47524772 }
47534773 headers.resize (nCount);
47544774 for (unsigned int n = 0 ; n < nCount; n++) {
4755- vRecv >> headers[n];
4756- ReadCompactSize (vRecv); // ignore tx count; assume it is 0.
4775+ // vRecv >> headers[n];
4776+ // ReadCompactSize(vRecv); // ignore tx count; assume it is 0.
4777+
4778+ size_t pos_before_header = vRecv.size ();
4779+ try {
4780+ vRecv >> headers[n];
4781+ } catch (const std::exception& e) {
4782+ LogPrintf (" HEADERS DEBUG: Failed deserializing header %u/%u at stream pos %zu, remaining bytes: %zu, error: %s\n " ,
4783+ n, nCount, pos_before_header, vRecv.size (), e.what ());
4784+ LogPrintf (" HEADERS DEBUG: Header version=0x%08x, IsAuxpow=%d\n " ,
4785+ headers[n].nVersion , headers[n].IsAuxpow ());
4786+ throw ;
4787+ }
4788+ size_t pos_after_header = vRecv.size ();
4789+ size_t header_size = pos_before_header - pos_after_header;
4790+
4791+ try {
4792+ uint64_t txcount = ReadCompactSize (vRecv); // ignore tx count; assume it is 0.
4793+ LogPrintf (" HEADERS DEBUG: header %u/%u size=%zu bytes, txcount=%lu, IsAuxpow=%d\n " ,
4794+ n, nCount, header_size, txcount, headers[n].IsAuxpow ());
4795+ } catch (const std::exception& e) {
4796+ LogPrintf (" HEADERS DEBUG: Failed reading txcount after header %u/%u, header_size=%zu, error: %s\n " ,
4797+ n, nCount, header_size, e.what ());
4798+ throw ;
4799+ }
47574800 }
47584801
47594802
@@ -5822,7 +5865,7 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
58225865 // blocks, or if the peer doesn't want headers, just
58235866 // add all to the inv queue.
58245867 LOCK (peer->m_block_inv_mutex );
5825- std::vector<CBlock > vHeaders;
5868+ std::vector<HeaderWithTxCount > vHeaders;
58265869 bool fRevertToInv = ((!peer->m_prefers_headers &&
58275870 (!state.m_requested_hb_cmpctblocks || peer->m_blocks_for_headers_relay .size () > 1 )) ||
58285871 peer->m_blocks_for_headers_relay .size () > MAX_BLOCKS_TO_ANNOUNCE);
@@ -5860,14 +5903,14 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
58605903 pBestIndex = pindex;
58615904 if (fFoundStartingHeader ) {
58625905 // add this to the headers message
5863- vHeaders.emplace_back ( pindex->GetBlockHeader (m_chainman.m_blockman ));
5906+ vHeaders.push_back (HeaderWithTxCount{ pindex->GetBlockHeader (m_chainman.m_blockman )} );
58645907 } else if (PeerHasHeader (&state, pindex)) {
58655908 continue ; // keep looking for the first new block
58665909 } else if (pindex->pprev == nullptr || PeerHasHeader (&state, pindex->pprev )) {
58675910 // Peer doesn't have this header but they do have the prior one.
58685911 // Start sending headers.
58695912 fFoundStartingHeader = true ;
5870- vHeaders.emplace_back ( pindex->GetBlockHeader (m_chainman.m_blockman ));
5913+ vHeaders.push_back (HeaderWithTxCount{ pindex->GetBlockHeader (m_chainman.m_blockman )} );
58715914 } else {
58725915 // Peer doesn't have this header or the prior one -- nothing will
58735916 // connect, so bail out.
@@ -5910,7 +5953,7 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
59105953 LogDebug (BCLog::NET, " %s: sending header %s to peer=%d\n " , __func__,
59115954 vHeaders.front ().GetHash ().ToString (), pto->GetId ());
59125955 }
5913- MakeAndPushMessage (*pto, NetMsgType::HEADERS, TX_WITH_WITNESS ( vHeaders) );
5956+ MakeAndPushMessage (*pto, NetMsgType::HEADERS, vHeaders);
59145957 state.pindexBestHeaderSent = pBestIndex;
59155958 } else
59165959 fRevertToInv = true ;
0 commit comments