diff --git a/README.md b/README.md index 8692a35..a0f6a77 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,6 @@ Windows 10 with Visual Studio 2019 for build environment and vcpkg for library m - openssl - boost -- tbb - fmt - spdlog diff --git a/tiny-lib/Chain.cpp b/tiny-lib/Chain.cpp index 21f2117..ffc9ef6 100644 --- a/tiny-lib/Chain.cpp +++ b/tiny-lib/Chain.cpp @@ -39,7 +39,7 @@ std::recursive_mutex Chain::Mutex; std::atomic_bool Chain::InitialBlockDownloadComplete = false; -int64_t Chain::GetCurrentHeight() +uint32_t Chain::GetCurrentHeight() { std::lock_guard lock(Mutex); @@ -53,15 +53,15 @@ int64_t Chain::GetMedianTimePast(uint32_t numLastBlocks) if (numLastBlocks > ActiveChain.size()) return 0; - const int64_t first_idx = ActiveChain.size() - numLastBlocks; - int64_t median_idx = first_idx + (numLastBlocks / 2); + const uint32_t first_idx = ActiveChain.size() - numLastBlocks; + uint32_t median_idx = first_idx + (numLastBlocks / 2); if (numLastBlocks % 2 == 0) median_idx -= 1; return ActiveChain[median_idx]->Timestamp; } -int64_t Chain::ValidateBlock(const std::shared_ptr& block) +uint32_t Chain::ValidateBlock(const std::shared_ptr& block) { std::lock_guard lock(Mutex); @@ -110,7 +110,7 @@ int64_t Chain::ValidateBlock(const std::shared_ptr& block) if (block->Timestamp <= GetMedianTimePast(11)) throw BlockValidationException("Timestamp is too old"); - int64_t prev_block_chain_idx; + uint32_t prev_block_chain_idx; if (block->PrevBlockHash.empty()) { prev_block_chain_idx = ActiveChainIdx; @@ -162,7 +162,7 @@ int64_t Chain::ConnectBlock(const std::shared_ptr& block, bool doingReorg const auto blockId = block->Id(); - std::shared_ptr located_block; //HACK: this could be a ref + std::shared_ptr located_block; if (!doingReorg) { auto [located_block2, located_block_height, located_block_chain_idx] = LocateBlockInAllChains(block->Id()); @@ -180,7 +180,7 @@ int64_t Chain::ConnectBlock(const std::shared_ptr& block, bool doingReorg return -1; } - int64_t chainIdx; + uint32_t chainIdx; try { chainIdx = ValidateBlock(block); @@ -307,12 +307,12 @@ bool Chain::ReorgIfNecessary() bool reorged = false; auto frozenSideBranches = SideBranches; - int64_t branch_idx = 1; + uint32_t branch_idx = 1; for (const auto& chain : frozenSideBranches) { auto [fork_block, fork_heigh] = LocateBlockInActiveChain(chain[0]->PrevBlockHash); - int64_t branchHeight = chain.size() + fork_heigh; + uint32_t branchHeight = chain.size() + fork_heigh; if (branchHeight > GetCurrentHeight()) { LOG_INFO("Attempting reorg of idx {} to active chain, new height of {} vs. {}", branch_idx, branchHeight, @@ -326,7 +326,7 @@ bool Chain::ReorgIfNecessary() return reorged; } -bool Chain::TryReorg(const std::vector>& branch, int64_t branchIdx, int64_t forkIdx) +bool Chain::TryReorg(const std::vector>& branch, uint32_t branchIdx, uint32_t forkIdx) { std::lock_guard lock(Mutex); @@ -338,8 +338,7 @@ bool Chain::TryReorg(const std::vector>& branch, int64_t for (const auto& block : branch) { - const int64_t connectedBlockIdx = ConnectBlock(block, true); - if (connectedBlockIdx != ActiveChainIdx) + if (ConnectBlock(block, true) != ActiveChainIdx) { RollbackReorg(oldActiveChain, fork_block, branchIdx); @@ -356,7 +355,7 @@ bool Chain::TryReorg(const std::vector>& branch, int64_t } void Chain::RollbackReorg(const std::vector>& oldActiveChain, - const std::shared_ptr& forkBlock, int64_t branchIdx) + const std::shared_ptr& forkBlock, uint32_t branchIdx) { std::lock_guard lock(Mutex); @@ -377,7 +376,7 @@ std::pair, int64_t> Chain::LocateBlockInChain(const std:: { std::lock_guard lock(Mutex); - int64_t height = 0; + uint32_t height = 0; for (const auto& block : chain) { if (block->Id() == blockHash) @@ -393,18 +392,14 @@ std::pair, int64_t> Chain::LocateBlockInChain(const std:: std::tuple, int64_t> Chain::LocateBlockInActiveChain(const std::string& blockHash) { - auto [located_block, located_block_height] = LocateBlockInChain(blockHash, ActiveChain); - if (located_block != nullptr) - return {located_block, located_block_height}; - - return {located_block, located_block_height}; + return LocateBlockInChain(blockHash, ActiveChain); } std::tuple, int64_t, int64_t> Chain::LocateBlockInAllChains(const std::string& blockHash) { std::lock_guard lock(Mutex); - int64_t chain_idx = 0; + uint32_t chain_idx = 0; auto [located_block, located_block_height] = LocateBlockInActiveChain(blockHash); if (located_block != nullptr) return {located_block, located_block_height, chain_idx}; diff --git a/tiny-lib/Chain.hpp b/tiny-lib/Chain.hpp index 265b3fb..e95976a 100644 --- a/tiny-lib/Chain.hpp +++ b/tiny-lib/Chain.hpp @@ -28,24 +28,23 @@ class Chain static std::recursive_mutex Mutex; - static constexpr int64_t ActiveChainIdx = 0; + static constexpr uint32_t ActiveChainIdx = 0; static std::atomic_bool InitialBlockDownloadComplete; - static int64_t GetCurrentHeight(); - + static uint32_t GetCurrentHeight(); static int64_t GetMedianTimePast(uint32_t numLastBlocks); - static int64_t ValidateBlock(const std::shared_ptr& block); + static uint32_t ValidateBlock(const std::shared_ptr& block); static int64_t ConnectBlock(const std::shared_ptr& block, bool doingReorg = false); static std::shared_ptr DisconnectBlock(const std::shared_ptr& block); static std::vector> DisconnectToFork(const std::shared_ptr& forkBlock); static bool ReorgIfNecessary(); - static bool TryReorg(const std::vector>& branch, int64_t branchIdx, int64_t forkIdx); + static bool TryReorg(const std::vector>& branch, uint32_t branchIdx, uint32_t forkIdx); static void RollbackReorg(const std::vector>& oldActiveChain, - const std::shared_ptr& forkBlock, int64_t branchIdx); + const std::shared_ptr& forkBlock, uint32_t branchIdx); static std::pair, int64_t> LocateBlockInChain( const std::string& blockHash, const std::vector>& chain); diff --git a/tiny-lib/Exceptions.cpp b/tiny-lib/Exceptions.cpp index 81c53c9..e9aed38 100644 --- a/tiny-lib/Exceptions.cpp +++ b/tiny-lib/Exceptions.cpp @@ -14,7 +14,7 @@ TxValidationException::TxValidationException(const char* msg) { } -TxValidationException::TxValidationException(const char* msg, std::shared_ptr toOrphan) +TxValidationException::TxValidationException(const char* msg, const std::shared_ptr& toOrphan) : std::exception(msg), ToOrphan(toOrphan) { } @@ -24,7 +24,7 @@ BlockValidationException::BlockValidationException(const char* msg) { } -BlockValidationException::BlockValidationException(const char* msg, std::shared_ptr toOrphan) +BlockValidationException::BlockValidationException(const char* msg, const std::shared_ptr& toOrphan) : std::exception(msg), ToOrphan(toOrphan) { } diff --git a/tiny-lib/Exceptions.hpp b/tiny-lib/Exceptions.hpp index 4b47481..ddeae4d 100644 --- a/tiny-lib/Exceptions.hpp +++ b/tiny-lib/Exceptions.hpp @@ -15,7 +15,7 @@ class TxValidationException : public std::exception { public: TxValidationException(const char* msg); - TxValidationException(const char* msg, std::shared_ptr toOrphan); + TxValidationException(const char* msg, const std::shared_ptr& toOrphan); std::shared_ptr ToOrphan; }; @@ -24,7 +24,7 @@ class BlockValidationException : public std::exception { public: BlockValidationException(const char* msg); - BlockValidationException(const char* msg, std::shared_ptr toOrphan); + BlockValidationException(const char* msg, const std::shared_ptr& toOrphan); std::shared_ptr ToOrphan; }; diff --git a/tiny-lib/GetBlockMsg.cpp b/tiny-lib/GetBlockMsg.cpp index ba9d32b..1307952 100644 --- a/tiny-lib/GetBlockMsg.cpp +++ b/tiny-lib/GetBlockMsg.cpp @@ -20,18 +20,19 @@ void GetBlockMsg::Handle(std::shared_ptr& con) if (height == -1) height = 1; - Chain::Mutex.lock(); - std::vector> blocks; blocks.reserve(ChunkSize); uint32_t max_height = height + ChunkSize; - if (max_height > Chain::ActiveChain.size()) - max_height = Chain::ActiveChain.size(); - for (uint32_t i = height; i < max_height - 1; i++) - blocks.push_back(Chain::ActiveChain[i]); - Chain::Mutex.unlock(); + { + std::lock_guard lock(Chain::Mutex); + + if (max_height > Chain::ActiveChain.size()) + max_height = Chain::ActiveChain.size(); + for (uint32_t i = height; i < max_height - 1; i++) + blocks.push_back(Chain::ActiveChain[i]); + } LOG_TRACE("Sending {} blocks to {}:{}", blocks.size(), endpoint.address().to_string(), endpoint.port()); NetClient::SendMsg(con, InvMsg(blocks)); diff --git a/tiny-lib/Mempool.cpp b/tiny-lib/Mempool.cpp index 5185904..eca5103 100644 --- a/tiny-lib/Mempool.cpp +++ b/tiny-lib/Mempool.cpp @@ -99,15 +99,7 @@ std::shared_ptr Mempool::TryAddToBlock(std::shared_ptr& block, con { const auto& toSpend = txIn->ToSpend; - auto map_it = std::ranges::find_if(UTXO::Map, - [&toSpend]( - const std::pair, std::shared_ptr>& - p) - { - const auto& [txOutPoint, utxo] = p; - return *txOutPoint == *toSpend; - }); - if (map_it != UTXO::Map.end()) + if (UTXO::FindInMap(toSpend) != nullptr) continue; const auto& inMempool = Find_UTXO_InMempool(toSpend); diff --git a/tiny-lib/NetClient.cpp b/tiny-lib/NetClient.cpp index 176ce93..cbe07e8 100644 --- a/tiny-lib/NetClient.cpp +++ b/tiny-lib/NetClient.cpp @@ -46,25 +46,31 @@ void NetClient::RunAsync() void NetClient::Stop() { - ConnectionsMutex.lock(); - for (const auto& con : Connections) { - if (con->Socket.is_open()) + std::lock_guard lock(ConnectionsMutex); + + for (const auto& con : Connections) { - con->Socket.shutdown(boost::asio::socket_base::shutdown_both); - con->Socket.close(); + auto& soc = con->Socket; + + if (soc.is_open()) + { + soc.shutdown(boost::asio::socket_base::shutdown_both); + soc.close(); + } } } - ConnectionsMutex.unlock(); IO_Service.stop(); if (IO_Thread.joinable()) IO_Thread.join(); - ConnectionsMutex.lock(); - MinerConnections.clear(); - Connections.clear(); - ConnectionsMutex.unlock(); + { + std::lock_guard lock(ConnectionsMutex); + + MinerConnections.clear(); + Connections.clear(); + } } void NetClient::Connect(const std::string& address, uint16_t port) @@ -80,9 +86,11 @@ void NetClient::Connect(const std::string& address, uint16_t port) return; } con->Socket.set_option(boost::asio::ip::tcp::no_delay(true)); - ConnectionsMutex.lock(); - Connections.push_back(con); - ConnectionsMutex.unlock(); + { + std::lock_guard lock(ConnectionsMutex); + + Connections.push_back(con); + } SendMsg(con, PeerHelloMsg()); DoAsyncRead(con); } @@ -117,19 +125,23 @@ bool NetClient::SendMsgRandom(const IMsg& msg) void NetClient::BroadcastMsg(const IMsg& msg) { - ConnectionsMutex.lock(); - if (MinerConnections.empty()) - return; - ConnectionsMutex.unlock(); + { + std::lock_guard lock(ConnectionsMutex); + + if (MinerConnections.empty()) + return; + } const auto msgBuffer = PrepareSendBuffer(msg); - ConnectionsMutex.lock(); - for (auto& con : MinerConnections) { - Write(con, msgBuffer); + std::lock_guard lock(ConnectionsMutex); + + for (auto& con : MinerConnections) + { + Write(con, msgBuffer); + } } - ConnectionsMutex.unlock(); } std::shared_ptr NetClient::GetRandomConnection() @@ -160,9 +172,11 @@ void NetClient::HandleAccept(std::shared_ptr& con, const boost::syst soc.remote_endpoint().port()); soc.set_option(boost::asio::ip::tcp::no_delay(true)); - ConnectionsMutex.lock(); - Connections.push_back(con); - ConnectionsMutex.unlock(); + { + std::lock_guard lock(ConnectionsMutex); + + Connections.push_back(con); + } SendMsg(con, PeerHelloMsg()); DoAsyncRead(con); } @@ -357,8 +371,9 @@ void NetClient::RemoveConnection(std::shared_ptr& con) if (soc.is_open()) { - LOG_INFO("Peer {}:{} disconnected", soc.remote_endpoint().address().to_string(), soc.remote_endpoint().port()); - + LOG_INFO("Peer {}:{} disconnected", soc.remote_endpoint().address().to_string(), + soc.remote_endpoint().port()); + soc.shutdown(boost::asio::socket_base::shutdown_both); soc.close(); } diff --git a/tiny-lib/SendActiveChainMsg.cpp b/tiny-lib/SendActiveChainMsg.cpp index 0e29f3d..e1d6da7 100644 --- a/tiny-lib/SendActiveChainMsg.cpp +++ b/tiny-lib/SendActiveChainMsg.cpp @@ -13,10 +13,14 @@ BinaryBuffer SendActiveChainMsg::Serialize() const { BinaryBuffer buffer; - buffer.WriteSize(Chain::ActiveChain.size()); - for (const auto& block : Chain::ActiveChain) { - buffer.WriteRaw(block->Serialize().GetBuffer()); + std::lock_guard lock(Chain::Mutex); + + buffer.WriteSize(Chain::ActiveChain.size()); + for (const auto& block : Chain::ActiveChain) + { + buffer.WriteRaw(block->Serialize().GetBuffer()); + } } return buffer; diff --git a/tiny-lib/Tx.cpp b/tiny-lib/Tx.cpp index 5639e6c..5988a19 100644 --- a/tiny-lib/Tx.cpp +++ b/tiny-lib/Tx.cpp @@ -148,22 +148,8 @@ void Tx::Validate(const ValidateRequest& req) const { const auto& txIn = TxIns[i]; - std::shared_ptr utxo = nullptr; //HACK: this could be a ref - - const auto& toSpend = txIn->ToSpend; - auto map_it = std::ranges::find_if(UTXO::Map, - [&toSpend]( - const std::pair, std::shared_ptr>& - p) - { - const auto& [txOutPoint, utxo] = p; - return *txOutPoint == *toSpend; - }); - if (map_it != UTXO::Map.end()) - { - utxo = map_it->second; - } - else + auto utxo = UTXO::FindInMap(txIn->ToSpend); + if (utxo == nullptr) { if (!req.SiblingsInBlock.empty()) { @@ -174,12 +160,12 @@ void Tx::Validate(const ValidateRequest& req) const { utxo = Mempool::Find_UTXO_InMempool(txIn->ToSpend); } - } - if (utxo == nullptr) - throw TxValidationException( - fmt::format("Couldn't not find any UTXO for TxIn {}, orphaning transaction", i).c_str(), - std::make_shared(*this)); + if (utxo == nullptr) + throw TxValidationException( + fmt::format("Couldn't not find any UTXO for TxIn {}, orphaning transaction", i).c_str(), + std::make_shared(*this)); + } if (utxo->IsCoinbase && (Chain::GetCurrentHeight() - utxo->Height) < NetParams::COINBASE_MATURITY) throw TxValidationException("Coinbase UTXO is not ready for spending"); diff --git a/tiny-lib/UnspentTxOut.cpp b/tiny-lib/UnspentTxOut.cpp index ae2aa0a..afcf636 100644 --- a/tiny-lib/UnspentTxOut.cpp +++ b/tiny-lib/UnspentTxOut.cpp @@ -62,7 +62,7 @@ bool UnspentTxOut::Deserialize(BinaryBuffer& buffer) std::unordered_map, std::shared_ptr> UnspentTxOut::Map; -void UnspentTxOut::AddToMap(std::shared_ptr<::TxOut> txOut, const std::string& txId, int64_t idx, bool isCoinbase, +void UnspentTxOut::AddToMap(std::shared_ptr<::TxOut>& txOut, const std::string& txId, int64_t idx, bool isCoinbase, int64_t height) { auto txOutPoint = std::make_shared<::TxOutPoint>(txId, idx); @@ -109,6 +109,24 @@ std::shared_ptr UnspentTxOut::FindInList(const std::shared_ptr UnspentTxOut::FindInMap(const std::shared_ptr<::TxOutPoint>& toSpend) +{ + auto map_it = std::ranges::find_if(Map, + [&toSpend]( + const std::pair, std::shared_ptr>& + p) + { + const auto& [txOutPoint, utxo] = p; + return *txOutPoint == *toSpend; + }); + if (map_it != Map.end()) + { + return map_it->second; + } + + return nullptr; +} + bool UnspentTxOut::operator==(const UnspentTxOut& obj) const { if (this == &obj) diff --git a/tiny-lib/UnspentTxOut.hpp b/tiny-lib/UnspentTxOut.hpp index ec72d0c..4a45a9e 100644 --- a/tiny-lib/UnspentTxOut.hpp +++ b/tiny-lib/UnspentTxOut.hpp @@ -34,12 +34,13 @@ class UnspentTxOut : public ISerializable, public IDeserializable //TODO: map mutex? static std::unordered_map, std::shared_ptr> Map; - static void AddToMap(std::shared_ptr<::TxOut> txOut, const std::string& txId, int64_t idx, bool isCoinbase, + static void AddToMap(std::shared_ptr<::TxOut>& txOut, const std::string& txId, int64_t idx, bool isCoinbase, int64_t height); static void RemoveFromMap(const std::string& txId, int64_t idx); static std::shared_ptr FindInList(const std::shared_ptr& txIn, const std::vector>& txs); + static std::shared_ptr FindInMap(const std::shared_ptr<::TxOutPoint>& toSpend); bool operator==(const UnspentTxOut& obj) const; diff --git a/tiny-lib/Wallet.cpp b/tiny-lib/Wallet.cpp index d4223dd..4e7ed77 100644 --- a/tiny-lib/Wallet.cpp +++ b/tiny-lib/Wallet.cpp @@ -162,18 +162,22 @@ Wallet::TxStatusResponse Wallet::GetTxStatus_Miner(const std::string& txId) } } - for (uint32_t height = 0; height < Chain::ActiveChain.size(); height++) { - const auto& block = Chain::ActiveChain[height]; - for (const auto& tx : block->Txs) + std::lock_guard lock(Chain::Mutex); + + for (uint32_t height = 0; height < Chain::ActiveChain.size(); height++) { - if (tx->Id() == txId) + const auto& block = Chain::ActiveChain[height]; + for (const auto& tx : block->Txs) { - ret.Status = TxStatus::Mined; - ret.BlockId = block->Id(); - ret.BlockHeight = height; - - return ret; + if (tx->Id() == txId) + { + ret.Status = TxStatus::Mined; + ret.BlockId = block->Id(); + ret.BlockHeight = height; + + return ret; + } } } } diff --git a/tiny-lib/pch.hpp b/tiny-lib/pch.hpp index 7640db5..145da2b 100644 --- a/tiny-lib/pch.hpp +++ b/tiny-lib/pch.hpp @@ -29,9 +29,6 @@ #include #include #include -#include -#include -#include #include "Log.hpp" diff --git a/tiny-sandbox/main.cpp b/tiny-sandbox/main.cpp index f0809a5..1a6f77d 100644 --- a/tiny-sandbox/main.cpp +++ b/tiny-sandbox/main.cpp @@ -128,7 +128,7 @@ int main(int argc, char** argv) { command.erase(0, send.length()); std::vector send_args; - boost::split(send_args, command, boost::is_any_of(" ")); + split(send_args, command, boost::is_any_of(" ")); if (send_args.size() != 2) { LOG_ERROR("Send command requires 2 arguments, receiver address and send value");