Fixes for script parser

This commit is contained in:
Selim Mustafaev 2021-11-24 22:04:48 +03:00
parent 4465f4c010
commit 56ff616e63
7 changed files with 43 additions and 12 deletions

View File

@ -2,8 +2,8 @@ cmake_minimum_required(VERSION 3.19)
project(btcexplorer) project(btcexplorer)
set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD 20)
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address") #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address")
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
if(APPLE) if(APPLE)

View File

@ -1,5 +1,7 @@
#include "Block.h" #include "Block.h"
#include "VarInt.h" #include "VarInt.h"
#include "../hash.h"
#include <iostream>
Block::Block(const std::byte* pBlock, size_t size): _header{} { Block::Block(const std::byte* pBlock, size_t size): _header{} {
_size = size; _size = size;
@ -29,3 +31,7 @@ const std::vector<Transaction>& Block::transactions() const {
size_t Block::size() const { size_t Block::size() const {
return _size; return _size;
} }
std::string Block::prevHeaderHash() const {
return hash::to_string_inverse(_header.prevBlockHeaderHash);
}

View File

@ -39,6 +39,7 @@ public:
[[nodiscard]] uint32_t time() const; [[nodiscard]] uint32_t time() const;
[[nodiscard]] const std::vector<Transaction>& transactions() const; [[nodiscard]] const std::vector<Transaction>& transactions() const;
[[nodiscard]] size_t size() const; [[nodiscard]] size_t size() const;
[[nodiscard]] std::string prevHeaderHash() const;
}; };
#endif //BTCEXPLORER_BLOCK_H #endif //BTCEXPLORER_BLOCK_H

View File

@ -4,26 +4,35 @@
#include <iostream> #include <iostream>
#include <iomanip> #include <iomanip>
Script::Script(std::span<uint8_t> data, bool coinbase): _operations(5) { Script::Script(std::span<uint8_t> data, bool coinbase): _operations(10) {
for(auto iter = data.begin(); iter != data.end();) { for(auto iter = data.begin(); iter != data.end();) {
ScriptOperation operation; ScriptOperation operation;
operation.opCode = OpCode(*iter++); operation.opCode = OpCode(*iter++);
//std::cout << "found opcode: " << std::showbase << std::hex << std::setw(4) << (int)operation.opCode << std::dec << std::endl;
size_t available = data.end() - iter;
if(operation.opCode <= OpCode::OP_PUSHDATA4) { if(operation.opCode <= OpCode::OP_PUSHDATA4) {
size_t dataSize = 0; size_t dataSize = 0;
if(operation.opCode < OpCode::OP_PUSHDATA1) { if(operation.opCode < OpCode::OP_PUSHDATA1) {
dataSize = operation.opCode; dataSize = operation.opCode;
} else if(operation.opCode == OpCode::OP_PUSHDATA1) { } else if(operation.opCode == OpCode::OP_PUSHDATA1 && available >= 1) {
dataSize = *iter++; dataSize = *iter++;
} else if(operation.opCode == OpCode::OP_PUSHDATA2) { } else if(operation.opCode == OpCode::OP_PUSHDATA2 && available >= 2) {
dataSize = *((uint16_t*)&iter[0]); dataSize = *((uint16_t*)&iter[0]);
iter += 2; iter += 2;
} else if(operation.opCode == OpCode::OP_PUSHDATA4) { } else if(operation.opCode == OpCode::OP_PUSHDATA4 && available >= 4) {
dataSize = *((uint32_t *)&iter[0]); dataSize = *((uint32_t *)&iter[0]);
iter += 4; iter += 4;
} }
operation.input = std::vector(iter, iter + dataSize);
iter += dataSize; available = data.end() - iter;
if(dataSize > available) {
dataSize = available;
}
if(dataSize > 0) {
operation.input = std::vector(iter, iter + dataSize);
iter += dataSize;
}
} }
_operations.emplace_back(operation); _operations.emplace_back(operation);
} }

View File

@ -9,7 +9,6 @@ TxOutput::TxOutput(const std::byte *data) {
VarInt scriptPubKeySize(data); VarInt scriptPubKeySize(data);
data += scriptPubKeySize.size(); data += scriptPubKeySize.size();
//std::cout << "=== Creating PubKey script of size: " << scriptPubKeySize.value() << std::endl;
_pubKeyScript = std::make_unique<Script>(std::span((uint8_t*)data, scriptPubKeySize.value())); _pubKeyScript = std::make_unique<Script>(std::span((uint8_t*)data, scriptPubKeySize.value()));
_size = sizeof(_value) + scriptPubKeySize.size() + scriptPubKeySize.value(); _size = sizeof(_value) + scriptPubKeySize.size() + scriptPubKeySize.value();

11
hash.h
View File

@ -45,6 +45,17 @@ namespace hash {
return str; return str;
} }
template<ByteArray T>
std::string to_string_inverse(const T& data) {
const size_t stringSize = data.size()*2;
std::string str(stringSize, ' ');
for(size_t i = 0; i < data.size(); ++i) {
str[stringSize - 2 - 2*i] = hex_table[(data[i] & 0xF0) >> 4];
str[stringSize - 1 - 2*i] = hex_table[data[i] & 0x0F];
}
return str;
}
template<ByteArray T> template<ByteArray T>
std::array<uint8_t,SHA256_DIGEST_LENGTH> sha256(const T& data) { std::array<uint8_t,SHA256_DIGEST_LENGTH> sha256(const T& data) {
std::array<uint8_t ,SHA256_DIGEST_LENGTH> hash{}; std::array<uint8_t ,SHA256_DIGEST_LENGTH> hash{};

View File

@ -20,12 +20,12 @@ int main() {
std::vector<Block> blocks; std::vector<Block> blocks;
auto start = std::chrono::high_resolution_clock::now(); auto start = std::chrono::high_resolution_clock::now();
size_t index = 0;
for (const auto & path: paths) { for (const auto & path: paths) {
std::fstream file(path); std::fstream file(path);
std::cout << "Parsing file: " << path << std::endl; std::cout << "Parsing file: " << path << std::endl;
PreBlockHeader header{}; PreBlockHeader header{};
size_t index = 0;
while (true) { while (true) {
file.read((char*)&header, sizeof(header)); file.read((char*)&header, sizeof(header));
header.magic = (BlockMagic)__builtin_bswap32(header.magic); header.magic = (BlockMagic)__builtin_bswap32(header.magic);
@ -34,10 +34,15 @@ int main() {
break; break;
} }
// if(index == 10117) {
// std::cout << "problem block" << std::endl;
// }
auto blockData = std::make_unique<std::byte[]>(header.blockSize); auto blockData = std::make_unique<std::byte[]>(header.blockSize);
file.read((char*)blockData.get(), header.blockSize); file.read((char*)blockData.get(), header.blockSize);
blocks.emplace_back(blockData.get(), header.blockSize); Block block(blockData.get(), header.blockSize);
//blocks.emplace_back(blockData.get(), header.blockSize);
//std::cout << "Parsed new block " << index++ << " with size: " << header.blockSize << std::endl; //std::cout << "Parsed new block " << index++ << " with size: " << header.blockSize << std::endl;
} }