Bitcoin ABC 0.26.3
P2P Digital Currency
Loading...
Searching...
No Matches
blockencodings.cpp
Go to the documentation of this file.
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
5#include <blockencodings.h>
6
7#include <chainparams.h>
8#include <common/system.h>
9#include <config.h>
10#include <consensus/consensus.h>
12#include <crypto/sha256.h>
13#include <crypto/siphash.h>
14#include <random.h>
15#include <streams.h>
16#include <txmempool.h>
17#include <validation.h>
18
19#include <unordered_map>
20
22 : nonce(GetRand<uint64_t>()), shorttxids(block.vtx.size() - 1),
23 prefilledtxn(1), header(block) {
25 // TODO: Use our mempool prior to block acceptance to predictively fill more
26 // than just the coinbase.
27 prefilledtxn[0] = {0, block.vtx[0]};
28 for (size_t i = 1; i < block.vtx.size(); i++) {
29 const CTransaction &tx = *block.vtx[i];
30 shorttxids[i - 1] = GetShortID(tx.GetHash());
31 }
32}
33
36 stream << header << nonce;
37 CSHA256 hasher;
38 hasher.Write((uint8_t *)&(*stream.begin()), stream.end() - stream.begin());
40 hasher.Finalize(shorttxidhash.begin());
41 shorttxidk0 = shorttxidhash.GetUint64(0);
42 shorttxidk1 = shorttxidhash.GetUint64(1);
43}
44
46 static_assert(SHORTTXIDS_LENGTH == 6,
47 "shorttxids calculation assumes 6-byte shorttxids");
48 return SipHashUint256(shorttxidk0, shorttxidk1, txhash) & 0xffffffffffffL;
49}
50
53 const std::vector<std::pair<TxHash, CTransactionRef>> &extra_txns) {
54 if (cmpctblock.header.IsNull() ||
55 (cmpctblock.shorttxids.empty() && cmpctblock.prefilledtxn.empty())) {
57 }
58 if (cmpctblock.shorttxids.size() + cmpctblock.prefilledtxn.size() >
61 }
62
63 if (!header.IsNull() || shortidProcessor != nullptr) {
65 }
66
67 header = cmpctblock.header;
68
69 for (const auto &prefilledtxn : cmpctblock.prefilledtxn) {
70 if (prefilledtxn.tx->IsNull()) {
72 }
73 }
74 prefilled_count = cmpctblock.prefilledtxn.size();
75
76 // To determine the chance that the number of entries in a bucket exceeds N,
77 // we use the fact that the number of elements in a single bucket is
78 // binomially distributed (with n = the number of shorttxids S, and
79 // p = 1 / the number of buckets), that in the worst case the number of
80 // buckets is equal to S (due to std::unordered_map having a default load
81 // factor of 1.0), and that the chance for any bucket to exceed N elements
82 // is at most buckets * (the chance that any given bucket is above N
83 // elements). Thus:
84 // P(max_elements_per_bucket > N) <= S * (1 - cdf(binomial(n=S,p=1/S), N))
85 // If we assume blocks of up to 16000, allowing 12 elements per bucket
86 // should only fail once per ~1 million block transfers (per peer and
87 // connection).
88 // FIXME the value of 16000 txs in a block should be re-evaluated.
89 shortidProcessor = std::make_shared<TransactionShortIdProcessor>(
90 cmpctblock.prefilledtxn, cmpctblock.shorttxids, 12);
91
92 if (!shortidProcessor->isEvenlyDistributed() ||
93 shortidProcessor->hasShortIdCollision() ||
94 shortidProcessor->hasOutOfBoundIndex()) {
95 // TODO: in the shortid-collision case, we should instead request both
96 // transactions which collided. Falling back to full-block-request here
97 // is overkill.
98 return READ_STATUS_FAILED;
99 }
100
101 {
102 LOCK(pool->cs);
103 auto it = pool->mapTx.begin();
104 while (it != pool->mapTx.end()) {
105 uint64_t shortid = cmpctblock.GetShortID((*it)->GetTx().GetHash());
106
108 shortidProcessor->matchKnownItem(shortid, (*it)->GetSharedTx());
109 it++;
110
111 if (mempool_count == shortidProcessor->getShortIdCount()) {
112 break;
113 }
114 }
115 }
116
117 for (auto &extra_txn : extra_txns) {
118 uint64_t shortid = cmpctblock.GetShortID(extra_txn.first);
119
120 int count = shortidProcessor->matchKnownItem(shortid, extra_txn.second);
123
124 if (mempool_count == shortidProcessor->getShortIdCount()) {
125 break;
126 }
127 }
128
130 "Initialized PartiallyDownloadedBlock for block %s using a "
131 "cmpctblock of size %lu\n",
132 cmpctblock.header.GetHash().ToString(),
134
135 return READ_STATUS_OK;
136}
137
139 if (header.IsNull()) {
140 return false;
141 }
142 if (shortidProcessor == nullptr) {
143 return false;
144 }
145 return shortidProcessor->getItem(index) != nullptr;
146}
147
149 CBlock &block, const std::vector<CTransactionRef> &vtx_missing) {
150 if (header.IsNull()) {
151 return READ_STATUS_INVALID;
152 }
153 uint256 hash = header.GetHash();
154 block = header;
155 const size_t txnCount = shortidProcessor->getItemCount();
156 block.vtx.resize(txnCount);
157
158 size_t tx_missing_offset = 0;
159 for (size_t i = 0; i < txnCount; i++) {
160 auto &txn_available = shortidProcessor->getItem(i);
161 if (!txn_available) {
162 if (vtx_missing.size() <= tx_missing_offset) {
163 return READ_STATUS_INVALID;
164 }
165 block.vtx[i] = vtx_missing[tx_missing_offset++];
166 } else {
167 block.vtx[i] = txn_available;
168 }
169 }
170
171 // Make sure we can't call FillBlock again.
172 header.SetNull();
173 shortidProcessor.reset();
174
175 if (vtx_missing.size() != tx_missing_offset) {
176 return READ_STATUS_INVALID;
177 }
178
180 if (!CheckBlock(block, state, config->GetChainParams().GetConsensus(),
182 // TODO: We really want to just check merkle tree manually here, but
183 // that is expensive, and CheckBlock caches a block's "checked-status"
184 // (in the CBlock?). CBlock should be able to check its own merkle root
185 // and cache that check.
187 // Possible Short ID collision.
188 return READ_STATUS_FAILED;
189 }
191 }
192
194 "Successfully reconstructed block %s with %lu txn prefilled, %lu "
195 "txn from mempool (incl at least %lu from extra pool) and %lu txn "
196 "requested\n",
198 vtx_missing.size());
199 if (vtx_missing.size() < 5) {
200 for (const auto &tx : vtx_missing) {
202 "Reconstructed block %s required tx %s\n", hash.ToString(),
203 tx->GetId().ToString());
204 }
205 }
206
207 return READ_STATUS_OK;
208}
@ READ_STATUS_OK
@ READ_STATUS_INVALID
@ READ_STATUS_CHECKBLOCK_FAILED
@ READ_STATUS_FAILED
enum ReadStatus_t ReadStatus
uint64_t GetShortID(const TxHash &txhash) const
std::vector< PrefilledTransaction > prefilledtxn
static constexpr int SHORTTXIDS_LENGTH
std::vector< uint64_t > shorttxids
BlockHash GetHash() const
Definition block.cpp:11
void SetNull()
Definition block.h:40
bool IsNull() const
Definition block.h:49
Definition block.h:60
std::vector< CTransactionRef > vtx
Definition block.h:63
const Consensus::Params & GetConsensus() const
Definition chainparams.h:92
Double ended buffer combining vector and stream-like interfaces.
Definition streams.h:177
const_iterator begin() const
Definition streams.h:219
const_iterator end() const
Definition streams.h:221
A hasher class for SHA-256.
Definition sha256.h:13
CSHA256 & Write(const uint8_t *data, size_t len)
Definition sha256.cpp:819
void Finalize(uint8_t hash[OUTPUT_SIZE])
Definition sha256.cpp:844
RecursiveMutex cs
This mutex needs to be locked when accessing mapTx or other members that are guarded by it.
Definition txmempool.h:307
virtual uint64_t GetMaxBlockSize() const =0
virtual const CChainParams & GetChainParams() const =0
const CTxMemPool * pool
ReadStatus InitData(const CBlockHeaderAndShortTxIDs &cmpctblock, const std::vector< std::pair< TxHash, CTransactionRef > > &extra_txn)
bool IsTxAvailable(size_t index) const
ReadStatus FillBlock(CBlock &block, const std::vector< CTransactionRef > &vtx_missing)
std::shared_ptr< TransactionShortIdProcessor > shortidProcessor
Result GetResult() const
Definition validation.h:122
std::string ToString() const
Definition uint256.h:80
256-bit opaque blob.
Definition uint256.h:129
@ BLOCK_MUTATED
the block's data didn't match the data committed to by the PoW
#define LogPrint(category,...)
Definition logging.h:238
@ CMPCTBLOCK
Definition logging.h:52
T GetRand(T nMax=std::numeric_limits< T >::max()) noexcept
Generate a uniform random integer of type T in the range [0..nMax) nMax defaults to std::numeric_limi...
Definition random.h:85
@ SER_NETWORK
Definition serialize.h:152
size_t GetSerializeSize(const T &t, int nVersion=0)
Definition serialize.h:1258
uint64_t SipHashUint256(uint64_t k0, uint64_t k1, const uint256 &val)
Optimized SipHash-2-4 implementation for uint256.
Definition siphash.cpp:99
A TxHash is the double sha256 hash of the full transaction data.
Definition txid.h:22
#define LOCK(cs)
Definition sync.h:306
static int count
Definition tests.c:31
bool CheckBlock(const CBlock &block, BlockValidationState &state, const Consensus::Params &params, BlockValidationOptions validationOptions)
Functions for validating blocks and updating the block tree.
#define MIN_TRANSACTION_SIZE
Definition validation.h:79
static const int PROTOCOL_VERSION
network protocol versioning
Definition version.h:11