You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

blockencodings.cpp 8.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. // Copyright (c) 2016 The Bitcoin Core developers
  2. // Distributed under the MIT software license, see the accompanying
  3. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
  4. #include "blockencodings.h"
  5. #include "consensus/consensus.h"
  6. #include "consensus/validation.h"
  7. #include "chainparams.h"
  8. #include "hash.h"
  9. #include "random.h"
  10. #include "streams.h"
  11. #include "txmempool.h"
  12. #include "validation.h"
  13. #include "util.h"
  14. #include <unordered_map>
  15. #define MIN_TRANSACTION_BASE_SIZE (::GetSerializeSize(CTransaction(), SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS))
  16. CBlockHeaderAndShortTxIDs::CBlockHeaderAndShortTxIDs(const CBlock& block, bool fUseWTXID) :
  17. nonce(GetRand(std::numeric_limits<uint64_t>::max())),
  18. shorttxids(block.vtx.size() - 1), prefilledtxn(1), header(block) {
  19. FillShortTxIDSelector();
  20. //TODO: Use our mempool prior to block acceptance to predictively fill more than just the coinbase
  21. prefilledtxn[0] = {0, block.vtx[0]};
  22. for (size_t i = 1; i < block.vtx.size(); i++) {
  23. const CTransaction& tx = *block.vtx[i];
  24. shorttxids[i - 1] = GetShortID(fUseWTXID ? tx.GetWitnessHash() : tx.GetHash());
  25. }
  26. }
  27. void CBlockHeaderAndShortTxIDs::FillShortTxIDSelector() const {
  28. CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
  29. stream << header << nonce;
  30. CSHA256 hasher;
  31. hasher.Write((unsigned char*)&(*stream.begin()), stream.end() - stream.begin());
  32. uint256 shorttxidhash;
  33. hasher.Finalize(shorttxidhash.begin());
  34. shorttxidk0 = shorttxidhash.GetUint64(0);
  35. shorttxidk1 = shorttxidhash.GetUint64(1);
  36. }
  37. uint64_t CBlockHeaderAndShortTxIDs::GetShortID(const uint256& txhash) const {
  38. static_assert(SHORTTXIDS_LENGTH == 6, "shorttxids calculation assumes 6-byte shorttxids");
  39. return SipHashUint256(shorttxidk0, shorttxidk1, txhash) & 0xffffffffffffL;
  40. }
  41. ReadStatus PartiallyDownloadedBlock::InitData(const CBlockHeaderAndShortTxIDs& cmpctblock) {
  42. if (cmpctblock.header.IsNull() || (cmpctblock.shorttxids.empty() && cmpctblock.prefilledtxn.empty()))
  43. return READ_STATUS_INVALID;
  44. if (cmpctblock.shorttxids.size() + cmpctblock.prefilledtxn.size() > MAX_BLOCK_BASE_SIZE / MIN_TRANSACTION_BASE_SIZE)
  45. return READ_STATUS_INVALID;
  46. assert(header.IsNull() && txn_available.empty());
  47. header = cmpctblock.header;
  48. txn_available.resize(cmpctblock.BlockTxCount());
  49. int32_t lastprefilledindex = -1;
  50. for (size_t i = 0; i < cmpctblock.prefilledtxn.size(); i++) {
  51. if (cmpctblock.prefilledtxn[i].tx->IsNull())
  52. return READ_STATUS_INVALID;
  53. lastprefilledindex += cmpctblock.prefilledtxn[i].index + 1; //index is a uint16_t, so can't overflow here
  54. if (lastprefilledindex > std::numeric_limits<uint16_t>::max())
  55. return READ_STATUS_INVALID;
  56. if ((uint32_t)lastprefilledindex > cmpctblock.shorttxids.size() + i) {
  57. // If we are inserting a tx at an index greater than our full list of shorttxids
  58. // plus the number of prefilled txn we've inserted, then we have txn for which we
  59. // have neither a prefilled txn or a shorttxid!
  60. return READ_STATUS_INVALID;
  61. }
  62. txn_available[lastprefilledindex] = cmpctblock.prefilledtxn[i].tx;
  63. }
  64. prefilled_count = cmpctblock.prefilledtxn.size();
  65. // Calculate map of txids -> positions and check mempool to see what we have (or don't)
  66. // Because well-formed cmpctblock messages will have a (relatively) uniform distribution
  67. // of short IDs, any highly-uneven distribution of elements can be safely treated as a
  68. // READ_STATUS_FAILED.
  69. std::unordered_map<uint64_t, uint16_t> shorttxids(cmpctblock.shorttxids.size());
  70. uint16_t index_offset = 0;
  71. for (size_t i = 0; i < cmpctblock.shorttxids.size(); i++) {
  72. while (txn_available[i + index_offset])
  73. index_offset++;
  74. shorttxids[cmpctblock.shorttxids[i]] = i + index_offset;
  75. // To determine the chance that the number of entries in a bucket exceeds N,
  76. // we use the fact that the number of elements in a single bucket is
  77. // binomially distributed (with n = the number of shorttxids S, and p =
  78. // 1 / the number of buckets), that in the worst case the number of buckets is
  79. // equal to S (due to std::unordered_map having a default load factor of 1.0),
  80. // and that the chance for any bucket to exceed N elements is at most
  81. // buckets * (the chance that any given bucket is above N elements).
  82. // Thus: P(max_elements_per_bucket > N) <= S * (1 - cdf(binomial(n=S,p=1/S), N)).
  83. // If we assume blocks of up to 16000, allowing 12 elements per bucket should
  84. // only fail once per ~1 million block transfers (per peer and connection).
  85. if (shorttxids.bucket_size(shorttxids.bucket(cmpctblock.shorttxids[i])) > 12)
  86. return READ_STATUS_FAILED;
  87. }
  88. // TODO: in the shortid-collision case, we should instead request both transactions
  89. // which collided. Falling back to full-block-request here is overkill.
  90. if (shorttxids.size() != cmpctblock.shorttxids.size())
  91. return READ_STATUS_FAILED; // Short ID collision
  92. std::vector<bool> have_txn(txn_available.size());
  93. LOCK(pool->cs);
  94. const std::vector<std::pair<uint256, CTxMemPool::txiter> >& vTxHashes = pool->vTxHashes;
  95. for (size_t i = 0; i < vTxHashes.size(); i++) {
  96. uint64_t shortid = cmpctblock.GetShortID(vTxHashes[i].first);
  97. std::unordered_map<uint64_t, uint16_t>::iterator idit = shorttxids.find(shortid);
  98. if (idit != shorttxids.end()) {
  99. if (!have_txn[idit->second]) {
  100. txn_available[idit->second] = vTxHashes[i].second->GetSharedTx();
  101. have_txn[idit->second] = true;
  102. mempool_count++;
  103. } else {
  104. // If we find two mempool txn that match the short id, just request it.
  105. // This should be rare enough that the extra bandwidth doesn't matter,
  106. // but eating a round-trip due to FillBlock failure would be annoying
  107. if (txn_available[idit->second]) {
  108. txn_available[idit->second].reset();
  109. mempool_count--;
  110. }
  111. }
  112. }
  113. // Though ideally we'd continue scanning for the two-txn-match-shortid case,
  114. // the performance win of an early exit here is too good to pass up and worth
  115. // the extra risk.
  116. if (mempool_count == shorttxids.size())
  117. break;
  118. }
  119. LogPrint("cmpctblock", "Initialized PartiallyDownloadedBlock for block %s using a cmpctblock of size %lu\n", cmpctblock.header.GetHash().ToString(), GetSerializeSize(cmpctblock, SER_NETWORK, PROTOCOL_VERSION));
  120. return READ_STATUS_OK;
  121. }
  122. bool PartiallyDownloadedBlock::IsTxAvailable(size_t index) const {
  123. assert(!header.IsNull());
  124. assert(index < txn_available.size());
  125. return txn_available[index] ? true : false;
  126. }
  127. ReadStatus PartiallyDownloadedBlock::FillBlock(CBlock& block, const std::vector<CTransactionRef>& vtx_missing) {
  128. assert(!header.IsNull());
  129. uint256 hash = header.GetHash();
  130. block = header;
  131. block.vtx.resize(txn_available.size());
  132. size_t tx_missing_offset = 0;
  133. for (size_t i = 0; i < txn_available.size(); i++) {
  134. if (!txn_available[i]) {
  135. if (vtx_missing.size() <= tx_missing_offset)
  136. return READ_STATUS_INVALID;
  137. block.vtx[i] = vtx_missing[tx_missing_offset++];
  138. } else
  139. block.vtx[i] = std::move(txn_available[i]);
  140. }
  141. // Make sure we can't call FillBlock again.
  142. header.SetNull();
  143. txn_available.clear();
  144. if (vtx_missing.size() != tx_missing_offset)
  145. return READ_STATUS_INVALID;
  146. CValidationState state;
  147. if (!CheckBlock(block, state, Params().GetConsensus())) {
  148. // TODO: We really want to just check merkle tree manually here,
  149. // but that is expensive, and CheckBlock caches a block's
  150. // "checked-status" (in the CBlock?). CBlock should be able to
  151. // check its own merkle root and cache that check.
  152. if (state.CorruptionPossible())
  153. return READ_STATUS_FAILED; // Possible Short ID collision
  154. return READ_STATUS_CHECKBLOCK_FAILED;
  155. }
  156. LogPrint("cmpctblock", "Successfully reconstructed block %s with %lu txn prefilled, %lu txn from mempool and %lu txn requested\n", hash.ToString(), prefilled_count, mempool_count, vtx_missing.size());
  157. if (vtx_missing.size() < 5) {
  158. for (const auto& tx : vtx_missing)
  159. LogPrint("cmpctblock", "Reconstructed block %s required tx %s\n", hash.ToString(), tx->GetHash().ToString());
  160. }
  161. return READ_STATUS_OK;
  162. }