Adding and changing a bunch of functionality.

This commit is contained in:
clemahieu 2014-05-07 23:34:38 -05:00
commit 31818ef434
13 changed files with 237 additions and 172 deletions

View file

@ -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)
target_link_libraries (mu_coin_test ${GTEST_LIBRARY} ${GTEST_MAIN_LIBRARY} ${CRYPTOPP_LIBRARY} mu_coin)

108
FindCryptoPP.cmake Normal file
View file

@ -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)

View file

@ -1,24 +0,0 @@
#include <mu_coin/balance.hpp>
#include <mu_coin/block.hpp>
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;
}

View file

@ -1,26 +0,0 @@
#pragma once
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/noncopyable.hpp>
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;
};
}

View file

@ -1,27 +1,77 @@
#include <mu_coin/block.hpp>
#include <cryptopp/sha.h>
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 <uint8_t *> (&bytes));
uint8_t * last (reinterpret_cast <uint8_t *> (&bytes + 1));
bytes = (number_a >> 192).convert_to <uint64_t> ();
std::reverse (first, last);
hash_a.Update (first, sizeof (bytes));
bytes = (number_a >> 128).convert_to <uint64_t> ();
std::reverse (first, last);
hash_a.Update (first, sizeof (bytes));
bytes = (number_a >> 64).convert_to <uint64_t> ();
std::reverse (first, last);
hash_a.Update (first, sizeof (bytes));
bytes = number_a.convert_to <uint64_t> ();
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 <mu_coin::entry>::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 <mu_coin::entry>::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 <uint8_t *> (&bytes));
uint8_t * last (reinterpret_cast <uint8_t *> (&bytes + 1));
bytes = *reinterpret_cast <uint64_t *> (digest);
std::reverse (first, last);
boost::multiprecision::uint256_t result (bytes);
bytes = *reinterpret_cast <uint64_t *> (digest + 8);
std::reverse (first, last);
result = (result << 64) | bytes;
bytes = *reinterpret_cast <uint64_t *> (digest + 16);
std::reverse (first, last);
result = (result << 64) | bytes;
bytes = *reinterpret_cast <uint64_t *> (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 <mu_coin::entry>::const_iterator i (inputs.begin ()), j (inputs.end ()); i != j; ++i)
{
input_sum += i->coins;
}
boost::multiprecision::uint256_t output_sum;
for (std::vector <mu_coin::entry>::const_iterator i (outputs.begin ()), j (outputs.end ()); i != j; ++i)
{
output_sum += i->coins;
}
return input_sum == output_sum;
}

View file

@ -1,35 +1,25 @@
#pragma once
#include <boost/multiprecision/cpp_int.hpp>
#include <mu_coin/address.hpp>
#include <mu_coin/delta.hpp>
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 <entry> inputs;
std::vector <entry> outputs;
bool balanced () const;
boost::multiprecision::uint256_t fee () const;
boost::multiprecision::uint256_t hash () const;
};
}

7
mu_coin/delta.cpp Normal file
View file

@ -0,0 +1,7 @@
#include <mu_coin/delta.hpp>
mu_coin::delta::delta (boost::multiprecision::uint256_t const & coins_a, boost::multiprecision::uint256_t const & votes_a) :
coins (coins_a),
votes (votes_a)
{
}

12
mu_coin/delta.hpp Normal file
View file

@ -0,0 +1,12 @@
#pragma once
#include <boost/multiprecision/cpp_int.hpp>
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;
};
}

View file

@ -1,14 +1,14 @@
#include <mu_coin/ledger.hpp>
#include <mu_coin/block.hpp>
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 ();
}

View file

@ -1,20 +1,14 @@
#pragma once
#include <mu_coin/balance.hpp>
#include <mu_coin/address.hpp>
#include <unordered_map>
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 <mu_coin::address, mu_coin::balance_memory *> entries;
};
class block;
class ledger
{
public:
mu_coin::block * previous (mu_coin::address const &);
bool has_balance (mu_coin::address const &);
std::unordered_map <mu_coin::address, mu_coin::block *> entries;
};
}

View file

@ -1,30 +0,0 @@
#include <gtest/gtest.h>
#include <mu_coin/balance.hpp>
#include <mu_coin/block.hpp>
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 ());
}

View file

@ -1,9 +1,13 @@
#include <gtest/gtest.h>
#include <mu_coin/block.hpp>
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 <std::string> ());
ASSERT_EQ (boost::multiprecision::uint256_t ("0xE3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855"), hash);
}

View file

@ -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)));
}