diff --git a/CMakeLists.txt b/CMakeLists.txt index e0b96d59..d1054fd2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,27 +6,26 @@ include_directories (${CMAKE_SOURCE_DIR}) find_package (Boost REQUIRED) include_directories (${Boost_INCLUDE_DIR}) -find_package (OpenSSL REQUIRED) -include_directories (${OpenSSL_INCLUDE_DIR}) - find_package (GTest REQUIRED) include_directories (${GTEST_INCLUDE_DIR}) +find_package (CryptoPP REQUIRED) +include_directories (${CRYPTOPP_INCLUDE_DIRS}) + add_library (mu_coin mu_coin/entry.cpp mu_coin/address.hpp mu_coin/address.cpp mu_coin/block.hpp mu_coin/block.cpp + mu_coin/delta.cpp + mu_coin/delta.hpp mu_coin/ledger.hpp - mu_coin/ledger.cpp - mu_coin/balance.hpp - mu_coin/balance.cpp) + mu_coin/ledger.cpp) add_executable (mu_coin_test mu_coin_test/entry.cpp mu_coin_test/ledger.cpp - mu_coin_test/balance.cpp mu_coin_test/block.cpp) -target_link_libraries (mu_coin_test ${GTEST_LIBRARY} ${GTEST_MAIN_LIBRARY} mu_coin) \ No newline at end of file +target_link_libraries (mu_coin_test ${GTEST_LIBRARY} ${GTEST_MAIN_LIBRARY} ${CRYPTOPP_LIBRARY} mu_coin) \ No newline at end of file diff --git a/FindCryptoPP.cmake b/FindCryptoPP.cmake new file mode 100644 index 00000000..74a01e83 --- /dev/null +++ b/FindCryptoPP.cmake @@ -0,0 +1,108 @@ +# Module for locating the Crypto++ encryption library. +# +# Customizable variables: +# CRYPTOPP_ROOT_DIR +# This variable points to the CryptoPP root directory. On Windows the +# library location typically will have to be provided explicitly using the +# -D command-line option. The directory should include the include/cryptopp, +# lib and/or bin sub-directories. +# +# Read-only variables: +# CRYPTOPP_FOUND +# Indicates whether the library has been found. +# +# CRYPTOPP_INCLUDE_DIRS +# Points to the CryptoPP include directory. +# +# CRYPTOPP_LIBRARIES +# Points to the CryptoPP libraries that should be passed to +# target_link_libararies. +# +# +# Copyright (c) 2012 Sergiu Dotenco +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +INCLUDE (FindPackageHandleStandardArgs) + +FIND_PATH (CRYPTOPP_ROOT_DIR + NAMES cryptopp/cryptlib.h include/cryptopp/cryptlib.h + PATHS ENV CRYPTOPPROOT + DOC "CryptoPP root directory") + +# Re-use the previous path: +FIND_PATH (CRYPTOPP_INCLUDE_DIR + NAMES cryptopp/cryptlib.h + HINTS ${CRYPTOPP_ROOT_DIR} + PATH_SUFFIXES include + DOC "CryptoPP include directory") + +FIND_LIBRARY (CRYPTOPP_LIBRARY_DEBUG + NAMES cryptlibd cryptoppd + HINTS ${CRYPTOPP_ROOT_DIR} + PATH_SUFFIXES lib + DOC "CryptoPP debug library") + +FIND_LIBRARY (CRYPTOPP_LIBRARY_RELEASE + NAMES cryptlib cryptopp + HINTS ${CRYPTOPP_ROOT_DIR} + PATH_SUFFIXES lib + DOC "CryptoPP release library") + +IF (CRYPTOPP_LIBRARY_DEBUG AND CRYPTOPP_LIBRARY_RELEASE) + SET (CRYPTOPP_LIBRARY + optimized ${CRYPTOPP_LIBRARY_RELEASE} + debug ${CRYPTOPP_LIBRARY_DEBUG} CACHE DOC "CryptoPP library") +ELSEIF (CRYPTOPP_LIBRARY_RELEASE) + SET (CRYPTOPP_LIBRARY ${CRYPTOPP_LIBRARY_RELEASE} CACHE DOC + "CryptoPP library") +ENDIF (CRYPTOPP_LIBRARY_DEBUG AND CRYPTOPP_LIBRARY_RELEASE) + +IF (CRYPTOPP_INCLUDE_DIR) + SET (_CRYPTOPP_VERSION_HEADER ${CRYPTOPP_INCLUDE_DIR}/cryptopp/config.h) + + IF (EXISTS ${_CRYPTOPP_VERSION_HEADER}) + FILE (STRINGS ${_CRYPTOPP_VERSION_HEADER} _CRYPTOPP_VERSION_TMP REGEX + "^#define CRYPTOPP_VERSION[ \t]+[0-9]+$") + + STRING (REGEX REPLACE + "^#define CRYPTOPP_VERSION[ \t]+([0-9]+)" "\\1" _CRYPTOPP_VERSION_TMP + ${_CRYPTOPP_VERSION_TMP}) + + STRING (REGEX REPLACE "([0-9]+)[0-9][0-9]" "\\1" CRYPTOPP_VERSION_MAJOR + ${_CRYPTOPP_VERSION_TMP}) + STRING (REGEX REPLACE "[0-9]([0-9])[0-9]" "\\1" CRYPTOPP_VERSION_MINOR + ${_CRYPTOPP_VERSION_TMP}) + STRING (REGEX REPLACE "[0-9][0-9]([0-9])" "\\1" CRYPTOPP_VERSION_PATCH + ${_CRYPTOPP_VERSION_TMP}) + + SET (CRYPTOPP_VERSION_COUNT 3) + SET (CRYPTOPP_VERSION + ${CRYPTOPP_VERSION_MAJOR}.${CRYPTOPP_VERSION_MINOR}.${CRYPTOPP_VERSION_PATCH}) + ENDIF (EXISTS ${_CRYPTOPP_VERSION_HEADER}) +ENDIF (CRYPTOPP_INCLUDE_DIR) + +SET (CRYPTOPP_INCLUDE_DIRS ${CRYPTOPP_INCLUDE_DIR}) +SET (CRYPTOPP_LIBRARIES ${CRYPTOPP_LIBRARY}) + +MARK_AS_ADVANCED (CRYPTOPP_INCLUDE_DIR CRYPTOPP_LIBRARY CRYPTOPP_LIBRARY_DEBUG + CRYPTOPP_LIBRARY_RELEASE) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS (CryptoPP REQUIRED_VARS CRYPTOPP_ROOT_DIR + CRYPTOPP_INCLUDE_DIR CRYPTOPP_LIBRARY VERSION_VAR CRYPTOPP_VERSION) diff --git a/mu_coin/balance.cpp b/mu_coin/balance.cpp deleted file mode 100644 index 29a41377..00000000 --- a/mu_coin/balance.cpp +++ /dev/null @@ -1,24 +0,0 @@ -#include -#include - -void mu_coin::balance_memory::operator += (mu_coin::block const & block_a) -{ - coins_m += block_a.coins (); - votes_m += block_a.votes (); -} - -void mu_coin::balance_memory::operator -= (mu_coin::block const & block_a) -{ - coins_m -= block_a.coins (); - votes_m -= block_a.votes (); -} - -boost::multiprecision::uint256_t mu_coin::balance_memory::coins () const -{ - return coins_m; -} - -boost::multiprecision::uint256_t mu_coin::balance_memory::votes () const -{ - return votes_m; -} \ No newline at end of file diff --git a/mu_coin/balance.hpp b/mu_coin/balance.hpp deleted file mode 100644 index a38b0d85..00000000 --- a/mu_coin/balance.hpp +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once -#include -#include - -namespace mu_coin { - class block; - class balance : boost::noncopyable - { - public: - virtual boost::multiprecision::uint256_t coins () const = 0; - virtual boost::multiprecision::uint256_t votes () const = 0; - virtual void operator += (mu_coin::block const &) = 0; - virtual void operator -= (mu_coin::block const &) = 0; - }; - - class balance_memory : public balance - { - public: - void operator += (mu_coin::block const &) override; - void operator -= (mu_coin::block const &) override; - boost::multiprecision::uint256_t coins () const override; - boost::multiprecision::uint256_t votes () const override; - boost::multiprecision::uint256_t coins_m; - boost::multiprecision::uint256_t votes_m; - }; -} \ No newline at end of file diff --git a/mu_coin/block.cpp b/mu_coin/block.cpp index bd678c84..f3aadbd7 100644 --- a/mu_coin/block.cpp +++ b/mu_coin/block.cpp @@ -1,27 +1,77 @@ #include +#include -mu_coin::address mu_coin::block_memory::address () const +mu_coin::entry::entry (boost::multiprecision::uint256_t const & coins_a, boost::multiprecision::uint256_t const & previous_a) : +previous (previous_a), +coins (coins_a) { - return address_m; } -mu_coin::block_hash mu_coin::block_memory::previous () const +void hash_number (CryptoPP::SHA256 & hash_a, boost::multiprecision::uint256_t const & number_a) { - return previous_m; + uint64_t bytes; + uint8_t * first (reinterpret_cast (&bytes)); + uint8_t * last (reinterpret_cast (&bytes + 1)); + bytes = (number_a >> 192).convert_to (); + std::reverse (first, last); + hash_a.Update (first, sizeof (bytes)); + bytes = (number_a >> 128).convert_to (); + std::reverse (first, last); + hash_a.Update (first, sizeof (bytes)); + bytes = (number_a >> 64).convert_to (); + std::reverse (first, last); + hash_a.Update (first, sizeof (bytes)); + bytes = number_a.convert_to (); + std::reverse (first, last); + hash_a.Update (first, sizeof (bytes)); } -boost::multiprecision::uint256_t mu_coin::block_memory::coins () const +boost::multiprecision::uint256_t mu_coin::block::hash () const { - return coins_m; + CryptoPP::SHA256 hash; + uint8_t digest [32]; + for (std::vector ::const_iterator i (inputs.begin ()), j (inputs.end ()); i != j; ++i) + { + hash_number (hash, i->address.number); + hash_number (hash, i->previous); + hash_number (hash, i->coins); + } + for (std::vector ::const_iterator i (outputs.begin ()), j (outputs.end ()); i != j; ++i) + { + hash_number (hash, i->address.number); + hash_number (hash, i->previous); + hash_number (hash, i->coins); + } + hash.Final (digest); + uint64_t bytes; + uint8_t * first (reinterpret_cast (&bytes)); + uint8_t * last (reinterpret_cast (&bytes + 1)); + bytes = *reinterpret_cast (digest); + std::reverse (first, last); + boost::multiprecision::uint256_t result (bytes); + bytes = *reinterpret_cast (digest + 8); + std::reverse (first, last); + result = (result << 64) | bytes; + bytes = *reinterpret_cast (digest + 16); + std::reverse (first, last); + result = (result << 64) | bytes; + bytes = *reinterpret_cast (digest + 24); + std::reverse (first, last); + result = (result << 64) | bytes; + return result; } -boost::multiprecision::uint256_t mu_coin::block_memory::votes () const -{ - return votes_m; -} - -mu_coin::block_memory::block_memory (boost::multiprecision::uint256_t const & coins_a, boost::multiprecision::uint256_t const & votes_a) : -coins_m (coins_a), -votes_m (votes_a) +bool mu_coin::block::balanced () const { + boost::multiprecision::uint256_t input_sum; + for (std::vector ::const_iterator i (inputs.begin ()), j (inputs.end ()); i != j; ++i) + { + input_sum += i->coins; + } + boost::multiprecision::uint256_t output_sum; + for (std::vector ::const_iterator i (outputs.begin ()), j (outputs.end ()); i != j; ++i) + { + output_sum += i->coins; + } + return input_sum == output_sum; } \ No newline at end of file diff --git a/mu_coin/block.hpp b/mu_coin/block.hpp index f38ec3a3..af1a1848 100644 --- a/mu_coin/block.hpp +++ b/mu_coin/block.hpp @@ -1,35 +1,25 @@ #pragma once #include #include +#include namespace mu_coin { - class block_hash + class entry { public: - boost::multiprecision::uint256_t number; + entry () = default; + entry (boost::multiprecision::uint256_t const &, boost::multiprecision::uint256_t const &); + mu_coin::address address; + boost::multiprecision::uint256_t previous; + boost::multiprecision::uint256_t coins; }; - class block { public: - virtual mu_coin::address address () const = 0; - virtual mu_coin::block_hash previous () const = 0; - virtual boost::multiprecision::uint256_t coins () const = 0; - virtual boost::multiprecision::uint256_t votes () const = 0; - }; - - class block_memory : public block - { - public: - block_memory () = default; - block_memory (boost::multiprecision::uint256_t const &, boost::multiprecision::uint256_t const &); - mu_coin::address address () const override; - mu_coin::block_hash previous () const override; - boost::multiprecision::uint256_t coins () const override; - boost::multiprecision::uint256_t votes () const override; - mu_coin::address address_m; - mu_coin::block_hash previous_m; - boost::multiprecision::uint256_t coins_m; - boost::multiprecision::uint256_t votes_m; + std::vector inputs; + std::vector outputs; + bool balanced () const; + boost::multiprecision::uint256_t fee () const; + boost::multiprecision::uint256_t hash () const; }; } \ No newline at end of file diff --git a/mu_coin/delta.cpp b/mu_coin/delta.cpp new file mode 100644 index 00000000..545380f0 --- /dev/null +++ b/mu_coin/delta.cpp @@ -0,0 +1,7 @@ +#include + +mu_coin::delta::delta (boost::multiprecision::uint256_t const & coins_a, boost::multiprecision::uint256_t const & votes_a) : +coins (coins_a), +votes (votes_a) +{ +} \ No newline at end of file diff --git a/mu_coin/delta.hpp b/mu_coin/delta.hpp new file mode 100644 index 00000000..3f70fc8f --- /dev/null +++ b/mu_coin/delta.hpp @@ -0,0 +1,12 @@ +#pragma once +#include + +namespace mu_coin { + class delta + { + public: + delta (boost::multiprecision::uint256_t const &, boost::multiprecision::uint256_t const &); + boost::multiprecision::uint256_t coins; + boost::multiprecision::uint256_t votes; + }; +} \ No newline at end of file diff --git a/mu_coin/ledger.cpp b/mu_coin/ledger.cpp index 807c9723..329a3abd 100644 --- a/mu_coin/ledger.cpp +++ b/mu_coin/ledger.cpp @@ -1,14 +1,14 @@ #include +#include -mu_coin::balance & mu_coin::ledger_memory::balance (mu_coin::address const & address_a) +mu_coin::block * mu_coin::ledger::previous (mu_coin::address const & address_a) { + assert (has_balance (address_a)); auto existing (entries.find (address_a)); - if (existing != entries.end ()) - { - return *existing->second; - } - else - { - return empty_balance; - } + return existing->second; +} + +bool mu_coin::ledger::has_balance (mu_coin::address const & address_a) +{ + return entries.find (address_a) != entries.end (); } \ No newline at end of file diff --git a/mu_coin/ledger.hpp b/mu_coin/ledger.hpp index 6179be28..906f3047 100644 --- a/mu_coin/ledger.hpp +++ b/mu_coin/ledger.hpp @@ -1,20 +1,14 @@ #pragma once -#include #include #include namespace mu_coin { - class ledger - { - public: - virtual mu_coin::balance & balance (mu_coin::address const &) = 0; - }; - - class ledger_memory : public ledger - { - public: - mu_coin::balance & balance (mu_coin::address const &) override; - mu_coin::balance_memory empty_balance; - std::unordered_map entries; - }; +class block; +class ledger +{ +public: + mu_coin::block * previous (mu_coin::address const &); + bool has_balance (mu_coin::address const &); + std::unordered_map entries; +}; } \ No newline at end of file diff --git a/mu_coin_test/balance.cpp b/mu_coin_test/balance.cpp deleted file mode 100644 index 49fe5bee..00000000 --- a/mu_coin_test/balance.cpp +++ /dev/null @@ -1,30 +0,0 @@ -#include -#include -#include - -TEST (balance, balance_memory) -{ - mu_coin::balance_memory balance; - ASSERT_EQ (0, balance.coins ()); - ASSERT_EQ (0, balance.votes ()); -} - -TEST (balance, balance_add) -{ - mu_coin::balance_memory balance; - mu_coin::block_memory block (100, 200); - balance += block; - ASSERT_EQ (100, balance.coins ()); - ASSERT_EQ (200, balance.votes ()); -} - -TEST (balance, balance_subtract) -{ - mu_coin::balance_memory balance; - mu_coin::block_memory block1 (400, 500); - balance += block1; - mu_coin::block_memory block2 (200, 100); - balance -= block2; - ASSERT_EQ (200, balance.coins ()); - ASSERT_EQ (400, balance.votes ()); -} \ No newline at end of file diff --git a/mu_coin_test/block.cpp b/mu_coin_test/block.cpp index 1809f9f7..aefd96a4 100644 --- a/mu_coin_test/block.cpp +++ b/mu_coin_test/block.cpp @@ -1,9 +1,13 @@ #include #include -TEST (block, block_memory) +TEST (block, empty) { - mu_coin::block_memory block; - ASSERT_EQ (0, block.coins ()); - ASSERT_EQ (0, block.votes ()); + mu_coin::block block; + ASSERT_EQ (0, block.inputs.size ()); + ASSERT_EQ (0, block.outputs.size ()); + ASSERT_TRUE (block.balanced ()); + boost::multiprecision::uint256_t hash (block.hash ()); + std::string str (hash.convert_to ()); + ASSERT_EQ (boost::multiprecision::uint256_t ("0xE3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855"), hash); } \ No newline at end of file diff --git a/mu_coin_test/ledger.cpp b/mu_coin_test/ledger.cpp index 1b2d0399..c9101c4c 100644 --- a/mu_coin_test/ledger.cpp +++ b/mu_coin_test/ledger.cpp @@ -5,25 +5,6 @@ TEST (ledger, empty) { - mu_coin::ledger_memory ledger; - mu_coin::balance & balance (ledger.balance (mu_coin::address (0))); - ASSERT_EQ (0, balance.coins ()); - ASSERT_EQ (0, balance.votes ()); -} - -TEST (ledger, separate_empty) -{ - mu_coin::ledger_memory ledger; - mu_coin::balance & balance1 (ledger.balance (mu_coin::address (0))); - ASSERT_EQ (0, balance1.coins ()); - ASSERT_EQ (0, balance1.votes ()); - mu_coin::balance & balance2 (ledger.balance (mu_coin::address (0))); - ASSERT_EQ (0, balance2.coins ()); - ASSERT_EQ (0, balance2.votes ()); - mu_coin::block_memory block1 (100, 200); - balance1 += block1; - ASSERT_EQ (100, balance1.coins ()); - ASSERT_EQ (200, balance1.votes ()); - ASSERT_EQ (0, balance2.coins ()); - ASSERT_EQ (0, balance2.votes ()); + mu_coin::ledger ledger; + ASSERT_FALSE (ledger.has_balance (mu_coin::address (0))); } \ No newline at end of file