From 9284358defc60419eab748652d5e43a56af656b3 Mon Sep 17 00:00:00 2001 From: Selim Mustafaev Date: Mon, 10 May 2021 21:24:30 +0300 Subject: [PATCH] Fix for address calculation --- CMakeLists.txt | 6 +++++- Models/Script.cpp | 19 +++++++++++-------- Models/Transaction.cpp | 4 ++-- hash.h | 21 +++++++++++++++++++++ main.cpp | 10 +++++----- 5 files changed, 44 insertions(+), 16 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b8cb89d..d4e295a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,9 +2,13 @@ cmake_minimum_required(VERSION 3.19) project(btcexplorer) set(CMAKE_CXX_STANDARD 20) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fconcepts-diagnostics-depth=2") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address") #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") +if(APPLE) + set(OPENSSL_ROOT_DIR "/usr/local/opt/openssl") +endif() + find_package(OpenSSL REQUIRED) include_directories(OPENSSL_INCLUDE_DIR) diff --git a/Models/Script.cpp b/Models/Script.cpp index ad6667a..c93a1e9 100644 --- a/Models/Script.cpp +++ b/Models/Script.cpp @@ -32,6 +32,10 @@ Script::Script(std::span data, bool coinbase) { } ScriptType Script::type() const { + if(_operations.size() < 2) { + return ScriptType::Unknown; + } + if(_operations[0].opCode <= OpCode::OP_PUSHDATA4 && _operations[1].opCode == OpCode::OP_CHECKSIG) { return ScriptType::P2PK; } else if(_operations[0].opCode == OpCode::OP_DUP @@ -42,21 +46,19 @@ ScriptType Script::type() const { { return ScriptType::P2PKH; } else { - throw std::runtime_error("Unsupported script type"); + return ScriptType::Unknown; + //throw std::runtime_error("Unsupported script type"); } } std::string Script::address() { auto pubKey = publicKey(); if(!pubKey.empty()) { - auto hash160 = hash::hash160(pubKey); - std::array prefixedHash{}; - prefixedHash[0] = 0; // TODO: this value should depend on BlockMagic - std::copy_n(hash160.begin(), hash160.size(), prefixedHash.begin() + 1); - auto secondHash = hash::sha256(prefixedHash); + auto hash160 = hash::hash160(pubKey, 0); // TODO: this value should depend on BlockMagic + auto secondHash = hash::hash256(hash160); std::array finalHash{}; - std::copy(prefixedHash.begin(), prefixedHash.end(), finalHash.begin()); - std::copy_n(secondHash.begin(), 4, finalHash.begin() + prefixedHash.size()); + std::copy(hash160.begin(), hash160.end(), finalHash.begin()); + std::copy_n(secondHash.begin(), 4, finalHash.begin() + hash160.size()); return hash::base58(finalHash); } else { return ""; @@ -66,6 +68,7 @@ std::string Script::address() { std::span Script::publicKey() { switch (_type) { case P2PK: return _operations[0].input; + case P2PKH: return _operations[2].input; default: return {}; } } diff --git a/Models/Transaction.cpp b/Models/Transaction.cpp index eccb860..7498931 100644 --- a/Models/Transaction.cpp +++ b/Models/Transaction.cpp @@ -8,7 +8,7 @@ Transaction::Transaction(const std::byte *data) { VarInt inputCount(data + sizeof(_version)); const std::byte* curPtr = data + sizeof(_version) + inputCount.size(); - std::cout << "======== Transaction ========" << std::endl; + //std::cout << "======== Transaction ========" << std::endl; for(size_t i = 0; i < inputCount.value(); ++i) { TxInput input(curPtr); @@ -21,7 +21,7 @@ Transaction::Transaction(const std::byte *data) { for(size_t i = 0; i < outputCount.value(); ++i) { TxOutput output(curPtr); curPtr += output.size(); - std::cout << "Output " << output.value()/100000000.0 << " BTC to address: " << output.address() << std::endl; + //std::cout << "Output " << output.value()/100000000.0 << " BTC to address: " << output.address() << std::endl; _outputs.emplace_back(std::move(output)); } diff --git a/hash.h b/hash.h index e80dc8b..69bff85 100644 --- a/hash.h +++ b/hash.h @@ -65,11 +65,32 @@ namespace hash { return hash; } + template + std::array ripemd160(const T& data, uint8_t prefix) { + std::array hash{}; + hash[0] = prefix; + RIPEMD160_CTX ctx; + RIPEMD160_Init(&ctx); + RIPEMD160_Update(&ctx, data.data(), data.size()); + RIPEMD160_Final(hash.data() + 1, &ctx); + return hash; + } + template std::array hash160(const T& data) { return ripemd160(sha256(data)); } + template + std::array hash160(const T& data, uint8_t prefix) { + return ripemd160(sha256(data), prefix); + } + + template + std::array hash256(const T& data) { + return sha256(sha256(data)); + } + template std::string base58(const T& data) { diff --git a/main.cpp b/main.cpp index bd1fd11..b0c9c6a 100644 --- a/main.cpp +++ b/main.cpp @@ -7,7 +7,7 @@ #include "Models/Block.h" int main() { - std::string path = "/home/selim/dl/blk00000.dat"; + std::string path = "/Users/selim/Documents/blk00000.dat"; //"/home/selim/dl/blk00000.dat"; std::fstream file(path); std::vector blocks; @@ -29,11 +29,11 @@ int main() { 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; - if(index == 1000) { - break; - } +// if(index == 171) { +// break; +// } } auto stop = std::chrono::high_resolution_clock::now();