Process single block and its transactions */
| 212 | |
| 213 | /** Process single block and its transactions */ |
| 214 | blocksci::RawBlock readNewBlock(uint32_t firstTxNum, uint64_t firstInputNum, uint64_t firstOutputNum, const BlockInfoBase &block, BlockFileReaderBase &fileReader, NewBlocksFiles &files, const std::function<bool(RawTransaction *&tx)> &loadFunc, const std::function<void(RawTransaction *tx)> &outFunc, bool isSegwit) { |
| 215 | std::vector<unsigned char> coinbase; |
| 216 | blocksci::uint256 nullHash; |
| 217 | nullHash.SetNull(); |
| 218 | uint32_t headerSize = 80 + variableLengthIntSize(block.nTx); |
| 219 | uint32_t baseSize = headerSize; |
| 220 | uint32_t realSize = headerSize; |
| 221 | uint32_t inputCount = 0; |
| 222 | uint32_t outputCount = 0; |
| 223 | |
| 224 | // Iterate over all transactions of the current block |
| 225 | for (uint32_t j = 0; j < block.nTx; j++) { |
| 226 | RawTransaction *tx = nullptr; |
| 227 | |
| 228 | // Try to re-use memory from transactions that have passed the entire queue |
| 229 | if (!loadFunc(tx)) { |
| 230 | // No tx is currently available in finished_transaction_queue -> allocate new memory |
| 231 | tx = new RawTransaction(); |
| 232 | } else { |
| 233 | // loadFunc(tx) set the pointer tx to memory from a finished RawTransaction -> reuse that space |
| 234 | assert(tx); |
| 235 | fileReader.receivedFinishedTx(tx); |
| 236 | } |
| 237 | |
| 238 | // Read next transaction into tx |
| 239 | fileReader.nextTx(tx, isSegwit); |
| 240 | |
| 241 | // For every tx, write blockchain-wide number of the first tx input and output to file (FixedSizeFileMapper<uint64_t>) |
| 242 | files.txFirstInput.write(firstInputNum + inputCount); |
| 243 | files.txFirstOutput.write(firstOutputNum + outputCount); |
| 244 | |
| 245 | // Write tx version to file (FixedSizeFileMapper<int32_t>) |
| 246 | files.txVersionFile.write(tx->version); |
| 247 | |
| 248 | // If transaction is a coinbase transaction, extract and assign coinbase data |
| 249 | if (tx->inputs.size() == 1 && tx->inputs[0].rawOutputPointer.hash == nullHash) { |
| 250 | auto scriptView = tx->inputs[0].getScriptView(); |
| 251 | coinbase.assign(scriptView.begin(), scriptView.end()); |
| 252 | tx->inputs.clear(); // do not store inputs for coinbase transactions |
| 253 | } |
| 254 | |
| 255 | for (auto &input : tx->inputs) { |
| 256 | // Write blockchain's sequence number field to file (FixedSizeFileMapper<uint32_t>) |
| 257 | files.inputSequenceFile.write(input.sequenceNum); |
| 258 | |
| 259 | // Write the tx-internal output number of the spent output to file (FixedSizeFileMapper<uint16_t>) |
| 260 | files.inputSpentOutNumFile.write(input.rawOutputPointer.outputNum); |
| 261 | } |
| 262 | |
| 263 | inputCount += tx->inputs.size(); |
| 264 | outputCount += tx->outputs.size(); |
| 265 | baseSize += tx->baseSize; |
| 266 | realSize += tx->realSize; |
| 267 | |
| 268 | // add tx to the queue of the first step of the processing pipeline |
| 269 | outFunc(tx); |
| 270 | } |
| 271 |
no test coverage detected