diff options
author | kenshi84 <kenshi84@protonmail.ch> | 2017-01-27 00:07:23 +0900 |
---|---|---|
committer | kenshi84 <kenshi84@protonmail.ch> | 2017-02-08 22:45:15 +0900 |
commit | 8027ce0c75f882de0523e668defa0bc3c8564e96 (patch) | |
tree | 40066ffa7c7afb28907291c93863d8cfdb14920c /src/cryptonote_core | |
parent | Merge pull request #1679 (diff) | |
download | monero-8027ce0c75f882de0523e668defa0bc3c8564e96.tar.xz |
extract some basic code from libcryptonote_core into libcryptonote_basic
Diffstat (limited to 'src/cryptonote_core')
30 files changed, 616 insertions, 5388 deletions
diff --git a/src/cryptonote_core/CMakeLists.txt b/src/cryptonote_core/CMakeLists.txt index ad1745b7f..a5f25041b 100644 --- a/src/cryptonote_core/CMakeLists.txt +++ b/src/cryptonote_core/CMakeLists.txt @@ -27,38 +27,19 @@ # THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. set(cryptonote_core_sources - account.cpp blockchain.cpp - checkpoints.cpp - cryptonote_basic_impl.cpp cryptonote_core.cpp - cryptonote_format_utils.cpp - difficulty.cpp - miner.cpp tx_pool.cpp - hardfork.cpp) + cryptonote_tx_utils.cpp) set(cryptonote_core_headers) set(cryptonote_core_private_headers - account.h - account_boost_serialization.h blockchain_storage_boost_serialization.h blockchain.h - checkpoints.h - connection_context.h - cryptonote_basic.h - cryptonote_basic_impl.h - cryptonote_boost_serialization.h cryptonote_core.h - cryptonote_format_utils.h - cryptonote_stat_info.h - difficulty.h - miner.h - tx_extra.h tx_pool.h - verification_context.h - hardfork.h) + cryptonote_tx_utils.h) if(PER_BLOCK_CHECKPOINT) set(Blocks "blocks") diff --git a/src/cryptonote_core/account.cpp b/src/cryptonote_core/account.cpp deleted file mode 100644 index 8f2db6863..000000000 --- a/src/cryptonote_core/account.cpp +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright (c) 2014-2016, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - -#include <fstream> - -#include "include_base_utils.h" -#include "account.h" -#include "warnings.h" -#include "crypto/crypto.h" -extern "C" -{ -#include "crypto/keccak.h" -} -#include "cryptonote_core/cryptonote_basic_impl.h" -#include "cryptonote_core/cryptonote_format_utils.h" - -#undef MONERO_DEFAULT_LOG_CATEGORY -#define MONERO_DEFAULT_LOG_CATEGORY "account" - -using namespace std; - -DISABLE_VS_WARNINGS(4244 4345) - - namespace cryptonote -{ - //----------------------------------------------------------------- - account_base::account_base() - { - set_null(); - } - //----------------------------------------------------------------- - void account_base::set_null() - { - m_keys = account_keys(); - } - //----------------------------------------------------------------- - void account_base::forget_spend_key() - { - m_keys.m_spend_secret_key = crypto::secret_key(); - } - //----------------------------------------------------------------- - crypto::secret_key account_base::generate(const crypto::secret_key& recovery_key, bool recover, bool two_random) - { - crypto::secret_key first = generate_keys(m_keys.m_account_address.m_spend_public_key, m_keys.m_spend_secret_key, recovery_key, recover); - - // rng for generating second set of keys is hash of first rng. means only one set of electrum-style words needed for recovery - crypto::secret_key second; - keccak((uint8_t *)&m_keys.m_spend_secret_key, sizeof(crypto::secret_key), (uint8_t *)&second, sizeof(crypto::secret_key)); - - generate_keys(m_keys.m_account_address.m_view_public_key, m_keys.m_view_secret_key, second, two_random ? false : true); - - struct tm timestamp = {0}; - timestamp.tm_year = 2014 - 1900; // year 2014 - timestamp.tm_mon = 6 - 1; // month june - timestamp.tm_mday = 8; // 8th of june - timestamp.tm_hour = 0; - timestamp.tm_min = 0; - timestamp.tm_sec = 0; - - if (recover) - { - m_creation_timestamp = mktime(×tamp); - if (m_creation_timestamp == (uint64_t)-1) // failure - m_creation_timestamp = 0; // lowest value - } - else - { - m_creation_timestamp = time(NULL); - } - return first; - } - //----------------------------------------------------------------- - void account_base::create_from_keys(const cryptonote::account_public_address& address, const crypto::secret_key& spendkey, const crypto::secret_key& viewkey) - { - m_keys.m_account_address = address; - m_keys.m_spend_secret_key = spendkey; - m_keys.m_view_secret_key = viewkey; - - struct tm timestamp = {0}; - timestamp.tm_year = 2014 - 1900; // year 2014 - timestamp.tm_mon = 4 - 1; // month april - timestamp.tm_mday = 15; // 15th of april - timestamp.tm_hour = 0; - timestamp.tm_min = 0; - timestamp.tm_sec = 0; - - m_creation_timestamp = mktime(×tamp); - if (m_creation_timestamp == (uint64_t)-1) // failure - m_creation_timestamp = 0; // lowest value - } - //----------------------------------------------------------------- - void account_base::create_from_viewkey(const cryptonote::account_public_address& address, const crypto::secret_key& viewkey) - { - crypto::secret_key fake; - memset(&fake, 0, sizeof(fake)); - create_from_keys(address, fake, viewkey); - } - //----------------------------------------------------------------- - const account_keys& account_base::get_keys() const - { - return m_keys; - } - //----------------------------------------------------------------- - std::string account_base::get_public_address_str(bool testnet) const - { - //TODO: change this code into base 58 - return get_account_address_as_str(testnet, m_keys.m_account_address); - } - //----------------------------------------------------------------- - std::string account_base::get_public_integrated_address_str(const crypto::hash8 &payment_id, bool testnet) const - { - //TODO: change this code into base 58 - return get_account_integrated_address_as_str(testnet, m_keys.m_account_address, payment_id); - } - //----------------------------------------------------------------- -} diff --git a/src/cryptonote_core/account.h b/src/cryptonote_core/account.h deleted file mode 100644 index 41a119b07..000000000 --- a/src/cryptonote_core/account.h +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright (c) 2014-2016, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - -#pragma once - -#include "cryptonote_core/cryptonote_basic.h" -#include "crypto/crypto.h" -#include "serialization/keyvalue_serialization.h" - -namespace cryptonote -{ - - struct account_keys - { - account_public_address m_account_address; - crypto::secret_key m_spend_secret_key; - crypto::secret_key m_view_secret_key; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(m_account_address) - KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE(m_spend_secret_key) - KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE(m_view_secret_key) - END_KV_SERIALIZE_MAP() - }; - - /************************************************************************/ - /* */ - /************************************************************************/ - class account_base - { - public: - account_base(); - crypto::secret_key generate(const crypto::secret_key& recovery_key = crypto::secret_key(), bool recover = false, bool two_random = false); - void create_from_keys(const cryptonote::account_public_address& address, const crypto::secret_key& spendkey, const crypto::secret_key& viewkey); - void create_from_viewkey(const cryptonote::account_public_address& address, const crypto::secret_key& viewkey); - const account_keys& get_keys() const; - std::string get_public_address_str(bool testnet) const; - std::string get_public_integrated_address_str(const crypto::hash8 &payment_id, bool testnet) const; - - uint64_t get_createtime() const { return m_creation_timestamp; } - void set_createtime(uint64_t val) { m_creation_timestamp = val; } - - bool load(const std::string& file_path); - bool store(const std::string& file_path); - - void forget_spend_key(); - - template <class t_archive> - inline void serialize(t_archive &a, const unsigned int /*ver*/) - { - a & m_keys; - a & m_creation_timestamp; - } - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(m_keys) - KV_SERIALIZE(m_creation_timestamp) - END_KV_SERIALIZE_MAP() - - private: - void set_null(); - account_keys m_keys; - uint64_t m_creation_timestamp; - }; -} diff --git a/src/cryptonote_core/account_boost_serialization.h b/src/cryptonote_core/account_boost_serialization.h deleted file mode 100644 index 4151d9b50..000000000 --- a/src/cryptonote_core/account_boost_serialization.h +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) 2014-2016, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - -#pragma once - -#include "account.h" -#include "cryptonote_core/cryptonote_boost_serialization.h" - -//namespace cryptonote { -namespace boost -{ - namespace serialization - { - template <class Archive> - inline void serialize(Archive &a, cryptonote::account_keys &x, const boost::serialization::version_type ver) - { - a & x.m_account_address; - a & x.m_spend_secret_key; - a & x.m_view_secret_key; - } - - template <class Archive> - inline void serialize(Archive &a, cryptonote::account_public_address &x, const boost::serialization::version_type ver) - { - a & x.m_spend_public_key; - a & x.m_view_public_key; - } - - } -} diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index b344c5597..a81286632 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -34,14 +34,13 @@ #include <boost/range/adaptor/reversed.hpp> #include "include_base_utils.h" -#include "cryptonote_basic_impl.h" +#include "cryptonote_basic/cryptonote_basic_impl.h" #include "tx_pool.h" #include "blockchain.h" #include "blockchain_db/blockchain_db.h" -#include "cryptonote_format_utils.h" -#include "cryptonote_boost_serialization.h" +#include "cryptonote_basic/cryptonote_boost_serialization.h" #include "cryptonote_config.h" -#include "miner.h" +#include "cryptonote_basic/miner.h" #include "misc_language.h" #include "profile_tools.h" #include "file_io_utils.h" @@ -49,8 +48,8 @@ #include "common/boost_serialization_helper.h" #include "warnings.h" #include "crypto/hash.h" -#include "cryptonote_core/checkpoints.h" -#include "cryptonote_core/cryptonote_core.h" +#include "cryptonote_basic/checkpoints.h" +#include "cryptonote_core.h" #include "ringct/rctSigs.h" #include "common/perf_timer.h" #if defined(PER_BLOCK_CHECKPOINT) diff --git a/src/cryptonote_core/blockchain.h b/src/cryptonote_core/blockchain.h index cd452faf4..c806c3505 100644 --- a/src/cryptonote_core/blockchain.h +++ b/src/cryptonote_core/blockchain.h @@ -42,16 +42,16 @@ #include "syncobj.h" #include "string_tools.h" -#include "cryptonote_basic.h" +#include "cryptonote_basic/cryptonote_basic.h" #include "common/util.h" #include "cryptonote_protocol/cryptonote_protocol_defs.h" #include "rpc/core_rpc_server_commands_defs.h" -#include "difficulty.h" -#include "cryptonote_core/cryptonote_format_utils.h" -#include "verification_context.h" +#include "cryptonote_basic/difficulty.h" +#include "cryptonote_tx_utils.h" +#include "cryptonote_basic/verification_context.h" #include "crypto/hash.h" -#include "checkpoints.h" -#include "hardfork.h" +#include "cryptonote_basic/checkpoints.h" +#include "cryptonote_basic/hardfork.h" #include "blockchain_db/blockchain_db.h" namespace cryptonote diff --git a/src/cryptonote_core/checkpoints.cpp b/src/cryptonote_core/checkpoints.cpp deleted file mode 100644 index 3cf804ede..000000000 --- a/src/cryptonote_core/checkpoints.cpp +++ /dev/null @@ -1,368 +0,0 @@ -// Copyright (c) 2014-2016, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - -#include "include_base_utils.h" - -using namespace epee; - -#include "checkpoints.h" - -#include "common/dns_utils.h" -#include "include_base_utils.h" -#include <sstream> -#include <random> - -#undef MONERO_DEFAULT_LOG_CATEGORY -#define MONERO_DEFAULT_LOG_CATEGORY "checkpoints" - -namespace -{ - bool dns_records_match(const std::vector<std::string>& a, const std::vector<std::string>& b) - { - if (a.size() != b.size()) return false; - - for (const auto& record_in_a : a) - { - bool ok = false; - for (const auto& record_in_b : b) - { - if (record_in_a == record_in_b) - { - ok = true; - break; - } - } - if (!ok) return false; - } - - return true; - } -} // anonymous namespace - -namespace cryptonote -{ - //--------------------------------------------------------------------------- - checkpoints::checkpoints() - { - } - //--------------------------------------------------------------------------- - bool checkpoints::add_checkpoint(uint64_t height, const std::string& hash_str) - { - crypto::hash h = null_hash; - bool r = epee::string_tools::parse_tpod_from_hex_string(hash_str, h); - CHECK_AND_ASSERT_MES(r, false, "Failed to parse checkpoint hash string into binary representation!"); - - // return false if adding at a height we already have AND the hash is different - if (m_points.count(height)) - { - CHECK_AND_ASSERT_MES(h == m_points[height], false, "Checkpoint at given height already exists, and hash for new checkpoint was different!"); - } - m_points[height] = h; - return true; - } - //--------------------------------------------------------------------------- - bool checkpoints::is_in_checkpoint_zone(uint64_t height) const - { - return !m_points.empty() && (height <= (--m_points.end())->first); - } - //--------------------------------------------------------------------------- - bool checkpoints::check_block(uint64_t height, const crypto::hash& h, bool& is_a_checkpoint) const - { - auto it = m_points.find(height); - is_a_checkpoint = it != m_points.end(); - if(!is_a_checkpoint) - return true; - - if(it->second == h) - { - MINFO("CHECKPOINT PASSED FOR HEIGHT " << height << " " << h); - return true; - }else - { - MWARNING("CHECKPOINT FAILED FOR HEIGHT " << height << ". EXPECTED HASH: " << it->second << ", FETCHED HASH: " << h); - return false; - } - } - //--------------------------------------------------------------------------- - bool checkpoints::check_block(uint64_t height, const crypto::hash& h) const - { - bool ignored; - return check_block(height, h, ignored); - } - //--------------------------------------------------------------------------- - //FIXME: is this the desired behavior? - bool checkpoints::is_alternative_block_allowed(uint64_t blockchain_height, uint64_t block_height) const - { - if (0 == block_height) - return false; - - auto it = m_points.upper_bound(blockchain_height); - // Is blockchain_height before the first checkpoint? - if (it == m_points.begin()) - return true; - - --it; - uint64_t checkpoint_height = it->first; - return checkpoint_height < block_height; - } - //--------------------------------------------------------------------------- - uint64_t checkpoints::get_max_height() const - { - std::map< uint64_t, crypto::hash >::const_iterator highest = - std::max_element( m_points.begin(), m_points.end(), - ( boost::bind(&std::map< uint64_t, crypto::hash >::value_type::first, _1) < - boost::bind(&std::map< uint64_t, crypto::hash >::value_type::first, _2 ) ) ); - return highest->first; - } - //--------------------------------------------------------------------------- - const std::map<uint64_t, crypto::hash>& checkpoints::get_points() const - { - return m_points; - } - - bool checkpoints::check_for_conflicts(const checkpoints& other) const - { - for (auto& pt : other.get_points()) - { - if (m_points.count(pt.first)) - { - CHECK_AND_ASSERT_MES(pt.second == m_points.at(pt.first), false, "Checkpoint at given height already exists, and hash for new checkpoint was different!"); - } - } - return true; - } - - bool checkpoints::init_default_checkpoints() - { - ADD_CHECKPOINT(1, "771fbcd656ec1464d3a02ead5e18644030007a0fc664c0a964d30922821a8148"); - ADD_CHECKPOINT(10, "c0e3b387e47042f72d8ccdca88071ff96bff1ac7cde09ae113dbb7ad3fe92381"); - ADD_CHECKPOINT(100, "ac3e11ca545e57c49fca2b4e8c48c03c23be047c43e471e1394528b1f9f80b2d"); - ADD_CHECKPOINT(1000, "5acfc45acffd2b2e7345caf42fa02308c5793f15ec33946e969e829f40b03876"); - ADD_CHECKPOINT(10000, "c758b7c81f928be3295d45e230646de8b852ec96a821eac3fea4daf3fcac0ca2"); - ADD_CHECKPOINT(22231, "7cb10e29d67e1c069e6e11b17d30b809724255fee2f6868dc14cfc6ed44dfb25"); - ADD_CHECKPOINT(29556, "53c484a8ed91e4da621bb2fa88106dbde426fe90d7ef07b9c1e5127fb6f3a7f6"); - ADD_CHECKPOINT(50000, "0fe8758ab06a8b9cb35b7328fd4f757af530a5d37759f9d3e421023231f7b31c"); - ADD_CHECKPOINT(80000, "a62dcd7b536f22e003ebae8726e9e7276f63d594e264b6f0cd7aab27b66e75e3"); - ADD_CHECKPOINT(202612, "bbd604d2ba11ba27935e006ed39c9bfdd99b76bf4a50654bc1e1e61217962698"); - ADD_CHECKPOINT(202613, "e2aa337e78df1f98f462b3b1e560c6b914dec47b610698b7b7d1e3e86b6197c2"); - ADD_CHECKPOINT(202614, "c29e3dc37d8da3e72e506e31a213a58771b24450144305bcba9e70fa4d6ea6fb"); - ADD_CHECKPOINT(205000, "5d3d7a26e6dc7535e34f03def711daa8c263785f73ec1fadef8a45880fde8063"); - ADD_CHECKPOINT(220000, "9613f455933c00e3e33ac315cc6b455ee8aa0c567163836858c2d9caff111553"); - ADD_CHECKPOINT(230300, "bae7a80c46859db355556e3a9204a337ae8f24309926a1312323fdecf1920e61"); - ADD_CHECKPOINT(230700, "93e631240ceac831da1aebfc5dac8f722c430463024763ebafa888796ceaeedf"); - ADD_CHECKPOINT(231350, "b5add137199b820e1ea26640e5c3e121fd85faa86a1e39cf7e6cc097bdeb1131"); - ADD_CHECKPOINT(232150, "955de8e6b6508af2c24f7334f97beeea651d78e9ade3ab18fec3763be3201aa8"); - ADD_CHECKPOINT(249380, "654fb0a81ce3e5caf7e3264a70f447d4bd07586c08fa50f6638cc54da0a52b2d"); - ADD_CHECKPOINT(460000, "75037a7aed3e765db96c75bcf908f59d690a5f3390baebb9edeafd336a1c4831"); - ADD_CHECKPOINT(500000, "2428f0dbe49796be05ed81b347f53e1f7f44aed0abf641446ec2b94cae066b02"); - ADD_CHECKPOINT(600000, "f5828ebf7d7d1cb61762c4dfe3ccf4ecab2e1aad23e8113668d981713b7a54c5"); - ADD_CHECKPOINT(700000, "12be9b3d210b93f574d2526abb9c1ab2a881b479131fd0d4f7dac93875f503cd"); - ADD_CHECKPOINT(825000, "56503f9ad766774b575be3aff73245e9d159be88132c93d1754764f28da2ff60"); - ADD_CHECKPOINT(900000, "d9958d0e7dcf91a5a7b11de225927bf7efc6eb26240315ce12372be902cc1337"); - ADD_CHECKPOINT(913193, "5292d5d56f6ba4de33a58d9a34d263e2cb3c6fee0aed2286fd4ac7f36d53c85f"); - ADD_CHECKPOINT(1000000, "a886ef5149902d8342475fee9bb296341b891ac67c4842f47a833f23c00ed721"); - ADD_CHECKPOINT(1100000, "3fd720c5c8b3072fc1ccda922dec1ef25f9ed88a1e6ad4103d0fe00b180a5903"); - ADD_CHECKPOINT(1150000, "1dd16f626d18e1e988490dfd06de5920e22629c972c58b4d8daddea0038627b2"); - ADD_CHECKPOINT(1200000, "fa7d13a90850882060479d100141ff84286599ae39c3277c8ea784393f882d1f"); - - - return true; - } - - bool checkpoints::load_checkpoints_from_json(const std::string json_hashfile_fullpath) - { - boost::system::error_code errcode; - if (! (boost::filesystem::exists(json_hashfile_fullpath, errcode))) - { - LOG_PRINT_L1("Blockchain checkpoints file not found"); - return true; - } - - LOG_PRINT_L1("Adding checkpoints from blockchain hashfile"); - - uint64_t prev_max_height = get_max_height(); - LOG_PRINT_L1("Hard-coded max checkpoint height is " << prev_max_height); - t_hash_json hashes; - epee::serialization::load_t_from_json_file(hashes, json_hashfile_fullpath); - for (std::vector<t_hashline>::const_iterator it = hashes.hashlines.begin(); it != hashes.hashlines.end(); ) - { - uint64_t height; - height = it->height; - if (height <= prev_max_height) { - LOG_PRINT_L1("ignoring checkpoint height " << height); - } else { - std::string blockhash = it->hash; - LOG_PRINT_L1("Adding checkpoint height " << height << ", hash=" << blockhash); - ADD_CHECKPOINT(height, blockhash); - } - ++it; - } - - return true; - } - - bool checkpoints::load_checkpoints_from_dns(bool testnet) - { - // All four MoneroPulse domains have DNSSEC on and valid - static const std::vector<std::string> dns_urls = { "checkpoints.moneropulse.se" - , "checkpoints.moneropulse.org" - , "checkpoints.moneropulse.net" - , "checkpoints.moneropulse.co" - }; - - static const std::vector<std::string> testnet_dns_urls = { "testpoints.moneropulse.se" - , "testpoints.moneropulse.org" - , "testpoints.moneropulse.net" - , "testpoints.moneropulse.co" - }; - - std::vector<std::vector<std::string> > records; - records.resize(dns_urls.size()); - - std::random_device rd; - std::mt19937 gen(rd()); - std::uniform_int_distribution<int> dis(0, dns_urls.size() - 1); - size_t first_index = dis(gen); - - bool avail, valid; - size_t cur_index = first_index; - do - { - std::string url; - if (testnet) - { - url = testnet_dns_urls[cur_index]; - } - else - { - url = dns_urls[cur_index]; - } - - records[cur_index] = tools::DNSResolver::instance().get_txt_record(url, avail, valid); - if (!avail) - { - records[cur_index].clear(); - LOG_PRINT_L2("DNSSEC not available for checkpoint update at URL: " << url << ", skipping."); - } - if (!valid) - { - records[cur_index].clear(); - LOG_PRINT_L2("DNSSEC validation failed for checkpoint update at URL: " << url << ", skipping."); - } - - cur_index++; - if (cur_index == dns_urls.size()) - { - cur_index = 0; - } - records[cur_index].clear(); - } while (cur_index != first_index); - - size_t num_valid_records = 0; - - for( const auto& record_set : records) - { - if (record_set.size() != 0) - { - num_valid_records++; - } - } - - if (num_valid_records < 2) - { - LOG_PRINT_L0("WARNING: no two valid MoneroPulse DNS checkpoint records were received"); - return true; - } - - int good_records_index = -1; - for (size_t i = 0; i < records.size() - 1; ++i) - { - if (records[i].size() == 0) continue; - - for (size_t j = i + 1; j < records.size(); ++j) - { - if (dns_records_match(records[i], records[j])) - { - good_records_index = i; - break; - } - } - if (good_records_index >= 0) break; - } - - if (good_records_index < 0) - { - LOG_PRINT_L0("WARNING: no two MoneroPulse DNS checkpoint records matched"); - return true; - } - - for (auto& record : records[good_records_index]) - { - auto pos = record.find(":"); - if (pos != std::string::npos) - { - uint64_t height; - crypto::hash hash; - - // parse the first part as uint64_t, - // if this fails move on to the next record - std::stringstream ss(record.substr(0, pos)); - if (!(ss >> height)) - { - continue; - } - - // parse the second part as crypto::hash, - // if this fails move on to the next record - std::string hashStr = record.substr(pos + 1); - if (!epee::string_tools::parse_tpod_from_hex_string(hashStr, hash)) - { - continue; - } - - ADD_CHECKPOINT(height, hashStr); - } - } - return true; - } - - bool checkpoints::load_new_checkpoints(const std::string json_hashfile_fullpath, bool testnet, bool dns) - { - bool result; - - result = load_checkpoints_from_json(json_hashfile_fullpath); - if (dns) - { - result &= load_checkpoints_from_dns(testnet); - } - - return result; - } -} diff --git a/src/cryptonote_core/checkpoints.h b/src/cryptonote_core/checkpoints.h deleted file mode 100644 index 71727753e..000000000 --- a/src/cryptonote_core/checkpoints.h +++ /dev/null @@ -1,217 +0,0 @@ -// Copyright (c) 2014-2016, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - -#pragma once -#include <map> -#include <vector> -#include "cryptonote_basic_impl.h" -#include "misc_log_ex.h" -#include "storages/portable_storage_template_helper.h" // epee json include - -#define ADD_CHECKPOINT(h, hash) CHECK_AND_ASSERT(add_checkpoint(h, hash), false); -#define JSON_HASH_FILE_NAME "checkpoints.json" - - -namespace cryptonote -{ - /** - * @brief A container for blockchain checkpoints - * - * A checkpoint is a pre-defined hash for the block at a given height. - * Some of these are compiled-in, while others can be loaded at runtime - * either from a json file or via DNS from a checkpoint-hosting server. - */ - class checkpoints - { - public: - - /** - * @brief default constructor - */ - checkpoints(); - - /** - * @brief adds a checkpoint to the container - * - * @param height the height of the block the checkpoint is for - * @param hash_str the hash of the block, as a string - * - * @return false if parsing the hash fails, or if the height is a duplicate - * AND the existing checkpoint hash does not match the new one, - * otherwise returns true - */ - bool add_checkpoint(uint64_t height, const std::string& hash_str); - - /** - * @brief checks if there is a checkpoint in the future - * - * This function checks if the height passed is lower than the highest - * checkpoint. - * - * @param height the height to check against - * - * @return false if no checkpoints, otherwise returns whether or not - * the height passed is lower than the highest checkpoint. - */ - bool is_in_checkpoint_zone(uint64_t height) const; - - /** - * @brief checks if the given height and hash agree with the checkpoints - * - * This function checks if the given height and hash exist in the - * checkpoints container. If so, it returns whether or not the passed - * parameters match the stored values. - * - * @param height the height to be checked - * @param h the hash to be checked - * @param is_a_checkpoint return-by-reference if there is a checkpoint at the given height - * - * @return true if there is no checkpoint at the given height, - * true if the passed parameters match the stored checkpoint, - * false otherwise - */ - bool check_block(uint64_t height, const crypto::hash& h, bool& is_a_checkpoint) const; - - /** - * @overload - */ - bool check_block(uint64_t height, const crypto::hash& h) const; - - /** - * @brief checks if alternate chain blocks should be kept for a given height - * - * this basically says if the blockchain is smaller than the first - * checkpoint then alternate blocks are allowed. Alternatively, if the - * last checkpoint *before* the end of the current chain is also before - * the block to be added, then this is fine. - * - * @param blockchain_height the current blockchain height - * @param block_height the height of the block to be added as alternate - * - * @return true if alternate blocks are allowed given the parameters, - * otherwise false - */ - bool is_alternative_block_allowed(uint64_t blockchain_height, uint64_t block_height) const; - - /** - * @brief gets the highest checkpoint height - * - * @return the height of the highest checkpoint - */ - uint64_t get_max_height() const; - - /** - * @brief gets the checkpoints container - * - * @return a const reference to the checkpoints container - */ - const std::map<uint64_t, crypto::hash>& get_points() const; - - /** - * @brief checks if our checkpoints container conflicts with another - * - * A conflict refers to a case where both checkpoint sets have a checkpoint - * for a specific height but their hashes for that height do not match. - * - * @param other the other checkpoints instance to check against - * - * @return false if any conflict is found, otherwise true - */ - bool check_for_conflicts(const checkpoints& other) const; - - /** - * @brief loads the default main chain checkpoints - * - * @return true unless adding a checkpoint fails - */ - bool init_default_checkpoints(); - - /** - * @brief load new checkpoints - * - * Loads new checkpoints from the specified json file, as well as - * (optionally) from DNS. - * - * @param json_hashfile_fullpath path to the json checkpoints file - * @param testnet whether to load testnet checkpoints or mainnet - * @param dns whether or not to load DNS checkpoints - * - * @return true if loading successful and no conflicts - */ - bool load_new_checkpoints(const std::string json_hashfile_fullpath, bool testnet=false, bool dns=true); - - /** - * @brief load new checkpoints from json - * - * @param json_hashfile_fullpath path to the json checkpoints file - * - * @return true if loading successful and no conflicts - */ - bool load_checkpoints_from_json(const std::string json_hashfile_fullpath); - - /** - * @brief load new checkpoints from DNS - * - * @param testnet whether to load testnet checkpoints or mainnet - * - * @return true if loading successful and no conflicts - */ - bool load_checkpoints_from_dns(bool testnet = false); - - private: - - - /** - * @brief struct for loading a checkpoint from json - */ - struct t_hashline - { - uint64_t height; //!< the height of the checkpoint - std::string hash; //!< the hash for the checkpoint - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(height) - KV_SERIALIZE(hash) - END_KV_SERIALIZE_MAP() - }; - - /** - * @brief struct for loading many checkpoints from json - */ - struct t_hash_json { - std::vector<t_hashline> hashlines; //!< the checkpoint lines from the file - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(hashlines) - END_KV_SERIALIZE_MAP() - }; - - std::map<uint64_t, crypto::hash> m_points; //!< the checkpoints container - - }; -} diff --git a/src/cryptonote_core/connection_context.h b/src/cryptonote_core/connection_context.h deleted file mode 100644 index 7e62e77b9..000000000 --- a/src/cryptonote_core/connection_context.h +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright (c) 2014-2016, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - -#pragma once -#include <unordered_set> -#include <atomic> -#include "net/net_utils_base.h" -#include "copyable_atomic.h" - -namespace cryptonote -{ - - struct cryptonote_connection_context: public epee::net_utils::connection_context_base - { - - enum state - { - state_befor_handshake = 0, //default state - state_synchronizing, - state_idle, - state_normal - }; - - state m_state; - std::list<crypto::hash> m_needed_objects; - std::unordered_set<crypto::hash> m_requested_objects; - uint64_t m_remote_blockchain_height; - uint64_t m_last_response_height; - epee::copyable_atomic m_callback_request_count; //in debug purpose: problem with double callback rise - //size_t m_score; TODO: add score calculations - }; - - inline std::string get_protocol_state_string(cryptonote_connection_context::state s) - { - switch (s) - { - case cryptonote_connection_context::state_befor_handshake: - return "state_befor_handshake"; - case cryptonote_connection_context::state_synchronizing: - return "state_synchronizing"; - case cryptonote_connection_context::state_idle: - return "state_idle"; - case cryptonote_connection_context::state_normal: - return "state_normal"; - default: - return "unknown"; - } - } - -} diff --git a/src/cryptonote_core/cryptonote_basic.h b/src/cryptonote_core/cryptonote_basic.h deleted file mode 100644 index da069a21a..000000000 --- a/src/cryptonote_core/cryptonote_basic.h +++ /dev/null @@ -1,397 +0,0 @@ -// Copyright (c) 2014-2016, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - -#pragma once - -#include <boost/variant.hpp> -#include <boost/functional/hash/hash.hpp> -#include <vector> -#include <cstring> // memcmp -#include <sstream> -#include "serialization/serialization.h" -#include "serialization/variant.h" -#include "serialization/vector.h" -#include "serialization/binary_archive.h" -#include "serialization/json_archive.h" -#include "serialization/debug_archive.h" -#include "serialization/crypto.h" -#include "serialization/keyvalue_serialization.h" // eepe named serialization -#include "string_tools.h" -#include "cryptonote_config.h" -#include "crypto/crypto.h" -#include "crypto/hash.h" -#include "misc_language.h" -#include "tx_extra.h" -#include "ringct/rctTypes.h" - -namespace cryptonote -{ - - const static crypto::hash null_hash = AUTO_VAL_INIT(null_hash); - const static crypto::hash8 null_hash8 = AUTO_VAL_INIT(null_hash8); - const static crypto::public_key null_pkey = AUTO_VAL_INIT(null_pkey); - - typedef std::vector<crypto::signature> ring_signature; - - - /* outputs */ - - struct txout_to_script - { - std::vector<crypto::public_key> keys; - std::vector<uint8_t> script; - - BEGIN_SERIALIZE_OBJECT() - FIELD(keys) - FIELD(script) - END_SERIALIZE() - }; - - struct txout_to_scripthash - { - crypto::hash hash; - }; - - struct txout_to_key - { - txout_to_key() { } - txout_to_key(const crypto::public_key &_key) : key(_key) { } - crypto::public_key key; - }; - - - /* inputs */ - - struct txin_gen - { - size_t height; - - BEGIN_SERIALIZE_OBJECT() - VARINT_FIELD(height) - END_SERIALIZE() - }; - - struct txin_to_script - { - crypto::hash prev; - size_t prevout; - std::vector<uint8_t> sigset; - - BEGIN_SERIALIZE_OBJECT() - FIELD(prev) - VARINT_FIELD(prevout) - FIELD(sigset) - END_SERIALIZE() - }; - - struct txin_to_scripthash - { - crypto::hash prev; - size_t prevout; - txout_to_script script; - std::vector<uint8_t> sigset; - - BEGIN_SERIALIZE_OBJECT() - FIELD(prev) - VARINT_FIELD(prevout) - FIELD(script) - FIELD(sigset) - END_SERIALIZE() - }; - - struct txin_to_key - { - uint64_t amount; - std::vector<uint64_t> key_offsets; - crypto::key_image k_image; // double spending protection - - BEGIN_SERIALIZE_OBJECT() - VARINT_FIELD(amount) - FIELD(key_offsets) - FIELD(k_image) - END_SERIALIZE() - }; - - - typedef boost::variant<txin_gen, txin_to_script, txin_to_scripthash, txin_to_key> txin_v; - - typedef boost::variant<txout_to_script, txout_to_scripthash, txout_to_key> txout_target_v; - - //typedef std::pair<uint64_t, txout> out_t; - struct tx_out - { - uint64_t amount; - txout_target_v target; - - BEGIN_SERIALIZE_OBJECT() - VARINT_FIELD(amount) - FIELD(target) - END_SERIALIZE() - - - }; - - class transaction_prefix - { - - public: - // tx information - size_t version; - uint64_t unlock_time; //number of block (or time), used as a limitation like: spend this tx not early then block/time - - std::vector<txin_v> vin; - std::vector<tx_out> vout; - //extra - std::vector<uint8_t> extra; - - BEGIN_SERIALIZE() - VARINT_FIELD(version) - if(version == 0 || CURRENT_TRANSACTION_VERSION < version) return false; - VARINT_FIELD(unlock_time) - FIELD(vin) - FIELD(vout) - FIELD(extra) - END_SERIALIZE() - - public: - transaction_prefix(){} - }; - - class transaction: public transaction_prefix - { - public: - std::vector<std::vector<crypto::signature> > signatures; //count signatures always the same as inputs count - rct::rctSig rct_signatures; - - transaction(); - virtual ~transaction(); - void set_null(); - - BEGIN_SERIALIZE_OBJECT() - FIELDS(*static_cast<transaction_prefix *>(this)) - - if (version == 1) - { - ar.tag("signatures"); - ar.begin_array(); - PREPARE_CUSTOM_VECTOR_SERIALIZATION(vin.size(), signatures); - bool signatures_not_expected = signatures.empty(); - if (!signatures_not_expected && vin.size() != signatures.size()) - return false; - - for (size_t i = 0; i < vin.size(); ++i) - { - size_t signature_size = get_signature_size(vin[i]); - if (signatures_not_expected) - { - if (0 == signature_size) - continue; - else - return false; - } - - PREPARE_CUSTOM_VECTOR_SERIALIZATION(signature_size, signatures[i]); - if (signature_size != signatures[i].size()) - return false; - - FIELDS(signatures[i]); - - if (vin.size() - i > 1) - ar.delimit_array(); - } - ar.end_array(); - } - else - { - ar.tag("rct_signatures"); - if (!vin.empty()) - { - ar.begin_object(); - bool r = rct_signatures.serialize_rctsig_base(ar, vin.size(), vout.size()); - if (!r || !ar.stream().good()) return false; - ar.end_object(); - if (rct_signatures.type != rct::RCTTypeNull) - { - ar.tag("rctsig_prunable"); - ar.begin_object(); - r = rct_signatures.p.serialize_rctsig_prunable(ar, rct_signatures.type, vin.size(), vout.size(), - vin[0].type() == typeid(txin_to_key) ? boost::get<txin_to_key>(vin[0]).key_offsets.size() - 1 : 0); - if (!r || !ar.stream().good()) return false; - ar.end_object(); - } - } - } - END_SERIALIZE() - - private: - static size_t get_signature_size(const txin_v& tx_in); - }; - - - inline - transaction::transaction() - { - set_null(); - } - - inline - transaction::~transaction() - { - //set_null(); - } - - inline - void transaction::set_null() - { - version = 1; - unlock_time = 0; - vin.clear(); - vout.clear(); - extra.clear(); - signatures.clear(); - rct_signatures.type = rct::RCTTypeNull; - } - - inline - size_t transaction::get_signature_size(const txin_v& tx_in) - { - struct txin_signature_size_visitor : public boost::static_visitor<size_t> - { - size_t operator()(const txin_gen& txin) const{return 0;} - size_t operator()(const txin_to_script& txin) const{return 0;} - size_t operator()(const txin_to_scripthash& txin) const{return 0;} - size_t operator()(const txin_to_key& txin) const {return txin.key_offsets.size();} - }; - - return boost::apply_visitor(txin_signature_size_visitor(), tx_in); - } - - - - /************************************************************************/ - /* */ - /************************************************************************/ - struct block_header - { - uint8_t major_version; - uint8_t minor_version; // now used as a voting mechanism, rather than how this particular block is built - uint64_t timestamp; - crypto::hash prev_id; - uint32_t nonce; - - BEGIN_SERIALIZE() - VARINT_FIELD(major_version) - VARINT_FIELD(minor_version) - VARINT_FIELD(timestamp) - FIELD(prev_id) - FIELD(nonce) - END_SERIALIZE() - }; - - struct block: public block_header - { - transaction miner_tx; - std::vector<crypto::hash> tx_hashes; - - BEGIN_SERIALIZE_OBJECT() - FIELDS(*static_cast<block_header *>(this)) - FIELD(miner_tx) - FIELD(tx_hashes) - END_SERIALIZE() - }; - - - /************************************************************************/ - /* */ - /************************************************************************/ - struct account_public_address - { - crypto::public_key m_spend_public_key; - crypto::public_key m_view_public_key; - - BEGIN_SERIALIZE_OBJECT() - FIELD(m_spend_public_key) - FIELD(m_view_public_key) - END_SERIALIZE() - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE(m_spend_public_key) - KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE(m_view_public_key) - END_KV_SERIALIZE_MAP() - }; - - struct keypair - { - crypto::public_key pub; - crypto::secret_key sec; - - static inline keypair generate() - { - keypair k; - generate_keys(k.pub, k.sec); - return k; - } - }; - //--------------------------------------------------------------- - -} - -BLOB_SERIALIZER(cryptonote::txout_to_key); -BLOB_SERIALIZER(cryptonote::txout_to_scripthash); - -VARIANT_TAG(binary_archive, cryptonote::txin_gen, 0xff); -VARIANT_TAG(binary_archive, cryptonote::txin_to_script, 0x0); -VARIANT_TAG(binary_archive, cryptonote::txin_to_scripthash, 0x1); -VARIANT_TAG(binary_archive, cryptonote::txin_to_key, 0x2); -VARIANT_TAG(binary_archive, cryptonote::txout_to_script, 0x0); -VARIANT_TAG(binary_archive, cryptonote::txout_to_scripthash, 0x1); -VARIANT_TAG(binary_archive, cryptonote::txout_to_key, 0x2); -VARIANT_TAG(binary_archive, cryptonote::transaction, 0xcc); -VARIANT_TAG(binary_archive, cryptonote::block, 0xbb); - -VARIANT_TAG(json_archive, cryptonote::txin_gen, "gen"); -VARIANT_TAG(json_archive, cryptonote::txin_to_script, "script"); -VARIANT_TAG(json_archive, cryptonote::txin_to_scripthash, "scripthash"); -VARIANT_TAG(json_archive, cryptonote::txin_to_key, "key"); -VARIANT_TAG(json_archive, cryptonote::txout_to_script, "script"); -VARIANT_TAG(json_archive, cryptonote::txout_to_scripthash, "scripthash"); -VARIANT_TAG(json_archive, cryptonote::txout_to_key, "key"); -VARIANT_TAG(json_archive, cryptonote::transaction, "tx"); -VARIANT_TAG(json_archive, cryptonote::block, "block"); - -VARIANT_TAG(debug_archive, cryptonote::txin_gen, "gen"); -VARIANT_TAG(debug_archive, cryptonote::txin_to_script, "script"); -VARIANT_TAG(debug_archive, cryptonote::txin_to_scripthash, "scripthash"); -VARIANT_TAG(debug_archive, cryptonote::txin_to_key, "key"); -VARIANT_TAG(debug_archive, cryptonote::txout_to_script, "script"); -VARIANT_TAG(debug_archive, cryptonote::txout_to_scripthash, "scripthash"); -VARIANT_TAG(debug_archive, cryptonote::txout_to_key, "key"); -VARIANT_TAG(debug_archive, cryptonote::transaction, "tx"); -VARIANT_TAG(debug_archive, cryptonote::block, "block"); diff --git a/src/cryptonote_core/cryptonote_basic_impl.cpp b/src/cryptonote_core/cryptonote_basic_impl.cpp deleted file mode 100644 index 338210f01..000000000 --- a/src/cryptonote_core/cryptonote_basic_impl.cpp +++ /dev/null @@ -1,347 +0,0 @@ -// Copyright (c) 2014-2016, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - -#include "include_base_utils.h" -using namespace epee; - -#include "cryptonote_basic_impl.h" -#include "string_tools.h" -#include "serialization/binary_utils.h" -#include "serialization/vector.h" -#include "cryptonote_format_utils.h" -#include "cryptonote_config.h" -#include "misc_language.h" -#include "common/base58.h" -#include "crypto/hash.h" -#include "common/int-util.h" -#include "common/dns_utils.h" - -#undef MONERO_DEFAULT_LOG_CATEGORY -#define MONERO_DEFAULT_LOG_CATEGORY "cn" - -namespace cryptonote { - - struct integrated_address { - account_public_address adr; - crypto::hash8 payment_id; - - BEGIN_SERIALIZE_OBJECT() - FIELD(adr) - FIELD(payment_id) - END_SERIALIZE() - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(adr) - KV_SERIALIZE(payment_id) - END_KV_SERIALIZE_MAP() - }; - - /************************************************************************/ - /* Cryptonote helper functions */ - /************************************************************************/ - //----------------------------------------------------------------------------------------------- - size_t get_max_block_size() - { - return CRYPTONOTE_MAX_BLOCK_SIZE; - } - //----------------------------------------------------------------------------------------------- - size_t get_max_tx_size() - { - return CRYPTONOTE_MAX_TX_SIZE; - } - //----------------------------------------------------------------------------------------------- - bool get_block_reward(size_t median_size, size_t current_block_size, uint64_t already_generated_coins, uint64_t &reward, uint8_t version) { - static_assert(DIFFICULTY_TARGET_V2%60==0&&DIFFICULTY_TARGET_V1%60==0,"difficulty targets must be a multiple of 60"); - const int target = version < 2 ? DIFFICULTY_TARGET_V1 : DIFFICULTY_TARGET_V2; - const int target_minutes = target / 60; - const int emission_speed_factor = EMISSION_SPEED_FACTOR_PER_MINUTE - (target_minutes-1); - - uint64_t base_reward = (MONEY_SUPPLY - already_generated_coins) >> emission_speed_factor; - if (base_reward < FINAL_SUBSIDY_PER_MINUTE*target_minutes) - { - base_reward = FINAL_SUBSIDY_PER_MINUTE*target_minutes; - } - - uint64_t full_reward_zone = version < 2 ? CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V1 : CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2; - - //make it soft - if (median_size < full_reward_zone) { - median_size = full_reward_zone; - } - - if (current_block_size <= median_size) { - reward = base_reward; - return true; - } - - if(current_block_size > 2 * median_size) { - MERROR("Block cumulative size is too big: " << current_block_size << ", expected less than " << 2 * median_size); - return false; - } - - assert(median_size < std::numeric_limits<uint32_t>::max()); - assert(current_block_size < std::numeric_limits<uint32_t>::max()); - - uint64_t product_hi; - // BUGFIX: 32-bit saturation bug (e.g. ARM7), the result was being - // treated as 32-bit by default. - uint64_t multiplicand = 2 * median_size - current_block_size; - multiplicand *= current_block_size; - uint64_t product_lo = mul128(base_reward, multiplicand, &product_hi); - - uint64_t reward_hi; - uint64_t reward_lo; - div128_32(product_hi, product_lo, static_cast<uint32_t>(median_size), &reward_hi, &reward_lo); - div128_32(reward_hi, reward_lo, static_cast<uint32_t>(median_size), &reward_hi, &reward_lo); - assert(0 == reward_hi); - assert(reward_lo < base_reward); - - reward = reward_lo; - return true; - } - //------------------------------------------------------------------------------------ - uint8_t get_account_address_checksum(const public_address_outer_blob& bl) - { - const unsigned char* pbuf = reinterpret_cast<const unsigned char*>(&bl); - uint8_t summ = 0; - for(size_t i = 0; i!= sizeof(public_address_outer_blob)-1; i++) - summ += pbuf[i]; - - return summ; - } - //------------------------------------------------------------------------------------ - uint8_t get_account_integrated_address_checksum(const public_integrated_address_outer_blob& bl) - { - const unsigned char* pbuf = reinterpret_cast<const unsigned char*>(&bl); - uint8_t summ = 0; - for(size_t i = 0; i!= sizeof(public_integrated_address_outer_blob)-1; i++) - summ += pbuf[i]; - - return summ; - } - //----------------------------------------------------------------------- - std::string get_account_address_as_str( - bool testnet - , account_public_address const & adr - ) - { - uint64_t address_prefix = testnet ? - config::testnet::CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX : config::CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX; - - return tools::base58::encode_addr(address_prefix, t_serializable_object_to_blob(adr)); - } - //----------------------------------------------------------------------- - std::string get_account_integrated_address_as_str( - bool testnet - , account_public_address const & adr - , crypto::hash8 const & payment_id - ) - { - uint64_t integrated_address_prefix = testnet ? - config::testnet::CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX : config::CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX; - - integrated_address iadr = { - adr, payment_id - }; - return tools::base58::encode_addr(integrated_address_prefix, t_serializable_object_to_blob(iadr)); - } - //----------------------------------------------------------------------- - bool is_coinbase(const transaction& tx) - { - if(tx.vin.size() != 1) - return false; - - if(tx.vin[0].type() != typeid(txin_gen)) - return false; - - return true; - } - //----------------------------------------------------------------------- - bool get_account_integrated_address_from_str( - account_public_address& adr - , bool& has_payment_id - , crypto::hash8& payment_id - , bool testnet - , std::string const & str - ) - { - uint64_t address_prefix = testnet ? - config::testnet::CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX : config::CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX; - uint64_t integrated_address_prefix = testnet ? - config::testnet::CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX : config::CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX; - - if (2 * sizeof(public_address_outer_blob) != str.size()) - { - blobdata data; - uint64_t prefix; - if (!tools::base58::decode_addr(str, prefix, data)) - { - LOG_PRINT_L2("Invalid address format"); - return false; - } - - if (integrated_address_prefix == prefix) - { - has_payment_id = true; - } - else if (address_prefix == prefix) - { - has_payment_id = false; - } - else { - LOG_PRINT_L1("Wrong address prefix: " << prefix << ", expected " << address_prefix << " or " << integrated_address_prefix); - return false; - } - - if (has_payment_id) - { - integrated_address iadr; - if (!::serialization::parse_binary(data, iadr)) - { - LOG_PRINT_L1("Account public address keys can't be parsed"); - return false; - } - adr = iadr.adr; - payment_id = iadr.payment_id; - } - else - { - if (!::serialization::parse_binary(data, adr)) - { - LOG_PRINT_L1("Account public address keys can't be parsed"); - return false; - } - } - - if (!crypto::check_key(adr.m_spend_public_key) || !crypto::check_key(adr.m_view_public_key)) - { - LOG_PRINT_L1("Failed to validate address keys"); - return false; - } - } - else - { - // Old address format - std::string buff; - if(!string_tools::parse_hexstr_to_binbuff(str, buff)) - return false; - - if(buff.size()!=sizeof(public_address_outer_blob)) - { - LOG_PRINT_L1("Wrong public address size: " << buff.size() << ", expected size: " << sizeof(public_address_outer_blob)); - return false; - } - - public_address_outer_blob blob = *reinterpret_cast<const public_address_outer_blob*>(buff.data()); - - - if(blob.m_ver > CRYPTONOTE_PUBLIC_ADDRESS_TEXTBLOB_VER) - { - LOG_PRINT_L1("Unknown version of public address: " << blob.m_ver << ", expected " << CRYPTONOTE_PUBLIC_ADDRESS_TEXTBLOB_VER); - return false; - } - - if(blob.check_sum != get_account_address_checksum(blob)) - { - LOG_PRINT_L1("Wrong public address checksum"); - return false; - } - - //we success - adr = blob.m_address; - has_payment_id = false; - } - - return true; - } - //----------------------------------------------------------------------- - bool get_account_address_from_str( - account_public_address& adr - , bool testnet - , std::string const & str - ) - { - bool has_payment_id; - crypto::hash8 payment_id; - return get_account_integrated_address_from_str(adr, has_payment_id, payment_id, testnet, str); - } - //-------------------------------------------------------------------------------- - bool get_account_address_from_str_or_url( - cryptonote::account_public_address& address - , bool& has_payment_id - , crypto::hash8& payment_id - , bool testnet - , const std::string& str_or_url - ) - { - if (get_account_integrated_address_from_str(address, has_payment_id, payment_id, testnet, str_or_url)) - return true; - bool dnssec_valid; - std::string address_str = tools::dns_utils::get_account_address_as_str_from_url(str_or_url, dnssec_valid); - return !address_str.empty() && - get_account_integrated_address_from_str(address, has_payment_id, payment_id, testnet, address_str); - } - //-------------------------------------------------------------------------------- - bool get_account_address_from_str_or_url( - cryptonote::account_public_address& address - , bool testnet - , const std::string& str_or_url - ) - { - bool has_payment_id; - crypto::hash8 payment_id; - return get_account_address_from_str_or_url(address, has_payment_id, payment_id, testnet, str_or_url); - } - //-------------------------------------------------------------------------------- - bool operator ==(const cryptonote::transaction& a, const cryptonote::transaction& b) { - return cryptonote::get_transaction_hash(a) == cryptonote::get_transaction_hash(b); - } - - bool operator ==(const cryptonote::block& a, const cryptonote::block& b) { - return cryptonote::get_block_hash(a) == cryptonote::get_block_hash(b); - } -} - -//-------------------------------------------------------------------------------- -bool parse_hash256(const std::string str_hash, crypto::hash& hash) -{ - std::string buf; - bool res = epee::string_tools::parse_hexstr_to_binbuff(str_hash, buf); - if (!res || buf.size() != sizeof(crypto::hash)) - { - std::cout << "invalid hash format: <" << str_hash << '>' << std::endl; - return false; - } - else - { - buf.copy(reinterpret_cast<char *>(&hash), sizeof(crypto::hash)); - return true; - } -} diff --git a/src/cryptonote_core/cryptonote_basic_impl.h b/src/cryptonote_core/cryptonote_basic_impl.h deleted file mode 100644 index 5703a7d75..000000000 --- a/src/cryptonote_core/cryptonote_basic_impl.h +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright (c) 2014-2016, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - -#pragma once - -#include "cryptonote_basic.h" -#include "crypto/crypto.h" -#include "crypto/hash.h" - - -namespace cryptonote { - /************************************************************************/ - /* */ - /************************************************************************/ - template<class t_array> - struct array_hasher: std::unary_function<t_array&, std::size_t> - { - std::size_t operator()(const t_array& val) const - { - return boost::hash_range(&val.data[0], &val.data[sizeof(val.data)]); - } - }; - - -#pragma pack(push, 1) - struct public_address_outer_blob - { - uint8_t m_ver; - account_public_address m_address; - uint8_t check_sum; - }; - struct public_integrated_address_outer_blob - { - uint8_t m_ver; - account_public_address m_address; - crypto::hash8 payment_id; - uint8_t check_sum; - }; -#pragma pack (pop) - - - /************************************************************************/ - /* Cryptonote helper functions */ - /************************************************************************/ - size_t get_max_block_size(); - size_t get_max_tx_size(); - bool get_block_reward(size_t median_size, size_t current_block_size, uint64_t already_generated_coins, uint64_t &reward, uint8_t version); - uint8_t get_account_address_checksum(const public_address_outer_blob& bl); - uint8_t get_account_integrated_address_checksum(const public_integrated_address_outer_blob& bl); - - std::string get_account_address_as_str( - bool testnet - , const account_public_address& adr - ); - - std::string get_account_integrated_address_as_str( - bool testnet - , const account_public_address& adr - , const crypto::hash8& payment_id - ); - - bool get_account_integrated_address_from_str( - account_public_address& adr - , bool& has_payment_id - , crypto::hash8& payment_id - , bool testnet - , const std::string& str - ); - - bool get_account_address_from_str( - account_public_address& adr - , bool testnet - , const std::string& str - ); - - bool get_account_address_from_str_or_url( - cryptonote::account_public_address& address - , bool& has_payment_id - , crypto::hash8& payment_id - , bool testnet - , const std::string& str_or_url - ); - - bool get_account_address_from_str_or_url( - cryptonote::account_public_address& address - , bool testnet - , const std::string& str_or_url - ); - - bool is_coinbase(const transaction& tx); - - bool operator ==(const cryptonote::transaction& a, const cryptonote::transaction& b); - bool operator ==(const cryptonote::block& a, const cryptonote::block& b); -} - -template <class T> -std::ostream &print256(std::ostream &o, const T &v) { - return o << "<" << epee::string_tools::pod_to_hex(v) << ">"; -} -template <class T> -std::ostream &print64(std::ostream &o, const T &v) { - return o << "<" << epee::string_tools::pod_to_hex(v) << ">"; -} - -bool parse_hash256(const std::string str_hash, crypto::hash& hash); - -namespace crypto { - inline std::ostream &operator <<(std::ostream &o, const crypto::public_key &v) { return print256(o, v); } - inline std::ostream &operator <<(std::ostream &o, const crypto::secret_key &v) { return print256(o, v); } - inline std::ostream &operator <<(std::ostream &o, const crypto::key_derivation &v) { return print256(o, v); } - inline std::ostream &operator <<(std::ostream &o, const crypto::key_image &v) { return print256(o, v); } - inline std::ostream &operator <<(std::ostream &o, const crypto::signature &v) { return print256(o, v); } - inline std::ostream &operator <<(std::ostream &o, const crypto::hash &v) { return print256(o, v); } - inline std::ostream &operator <<(std::ostream &o, const crypto::hash8 &v) { return print64(o, v); } -} diff --git a/src/cryptonote_core/cryptonote_boost_serialization.h b/src/cryptonote_core/cryptonote_boost_serialization.h deleted file mode 100644 index 409b9798c..000000000 --- a/src/cryptonote_core/cryptonote_boost_serialization.h +++ /dev/null @@ -1,301 +0,0 @@ -// Copyright (c) 2014-2016, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - -#pragma once - -#include <boost/serialization/vector.hpp> -#include <boost/serialization/utility.hpp> -#include <boost/serialization/variant.hpp> -#include <boost/serialization/set.hpp> -#include <boost/serialization/map.hpp> -#include <boost/serialization/is_bitwise_serializable.hpp> -#include <boost/archive/binary_iarchive.hpp> -#include <boost/archive/portable_binary_iarchive.hpp> -#include <boost/archive/portable_binary_oarchive.hpp> -#include "cryptonote_basic.h" -#include "common/unordered_containers_boost_serialization.h" -#include "crypto/crypto.h" -#include "ringct/rctTypes.h" -#include "ringct/rctOps.h" - -//namespace cryptonote { -namespace boost -{ - namespace serialization - { - - //--------------------------------------------------- - template <class Archive> - inline void serialize(Archive &a, crypto::public_key &x, const boost::serialization::version_type ver) - { - a & reinterpret_cast<char (&)[sizeof(crypto::public_key)]>(x); - } - template <class Archive> - inline void serialize(Archive &a, crypto::secret_key &x, const boost::serialization::version_type ver) - { - a & reinterpret_cast<char (&)[sizeof(crypto::secret_key)]>(x); - } - template <class Archive> - inline void serialize(Archive &a, crypto::key_derivation &x, const boost::serialization::version_type ver) - { - a & reinterpret_cast<char (&)[sizeof(crypto::key_derivation)]>(x); - } - template <class Archive> - inline void serialize(Archive &a, crypto::key_image &x, const boost::serialization::version_type ver) - { - a & reinterpret_cast<char (&)[sizeof(crypto::key_image)]>(x); - } - - template <class Archive> - inline void serialize(Archive &a, crypto::signature &x, const boost::serialization::version_type ver) - { - a & reinterpret_cast<char (&)[sizeof(crypto::signature)]>(x); - } - template <class Archive> - inline void serialize(Archive &a, crypto::hash &x, const boost::serialization::version_type ver) - { - a & reinterpret_cast<char (&)[sizeof(crypto::hash)]>(x); - } - - template <class Archive> - inline void serialize(Archive &a, cryptonote::txout_to_script &x, const boost::serialization::version_type ver) - { - a & x.keys; - a & x.script; - } - - - template <class Archive> - inline void serialize(Archive &a, cryptonote::txout_to_key &x, const boost::serialization::version_type ver) - { - a & x.key; - } - - template <class Archive> - inline void serialize(Archive &a, cryptonote::txout_to_scripthash &x, const boost::serialization::version_type ver) - { - a & x.hash; - } - - template <class Archive> - inline void serialize(Archive &a, cryptonote::txin_gen &x, const boost::serialization::version_type ver) - { - a & x.height; - } - - template <class Archive> - inline void serialize(Archive &a, cryptonote::txin_to_script &x, const boost::serialization::version_type ver) - { - a & x.prev; - a & x.prevout; - a & x.sigset; - } - - template <class Archive> - inline void serialize(Archive &a, cryptonote::txin_to_scripthash &x, const boost::serialization::version_type ver) - { - a & x.prev; - a & x.prevout; - a & x.script; - a & x.sigset; - } - - template <class Archive> - inline void serialize(Archive &a, cryptonote::txin_to_key &x, const boost::serialization::version_type ver) - { - a & x.amount; - a & x.key_offsets; - a & x.k_image; - } - - template <class Archive> - inline void serialize(Archive &a, cryptonote::tx_out &x, const boost::serialization::version_type ver) - { - a & x.amount; - a & x.target; - } - - - template <class Archive> - inline void serialize(Archive &a, cryptonote::transaction_prefix &x, const boost::serialization::version_type ver) - { - a & x.version; - a & x.unlock_time; - a & x.vin; - a & x.vout; - a & x.extra; - } - - template <class Archive> - inline void serialize(Archive &a, cryptonote::transaction &x, const boost::serialization::version_type ver) - { - a & x.version; - a & x.unlock_time; - a & x.vin; - a & x.vout; - a & x.extra; - if (x.version == 1) - { - a & x.signatures; - } - else - { - a & (rct::rctSigBase&)x.rct_signatures; - if (x.rct_signatures.type != rct::RCTTypeNull) - a & x.rct_signatures.p; - } - } - - template <class Archive> - inline void serialize(Archive &a, cryptonote::block &b, const boost::serialization::version_type ver) - { - a & b.major_version; - a & b.minor_version; - a & b.timestamp; - a & b.prev_id; - a & b.nonce; - //------------------ - a & b.miner_tx; - a & b.tx_hashes; - } - - template <class Archive> - inline void serialize(Archive &a, rct::key &x, const boost::serialization::version_type ver) - { - a & reinterpret_cast<char (&)[sizeof(rct::key)]>(x); - } - - template <class Archive> - inline void serialize(Archive &a, rct::ctkey &x, const boost::serialization::version_type ver) - { - a & x.dest; - a & x.mask; - } - - template <class Archive> - inline void serialize(Archive &a, rct::rangeSig &x, const boost::serialization::version_type ver) - { - a & x.asig; - a & x.Ci; - } - - template <class Archive> - inline void serialize(Archive &a, rct::boroSig &x, const boost::serialization::version_type ver) - { - a & x.s0; - a & x.s1; - a & x.ee; - } - - template <class Archive> - inline void serialize(Archive &a, rct::mgSig &x, const boost::serialization::version_type ver) - { - a & x.ss; - a & x.cc; - // a & x.II; // not serialized, we can recover it from the tx vin - } - - template <class Archive> - inline void serialize(Archive &a, rct::ecdhTuple &x, const boost::serialization::version_type ver) - { - a & x.mask; - a & x.amount; - // a & x.senderPk; // not serialized, as we do not use it in monero currently - } - - template <class Archive> - inline typename std::enable_if<Archive::is_loading::value, void>::type serializeOutPk(Archive &a, rct::ctkeyV &outPk_, const boost::serialization::version_type ver) - { - rct::keyV outPk; - a & outPk; - outPk_.resize(outPk.size()); - for (size_t n = 0; n < outPk_.size(); ++n) - { - outPk_[n].dest = rct::identity(); - outPk_[n].mask = outPk[n]; - } - } - - template <class Archive> - inline typename std::enable_if<Archive::is_saving::value, void>::type serializeOutPk(Archive &a, rct::ctkeyV &outPk_, const boost::serialization::version_type ver) - { - rct::keyV outPk(outPk_.size()); - for (size_t n = 0; n < outPk_.size(); ++n) - outPk[n] = outPk_[n].mask; - a & outPk; - } - - template <class Archive> - inline void serialize(Archive &a, rct::rctSigBase &x, const boost::serialization::version_type ver) - { - a & x.type; - if (x.type == rct::RCTTypeNull) - return; - if (x.type != rct::RCTTypeFull && x.type != rct::RCTTypeSimple) - throw boost::archive::archive_exception(boost::archive::archive_exception::other_exception, "Unsupported rct type"); - // a & x.message; message is not serialized, as it can be reconstructed from the tx data - // a & x.mixRing; mixRing is not serialized, as it can be reconstructed from the offsets - if (x.type == rct::RCTTypeSimple) - a & x.pseudoOuts; - a & x.ecdhInfo; - serializeOutPk(a, x.outPk, ver); - a & x.txnFee; - } - - template <class Archive> - inline void serialize(Archive &a, rct::rctSigPrunable &x, const boost::serialization::version_type ver) - { - a & x.rangeSigs; - a & x.MGs; - } - - template <class Archive> - inline void serialize(Archive &a, rct::rctSig &x, const boost::serialization::version_type ver) - { - a & x.type; - if (x.type == rct::RCTTypeNull) - return; - if (x.type != rct::RCTTypeFull && x.type != rct::RCTTypeSimple) - throw boost::archive::archive_exception(boost::archive::archive_exception::other_exception, "Unsupported rct type"); - // a & x.message; message is not serialized, as it can be reconstructed from the tx data - // a & x.mixRing; mixRing is not serialized, as it can be reconstructed from the offsets - if (x.type == rct::RCTTypeSimple) - a & x.pseudoOuts; - a & x.ecdhInfo; - serializeOutPk(a, x.outPk, ver); - a & x.txnFee; - //-------------- - a & x.p.rangeSigs; - a & x.p.MGs; - } -} -} - -//} diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp index 900dc58ba..b940dba3c 100644 --- a/src/cryptonote_core/cryptonote_core.cpp +++ b/src/cryptonote_core/cryptonote_core.cpp @@ -38,11 +38,11 @@ using namespace epee; #include "warnings.h" #include "crypto/crypto.h" #include "cryptonote_config.h" -#include "cryptonote_format_utils.h" +#include "cryptonote_tx_utils.h" #include "misc_language.h" #include <csignal> #include <p2p/net_node.h> -#include "cryptonote_core/checkpoints.h" +#include "cryptonote_basic/checkpoints.h" #include "ringct/rctTypes.h" #include "blockchain_db/blockchain_db.h" #include "blockchain_db/lmdb/db_lmdb.h" diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h index 1b9518c96..fe1d11916 100644 --- a/src/cryptonote_core/cryptonote_core.h +++ b/src/cryptonote_core/cryptonote_core.h @@ -41,9 +41,9 @@ #include "storages/portable_storage_template_helper.h" #include "tx_pool.h" #include "blockchain.h" -#include "miner.h" -#include "connection_context.h" -#include "cryptonote_core/cryptonote_stat_info.h" +#include "cryptonote_basic/miner.h" +#include "cryptonote_basic/connection_context.h" +#include "cryptonote_basic/cryptonote_stat_info.h" #include "warnings.h" #include "crypto/hash.h" diff --git a/src/cryptonote_core/cryptonote_format_utils.cpp b/src/cryptonote_core/cryptonote_format_utils.cpp deleted file mode 100644 index 2e6917878..000000000 --- a/src/cryptonote_core/cryptonote_format_utils.cpp +++ /dev/null @@ -1,1193 +0,0 @@ -// Copyright (c) 2014-2016, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - -#include "include_base_utils.h" -using namespace epee; - -#include "cryptonote_format_utils.h" -#include "cryptonote_config.h" -#include "miner.h" -#include "crypto/crypto.h" -#include "crypto/hash.h" -#include "ringct/rctSigs.h" - -#undef MONERO_DEFAULT_LOG_CATEGORY -#define MONERO_DEFAULT_LOG_CATEGORY "cn" - -#define ENCRYPTED_PAYMENT_ID_TAIL 0x8d - -static const uint64_t valid_decomposed_outputs[] = { - (uint64_t)1, (uint64_t)2, (uint64_t)3, (uint64_t)4, (uint64_t)5, (uint64_t)6, (uint64_t)7, (uint64_t)8, (uint64_t)9, // 1 piconero - (uint64_t)10, (uint64_t)20, (uint64_t)30, (uint64_t)40, (uint64_t)50, (uint64_t)60, (uint64_t)70, (uint64_t)80, (uint64_t)90, - (uint64_t)100, (uint64_t)200, (uint64_t)300, (uint64_t)400, (uint64_t)500, (uint64_t)600, (uint64_t)700, (uint64_t)800, (uint64_t)900, - (uint64_t)1000, (uint64_t)2000, (uint64_t)3000, (uint64_t)4000, (uint64_t)5000, (uint64_t)6000, (uint64_t)7000, (uint64_t)8000, (uint64_t)9000, - (uint64_t)10000, (uint64_t)20000, (uint64_t)30000, (uint64_t)40000, (uint64_t)50000, (uint64_t)60000, (uint64_t)70000, (uint64_t)80000, (uint64_t)90000, - (uint64_t)100000, (uint64_t)200000, (uint64_t)300000, (uint64_t)400000, (uint64_t)500000, (uint64_t)600000, (uint64_t)700000, (uint64_t)800000, (uint64_t)900000, - (uint64_t)1000000, (uint64_t)2000000, (uint64_t)3000000, (uint64_t)4000000, (uint64_t)5000000, (uint64_t)6000000, (uint64_t)7000000, (uint64_t)8000000, (uint64_t)9000000, // 1 micronero - (uint64_t)10000000, (uint64_t)20000000, (uint64_t)30000000, (uint64_t)40000000, (uint64_t)50000000, (uint64_t)60000000, (uint64_t)70000000, (uint64_t)80000000, (uint64_t)90000000, - (uint64_t)100000000, (uint64_t)200000000, (uint64_t)300000000, (uint64_t)400000000, (uint64_t)500000000, (uint64_t)600000000, (uint64_t)700000000, (uint64_t)800000000, (uint64_t)900000000, - (uint64_t)1000000000, (uint64_t)2000000000, (uint64_t)3000000000, (uint64_t)4000000000, (uint64_t)5000000000, (uint64_t)6000000000, (uint64_t)7000000000, (uint64_t)8000000000, (uint64_t)9000000000, - (uint64_t)10000000000, (uint64_t)20000000000, (uint64_t)30000000000, (uint64_t)40000000000, (uint64_t)50000000000, (uint64_t)60000000000, (uint64_t)70000000000, (uint64_t)80000000000, (uint64_t)90000000000, - (uint64_t)100000000000, (uint64_t)200000000000, (uint64_t)300000000000, (uint64_t)400000000000, (uint64_t)500000000000, (uint64_t)600000000000, (uint64_t)700000000000, (uint64_t)800000000000, (uint64_t)900000000000, - (uint64_t)1000000000000, (uint64_t)2000000000000, (uint64_t)3000000000000, (uint64_t)4000000000000, (uint64_t)5000000000000, (uint64_t)6000000000000, (uint64_t)7000000000000, (uint64_t)8000000000000, (uint64_t)9000000000000, // 1 monero - (uint64_t)10000000000000, (uint64_t)20000000000000, (uint64_t)30000000000000, (uint64_t)40000000000000, (uint64_t)50000000000000, (uint64_t)60000000000000, (uint64_t)70000000000000, (uint64_t)80000000000000, (uint64_t)90000000000000, - (uint64_t)100000000000000, (uint64_t)200000000000000, (uint64_t)300000000000000, (uint64_t)400000000000000, (uint64_t)500000000000000, (uint64_t)600000000000000, (uint64_t)700000000000000, (uint64_t)800000000000000, (uint64_t)900000000000000, - (uint64_t)1000000000000000, (uint64_t)2000000000000000, (uint64_t)3000000000000000, (uint64_t)4000000000000000, (uint64_t)5000000000000000, (uint64_t)6000000000000000, (uint64_t)7000000000000000, (uint64_t)8000000000000000, (uint64_t)9000000000000000, - (uint64_t)10000000000000000, (uint64_t)20000000000000000, (uint64_t)30000000000000000, (uint64_t)40000000000000000, (uint64_t)50000000000000000, (uint64_t)60000000000000000, (uint64_t)70000000000000000, (uint64_t)80000000000000000, (uint64_t)90000000000000000, - (uint64_t)100000000000000000, (uint64_t)200000000000000000, (uint64_t)300000000000000000, (uint64_t)400000000000000000, (uint64_t)500000000000000000, (uint64_t)600000000000000000, (uint64_t)700000000000000000, (uint64_t)800000000000000000, (uint64_t)900000000000000000, - (uint64_t)1000000000000000000, (uint64_t)2000000000000000000, (uint64_t)3000000000000000000, (uint64_t)4000000000000000000, (uint64_t)5000000000000000000, (uint64_t)6000000000000000000, (uint64_t)7000000000000000000, (uint64_t)8000000000000000000, (uint64_t)9000000000000000000, // 1 meganero - (uint64_t)10000000000000000000ull -}; - -namespace cryptonote -{ - //--------------------------------------------------------------- - void get_transaction_prefix_hash(const transaction_prefix& tx, crypto::hash& h) - { - std::ostringstream s; - binary_archive<true> a(s); - ::serialization::serialize(a, const_cast<transaction_prefix&>(tx)); - crypto::cn_fast_hash(s.str().data(), s.str().size(), h); - } - //--------------------------------------------------------------- - crypto::hash get_transaction_prefix_hash(const transaction_prefix& tx) - { - crypto::hash h = null_hash; - get_transaction_prefix_hash(tx, h); - return h; - } - //--------------------------------------------------------------- - bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx) - { - std::stringstream ss; - ss << tx_blob; - binary_archive<false> ba(ss); - bool r = ::serialization::serialize(ba, tx); - CHECK_AND_ASSERT_MES(r, false, "Failed to parse transaction from blob"); - return true; - } - //--------------------------------------------------------------- - bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx, crypto::hash& tx_hash, crypto::hash& tx_prefix_hash) - { - std::stringstream ss; - ss << tx_blob; - binary_archive<false> ba(ss); - bool r = ::serialization::serialize(ba, tx); - CHECK_AND_ASSERT_MES(r, false, "Failed to parse transaction from blob"); - //TODO: validate tx - - get_transaction_hash(tx, tx_hash); - get_transaction_prefix_hash(tx, tx_prefix_hash); - return true; - } - //--------------------------------------------------------------- - bool construct_miner_tx(size_t height, size_t median_size, uint64_t already_generated_coins, size_t current_block_size, uint64_t fee, const account_public_address &miner_address, transaction& tx, const blobdata& extra_nonce, size_t max_outs, uint8_t hard_fork_version) { - tx.vin.clear(); - tx.vout.clear(); - tx.extra.clear(); - - keypair txkey = keypair::generate(); - add_tx_pub_key_to_extra(tx, txkey.pub); - if(!extra_nonce.empty()) - if(!add_extra_nonce_to_tx_extra(tx.extra, extra_nonce)) - return false; - - txin_gen in; - in.height = height; - - uint64_t block_reward; - if(!get_block_reward(median_size, current_block_size, already_generated_coins, block_reward, hard_fork_version)) - { - LOG_PRINT_L0("Block is too big"); - return false; - } - -#if defined(DEBUG_CREATE_BLOCK_TEMPLATE) - LOG_PRINT_L1("Creating block template: reward " << block_reward << - ", fee " << fee); -#endif - block_reward += fee; - - // from hard fork 2, we cut out the low significant digits. This makes the tx smaller, and - // keeps the paid amount almost the same. The unpaid remainder gets pushed back to the - // emission schedule - // from hard fork 4, we use a single "dusty" output. This makes the tx even smaller, - // and avoids the quantization. These outputs will be added as rct outputs with identity - // masks, to they can be used as rct inputs. - if (hard_fork_version >= 2 && hard_fork_version < 4) { - block_reward = block_reward - block_reward % ::config::BASE_REWARD_CLAMP_THRESHOLD; - } - - std::vector<uint64_t> out_amounts; - decompose_amount_into_digits(block_reward, hard_fork_version >= 2 ? 0 : ::config::DEFAULT_DUST_THRESHOLD, - [&out_amounts](uint64_t a_chunk) { out_amounts.push_back(a_chunk); }, - [&out_amounts](uint64_t a_dust) { out_amounts.push_back(a_dust); }); - - CHECK_AND_ASSERT_MES(1 <= max_outs, false, "max_out must be non-zero"); - if (height == 0 || hard_fork_version >= 4) - { - // the genesis block was not decomposed, for unknown reasons - while (max_outs < out_amounts.size()) - { - //out_amounts[out_amounts.size() - 2] += out_amounts.back(); - //out_amounts.resize(out_amounts.size() - 1); - out_amounts[1] += out_amounts[0]; - for (size_t n = 1; n < out_amounts.size(); ++n) - out_amounts[n - 1] = out_amounts[n]; - out_amounts.resize(out_amounts.size() - 1); - } - } - else - { - CHECK_AND_ASSERT_MES(max_outs >= out_amounts.size(), false, "max_out exceeded"); - } - - uint64_t summary_amounts = 0; - for (size_t no = 0; no < out_amounts.size(); no++) - { - crypto::key_derivation derivation = AUTO_VAL_INIT(derivation);; - crypto::public_key out_eph_public_key = AUTO_VAL_INIT(out_eph_public_key); - bool r = crypto::generate_key_derivation(miner_address.m_view_public_key, txkey.sec, derivation); - CHECK_AND_ASSERT_MES(r, false, "while creating outs: failed to generate_key_derivation(" << miner_address.m_view_public_key << ", " << txkey.sec << ")"); - - r = crypto::derive_public_key(derivation, no, miner_address.m_spend_public_key, out_eph_public_key); - CHECK_AND_ASSERT_MES(r, false, "while creating outs: failed to derive_public_key(" << derivation << ", " << no << ", "<< miner_address.m_spend_public_key << ")"); - - txout_to_key tk; - tk.key = out_eph_public_key; - - tx_out out; - summary_amounts += out.amount = out_amounts[no]; - out.target = tk; - tx.vout.push_back(out); - } - - CHECK_AND_ASSERT_MES(summary_amounts == block_reward, false, "Failed to construct miner tx, summary_amounts = " << summary_amounts << " not equal block_reward = " << block_reward); - - if (hard_fork_version >= 4) - tx.version = 2; - else - tx.version = 1; - - //lock - tx.unlock_time = height + CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW; - tx.vin.push_back(in); - //LOG_PRINT("MINER_TX generated ok, block_reward=" << print_money(block_reward) << "(" << print_money(block_reward - fee) << "+" << print_money(fee) - // << "), current_block_size=" << current_block_size << ", already_generated_coins=" << already_generated_coins << ", tx_id=" << get_transaction_hash(tx), LOG_LEVEL_2); - return true; - } - //--------------------------------------------------------------- - bool generate_key_image_helper(const account_keys& ack, const crypto::public_key& tx_public_key, size_t real_output_index, keypair& in_ephemeral, crypto::key_image& ki) - { - crypto::key_derivation recv_derivation = AUTO_VAL_INIT(recv_derivation); - bool r = crypto::generate_key_derivation(tx_public_key, ack.m_view_secret_key, recv_derivation); - CHECK_AND_ASSERT_MES(r, false, "key image helper: failed to generate_key_derivation(" << tx_public_key << ", " << ack.m_view_secret_key << ")"); - - r = crypto::derive_public_key(recv_derivation, real_output_index, ack.m_account_address.m_spend_public_key, in_ephemeral.pub); - CHECK_AND_ASSERT_MES(r, false, "key image helper: failed to derive_public_key(" << recv_derivation << ", " << real_output_index << ", " << ack.m_account_address.m_spend_public_key << ")"); - - crypto::derive_secret_key(recv_derivation, real_output_index, ack.m_spend_secret_key, in_ephemeral.sec); - - crypto::generate_key_image(in_ephemeral.pub, in_ephemeral.sec, ki); - return true; - } - //--------------------------------------------------------------- - uint64_t power_integral(uint64_t a, uint64_t b) - { - if(b == 0) - return 1; - uint64_t total = a; - for(uint64_t i = 1; i != b; i++) - total *= a; - return total; - } - //--------------------------------------------------------------- - bool parse_amount(uint64_t& amount, const std::string& str_amount_) - { - std::string str_amount = str_amount_; - boost::algorithm::trim(str_amount); - - size_t point_index = str_amount.find_first_of('.'); - size_t fraction_size; - if (std::string::npos != point_index) - { - fraction_size = str_amount.size() - point_index - 1; - while (CRYPTONOTE_DISPLAY_DECIMAL_POINT < fraction_size && '0' == str_amount.back()) - { - str_amount.erase(str_amount.size() - 1, 1); - --fraction_size; - } - if (CRYPTONOTE_DISPLAY_DECIMAL_POINT < fraction_size) - return false; - str_amount.erase(point_index, 1); - } - else - { - fraction_size = 0; - } - - if (str_amount.empty()) - return false; - - if (fraction_size < CRYPTONOTE_DISPLAY_DECIMAL_POINT) - { - str_amount.append(CRYPTONOTE_DISPLAY_DECIMAL_POINT - fraction_size, '0'); - } - - return string_tools::get_xtype_from_string(amount, str_amount); - } - //--------------------------------------------------------------- - bool get_tx_fee(const transaction& tx, uint64_t & fee) - { - if (tx.version > 1) - { - fee = tx.rct_signatures.txnFee; - return true; - } - uint64_t amount_in = 0; - uint64_t amount_out = 0; - for(auto& in: tx.vin) - { - CHECK_AND_ASSERT_MES(in.type() == typeid(txin_to_key), 0, "unexpected type id in transaction"); - amount_in += boost::get<txin_to_key>(in).amount; - } - for(auto& o: tx.vout) - amount_out += o.amount; - - CHECK_AND_ASSERT_MES(amount_in >= amount_out, false, "transaction spend (" <<amount_in << ") more than it has (" << amount_out << ")"); - fee = amount_in - amount_out; - return true; - } - //--------------------------------------------------------------- - uint64_t get_tx_fee(const transaction& tx) - { - uint64_t r = 0; - if(!get_tx_fee(tx, r)) - return 0; - return r; - } - //--------------------------------------------------------------- - bool parse_tx_extra(const std::vector<uint8_t>& tx_extra, std::vector<tx_extra_field>& tx_extra_fields) - { - tx_extra_fields.clear(); - - if(tx_extra.empty()) - return true; - - std::string extra_str(reinterpret_cast<const char*>(tx_extra.data()), tx_extra.size()); - std::istringstream iss(extra_str); - binary_archive<false> ar(iss); - - bool eof = false; - while (!eof) - { - tx_extra_field field; - bool r = ::do_serialize(ar, field); - CHECK_AND_NO_ASSERT_MES_L1(r, false, "failed to deserialize extra field. extra = " << string_tools::buff_to_hex_nodelimer(std::string(reinterpret_cast<const char*>(tx_extra.data()), tx_extra.size()))); - tx_extra_fields.push_back(field); - - std::ios_base::iostate state = iss.rdstate(); - eof = (EOF == iss.peek()); - iss.clear(state); - } - CHECK_AND_NO_ASSERT_MES_L1(::serialization::check_stream_state(ar), false, "failed to deserialize extra field. extra = " << string_tools::buff_to_hex_nodelimer(std::string(reinterpret_cast<const char*>(tx_extra.data()), tx_extra.size()))); - - return true; - } - //--------------------------------------------------------------- - crypto::public_key get_tx_pub_key_from_extra(const std::vector<uint8_t>& tx_extra, size_t pk_index) - { - std::vector<tx_extra_field> tx_extra_fields; - parse_tx_extra(tx_extra, tx_extra_fields); - - tx_extra_pub_key pub_key_field; - if(!find_tx_extra_field_by_type(tx_extra_fields, pub_key_field, pk_index)) - return null_pkey; - - return pub_key_field.pub_key; - } - //--------------------------------------------------------------- - crypto::public_key get_tx_pub_key_from_extra(const transaction_prefix& tx_prefix, size_t pk_index) - { - return get_tx_pub_key_from_extra(tx_prefix.extra, pk_index); - } - //--------------------------------------------------------------- - crypto::public_key get_tx_pub_key_from_extra(const transaction& tx, size_t pk_index) - { - return get_tx_pub_key_from_extra(tx.extra, pk_index); - } - //--------------------------------------------------------------- - bool add_tx_pub_key_to_extra(transaction& tx, const crypto::public_key& tx_pub_key) - { - tx.extra.resize(tx.extra.size() + 1 + sizeof(crypto::public_key)); - tx.extra[tx.extra.size() - 1 - sizeof(crypto::public_key)] = TX_EXTRA_TAG_PUBKEY; - *reinterpret_cast<crypto::public_key*>(&tx.extra[tx.extra.size() - sizeof(crypto::public_key)]) = tx_pub_key; - return true; - } - //--------------------------------------------------------------- - bool add_extra_nonce_to_tx_extra(std::vector<uint8_t>& tx_extra, const blobdata& extra_nonce) - { - CHECK_AND_ASSERT_MES(extra_nonce.size() <= TX_EXTRA_NONCE_MAX_COUNT, false, "extra nonce could be 255 bytes max"); - size_t start_pos = tx_extra.size(); - tx_extra.resize(tx_extra.size() + 2 + extra_nonce.size()); - //write tag - tx_extra[start_pos] = TX_EXTRA_NONCE; - //write len - ++start_pos; - tx_extra[start_pos] = static_cast<uint8_t>(extra_nonce.size()); - //write data - ++start_pos; - memcpy(&tx_extra[start_pos], extra_nonce.data(), extra_nonce.size()); - return true; - } - //--------------------------------------------------------------- - bool remove_field_from_tx_extra(std::vector<uint8_t>& tx_extra, const std::type_info &type) - { - if (tx_extra.empty()) - return true; - std::string extra_str(reinterpret_cast<const char*>(tx_extra.data()), tx_extra.size()); - std::istringstream iss(extra_str); - binary_archive<false> ar(iss); - std::ostringstream oss; - binary_archive<true> newar(oss); - - bool eof = false; - while (!eof) - { - tx_extra_field field; - bool r = ::do_serialize(ar, field); - CHECK_AND_NO_ASSERT_MES_L1(r, false, "failed to deserialize extra field. extra = " << string_tools::buff_to_hex_nodelimer(std::string(reinterpret_cast<const char*>(tx_extra.data()), tx_extra.size()))); - if (field.type() != type) - ::do_serialize(newar, field); - - std::ios_base::iostate state = iss.rdstate(); - eof = (EOF == iss.peek()); - iss.clear(state); - } - CHECK_AND_NO_ASSERT_MES_L1(::serialization::check_stream_state(ar), false, "failed to deserialize extra field. extra = " << string_tools::buff_to_hex_nodelimer(std::string(reinterpret_cast<const char*>(tx_extra.data()), tx_extra.size()))); - tx_extra.clear(); - std::string s = oss.str(); - tx_extra.reserve(s.size()); - std::copy(s.begin(), s.end(), std::back_inserter(tx_extra)); - return true; - } - //--------------------------------------------------------------- - void set_payment_id_to_tx_extra_nonce(blobdata& extra_nonce, const crypto::hash& payment_id) - { - extra_nonce.clear(); - extra_nonce.push_back(TX_EXTRA_NONCE_PAYMENT_ID); - const uint8_t* payment_id_ptr = reinterpret_cast<const uint8_t*>(&payment_id); - std::copy(payment_id_ptr, payment_id_ptr + sizeof(payment_id), std::back_inserter(extra_nonce)); - } - //--------------------------------------------------------------- - void set_encrypted_payment_id_to_tx_extra_nonce(blobdata& extra_nonce, const crypto::hash8& payment_id) - { - extra_nonce.clear(); - extra_nonce.push_back(TX_EXTRA_NONCE_ENCRYPTED_PAYMENT_ID); - const uint8_t* payment_id_ptr = reinterpret_cast<const uint8_t*>(&payment_id); - std::copy(payment_id_ptr, payment_id_ptr + sizeof(payment_id), std::back_inserter(extra_nonce)); - } - //--------------------------------------------------------------- - bool get_payment_id_from_tx_extra_nonce(const blobdata& extra_nonce, crypto::hash& payment_id) - { - if(sizeof(crypto::hash) + 1 != extra_nonce.size()) - return false; - if(TX_EXTRA_NONCE_PAYMENT_ID != extra_nonce[0]) - return false; - payment_id = *reinterpret_cast<const crypto::hash*>(extra_nonce.data() + 1); - return true; - } - //--------------------------------------------------------------- - bool get_encrypted_payment_id_from_tx_extra_nonce(const blobdata& extra_nonce, crypto::hash8& payment_id) - { - if(sizeof(crypto::hash8) + 1 != extra_nonce.size()) - return false; - if (TX_EXTRA_NONCE_ENCRYPTED_PAYMENT_ID != extra_nonce[0]) - return false; - payment_id = *reinterpret_cast<const crypto::hash8*>(extra_nonce.data() + 1); - return true; - } - //--------------------------------------------------------------- - crypto::public_key get_destination_view_key_pub(const std::vector<tx_destination_entry> &destinations, const account_keys &sender_keys) - { - if (destinations.empty()) - return null_pkey; - for (size_t n = 1; n < destinations.size(); ++n) - { - if (!memcmp(&destinations[n].addr, &sender_keys.m_account_address, sizeof(destinations[0].addr))) - continue; - if (destinations[n].amount == 0) - continue; - if (memcmp(&destinations[n].addr, &destinations[0].addr, sizeof(destinations[0].addr))) - return null_pkey; - } - return destinations[0].addr.m_view_public_key; - } - //--------------------------------------------------------------- - bool encrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key) - { - crypto::key_derivation derivation; - crypto::hash hash; - char data[33]; /* A hash, and an extra byte */ - - if (!generate_key_derivation(public_key, secret_key, derivation)) - return false; - - memcpy(data, &derivation, 32); - data[32] = ENCRYPTED_PAYMENT_ID_TAIL; - cn_fast_hash(data, 33, hash); - - for (size_t b = 0; b < 8; ++b) - payment_id.data[b] ^= hash.data[b]; - - return true; - } - bool decrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key) - { - // Encryption and decryption are the same operation (xor with a key) - return encrypt_payment_id(payment_id, public_key, secret_key); - } - //--------------------------------------------------------------- - bool construct_tx_and_get_tx_key(const account_keys& sender_account_keys, const std::vector<tx_source_entry>& sources, const std::vector<tx_destination_entry>& destinations, std::vector<uint8_t> extra, transaction& tx, uint64_t unlock_time, crypto::secret_key &tx_key, bool rct) - { - std::vector<rct::key> amount_keys; - tx.set_null(); - amount_keys.clear(); - - tx.version = rct ? 2 : 1; - tx.unlock_time = unlock_time; - - tx.extra = extra; - keypair txkey = keypair::generate(); - remove_field_from_tx_extra(tx.extra, typeid(tx_extra_pub_key)); - add_tx_pub_key_to_extra(tx, txkey.pub); - tx_key = txkey.sec; - - // if we have a stealth payment id, find it and encrypt it with the tx key now - std::vector<tx_extra_field> tx_extra_fields; - if (parse_tx_extra(tx.extra, tx_extra_fields)) - { - tx_extra_nonce extra_nonce; - if (find_tx_extra_field_by_type(tx_extra_fields, extra_nonce)) - { - crypto::hash8 payment_id = null_hash8; - if (get_encrypted_payment_id_from_tx_extra_nonce(extra_nonce.nonce, payment_id)) - { - LOG_PRINT_L2("Encrypting payment id " << payment_id); - crypto::public_key view_key_pub = get_destination_view_key_pub(destinations, sender_account_keys); - if (view_key_pub == null_pkey) - { - LOG_ERROR("Destinations have to have exactly one output to support encrypted payment ids"); - return false; - } - - if (!encrypt_payment_id(payment_id, view_key_pub, txkey.sec)) - { - LOG_ERROR("Failed to encrypt payment id"); - return false; - } - - std::string extra_nonce; - set_encrypted_payment_id_to_tx_extra_nonce(extra_nonce, payment_id); - remove_field_from_tx_extra(tx.extra, typeid(tx_extra_nonce)); - if (!add_extra_nonce_to_tx_extra(tx.extra, extra_nonce)) - { - LOG_ERROR("Failed to add encrypted payment id to tx extra"); - return false; - } - LOG_PRINT_L1("Encrypted payment ID: " << payment_id); - } - } - } - else - { - LOG_ERROR("Failed to parse tx extra"); - return false; - } - - struct input_generation_context_data - { - keypair in_ephemeral; - }; - std::vector<input_generation_context_data> in_contexts; - - uint64_t summary_inputs_money = 0; - //fill inputs - int idx = -1; - for(const tx_source_entry& src_entr: sources) - { - ++idx; - if(src_entr.real_output >= src_entr.outputs.size()) - { - LOG_ERROR("real_output index (" << src_entr.real_output << ")bigger than output_keys.size()=" << src_entr.outputs.size()); - return false; - } - summary_inputs_money += src_entr.amount; - - //key_derivation recv_derivation; - in_contexts.push_back(input_generation_context_data()); - keypair& in_ephemeral = in_contexts.back().in_ephemeral; - crypto::key_image img; - if(!generate_key_image_helper(sender_account_keys, src_entr.real_out_tx_key, src_entr.real_output_in_tx_index, in_ephemeral, img)) - return false; - - //check that derivated key is equal with real output key - if( !(in_ephemeral.pub == src_entr.outputs[src_entr.real_output].second.dest) ) - { - LOG_ERROR("derived public key mismatch with output public key at index " << idx << ", real out " << src_entr.real_output << "! "<< ENDL << "derived_key:" - << string_tools::pod_to_hex(in_ephemeral.pub) << ENDL << "real output_public_key:" - << string_tools::pod_to_hex(src_entr.outputs[src_entr.real_output].second) ); - LOG_ERROR("amount " << src_entr.amount << ", rct " << src_entr.rct); - LOG_ERROR("tx pubkey " << src_entr.real_out_tx_key << ", real_output_in_tx_index " << src_entr.real_output_in_tx_index); - return false; - } - - //put key image into tx input - txin_to_key input_to_key; - input_to_key.amount = src_entr.amount; - input_to_key.k_image = img; - - //fill outputs array and use relative offsets - for(const tx_source_entry::output_entry& out_entry: src_entr.outputs) - input_to_key.key_offsets.push_back(out_entry.first); - - input_to_key.key_offsets = absolute_output_offsets_to_relative(input_to_key.key_offsets); - tx.vin.push_back(input_to_key); - } - - // "Shuffle" outs - std::vector<tx_destination_entry> shuffled_dsts(destinations); - std::sort(shuffled_dsts.begin(), shuffled_dsts.end(), [](const tx_destination_entry& de1, const tx_destination_entry& de2) { return de1.amount < de2.amount; } ); - - uint64_t summary_outs_money = 0; - //fill outputs - size_t output_index = 0; - for(const tx_destination_entry& dst_entr: shuffled_dsts) - { - CHECK_AND_ASSERT_MES(dst_entr.amount > 0 || tx.version > 1, false, "Destination with wrong amount: " << dst_entr.amount); - crypto::key_derivation derivation; - crypto::public_key out_eph_public_key; - bool r = crypto::generate_key_derivation(dst_entr.addr.m_view_public_key, txkey.sec, derivation); - CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to generate_key_derivation(" << dst_entr.addr.m_view_public_key << ", " << txkey.sec << ")"); - - if (tx.version > 1) - { - crypto::secret_key scalar1; - crypto::derivation_to_scalar(derivation, output_index, scalar1); - amount_keys.push_back(rct::sk2rct(scalar1)); - } - r = crypto::derive_public_key(derivation, output_index, dst_entr.addr.m_spend_public_key, out_eph_public_key); - CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to derive_public_key(" << derivation << ", " << output_index << ", "<< dst_entr.addr.m_spend_public_key << ")"); - - tx_out out; - out.amount = dst_entr.amount; - txout_to_key tk; - tk.key = out_eph_public_key; - out.target = tk; - tx.vout.push_back(out); - output_index++; - summary_outs_money += dst_entr.amount; - } - - //check money - if(summary_outs_money > summary_inputs_money ) - { - LOG_ERROR("Transaction inputs money ("<< summary_inputs_money << ") less than outputs money (" << summary_outs_money << ")"); - return false; - } - - // check for watch only wallet - bool zero_secret_key = true; - for (size_t i = 0; i < sizeof(sender_account_keys.m_spend_secret_key); ++i) - zero_secret_key &= (sender_account_keys.m_spend_secret_key.data[i] == 0); - if (zero_secret_key) - { - MDEBUG("Null secret key, skipping signatures"); - } - - if (tx.version == 1) - { - //generate ring signatures - crypto::hash tx_prefix_hash; - get_transaction_prefix_hash(tx, tx_prefix_hash); - - std::stringstream ss_ring_s; - size_t i = 0; - for(const tx_source_entry& src_entr: sources) - { - ss_ring_s << "pub_keys:" << ENDL; - std::vector<const crypto::public_key*> keys_ptrs; - std::vector<crypto::public_key> keys(src_entr.outputs.size()); - size_t ii = 0; - for(const tx_source_entry::output_entry& o: src_entr.outputs) - { - keys[ii] = rct2pk(o.second.dest); - keys_ptrs.push_back(&keys[ii]); - ss_ring_s << o.second.dest << ENDL; - ++ii; - } - - tx.signatures.push_back(std::vector<crypto::signature>()); - std::vector<crypto::signature>& sigs = tx.signatures.back(); - sigs.resize(src_entr.outputs.size()); - if (!zero_secret_key) - crypto::generate_ring_signature(tx_prefix_hash, boost::get<txin_to_key>(tx.vin[i]).k_image, keys_ptrs, in_contexts[i].in_ephemeral.sec, src_entr.real_output, sigs.data()); - ss_ring_s << "signatures:" << ENDL; - std::for_each(sigs.begin(), sigs.end(), [&](const crypto::signature& s){ss_ring_s << s << ENDL;}); - ss_ring_s << "prefix_hash:" << tx_prefix_hash << ENDL << "in_ephemeral_key: " << in_contexts[i].in_ephemeral.sec << ENDL << "real_output: " << src_entr.real_output; - i++; - } - - MCINFO("construct_tx", "transaction_created: " << get_transaction_hash(tx) << ENDL << obj_to_json_str(tx) << ENDL << ss_ring_s.str()); - } - else - { - size_t n_total_outs = sources[0].outputs.size(); // only for non-simple rct - - // the non-simple version is slightly smaller, but assumes all real inputs - // are on the same index, so can only be used if there just one ring. - bool use_simple_rct = sources.size() > 1; - - if (!use_simple_rct) - { - // non simple ringct requires all real inputs to be at the same index for all inputs - for(const tx_source_entry& src_entr: sources) - { - if(src_entr.real_output != sources.begin()->real_output) - { - LOG_ERROR("All inputs must have the same index for non-simple ringct"); - return false; - } - } - - // enforce same mixin for all outputs - for (size_t i = 1; i < sources.size(); ++i) { - if (n_total_outs != sources[i].outputs.size()) { - LOG_ERROR("Non-simple ringct transaction has varying mixin"); - return false; - } - } - } - - uint64_t amount_in = 0, amount_out = 0; - rct::ctkeyV inSk; - // mixRing indexing is done the other way round for simple - rct::ctkeyM mixRing(use_simple_rct ? sources.size() : n_total_outs); - rct::keyV destinations; - std::vector<uint64_t> inamounts, outamounts; - std::vector<unsigned int> index; - for (size_t i = 0; i < sources.size(); ++i) - { - rct::ctkey ctkey; - amount_in += sources[i].amount; - inamounts.push_back(sources[i].amount); - index.push_back(sources[i].real_output); - // inSk: (secret key, mask) - ctkey.dest = rct::sk2rct(in_contexts[i].in_ephemeral.sec); - ctkey.mask = sources[i].mask; - inSk.push_back(ctkey); - // inPk: (public key, commitment) - // will be done when filling in mixRing - } - for (size_t i = 0; i < tx.vout.size(); ++i) - { - destinations.push_back(rct::pk2rct(boost::get<txout_to_key>(tx.vout[i].target).key)); - outamounts.push_back(tx.vout[i].amount); - amount_out += tx.vout[i].amount; - } - - if (use_simple_rct) - { - // mixRing indexing is done the other way round for simple - for (size_t i = 0; i < sources.size(); ++i) - { - mixRing[i].resize(sources[i].outputs.size()); - for (size_t n = 0; n < sources[i].outputs.size(); ++n) - { - mixRing[i][n] = sources[i].outputs[n].second; - } - } - } - else - { - for (size_t i = 0; i < n_total_outs; ++i) // same index assumption - { - mixRing[i].resize(sources.size()); - for (size_t n = 0; n < sources.size(); ++n) - { - mixRing[i][n] = sources[n].outputs[i].second; - } - } - } - - // fee - if (!use_simple_rct && amount_in > amount_out) - outamounts.push_back(amount_in - amount_out); - - // zero out all amounts to mask rct outputs, real amounts are now encrypted - for (size_t i = 0; i < tx.vin.size(); ++i) - { - if (sources[i].rct) - boost::get<txin_to_key>(tx.vin[i]).amount = 0; - } - for (size_t i = 0; i < tx.vout.size(); ++i) - tx.vout[i].amount = 0; - - crypto::hash tx_prefix_hash; - get_transaction_prefix_hash(tx, tx_prefix_hash); - rct::ctkeyV outSk; - if (use_simple_rct) - tx.rct_signatures = rct::genRctSimple(rct::hash2rct(tx_prefix_hash), inSk, destinations, inamounts, outamounts, amount_in - amount_out, mixRing, amount_keys, index, outSk); - else - tx.rct_signatures = rct::genRct(rct::hash2rct(tx_prefix_hash), inSk, destinations, outamounts, mixRing, amount_keys, sources[0].real_output, outSk); // same index assumption - - CHECK_AND_ASSERT_MES(tx.vout.size() == outSk.size(), false, "outSk size does not match vout"); - - MCINFO("construct_tx", "transaction_created: " << get_transaction_hash(tx) << ENDL << obj_to_json_str(tx) << ENDL); - } - - return true; - } - //--------------------------------------------------------------- - bool construct_tx(const account_keys& sender_account_keys, const std::vector<tx_source_entry>& sources, const std::vector<tx_destination_entry>& destinations, std::vector<uint8_t> extra, transaction& tx, uint64_t unlock_time) - { - crypto::secret_key tx_key; - return construct_tx_and_get_tx_key(sender_account_keys, sources, destinations, extra, tx, unlock_time, tx_key); - } - //--------------------------------------------------------------- - bool get_inputs_money_amount(const transaction& tx, uint64_t& money) - { - money = 0; - for(const auto& in: tx.vin) - { - CHECKED_GET_SPECIFIC_VARIANT(in, const txin_to_key, tokey_in, false); - money += tokey_in.amount; - } - return true; - } - //--------------------------------------------------------------- - uint64_t get_block_height(const block& b) - { - CHECK_AND_ASSERT_MES(b.miner_tx.vin.size() == 1, 0, "wrong miner tx in block: " << get_block_hash(b) << ", b.miner_tx.vin.size() != 1"); - CHECKED_GET_SPECIFIC_VARIANT(b.miner_tx.vin[0], const txin_gen, coinbase_in, 0); - return coinbase_in.height; - } - //--------------------------------------------------------------- - bool check_inputs_types_supported(const transaction& tx) - { - for(const auto& in: tx.vin) - { - CHECK_AND_ASSERT_MES(in.type() == typeid(txin_to_key), false, "wrong variant type: " - << in.type().name() << ", expected " << typeid(txin_to_key).name() - << ", in transaction id=" << get_transaction_hash(tx)); - - } - return true; - } - //----------------------------------------------------------------------------------------------- - bool check_outs_valid(const transaction& tx) - { - for(const tx_out& out: tx.vout) - { - CHECK_AND_ASSERT_MES(out.target.type() == typeid(txout_to_key), false, "wrong variant type: " - << out.target.type().name() << ", expected " << typeid(txout_to_key).name() - << ", in transaction id=" << get_transaction_hash(tx)); - - if (tx.version == 1) - { - CHECK_AND_NO_ASSERT_MES(0 < out.amount, false, "zero amount output in transaction id=" << get_transaction_hash(tx)); - } - - if(!check_key(boost::get<txout_to_key>(out.target).key)) - return false; - } - return true; - } - //----------------------------------------------------------------------------------------------- - bool check_money_overflow(const transaction& tx) - { - return check_inputs_overflow(tx) && check_outs_overflow(tx); - } - //--------------------------------------------------------------- - bool check_inputs_overflow(const transaction& tx) - { - uint64_t money = 0; - for(const auto& in: tx.vin) - { - CHECKED_GET_SPECIFIC_VARIANT(in, const txin_to_key, tokey_in, false); - if(money > tokey_in.amount + money) - return false; - money += tokey_in.amount; - } - return true; - } - //--------------------------------------------------------------- - bool check_outs_overflow(const transaction& tx) - { - uint64_t money = 0; - for(const auto& o: tx.vout) - { - if(money > o.amount + money) - return false; - money += o.amount; - } - return true; - } - //--------------------------------------------------------------- - uint64_t get_outs_money_amount(const transaction& tx) - { - uint64_t outputs_amount = 0; - for(const auto& o: tx.vout) - outputs_amount += o.amount; - return outputs_amount; - } - //--------------------------------------------------------------- - std::string short_hash_str(const crypto::hash& h) - { - std::string res = string_tools::pod_to_hex(h); - CHECK_AND_ASSERT_MES(res.size() == 64, res, "wrong hash256 with string_tools::pod_to_hex conversion"); - auto erased_pos = res.erase(8, 48); - res.insert(8, "...."); - return res; - } - //--------------------------------------------------------------- - bool is_out_to_acc(const account_keys& acc, const txout_to_key& out_key, const crypto::public_key& tx_pub_key, size_t output_index) - { - crypto::key_derivation derivation; - generate_key_derivation(tx_pub_key, acc.m_view_secret_key, derivation); - crypto::public_key pk; - derive_public_key(derivation, output_index, acc.m_account_address.m_spend_public_key, pk); - return pk == out_key.key; - } - //--------------------------------------------------------------- - bool is_out_to_acc_precomp(const crypto::public_key& spend_public_key, const txout_to_key& out_key, const crypto::key_derivation& derivation, size_t output_index) - { - crypto::public_key pk; - derive_public_key(derivation, output_index, spend_public_key, pk); - return pk == out_key.key; - } - //--------------------------------------------------------------- - bool lookup_acc_outs(const account_keys& acc, const transaction& tx, std::vector<size_t>& outs, uint64_t& money_transfered) - { - crypto::public_key tx_pub_key = get_tx_pub_key_from_extra(tx); - if(null_pkey == tx_pub_key) - return false; - return lookup_acc_outs(acc, tx, tx_pub_key, outs, money_transfered); - } - //--------------------------------------------------------------- - bool lookup_acc_outs(const account_keys& acc, const transaction& tx, const crypto::public_key& tx_pub_key, std::vector<size_t>& outs, uint64_t& money_transfered) - { - money_transfered = 0; - size_t i = 0; - for(const tx_out& o: tx.vout) - { - CHECK_AND_ASSERT_MES(o.target.type() == typeid(txout_to_key), false, "wrong type id in transaction out" ); - if(is_out_to_acc(acc, boost::get<txout_to_key>(o.target), tx_pub_key, i)) - { - outs.push_back(i); - money_transfered += o.amount; - } - i++; - } - return true; - } - //--------------------------------------------------------------- - void get_blob_hash(const blobdata& blob, crypto::hash& res) - { - cn_fast_hash(blob.data(), blob.size(), res); - } - //--------------------------------------------------------------- - std::string print_money(uint64_t amount) - { - std::string s = std::to_string(amount); - if(s.size() < CRYPTONOTE_DISPLAY_DECIMAL_POINT+1) - { - s.insert(0, CRYPTONOTE_DISPLAY_DECIMAL_POINT+1 - s.size(), '0'); - } - s.insert(s.size() - CRYPTONOTE_DISPLAY_DECIMAL_POINT, "."); - return s; - } - //--------------------------------------------------------------- - crypto::hash get_blob_hash(const blobdata& blob) - { - crypto::hash h = null_hash; - get_blob_hash(blob, h); - return h; - } - //--------------------------------------------------------------- - crypto::hash get_transaction_hash(const transaction& t) - { - crypto::hash h = null_hash; - get_transaction_hash(t, h, NULL); - return h; - } - //--------------------------------------------------------------- - bool get_transaction_hash(const transaction& t, crypto::hash& res) - { - return get_transaction_hash(t, res, NULL); - } - //--------------------------------------------------------------- - bool get_transaction_hash(const transaction& t, crypto::hash& res, size_t* blob_size) - { - // v1 transactions hash the entire blob - if (t.version == 1) - { - size_t ignored_blob_size, &blob_size_ref = blob_size ? *blob_size : ignored_blob_size; - return get_object_hash(t, res, blob_size_ref); - } - - // v2 transactions hash different parts together, than hash the set of those hashes - crypto::hash hashes[3]; - - // prefix - get_transaction_prefix_hash(t, hashes[0]); - - transaction &tt = const_cast<transaction&>(t); - - // base rct - { - std::stringstream ss; - binary_archive<true> ba(ss); - const size_t inputs = t.vin.size(); - const size_t outputs = t.vout.size(); - bool r = tt.rct_signatures.serialize_rctsig_base(ba, inputs, outputs); - CHECK_AND_ASSERT_MES(r, false, "Failed to serialize rct signatures base"); - cryptonote::get_blob_hash(ss.str(), hashes[1]); - } - - // prunable rct - if (t.rct_signatures.type == rct::RCTTypeNull) - { - hashes[2] = cryptonote::null_hash; - } - else - { - std::stringstream ss; - binary_archive<true> ba(ss); - const size_t inputs = t.vin.size(); - const size_t outputs = t.vout.size(); - const size_t mixin = t.vin.empty() ? 0 : t.vin[0].type() == typeid(txin_to_key) ? boost::get<txin_to_key>(t.vin[0]).key_offsets.size() - 1 : 0; - bool r = tt.rct_signatures.p.serialize_rctsig_prunable(ba, t.rct_signatures.type, inputs, outputs, mixin); - CHECK_AND_ASSERT_MES(r, false, "Failed to serialize rct signatures prunable"); - cryptonote::get_blob_hash(ss.str(), hashes[2]); - } - - // the tx hash is the hash of the 3 hashes - res = cn_fast_hash(hashes, sizeof(hashes)); - - // we still need the size - if (blob_size) - *blob_size = get_object_blobsize(t); - - return true; - } - //--------------------------------------------------------------- - bool get_transaction_hash(const transaction& t, crypto::hash& res, size_t& blob_size) - { - return get_transaction_hash(t, res, &blob_size); - } - //--------------------------------------------------------------- - blobdata get_block_hashing_blob(const block& b) - { - blobdata blob = t_serializable_object_to_blob(static_cast<block_header>(b)); - crypto::hash tree_root_hash = get_tx_tree_hash(b); - blob.append(reinterpret_cast<const char*>(&tree_root_hash), sizeof(tree_root_hash)); - blob.append(tools::get_varint_data(b.tx_hashes.size()+1)); - return blob; - } - //--------------------------------------------------------------- - bool get_block_hash(const block& b, crypto::hash& res) - { - // EXCEPTION FOR BLOCK 202612 - const std::string correct_blob_hash_202612 = "3a8a2b3a29b50fc86ff73dd087ea43c6f0d6b8f936c849194d5c84c737903966"; - const std::string existing_block_id_202612 = "bbd604d2ba11ba27935e006ed39c9bfdd99b76bf4a50654bc1e1e61217962698"; - crypto::hash block_blob_hash = get_blob_hash(block_to_blob(b)); - - if (string_tools::pod_to_hex(block_blob_hash) == correct_blob_hash_202612) - { - string_tools::hex_to_pod(existing_block_id_202612, res); - return true; - } - bool hash_result = get_object_hash(get_block_hashing_blob(b), res); - - if (hash_result) - { - // make sure that we aren't looking at a block with the 202612 block id but not the correct blobdata - if (string_tools::pod_to_hex(res) == existing_block_id_202612) - { - LOG_ERROR("Block with block id for 202612 but incorrect block blob hash found!"); - res = null_hash; - return false; - } - } - return hash_result; - } - //--------------------------------------------------------------- - crypto::hash get_block_hash(const block& b) - { - crypto::hash p = null_hash; - get_block_hash(b, p); - return p; - } - //--------------------------------------------------------------- - bool generate_genesis_block( - block& bl - , std::string const & genesis_tx - , uint32_t nonce - ) - { - //genesis block - bl = boost::value_initialized<block>(); - - - account_public_address ac = boost::value_initialized<account_public_address>(); - std::vector<size_t> sz; - construct_miner_tx(0, 0, 0, 0, 0, ac, bl.miner_tx); // zero fee in genesis - blobdata txb = tx_to_blob(bl.miner_tx); - std::string hex_tx_represent = string_tools::buff_to_hex_nodelimer(txb); - - std::string genesis_coinbase_tx_hex = config::GENESIS_TX; - - blobdata tx_bl; - string_tools::parse_hexstr_to_binbuff(genesis_coinbase_tx_hex, tx_bl); - bool r = parse_and_validate_tx_from_blob(tx_bl, bl.miner_tx); - CHECK_AND_ASSERT_MES(r, false, "failed to parse coinbase tx from hard coded blob"); - bl.major_version = CURRENT_BLOCK_MAJOR_VERSION; - bl.minor_version = CURRENT_BLOCK_MINOR_VERSION; - bl.timestamp = 0; - bl.nonce = nonce; - miner::find_nonce_for_given_block(bl, 1, 0); - return true; - } - //--------------------------------------------------------------- - bool get_block_longhash(const block& b, crypto::hash& res, uint64_t height) - { - // block 202612 bug workaround - const std::string longhash_202612 = "84f64766475d51837ac9efbef1926486e58563c95a19fef4aec3254f03000000"; - if (height == 202612) - { - string_tools::hex_to_pod(longhash_202612, res); - return true; - } - block b_local = b; //workaround to avoid const errors with do_serialize - blobdata bd = get_block_hashing_blob(b); - crypto::cn_slow_hash(bd.data(), bd.size(), res); - return true; - } - //--------------------------------------------------------------- - std::vector<uint64_t> relative_output_offsets_to_absolute(const std::vector<uint64_t>& off) - { - std::vector<uint64_t> res = off; - for(size_t i = 1; i < res.size(); i++) - res[i] += res[i-1]; - return res; - } - //--------------------------------------------------------------- - std::vector<uint64_t> absolute_output_offsets_to_relative(const std::vector<uint64_t>& off) - { - std::vector<uint64_t> res = off; - if(!off.size()) - return res; - std::sort(res.begin(), res.end());//just to be sure, actually it is already should be sorted - for(size_t i = res.size()-1; i != 0; i--) - res[i] -= res[i-1]; - - return res; - } - //--------------------------------------------------------------- - crypto::hash get_block_longhash(const block& b, uint64_t height) - { - crypto::hash p = null_hash; - get_block_longhash(b, p, height); - return p; - } - //--------------------------------------------------------------- - bool parse_and_validate_block_from_blob(const blobdata& b_blob, block& b) - { - std::stringstream ss; - ss << b_blob; - binary_archive<false> ba(ss); - bool r = ::serialization::serialize(ba, b); - CHECK_AND_ASSERT_MES(r, false, "Failed to parse block from blob"); - return true; - } - //--------------------------------------------------------------- - blobdata block_to_blob(const block& b) - { - return t_serializable_object_to_blob(b); - } - //--------------------------------------------------------------- - bool block_to_blob(const block& b, blobdata& b_blob) - { - return t_serializable_object_to_blob(b, b_blob); - } - //--------------------------------------------------------------- - blobdata tx_to_blob(const transaction& tx) - { - return t_serializable_object_to_blob(tx); - } - //--------------------------------------------------------------- - bool tx_to_blob(const transaction& tx, blobdata& b_blob) - { - return t_serializable_object_to_blob(tx, b_blob); - } - //--------------------------------------------------------------- - void get_tx_tree_hash(const std::vector<crypto::hash>& tx_hashes, crypto::hash& h) - { - tree_hash(tx_hashes.data(), tx_hashes.size(), h); - } - //--------------------------------------------------------------- - crypto::hash get_tx_tree_hash(const std::vector<crypto::hash>& tx_hashes) - { - crypto::hash h = null_hash; - get_tx_tree_hash(tx_hashes, h); - return h; - } - //--------------------------------------------------------------- - crypto::hash get_tx_tree_hash(const block& b) - { - std::vector<crypto::hash> txs_ids; - crypto::hash h = null_hash; - size_t bl_sz = 0; - get_transaction_hash(b.miner_tx, h, bl_sz); - txs_ids.push_back(h); - for(auto& th: b.tx_hashes) - txs_ids.push_back(th); - return get_tx_tree_hash(txs_ids); - } - //--------------------------------------------------------------- - bool is_valid_decomposed_amount(uint64_t amount) - { - const uint64_t *begin = valid_decomposed_outputs; - const uint64_t *end = valid_decomposed_outputs + sizeof(valid_decomposed_outputs) / sizeof(valid_decomposed_outputs[0]); - return std::binary_search(begin, end, amount); - } - //--------------------------------------------------------------- -} diff --git a/src/cryptonote_core/cryptonote_format_utils.h b/src/cryptonote_core/cryptonote_format_utils.h deleted file mode 100644 index a6610e60d..000000000 --- a/src/cryptonote_core/cryptonote_format_utils.h +++ /dev/null @@ -1,274 +0,0 @@ -// Copyright (c) 2014-2016, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - -#pragma once -#include "cryptonote_protocol/cryptonote_protocol_defs.h" -#include "cryptonote_core/cryptonote_basic_impl.h" -#include "account.h" -#include "include_base_utils.h" -#include "crypto/crypto.h" -#include "crypto/hash.h" -#include "ringct/rctOps.h" -#include <boost/serialization/vector.hpp> -#include <boost/serialization/utility.hpp> - -namespace cryptonote -{ - //--------------------------------------------------------------- - void get_transaction_prefix_hash(const transaction_prefix& tx, crypto::hash& h); - crypto::hash get_transaction_prefix_hash(const transaction_prefix& tx); - bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx, crypto::hash& tx_hash, crypto::hash& tx_prefix_hash); - bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx); - bool construct_miner_tx(size_t height, size_t median_size, uint64_t already_generated_coins, size_t current_block_size, uint64_t fee, const account_public_address &miner_address, transaction& tx, const blobdata& extra_nonce = blobdata(), size_t max_outs = 999, uint8_t hard_fork_version = 1); - bool encrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key); - bool decrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key); - - struct tx_source_entry - { - typedef std::pair<uint64_t, rct::ctkey> output_entry; - - std::vector<output_entry> outputs; //index + key + optional ringct commitment - size_t real_output; //index in outputs vector of real output_entry - crypto::public_key real_out_tx_key; //incoming real tx public key - size_t real_output_in_tx_index; //index in transaction outputs vector - uint64_t amount; //money - bool rct; //true if the output is rct - rct::key mask; //ringct amount mask - - void push_output(uint64_t idx, const crypto::public_key &k, uint64_t amount) { outputs.push_back(std::make_pair(idx, rct::ctkey({rct::pk2rct(k), rct::zeroCommit(amount)}))); } - }; - - struct tx_destination_entry - { - uint64_t amount; //money - account_public_address addr; //destination address - - tx_destination_entry() : amount(0), addr(AUTO_VAL_INIT(addr)) { } - tx_destination_entry(uint64_t a, const account_public_address &ad) : amount(a), addr(ad) { } - - BEGIN_SERIALIZE_OBJECT() - VARINT_FIELD(amount) - FIELD(addr) - END_SERIALIZE() - }; - - //--------------------------------------------------------------- - bool construct_tx(const account_keys& sender_account_keys, const std::vector<tx_source_entry>& sources, const std::vector<tx_destination_entry>& destinations, std::vector<uint8_t> extra, transaction& tx, uint64_t unlock_time); - bool construct_tx_and_get_tx_key(const account_keys& sender_account_keys, const std::vector<tx_source_entry>& sources, const std::vector<tx_destination_entry>& destinations, std::vector<uint8_t> extra, transaction& tx, uint64_t unlock_time, crypto::secret_key &tx_key, bool rct = false); - - template<typename T> - bool find_tx_extra_field_by_type(const std::vector<tx_extra_field>& tx_extra_fields, T& field, size_t index = 0) - { - auto it = std::find_if(tx_extra_fields.begin(), tx_extra_fields.end(), [&index](const tx_extra_field& f) { return typeid(T) == f.type() && !index--; }); - if(tx_extra_fields.end() == it) - return false; - - field = boost::get<T>(*it); - return true; - } - - bool parse_tx_extra(const std::vector<uint8_t>& tx_extra, std::vector<tx_extra_field>& tx_extra_fields); - crypto::public_key get_tx_pub_key_from_extra(const std::vector<uint8_t>& tx_extra, size_t pk_index = 0); - crypto::public_key get_tx_pub_key_from_extra(const transaction_prefix& tx, size_t pk_index = 0); - crypto::public_key get_tx_pub_key_from_extra(const transaction& tx, size_t pk_index = 0); - bool add_tx_pub_key_to_extra(transaction& tx, const crypto::public_key& tx_pub_key); - bool add_extra_nonce_to_tx_extra(std::vector<uint8_t>& tx_extra, const blobdata& extra_nonce); - bool remove_field_from_tx_extra(std::vector<uint8_t>& tx_extra, const std::type_info &type); - void set_payment_id_to_tx_extra_nonce(blobdata& extra_nonce, const crypto::hash& payment_id); - void set_encrypted_payment_id_to_tx_extra_nonce(blobdata& extra_nonce, const crypto::hash8& payment_id); - bool get_payment_id_from_tx_extra_nonce(const blobdata& extra_nonce, crypto::hash& payment_id); - bool get_encrypted_payment_id_from_tx_extra_nonce(const blobdata& extra_nonce, crypto::hash8& payment_id); - bool is_out_to_acc(const account_keys& acc, const txout_to_key& out_key, const crypto::public_key& tx_pub_key, size_t output_index); - bool is_out_to_acc_precomp(const crypto::public_key& spend_public_key, const txout_to_key& out_key, const crypto::key_derivation& derivation, size_t output_index); - bool lookup_acc_outs(const account_keys& acc, const transaction& tx, const crypto::public_key& tx_pub_key, std::vector<size_t>& outs, uint64_t& money_transfered); - bool lookup_acc_outs(const account_keys& acc, const transaction& tx, std::vector<size_t>& outs, uint64_t& money_transfered); - bool get_tx_fee(const transaction& tx, uint64_t & fee); - uint64_t get_tx_fee(const transaction& tx); - bool generate_key_image_helper(const account_keys& ack, const crypto::public_key& tx_public_key, size_t real_output_index, keypair& in_ephemeral, crypto::key_image& ki); - void get_blob_hash(const blobdata& blob, crypto::hash& res); - crypto::hash get_blob_hash(const blobdata& blob); - std::string short_hash_str(const crypto::hash& h); - - crypto::hash get_transaction_hash(const transaction& t); - bool get_transaction_hash(const transaction& t, crypto::hash& res); - bool get_transaction_hash(const transaction& t, crypto::hash& res, size_t& blob_size); - bool get_transaction_hash(const transaction& t, crypto::hash& res, size_t* blob_size); - blobdata get_block_hashing_blob(const block& b); - bool get_block_hash(const block& b, crypto::hash& res); - crypto::hash get_block_hash(const block& b); - bool get_block_longhash(const block& b, crypto::hash& res, uint64_t height); - crypto::hash get_block_longhash(const block& b, uint64_t height); - bool generate_genesis_block( - block& bl - , std::string const & genesis_tx - , uint32_t nonce - ); - bool parse_and_validate_block_from_blob(const blobdata& b_blob, block& b); - bool get_inputs_money_amount(const transaction& tx, uint64_t& money); - uint64_t get_outs_money_amount(const transaction& tx); - bool check_inputs_types_supported(const transaction& tx); - bool check_outs_valid(const transaction& tx); - bool parse_amount(uint64_t& amount, const std::string& str_amount); - - bool check_money_overflow(const transaction& tx); - bool check_outs_overflow(const transaction& tx); - bool check_inputs_overflow(const transaction& tx); - uint64_t get_block_height(const block& b); - std::vector<uint64_t> relative_output_offsets_to_absolute(const std::vector<uint64_t>& off); - std::vector<uint64_t> absolute_output_offsets_to_relative(const std::vector<uint64_t>& off); - std::string print_money(uint64_t amount); - //--------------------------------------------------------------- - template<class t_object> - bool t_serializable_object_to_blob(const t_object& to, blobdata& b_blob) - { - std::stringstream ss; - binary_archive<true> ba(ss); - bool r = ::serialization::serialize(ba, const_cast<t_object&>(to)); - b_blob = ss.str(); - return r; - } - //--------------------------------------------------------------- - template<class t_object> - blobdata t_serializable_object_to_blob(const t_object& to) - { - blobdata b; - t_serializable_object_to_blob(to, b); - return b; - } - //--------------------------------------------------------------- - template<class t_object> - bool get_object_hash(const t_object& o, crypto::hash& res) - { - get_blob_hash(t_serializable_object_to_blob(o), res); - return true; - } - //--------------------------------------------------------------- - template<class t_object> - size_t get_object_blobsize(const t_object& o) - { - blobdata b = t_serializable_object_to_blob(o); - return b.size(); - } - //--------------------------------------------------------------- - template<class t_object> - bool get_object_hash(const t_object& o, crypto::hash& res, size_t& blob_size) - { - blobdata bl = t_serializable_object_to_blob(o); - blob_size = bl.size(); - get_blob_hash(bl, res); - return true; - } - //--------------------------------------------------------------- - template <typename T> - std::string obj_to_json_str(T& obj) - { - std::stringstream ss; - json_archive<true> ar(ss, true); - bool r = ::serialization::serialize(ar, obj); - CHECK_AND_ASSERT_MES(r, "", "obj_to_json_str failed: serialization::serialize returned false"); - return ss.str(); - } - //--------------------------------------------------------------- - // 62387455827 -> 455827 + 7000000 + 80000000 + 300000000 + 2000000000 + 60000000000, where 455827 <= dust_threshold - template<typename chunk_handler_t, typename dust_handler_t> - void decompose_amount_into_digits(uint64_t amount, uint64_t dust_threshold, const chunk_handler_t& chunk_handler, const dust_handler_t& dust_handler) - { - if (0 == amount) - { - return; - } - - bool is_dust_handled = false; - uint64_t dust = 0; - uint64_t order = 1; - while (0 != amount) - { - uint64_t chunk = (amount % 10) * order; - amount /= 10; - order *= 10; - - if (dust + chunk <= dust_threshold) - { - dust += chunk; - } - else - { - if (!is_dust_handled && 0 != dust) - { - dust_handler(dust); - is_dust_handled = true; - } - if (0 != chunk) - { - chunk_handler(chunk); - } - } - } - - if (!is_dust_handled && 0 != dust) - { - dust_handler(dust); - } - } - //--------------------------------------------------------------- - blobdata block_to_blob(const block& b); - bool block_to_blob(const block& b, blobdata& b_blob); - blobdata tx_to_blob(const transaction& b); - bool tx_to_blob(const transaction& b, blobdata& b_blob); - void get_tx_tree_hash(const std::vector<crypto::hash>& tx_hashes, crypto::hash& h); - crypto::hash get_tx_tree_hash(const std::vector<crypto::hash>& tx_hashes); - crypto::hash get_tx_tree_hash(const block& b); - bool is_valid_decomposed_amount(uint64_t amount); - -#define CHECKED_GET_SPECIFIC_VARIANT(variant_var, specific_type, variable_name, fail_return_val) \ - CHECK_AND_ASSERT_MES(variant_var.type() == typeid(specific_type), fail_return_val, "wrong variant type: " << variant_var.type().name() << ", expected " << typeid(specific_type).name()); \ - specific_type& variable_name = boost::get<specific_type>(variant_var); - -} - -BOOST_CLASS_VERSION(cryptonote::tx_source_entry, 0) - -namespace boost -{ - namespace serialization - { - template <class Archive> - inline void serialize(Archive &a, cryptonote::tx_source_entry &x, const boost::serialization::version_type ver) - { - a & x.outputs; - a & x.real_output; - a & x.real_out_tx_key; - a & x.real_output_in_tx_index; - a & x.amount; - a & x.rct; - a & x.mask; - } - } -} diff --git a/src/cryptonote_core/cryptonote_stat_info.h b/src/cryptonote_core/cryptonote_stat_info.h deleted file mode 100644 index d44904b6d..000000000 --- a/src/cryptonote_core/cryptonote_stat_info.h +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) 2014-2016, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - -#pragma once -#include "serialization/keyvalue_serialization.h" - - -namespace cryptonote -{ - struct core_stat_info - { - uint64_t tx_pool_size; - uint64_t blockchain_height; - uint64_t mining_speed; - uint64_t alternative_blocks; - std::string top_block_id_str; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(tx_pool_size) - KV_SERIALIZE(blockchain_height) - KV_SERIALIZE(mining_speed) - KV_SERIALIZE(alternative_blocks) - KV_SERIALIZE(top_block_id_str) - END_KV_SERIALIZE_MAP() - }; -} diff --git a/src/cryptonote_core/cryptonote_tx_utils.cpp b/src/cryptonote_core/cryptonote_tx_utils.cpp new file mode 100644 index 000000000..42e612e2f --- /dev/null +++ b/src/cryptonote_core/cryptonote_tx_utils.cpp @@ -0,0 +1,493 @@ +// Copyright (c) 2014-2016, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers + +#include "include_base_utils.h" +using namespace epee; + +#include "cryptonote_tx_utils.h" +#include "cryptonote_config.h" +#include "cryptonote_basic/miner.h" +#include "crypto/crypto.h" +#include "crypto/hash.h" +#include "ringct/rctSigs.h" + +namespace cryptonote +{ + //--------------------------------------------------------------- + bool construct_miner_tx(size_t height, size_t median_size, uint64_t already_generated_coins, size_t current_block_size, uint64_t fee, const account_public_address &miner_address, transaction& tx, const blobdata& extra_nonce, size_t max_outs, uint8_t hard_fork_version) { + tx.vin.clear(); + tx.vout.clear(); + tx.extra.clear(); + + keypair txkey = keypair::generate(); + add_tx_pub_key_to_extra(tx, txkey.pub); + if(!extra_nonce.empty()) + if(!add_extra_nonce_to_tx_extra(tx.extra, extra_nonce)) + return false; + + txin_gen in; + in.height = height; + + uint64_t block_reward; + if(!get_block_reward(median_size, current_block_size, already_generated_coins, block_reward, hard_fork_version)) + { + LOG_PRINT_L0("Block is too big"); + return false; + } + +#if defined(DEBUG_CREATE_BLOCK_TEMPLATE) + LOG_PRINT_L1("Creating block template: reward " << block_reward << + ", fee " << fee); +#endif + block_reward += fee; + + // from hard fork 2, we cut out the low significant digits. This makes the tx smaller, and + // keeps the paid amount almost the same. The unpaid remainder gets pushed back to the + // emission schedule + // from hard fork 4, we use a single "dusty" output. This makes the tx even smaller, + // and avoids the quantization. These outputs will be added as rct outputs with identity + // masks, to they can be used as rct inputs. + if (hard_fork_version >= 2 && hard_fork_version < 4) { + block_reward = block_reward - block_reward % ::config::BASE_REWARD_CLAMP_THRESHOLD; + } + + std::vector<uint64_t> out_amounts; + decompose_amount_into_digits(block_reward, hard_fork_version >= 2 ? 0 : ::config::DEFAULT_DUST_THRESHOLD, + [&out_amounts](uint64_t a_chunk) { out_amounts.push_back(a_chunk); }, + [&out_amounts](uint64_t a_dust) { out_amounts.push_back(a_dust); }); + + CHECK_AND_ASSERT_MES(1 <= max_outs, false, "max_out must be non-zero"); + if (height == 0 || hard_fork_version >= 4) + { + // the genesis block was not decomposed, for unknown reasons + while (max_outs < out_amounts.size()) + { + //out_amounts[out_amounts.size() - 2] += out_amounts.back(); + //out_amounts.resize(out_amounts.size() - 1); + out_amounts[1] += out_amounts[0]; + for (size_t n = 1; n < out_amounts.size(); ++n) + out_amounts[n - 1] = out_amounts[n]; + out_amounts.resize(out_amounts.size() - 1); + } + } + else + { + CHECK_AND_ASSERT_MES(max_outs >= out_amounts.size(), false, "max_out exceeded"); + } + + uint64_t summary_amounts = 0; + for (size_t no = 0; no < out_amounts.size(); no++) + { + crypto::key_derivation derivation = AUTO_VAL_INIT(derivation);; + crypto::public_key out_eph_public_key = AUTO_VAL_INIT(out_eph_public_key); + bool r = crypto::generate_key_derivation(miner_address.m_view_public_key, txkey.sec, derivation); + CHECK_AND_ASSERT_MES(r, false, "while creating outs: failed to generate_key_derivation(" << miner_address.m_view_public_key << ", " << txkey.sec << ")"); + + r = crypto::derive_public_key(derivation, no, miner_address.m_spend_public_key, out_eph_public_key); + CHECK_AND_ASSERT_MES(r, false, "while creating outs: failed to derive_public_key(" << derivation << ", " << no << ", "<< miner_address.m_spend_public_key << ")"); + + txout_to_key tk; + tk.key = out_eph_public_key; + + tx_out out; + summary_amounts += out.amount = out_amounts[no]; + out.target = tk; + tx.vout.push_back(out); + } + + CHECK_AND_ASSERT_MES(summary_amounts == block_reward, false, "Failed to construct miner tx, summary_amounts = " << summary_amounts << " not equal block_reward = " << block_reward); + + if (hard_fork_version >= 4) + tx.version = 2; + else + tx.version = 1; + + //lock + tx.unlock_time = height + CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW; + tx.vin.push_back(in); + //LOG_PRINT("MINER_TX generated ok, block_reward=" << print_money(block_reward) << "(" << print_money(block_reward - fee) << "+" << print_money(fee) + // << "), current_block_size=" << current_block_size << ", already_generated_coins=" << already_generated_coins << ", tx_id=" << get_transaction_hash(tx), LOG_LEVEL_2); + return true; + } + //--------------------------------------------------------------- + crypto::public_key get_destination_view_key_pub(const std::vector<tx_destination_entry> &destinations, const account_keys &sender_keys) + { + if (destinations.empty()) + return null_pkey; + for (size_t n = 1; n < destinations.size(); ++n) + { + if (!memcmp(&destinations[n].addr, &sender_keys.m_account_address, sizeof(destinations[0].addr))) + continue; + if (destinations[n].amount == 0) + continue; + if (memcmp(&destinations[n].addr, &destinations[0].addr, sizeof(destinations[0].addr))) + return null_pkey; + } + return destinations[0].addr.m_view_public_key; + } + //--------------------------------------------------------------- + bool construct_tx_and_get_tx_key(const account_keys& sender_account_keys, const std::vector<tx_source_entry>& sources, const std::vector<tx_destination_entry>& destinations, std::vector<uint8_t> extra, transaction& tx, uint64_t unlock_time, crypto::secret_key &tx_key, bool rct) + { + std::vector<rct::key> amount_keys; + tx.set_null(); + amount_keys.clear(); + + tx.version = rct ? 2 : 1; + tx.unlock_time = unlock_time; + + tx.extra = extra; + keypair txkey = keypair::generate(); + remove_field_from_tx_extra(tx.extra, typeid(tx_extra_pub_key)); + add_tx_pub_key_to_extra(tx, txkey.pub); + tx_key = txkey.sec; + + // if we have a stealth payment id, find it and encrypt it with the tx key now + std::vector<tx_extra_field> tx_extra_fields; + if (parse_tx_extra(tx.extra, tx_extra_fields)) + { + tx_extra_nonce extra_nonce; + if (find_tx_extra_field_by_type(tx_extra_fields, extra_nonce)) + { + crypto::hash8 payment_id = null_hash8; + if (get_encrypted_payment_id_from_tx_extra_nonce(extra_nonce.nonce, payment_id)) + { + LOG_PRINT_L2("Encrypting payment id " << payment_id); + crypto::public_key view_key_pub = get_destination_view_key_pub(destinations, sender_account_keys); + if (view_key_pub == null_pkey) + { + LOG_ERROR("Destinations have to have exactly one output to support encrypted payment ids"); + return false; + } + + if (!encrypt_payment_id(payment_id, view_key_pub, txkey.sec)) + { + LOG_ERROR("Failed to encrypt payment id"); + return false; + } + + std::string extra_nonce; + set_encrypted_payment_id_to_tx_extra_nonce(extra_nonce, payment_id); + remove_field_from_tx_extra(tx.extra, typeid(tx_extra_nonce)); + if (!add_extra_nonce_to_tx_extra(tx.extra, extra_nonce)) + { + LOG_ERROR("Failed to add encrypted payment id to tx extra"); + return false; + } + LOG_PRINT_L1("Encrypted payment ID: " << payment_id); + } + } + } + else + { + LOG_ERROR("Failed to parse tx extra"); + return false; + } + + struct input_generation_context_data + { + keypair in_ephemeral; + }; + std::vector<input_generation_context_data> in_contexts; + + uint64_t summary_inputs_money = 0; + //fill inputs + int idx = -1; + for(const tx_source_entry& src_entr: sources) + { + ++idx; + if(src_entr.real_output >= src_entr.outputs.size()) + { + LOG_ERROR("real_output index (" << src_entr.real_output << ")bigger than output_keys.size()=" << src_entr.outputs.size()); + return false; + } + summary_inputs_money += src_entr.amount; + + //key_derivation recv_derivation; + in_contexts.push_back(input_generation_context_data()); + keypair& in_ephemeral = in_contexts.back().in_ephemeral; + crypto::key_image img; + if(!generate_key_image_helper(sender_account_keys, src_entr.real_out_tx_key, src_entr.real_output_in_tx_index, in_ephemeral, img)) + return false; + + //check that derivated key is equal with real output key + if( !(in_ephemeral.pub == src_entr.outputs[src_entr.real_output].second.dest) ) + { + LOG_ERROR("derived public key mismatch with output public key at index " << idx << ", real out " << src_entr.real_output << "! "<< ENDL << "derived_key:" + << string_tools::pod_to_hex(in_ephemeral.pub) << ENDL << "real output_public_key:" + << string_tools::pod_to_hex(src_entr.outputs[src_entr.real_output].second) ); + LOG_ERROR("amount " << src_entr.amount << ", rct " << src_entr.rct); + LOG_ERROR("tx pubkey " << src_entr.real_out_tx_key << ", real_output_in_tx_index " << src_entr.real_output_in_tx_index); + return false; + } + + //put key image into tx input + txin_to_key input_to_key; + input_to_key.amount = src_entr.amount; + input_to_key.k_image = img; + + //fill outputs array and use relative offsets + for(const tx_source_entry::output_entry& out_entry: src_entr.outputs) + input_to_key.key_offsets.push_back(out_entry.first); + + input_to_key.key_offsets = absolute_output_offsets_to_relative(input_to_key.key_offsets); + tx.vin.push_back(input_to_key); + } + + // "Shuffle" outs + std::vector<tx_destination_entry> shuffled_dsts(destinations); + std::sort(shuffled_dsts.begin(), shuffled_dsts.end(), [](const tx_destination_entry& de1, const tx_destination_entry& de2) { return de1.amount < de2.amount; } ); + + uint64_t summary_outs_money = 0; + //fill outputs + size_t output_index = 0; + for(const tx_destination_entry& dst_entr: shuffled_dsts) + { + CHECK_AND_ASSERT_MES(dst_entr.amount > 0 || tx.version > 1, false, "Destination with wrong amount: " << dst_entr.amount); + crypto::key_derivation derivation; + crypto::public_key out_eph_public_key; + bool r = crypto::generate_key_derivation(dst_entr.addr.m_view_public_key, txkey.sec, derivation); + CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to generate_key_derivation(" << dst_entr.addr.m_view_public_key << ", " << txkey.sec << ")"); + + if (tx.version > 1) + { + crypto::secret_key scalar1; + crypto::derivation_to_scalar(derivation, output_index, scalar1); + amount_keys.push_back(rct::sk2rct(scalar1)); + } + r = crypto::derive_public_key(derivation, output_index, dst_entr.addr.m_spend_public_key, out_eph_public_key); + CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to derive_public_key(" << derivation << ", " << output_index << ", "<< dst_entr.addr.m_spend_public_key << ")"); + + tx_out out; + out.amount = dst_entr.amount; + txout_to_key tk; + tk.key = out_eph_public_key; + out.target = tk; + tx.vout.push_back(out); + output_index++; + summary_outs_money += dst_entr.amount; + } + + //check money + if(summary_outs_money > summary_inputs_money ) + { + LOG_ERROR("Transaction inputs money ("<< summary_inputs_money << ") less than outputs money (" << summary_outs_money << ")"); + return false; + } + + // check for watch only wallet + bool zero_secret_key = true; + for (size_t i = 0; i < sizeof(sender_account_keys.m_spend_secret_key); ++i) + zero_secret_key &= (sender_account_keys.m_spend_secret_key.data[i] == 0); + if (zero_secret_key) + { + MDEBUG("Null secret key, skipping signatures"); + } + + if (tx.version == 1) + { + //generate ring signatures + crypto::hash tx_prefix_hash; + get_transaction_prefix_hash(tx, tx_prefix_hash); + + std::stringstream ss_ring_s; + size_t i = 0; + for(const tx_source_entry& src_entr: sources) + { + ss_ring_s << "pub_keys:" << ENDL; + std::vector<const crypto::public_key*> keys_ptrs; + std::vector<crypto::public_key> keys(src_entr.outputs.size()); + size_t ii = 0; + for(const tx_source_entry::output_entry& o: src_entr.outputs) + { + keys[ii] = rct2pk(o.second.dest); + keys_ptrs.push_back(&keys[ii]); + ss_ring_s << o.second.dest << ENDL; + ++ii; + } + + tx.signatures.push_back(std::vector<crypto::signature>()); + std::vector<crypto::signature>& sigs = tx.signatures.back(); + sigs.resize(src_entr.outputs.size()); + if (!zero_secret_key) + crypto::generate_ring_signature(tx_prefix_hash, boost::get<txin_to_key>(tx.vin[i]).k_image, keys_ptrs, in_contexts[i].in_ephemeral.sec, src_entr.real_output, sigs.data()); + ss_ring_s << "signatures:" << ENDL; + std::for_each(sigs.begin(), sigs.end(), [&](const crypto::signature& s){ss_ring_s << s << ENDL;}); + ss_ring_s << "prefix_hash:" << tx_prefix_hash << ENDL << "in_ephemeral_key: " << in_contexts[i].in_ephemeral.sec << ENDL << "real_output: " << src_entr.real_output; + i++; + } + + MCINFO("construct_tx", "transaction_created: " << get_transaction_hash(tx) << ENDL << obj_to_json_str(tx) << ENDL << ss_ring_s.str()); + } + else + { + size_t n_total_outs = sources[0].outputs.size(); // only for non-simple rct + + // the non-simple version is slightly smaller, but assumes all real inputs + // are on the same index, so can only be used if there just one ring. + bool use_simple_rct = sources.size() > 1; + + if (!use_simple_rct) + { + // non simple ringct requires all real inputs to be at the same index for all inputs + for(const tx_source_entry& src_entr: sources) + { + if(src_entr.real_output != sources.begin()->real_output) + { + LOG_ERROR("All inputs must have the same index for non-simple ringct"); + return false; + } + } + + // enforce same mixin for all outputs + for (size_t i = 1; i < sources.size(); ++i) { + if (n_total_outs != sources[i].outputs.size()) { + LOG_ERROR("Non-simple ringct transaction has varying mixin"); + return false; + } + } + } + + uint64_t amount_in = 0, amount_out = 0; + rct::ctkeyV inSk; + // mixRing indexing is done the other way round for simple + rct::ctkeyM mixRing(use_simple_rct ? sources.size() : n_total_outs); + rct::keyV destinations; + std::vector<uint64_t> inamounts, outamounts; + std::vector<unsigned int> index; + for (size_t i = 0; i < sources.size(); ++i) + { + rct::ctkey ctkey; + amount_in += sources[i].amount; + inamounts.push_back(sources[i].amount); + index.push_back(sources[i].real_output); + // inSk: (secret key, mask) + ctkey.dest = rct::sk2rct(in_contexts[i].in_ephemeral.sec); + ctkey.mask = sources[i].mask; + inSk.push_back(ctkey); + // inPk: (public key, commitment) + // will be done when filling in mixRing + } + for (size_t i = 0; i < tx.vout.size(); ++i) + { + destinations.push_back(rct::pk2rct(boost::get<txout_to_key>(tx.vout[i].target).key)); + outamounts.push_back(tx.vout[i].amount); + amount_out += tx.vout[i].amount; + } + + if (use_simple_rct) + { + // mixRing indexing is done the other way round for simple + for (size_t i = 0; i < sources.size(); ++i) + { + mixRing[i].resize(sources[i].outputs.size()); + for (size_t n = 0; n < sources[i].outputs.size(); ++n) + { + mixRing[i][n] = sources[i].outputs[n].second; + } + } + } + else + { + for (size_t i = 0; i < n_total_outs; ++i) // same index assumption + { + mixRing[i].resize(sources.size()); + for (size_t n = 0; n < sources.size(); ++n) + { + mixRing[i][n] = sources[n].outputs[i].second; + } + } + } + + // fee + if (!use_simple_rct && amount_in > amount_out) + outamounts.push_back(amount_in - amount_out); + + // zero out all amounts to mask rct outputs, real amounts are now encrypted + for (size_t i = 0; i < tx.vin.size(); ++i) + { + if (sources[i].rct) + boost::get<txin_to_key>(tx.vin[i]).amount = 0; + } + for (size_t i = 0; i < tx.vout.size(); ++i) + tx.vout[i].amount = 0; + + crypto::hash tx_prefix_hash; + get_transaction_prefix_hash(tx, tx_prefix_hash); + rct::ctkeyV outSk; + if (use_simple_rct) + tx.rct_signatures = rct::genRctSimple(rct::hash2rct(tx_prefix_hash), inSk, destinations, inamounts, outamounts, amount_in - amount_out, mixRing, amount_keys, index, outSk); + else + tx.rct_signatures = rct::genRct(rct::hash2rct(tx_prefix_hash), inSk, destinations, outamounts, mixRing, amount_keys, sources[0].real_output, outSk); // same index assumption + + CHECK_AND_ASSERT_MES(tx.vout.size() == outSk.size(), false, "outSk size does not match vout"); + + MCINFO("construct_tx", "transaction_created: " << get_transaction_hash(tx) << ENDL << obj_to_json_str(tx) << ENDL); + } + + return true; + } + //--------------------------------------------------------------- + bool construct_tx(const account_keys& sender_account_keys, const std::vector<tx_source_entry>& sources, const std::vector<tx_destination_entry>& destinations, std::vector<uint8_t> extra, transaction& tx, uint64_t unlock_time) + { + crypto::secret_key tx_key; + return construct_tx_and_get_tx_key(sender_account_keys, sources, destinations, extra, tx, unlock_time, tx_key); + } + //--------------------------------------------------------------- + bool generate_genesis_block( + block& bl + , std::string const & genesis_tx + , uint32_t nonce + ) + { + //genesis block + bl = boost::value_initialized<block>(); + + + account_public_address ac = boost::value_initialized<account_public_address>(); + std::vector<size_t> sz; + construct_miner_tx(0, 0, 0, 0, 0, ac, bl.miner_tx); // zero fee in genesis + blobdata txb = tx_to_blob(bl.miner_tx); + std::string hex_tx_represent = string_tools::buff_to_hex_nodelimer(txb); + + std::string genesis_coinbase_tx_hex = config::GENESIS_TX; + + blobdata tx_bl; + string_tools::parse_hexstr_to_binbuff(genesis_coinbase_tx_hex, tx_bl); + bool r = parse_and_validate_tx_from_blob(tx_bl, bl.miner_tx); + CHECK_AND_ASSERT_MES(r, false, "failed to parse coinbase tx from hard coded blob"); + bl.major_version = CURRENT_BLOCK_MAJOR_VERSION; + bl.minor_version = CURRENT_BLOCK_MINOR_VERSION; + bl.timestamp = 0; + bl.nonce = nonce; + miner::find_nonce_for_given_block(bl, 1, 0); + return true; + } + //--------------------------------------------------------------- +} diff --git a/src/cryptonote_core/cryptonote_tx_utils.h b/src/cryptonote_core/cryptonote_tx_utils.h new file mode 100644 index 000000000..859318fe5 --- /dev/null +++ b/src/cryptonote_core/cryptonote_tx_utils.h @@ -0,0 +1,101 @@ +// Copyright (c) 2014-2016, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers + +#pragma once +#include "cryptonote_basic/cryptonote_format_utils.h" +#include <boost/serialization/vector.hpp> +#include <boost/serialization/utility.hpp> + +namespace cryptonote +{ + //--------------------------------------------------------------- + bool construct_miner_tx(size_t height, size_t median_size, uint64_t already_generated_coins, size_t current_block_size, uint64_t fee, const account_public_address &miner_address, transaction& tx, const blobdata& extra_nonce = blobdata(), size_t max_outs = 999, uint8_t hard_fork_version = 1); + + struct tx_source_entry + { + typedef std::pair<uint64_t, rct::ctkey> output_entry; + + std::vector<output_entry> outputs; //index + key + optional ringct commitment + size_t real_output; //index in outputs vector of real output_entry + crypto::public_key real_out_tx_key; //incoming real tx public key + size_t real_output_in_tx_index; //index in transaction outputs vector + uint64_t amount; //money + bool rct; //true if the output is rct + rct::key mask; //ringct amount mask + + void push_output(uint64_t idx, const crypto::public_key &k, uint64_t amount) { outputs.push_back(std::make_pair(idx, rct::ctkey({rct::pk2rct(k), rct::zeroCommit(amount)}))); } + }; + + struct tx_destination_entry + { + uint64_t amount; //money + account_public_address addr; //destination address + + tx_destination_entry() : amount(0), addr(AUTO_VAL_INIT(addr)) { } + tx_destination_entry(uint64_t a, const account_public_address &ad) : amount(a), addr(ad) { } + + BEGIN_SERIALIZE_OBJECT() + VARINT_FIELD(amount) + FIELD(addr) + END_SERIALIZE() + }; + + //--------------------------------------------------------------- + crypto::public_key get_destination_view_key_pub(const std::vector<tx_destination_entry> &destinations, const account_keys &sender_keys); + bool construct_tx(const account_keys& sender_account_keys, const std::vector<tx_source_entry>& sources, const std::vector<tx_destination_entry>& destinations, std::vector<uint8_t> extra, transaction& tx, uint64_t unlock_time); + bool construct_tx_and_get_tx_key(const account_keys& sender_account_keys, const std::vector<tx_source_entry>& sources, const std::vector<tx_destination_entry>& destinations, std::vector<uint8_t> extra, transaction& tx, uint64_t unlock_time, crypto::secret_key &tx_key, bool rct = false); + + bool generate_genesis_block( + block& bl + , std::string const & genesis_tx + , uint32_t nonce + ); + +} + +BOOST_CLASS_VERSION(cryptonote::tx_source_entry, 0) + +namespace boost +{ + namespace serialization + { + template <class Archive> + inline void serialize(Archive &a, cryptonote::tx_source_entry &x, const boost::serialization::version_type ver) + { + a & x.outputs; + a & x.real_output; + a & x.real_out_tx_key; + a & x.real_output_in_tx_index; + a & x.amount; + a & x.rct; + a & x.mask; + } + } +} diff --git a/src/cryptonote_core/difficulty.cpp b/src/cryptonote_core/difficulty.cpp deleted file mode 100644 index 1c5b9cfbd..000000000 --- a/src/cryptonote_core/difficulty.cpp +++ /dev/null @@ -1,165 +0,0 @@ -// Copyright (c) 2014-2016, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - -#include <algorithm> -#include <cassert> -#include <cstddef> -#include <cstdint> -#include <vector> - -#include "common/int-util.h" -#include "crypto/hash.h" -#include "cryptonote_config.h" -#include "difficulty.h" - -#undef MONERO_DEFAULT_LOG_CATEGORY -#define MONERO_DEFAULT_LOG_CATEGORY "difficulty" - -namespace cryptonote { - - using std::size_t; - using std::uint64_t; - using std::vector; - -#if defined(__x86_64__) - static inline void mul(uint64_t a, uint64_t b, uint64_t &low, uint64_t &high) { - low = mul128(a, b, &high); - } - -#else - - static inline void mul(uint64_t a, uint64_t b, uint64_t &low, uint64_t &high) { - // __int128 isn't part of the standard, so the previous function wasn't portable. mul128() in Windows is fine, - // but this portable function should be used elsewhere. Credit for this function goes to latexi95. - - uint64_t aLow = a & 0xFFFFFFFF; - uint64_t aHigh = a >> 32; - uint64_t bLow = b & 0xFFFFFFFF; - uint64_t bHigh = b >> 32; - - uint64_t res = aLow * bLow; - uint64_t lowRes1 = res & 0xFFFFFFFF; - uint64_t carry = res >> 32; - - res = aHigh * bLow + carry; - uint64_t highResHigh1 = res >> 32; - uint64_t highResLow1 = res & 0xFFFFFFFF; - - res = aLow * bHigh; - uint64_t lowRes2 = res & 0xFFFFFFFF; - carry = res >> 32; - - res = aHigh * bHigh + carry; - uint64_t highResHigh2 = res >> 32; - uint64_t highResLow2 = res & 0xFFFFFFFF; - - //Addition - - uint64_t r = highResLow1 + lowRes2; - carry = r >> 32; - low = (r << 32) | lowRes1; - r = highResHigh1 + highResLow2 + carry; - uint64_t d3 = r & 0xFFFFFFFF; - carry = r >> 32; - r = highResHigh2 + carry; - high = d3 | (r << 32); - } - -#endif - - static inline bool cadd(uint64_t a, uint64_t b) { - return a + b < a; - } - - static inline bool cadc(uint64_t a, uint64_t b, bool c) { - return a + b < a || (c && a + b == (uint64_t) -1); - } - - bool check_hash(const crypto::hash &hash, difficulty_type difficulty) { - uint64_t low, high, top, cur; - // First check the highest word, this will most likely fail for a random hash. - mul(swap64le(((const uint64_t *) &hash)[3]), difficulty, top, high); - if (high != 0) { - return false; - } - mul(swap64le(((const uint64_t *) &hash)[0]), difficulty, low, cur); - mul(swap64le(((const uint64_t *) &hash)[1]), difficulty, low, high); - bool carry = cadd(cur, low); - cur = high; - mul(swap64le(((const uint64_t *) &hash)[2]), difficulty, low, high); - carry = cadc(cur, low, carry); - carry = cadc(high, top, carry); - return !carry; - } - - difficulty_type next_difficulty(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds) { - - if(timestamps.size() > DIFFICULTY_WINDOW) - { - timestamps.resize(DIFFICULTY_WINDOW); - cumulative_difficulties.resize(DIFFICULTY_WINDOW); - } - - - size_t length = timestamps.size(); - assert(length == cumulative_difficulties.size()); - if (length <= 1) { - return 1; - } - static_assert(DIFFICULTY_WINDOW >= 2, "Window is too small"); - assert(length <= DIFFICULTY_WINDOW); - sort(timestamps.begin(), timestamps.end()); - size_t cut_begin, cut_end; - static_assert(2 * DIFFICULTY_CUT <= DIFFICULTY_WINDOW - 2, "Cut length is too large"); - if (length <= DIFFICULTY_WINDOW - 2 * DIFFICULTY_CUT) { - cut_begin = 0; - cut_end = length; - } else { - cut_begin = (length - (DIFFICULTY_WINDOW - 2 * DIFFICULTY_CUT) + 1) / 2; - cut_end = cut_begin + (DIFFICULTY_WINDOW - 2 * DIFFICULTY_CUT); - } - assert(/*cut_begin >= 0 &&*/ cut_begin + 2 <= cut_end && cut_end <= length); - uint64_t time_span = timestamps[cut_end - 1] - timestamps[cut_begin]; - if (time_span == 0) { - time_span = 1; - } - difficulty_type total_work = cumulative_difficulties[cut_end - 1] - cumulative_difficulties[cut_begin]; - assert(total_work > 0); - uint64_t low, high; - mul(total_work, target_seconds, low, high); - // blockchain errors "difficulty overhead" if this function returns zero. - // TODO: consider throwing an exception instead - if (high != 0 || low + time_span - 1 < low) { - return 0; - } - return (low + time_span - 1) / time_span; - } - -} diff --git a/src/cryptonote_core/difficulty.h b/src/cryptonote_core/difficulty.h deleted file mode 100644 index 910f97035..000000000 --- a/src/cryptonote_core/difficulty.h +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (c) 2014-2016, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - -#pragma once - -#include <cstdint> -#include <vector> - -#include "crypto/hash.h" - -namespace cryptonote -{ - typedef std::uint64_t difficulty_type; - - /** - * @brief checks if a hash fits the given difficulty - * - * The hash passes if (hash * difficulty) < 2^192. - * Phrased differently, if (hash * difficulty) fits without overflow into - * the least significant 192 bits of the 256 bit multiplication result. - * - * @param hash the hash to check - * @param difficulty the difficulty to check against - * - * @return true if valid, else false - */ - bool check_hash(const crypto::hash &hash, difficulty_type difficulty); - difficulty_type next_difficulty(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds); -} diff --git a/src/cryptonote_core/hardfork.cpp b/src/cryptonote_core/hardfork.cpp deleted file mode 100644 index 13d7d717d..000000000 --- a/src/cryptonote_core/hardfork.cpp +++ /dev/null @@ -1,416 +0,0 @@ -// Copyright (c) 2014-2016, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include <algorithm> -#include <cstdio> - -#include "cryptonote_core/cryptonote_basic.h" -#include "blockchain_db/blockchain_db.h" -#include "hardfork.h" - -#undef MONERO_DEFAULT_LOG_CATEGORY -#define MONERO_DEFAULT_LOG_CATEGORY "hardfork" - -using namespace cryptonote; - -static uint8_t get_block_vote(const cryptonote::block &b) -{ - // Pre-hardfork blocks have a minor version hardcoded to 0. - // For the purposes of voting, we consider 0 to refer to - // version number 1, which is what all blocks from the genesis - // block are. It makes things simpler. - if (b.minor_version == 0) - return 1; - return b.minor_version; -} - -static uint8_t get_block_version(const cryptonote::block &b) -{ - return b.major_version; -} - -HardFork::HardFork(cryptonote::BlockchainDB &db, uint8_t original_version, uint64_t original_version_till_height, time_t forked_time, time_t update_time, uint64_t window_size, uint8_t default_threshold_percent): - db(db), - original_version(original_version), - original_version_till_height(original_version_till_height), - forked_time(forked_time), - update_time(update_time), - window_size(window_size), - default_threshold_percent(default_threshold_percent) -{ - if (window_size == 0) - throw "window_size needs to be strictly positive"; - if (default_threshold_percent > 100) - throw "default_threshold_percent needs to be between 0 and 100"; -} - -bool HardFork::add_fork(uint8_t version, uint64_t height, uint8_t threshold, time_t time) -{ - CRITICAL_REGION_LOCAL(lock); - - // add in order - if (version == 0) - return false; - if (!heights.empty()) { - if (version <= heights.back().version) - return false; - if (height <= heights.back().height) - return false; - if (time <= heights.back().time) - return false; - } - if (threshold > 100) - return false; - heights.push_back(Params(version, height, threshold, time)); - return true; -} - -bool HardFork::add_fork(uint8_t version, uint64_t height, time_t time) -{ - return add_fork(version, height, default_threshold_percent, time); -} - -uint8_t HardFork::get_effective_version(uint8_t voting_version) const -{ - if (!heights.empty()) { - uint8_t max_version = heights.back().version; - if (voting_version > max_version) - voting_version = max_version; - } - return voting_version; -} - -bool HardFork::do_check(uint8_t block_version, uint8_t voting_version) const -{ - return block_version == heights[current_fork_index].version - && voting_version >= heights[current_fork_index].version; -} - -bool HardFork::check(const cryptonote::block &block) const -{ - CRITICAL_REGION_LOCAL(lock); - return do_check(::get_block_version(block), ::get_block_vote(block)); -} - -bool HardFork::do_check_for_height(uint8_t block_version, uint8_t voting_version, uint64_t height) const -{ - int fork_index = get_voted_fork_index(height); - return block_version == heights[fork_index].version - && voting_version >= heights[fork_index].version; -} - -bool HardFork::check_for_height(const cryptonote::block &block, uint64_t height) const -{ - CRITICAL_REGION_LOCAL(lock); - return do_check_for_height(::get_block_version(block), ::get_block_vote(block), height); -} - -bool HardFork::add(uint8_t block_version, uint8_t voting_version, uint64_t height) -{ - CRITICAL_REGION_LOCAL(lock); - - if (!do_check(block_version, voting_version)) - return false; - - db.set_hard_fork_version(height, heights[current_fork_index].version); - - voting_version = get_effective_version(voting_version); - - while (versions.size() >= window_size) { - const uint8_t old_version = versions.front(); - assert(last_versions[old_version] >= 1); - last_versions[old_version]--; - versions.pop_front(); - } - - last_versions[voting_version]++; - versions.push_back(voting_version); - - uint8_t voted = get_voted_fork_index(height + 1); - if (voted > current_fork_index) { - current_fork_index = voted; - } - - return true; -} - -bool HardFork::add(const cryptonote::block &block, uint64_t height) -{ - return add(::get_block_version(block), ::get_block_vote(block), height); -} - -void HardFork::init() -{ - CRITICAL_REGION_LOCAL(lock); - - // add a placeholder for the default version, to avoid special cases - if (heights.empty()) - heights.push_back(Params(original_version, 0, 0, 0)); - - versions.clear(); - for (size_t n = 0; n < 256; ++n) - last_versions[n] = 0; - current_fork_index = 0; - - // restore state from DB - uint64_t height = db.height(); - if (height > window_size) - height -= window_size - 1; - else - height = 1; - - bool populate = false; - try - { - db.get_hard_fork_version(0); - } - catch (...) { populate = true; } - if (populate) { - LOG_PRINT_L0("The DB has no hard fork info, reparsing from start"); - height = 1; - } - LOG_PRINT_L1("reorganizing from " << height); - if (populate) { - reorganize_from_chain_height(height); - // reorg will not touch the genesis block, use this as a flag for populating done - db.set_hard_fork_version(0, original_version); - } - else { - rescan_from_chain_height(height); - } - LOG_PRINT_L1("reorganization done"); -} - -uint8_t HardFork::get_block_version(uint64_t height) const -{ - if (height <= original_version_till_height) - return original_version; - - const cryptonote::block &block = db.get_block_from_height(height); - return ::get_block_version(block); -} - -bool HardFork::reorganize_from_block_height(uint64_t height) -{ - CRITICAL_REGION_LOCAL(lock); - if (height >= db.height()) - return false; - - db.set_batch_transactions(true); - db.batch_start(); - - versions.clear(); - - for (size_t n = 0; n < 256; ++n) - last_versions[n] = 0; - const uint64_t rescan_height = height >= (window_size - 1) ? height - (window_size -1) : 0; - const uint8_t start_version = height == 0 ? original_version : db.get_hard_fork_version(height); - while (current_fork_index > 0 && heights[current_fork_index].version > start_version) { - --current_fork_index; - } - for (uint64_t h = rescan_height; h <= height; ++h) { - cryptonote::block b = db.get_block_from_height(h); - const uint8_t v = get_effective_version(get_block_vote(b)); - last_versions[v]++; - versions.push_back(v); - } - - uint8_t voted = get_voted_fork_index(height + 1); - if (voted > current_fork_index) { - current_fork_index = voted; - } - - const uint64_t bc_height = db.height(); - for (uint64_t h = height + 1; h < bc_height; ++h) { - add(db.get_block_from_height(h), h); - } - - db.batch_stop(); - - return true; -} - -bool HardFork::reorganize_from_chain_height(uint64_t height) -{ - if (height == 0) - return false; - return reorganize_from_block_height(height - 1); -} - -bool HardFork::rescan_from_block_height(uint64_t height) -{ - CRITICAL_REGION_LOCAL(lock); - db.block_txn_start(true); - if (height >= db.height()) { - db.block_txn_stop(); - return false; - } - - versions.clear(); - - for (size_t n = 0; n < 256; ++n) - last_versions[n] = 0; - for (uint64_t h = height; h < db.height(); ++h) { - cryptonote::block b = db.get_block_from_height(h); - const uint8_t v = get_effective_version(get_block_vote(b)); - last_versions[v]++; - versions.push_back(v); - } - - uint8_t lastv = db.get_hard_fork_version(db.height() - 1); - current_fork_index = 0; - while (current_fork_index + 1 < heights.size() && heights[current_fork_index].version != lastv) - ++current_fork_index; - - uint8_t voted = get_voted_fork_index(db.height()); - if (voted > current_fork_index) { - current_fork_index = voted; - } - - db.block_txn_stop(); - - return true; -} - -bool HardFork::rescan_from_chain_height(uint64_t height) -{ - if (height == 0) - return false; - return rescan_from_block_height(height - 1); -} - -int HardFork::get_voted_fork_index(uint64_t height) const -{ - CRITICAL_REGION_LOCAL(lock); - uint32_t accumulated_votes = 0; - for (unsigned int n = heights.size() - 1; n > current_fork_index; --n) { - uint8_t v = heights[n].version; - accumulated_votes += last_versions[v]; - uint32_t threshold = (window_size * heights[n].threshold + 99) / 100; - if (height >= heights[n].height && accumulated_votes >= threshold) { - return n; - } - } - return current_fork_index; -} - -HardFork::State HardFork::get_state(time_t t) const -{ - CRITICAL_REGION_LOCAL(lock); - - // no hard forks setup yet - if (heights.size() <= 1) - return Ready; - - time_t t_last_fork = heights.back().time; - if (t >= t_last_fork + forked_time) - return LikelyForked; - if (t >= t_last_fork + update_time) - return UpdateNeeded; - return Ready; -} - -HardFork::State HardFork::get_state() const -{ - return get_state(time(NULL)); -} - -uint8_t HardFork::get(uint64_t height) const -{ - CRITICAL_REGION_LOCAL(lock); - if (height > db.height()) { - assert(false); - return 255; - } - if (height == db.height()) { - return get_current_version(); - } - return db.get_hard_fork_version(height); -} - -uint8_t HardFork::get_current_version() const -{ - CRITICAL_REGION_LOCAL(lock); - return heights[current_fork_index].version; -} - -uint8_t HardFork::get_ideal_version() const -{ - CRITICAL_REGION_LOCAL(lock); - return heights.back().version; -} - -uint8_t HardFork::get_ideal_version(uint64_t height) const -{ - CRITICAL_REGION_LOCAL(lock); - for (unsigned int n = heights.size() - 1; n > 0; --n) { - if (height >= heights[n].height) { - return heights[n].version; - } - } - return original_version; -} - -uint64_t HardFork::get_earliest_ideal_height_for_version(uint8_t version) const -{ - for (unsigned int n = heights.size() - 1; n > 0; --n) { - if (heights[n].version <= version) - return heights[n].height; - } - return 0; -} - -uint8_t HardFork::get_next_version() const -{ - CRITICAL_REGION_LOCAL(lock); - uint64_t height = db.height(); - for (unsigned int n = heights.size() - 1; n > 0; --n) { - if (height >= heights[n].height) { - return heights[n < heights.size() - 1 ? n + 1 : n].version; - } - } - return original_version; -} - -bool HardFork::get_voting_info(uint8_t version, uint32_t &window, uint32_t &votes, uint32_t &threshold, uint64_t &earliest_height, uint8_t &voting) const -{ - CRITICAL_REGION_LOCAL(lock); - - const uint8_t current_version = heights[current_fork_index].version; - const bool enabled = current_version >= version; - window = versions.size(); - votes = 0; - for (size_t n = version; n < 256; ++n) - votes += last_versions[n]; - threshold = (window * heights[current_fork_index].threshold + 99) / 100; - //assert((votes >= threshold) == enabled); - earliest_height = get_earliest_ideal_height_for_version(version); - voting = heights.back().version; - return enabled; -} - diff --git a/src/cryptonote_core/hardfork.h b/src/cryptonote_core/hardfork.h deleted file mode 100644 index 8d2edfa2a..000000000 --- a/src/cryptonote_core/hardfork.h +++ /dev/null @@ -1,265 +0,0 @@ -// Copyright (c) 2014-2016, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#pragma once - -#include "syncobj.h" -#include "cryptonote_core/cryptonote_basic.h" - -namespace cryptonote -{ - class BlockchainDB; - - class HardFork - { - public: - typedef enum { - LikelyForked, - UpdateNeeded, - Ready, - } State; - - static const uint64_t DEFAULT_ORIGINAL_VERSION_TILL_HEIGHT = 0; // <= actual height - static const time_t DEFAULT_FORKED_TIME = 31557600; // a year in seconds - static const time_t DEFAULT_UPDATE_TIME = 31557600 / 2; - static const uint64_t DEFAULT_WINDOW_SIZE = 10080; // supermajority window check length - a week - static const uint8_t DEFAULT_THRESHOLD_PERCENT = 80; - - /** - * @brief creates a new HardFork object - * - * @param original_version the block version for blocks 0 through to the first fork - * @param forked_time the time in seconds before thinking we're forked - * @param update_time the time in seconds before thinking we need to update - * @param window_size the size of the window in blocks to consider for version voting - * @param default_threshold_percent the size of the majority in percents - */ - HardFork(cryptonote::BlockchainDB &db, uint8_t original_version = 1, uint64_t original_version_till_height = DEFAULT_ORIGINAL_VERSION_TILL_HEIGHT, time_t forked_time = DEFAULT_FORKED_TIME, time_t update_time = DEFAULT_UPDATE_TIME, uint64_t window_size = DEFAULT_WINDOW_SIZE, uint8_t default_threshold_percent = DEFAULT_THRESHOLD_PERCENT); - - /** - * @brief add a new hardfork height - * - * returns true if no error, false otherwise - * - * @param version the major block version for the fork - * @param height The height the hardfork takes effect - * @param threshold The threshold of votes needed for this fork (0-100) - * @param time Approximate time of the hardfork (seconds since epoch) - */ - bool add_fork(uint8_t version, uint64_t height, uint8_t threshold, time_t time); - - /** - * @brief add a new hardfork height - * - * returns true if no error, false otherwise - * - * @param version the major block version for the fork - * @param voting_version the minor block version for the fork, used for voting - * @param height The height the hardfork takes effect - * @param time Approximate time of the hardfork (seconds since epoch) - */ - bool add_fork(uint8_t version, uint64_t height, time_t time); - - /** - * @brief initialize the object - * - * Must be done after adding all the required hardforks via add above - */ - void init(); - - /** - * @brief check whether a new block would be accepted - * - * returns true if the block is accepted, false otherwise - * - * @param block the new block - * - * This check is made by add. It is exposed publicly to allow - * the caller to inexpensively check whether a block would be - * accepted or rejected by its version number. Indeed, if this - * check could only be done as part of add, the caller would - * either have to add the block to the blockchain first, then - * call add, then have to pop the block from the blockchain if - * its version did not satisfy the hard fork requirements, or - * call add first, then, if the hard fork requirements are met, - * add the block to the blockchain, upon which a failure (the - * block being invalid, double spending, etc) would cause the - * hardfork object to reorganize. - */ - bool check(const cryptonote::block &block) const; - - /** - * @brief same as check, but for a particular height, rather than the top - * - * NOTE: this does not play well with voting, and relies on voting to be - * disabled (that is, forks happen on the scheduled date, whether or not - * enough blocks have voted for the fork). - * - * returns true if no error, false otherwise - * - * @param block the new block - * @param height which height to check for - */ - bool check_for_height(const cryptonote::block &block, uint64_t height) const; - - /** - * @brief add a new block - * - * returns true if no error, false otherwise - * - * @param block the new block - */ - bool add(const cryptonote::block &block, uint64_t height); - - /** - * @brief called when the blockchain is reorganized - * - * This will rescan the blockchain to determine which hard forks - * have been triggered - * - * returns true if no error, false otherwise - * - * @param blockchain the blockchain - * @param height of the last block kept from the previous blockchain - */ - bool reorganize_from_block_height(uint64_t height); - bool reorganize_from_chain_height(uint64_t height); - - /** - * @brief returns current state at the given time - * - * Based on the approximate time of the last known hard fork, - * estimate whether we need to update, or if we're way behind - * - * @param t the time to consider - */ - State get_state(time_t t) const; - State get_state() const; - - /** - * @brief returns the hard fork version for the given block height - * - * @param height height of the block to check - */ - uint8_t get(uint64_t height) const; - - /** - * @brief returns the latest "ideal" version - * - * This is the latest version that's been scheduled - */ - uint8_t get_ideal_version() const; - - /** - * @brief returns the "ideal" version for a given height - * - * @param height height of the block to check - */ - uint8_t get_ideal_version(uint64_t height) const; - - /** - * @brief returns the next version - * - * This is the version which will we fork to next - */ - uint8_t get_next_version() const; - - /** - * @brief returns the current version - * - * This is the latest version that's past its trigger date and had enough votes - * at one point in the past. - */ - uint8_t get_current_version() const; - - /** - * @brief returns the earliest block a given version may activate - */ - uint64_t get_earliest_ideal_height_for_version(uint8_t version) const; - - /** - * @brief returns information about current voting state - * - * returns true if the given version is enabled (ie, the current version - * is at least the passed version), false otherwise - * - * @param version the version to check voting for - * @param window the number of blocks considered in voting - * @param votes number of votes for next version - * @param threshold number of votes needed to switch to next version - * @param earliest_height earliest height at which the version can take effect - */ - bool get_voting_info(uint8_t version, uint32_t &window, uint32_t &votes, uint32_t &threshold, uint64_t &earliest_height, uint8_t &voting) const; - - /** - * @brief returns the size of the voting window in blocks - */ - uint64_t get_window_size() const { return window_size; } - - private: - - uint8_t get_block_version(uint64_t height) const; - bool do_check(uint8_t block_version, uint8_t voting_version) const; - bool do_check_for_height(uint8_t block_version, uint8_t voting_version, uint64_t height) const; - int get_voted_fork_index(uint64_t height) const; - uint8_t get_effective_version(uint8_t voting_version) const; - bool add(uint8_t block_version, uint8_t voting_version, uint64_t height); - - bool rescan_from_block_height(uint64_t height); - bool rescan_from_chain_height(uint64_t height); - - private: - - BlockchainDB &db; - - time_t forked_time; - time_t update_time; - uint64_t window_size; - uint8_t default_threshold_percent; - - uint8_t original_version; - uint64_t original_version_till_height; - - struct Params { - uint8_t version; - uint8_t threshold; - uint64_t height; - time_t time; - Params(uint8_t version, uint64_t height, uint8_t threshold, time_t time): version(version), threshold(threshold), height(height), time(time) {} - }; - std::vector<Params> heights; - - std::deque<uint8_t> versions; /* rolling window of the last N blocks' versions */ - unsigned int last_versions[256]; /* count of the block versions in the last N blocks */ - uint32_t current_fork_index; - - mutable epee::critical_section lock; - }; - -} // namespace cryptonote - diff --git a/src/cryptonote_core/miner.cpp b/src/cryptonote_core/miner.cpp deleted file mode 100644 index 88c631f80..000000000 --- a/src/cryptonote_core/miner.cpp +++ /dev/null @@ -1,414 +0,0 @@ -// Copyright (c) 2014-2016, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - -#include <sstream> -#include <numeric> -#include <boost/utility/value_init.hpp> -#include <boost/interprocess/detail/atomic.hpp> -#include <boost/limits.hpp> -#include "misc_language.h" -#include "include_base_utils.h" -#include "cryptonote_basic_impl.h" -#include "cryptonote_format_utils.h" -#include "file_io_utils.h" -#include "common/command_line.h" -#include "string_coding.h" -#include "storages/portable_storage_template_helper.h" - -#undef MONERO_DEFAULT_LOG_CATEGORY -#define MONERO_DEFAULT_LOG_CATEGORY "miner" - -using namespace epee; - -#include "miner.h" - - -extern "C" void slow_hash_allocate_state(); -extern "C" void slow_hash_free_state(); -namespace cryptonote -{ - - namespace - { - const command_line::arg_descriptor<std::string> arg_extra_messages = {"extra-messages-file", "Specify file for extra messages to include into coinbase transactions", "", true}; - const command_line::arg_descriptor<std::string> arg_start_mining = {"start-mining", "Specify wallet address to mining for", "", true}; - const command_line::arg_descriptor<uint32_t> arg_mining_threads = {"mining-threads", "Specify mining threads count", 0, true}; - } - - - miner::miner(i_miner_handler* phandler):m_stop(1), - m_template(boost::value_initialized<block>()), - m_template_no(0), - m_diffic(0), - m_thread_index(0), - m_phandler(phandler), - m_height(0), - m_pausers_count(0), - m_threads_total(0), - m_starter_nonce(0), - m_last_hr_merge_time(0), - m_hashes(0), - m_do_print_hashrate(false), - m_do_mining(false), - m_current_hash_rate(0) - { - - } - //----------------------------------------------------------------------------------------------------- - miner::~miner() - { - stop(); - } - //----------------------------------------------------------------------------------------------------- - bool miner::set_block_template(const block& bl, const difficulty_type& di, uint64_t height) - { - CRITICAL_REGION_LOCAL(m_template_lock); - m_template = bl; - m_diffic = di; - m_height = height; - ++m_template_no; - m_starter_nonce = crypto::rand<uint32_t>(); - return true; - } - //----------------------------------------------------------------------------------------------------- - bool miner::on_block_chain_update() - { - if(!is_mining()) - return true; - - return request_block_template(); - } - //----------------------------------------------------------------------------------------------------- - bool miner::request_block_template() - { - block bl = AUTO_VAL_INIT(bl); - difficulty_type di = AUTO_VAL_INIT(di); - uint64_t height = AUTO_VAL_INIT(height); - cryptonote::blobdata extra_nonce; - if(m_extra_messages.size() && m_config.current_extra_message_index < m_extra_messages.size()) - { - extra_nonce = m_extra_messages[m_config.current_extra_message_index]; - } - - if(!m_phandler->get_block_template(bl, m_mine_address, di, height, extra_nonce)) - { - LOG_ERROR("Failed to get_block_template(), stopping mining"); - return false; - } - set_block_template(bl, di, height); - return true; - } - //----------------------------------------------------------------------------------------------------- - bool miner::on_idle() - { - m_update_block_template_interval.do_call([&](){ - if(is_mining())request_block_template(); - return true; - }); - - m_update_merge_hr_interval.do_call([&](){ - merge_hr(); - return true; - }); - - return true; - } - //----------------------------------------------------------------------------------------------------- - void miner::do_print_hashrate(bool do_hr) - { - m_do_print_hashrate = do_hr; - } - //----------------------------------------------------------------------------------------------------- - void miner::merge_hr() - { - if(m_last_hr_merge_time && is_mining()) - { - m_current_hash_rate = m_hashes * 1000 / ((misc_utils::get_tick_count() - m_last_hr_merge_time + 1)); - CRITICAL_REGION_LOCAL(m_last_hash_rates_lock); - m_last_hash_rates.push_back(m_current_hash_rate); - if(m_last_hash_rates.size() > 19) - m_last_hash_rates.pop_front(); - if(m_do_print_hashrate) - { - uint64_t total_hr = std::accumulate(m_last_hash_rates.begin(), m_last_hash_rates.end(), 0); - float hr = static_cast<float>(total_hr)/static_cast<float>(m_last_hash_rates.size()); - std::cout << "hashrate: " << std::setprecision(4) << std::fixed << hr << ENDL; - } - } - m_last_hr_merge_time = misc_utils::get_tick_count(); - m_hashes = 0; - } - //----------------------------------------------------------------------------------------------------- - void miner::init_options(boost::program_options::options_description& desc) - { - command_line::add_arg(desc, arg_extra_messages); - command_line::add_arg(desc, arg_start_mining); - command_line::add_arg(desc, arg_mining_threads); - } - //----------------------------------------------------------------------------------------------------- - bool miner::init(const boost::program_options::variables_map& vm, bool testnet) - { - if(command_line::has_arg(vm, arg_extra_messages)) - { - std::string buff; - bool r = file_io_utils::load_file_to_string(command_line::get_arg(vm, arg_extra_messages), buff); - CHECK_AND_ASSERT_MES(r, false, "Failed to load file with extra messages: " << command_line::get_arg(vm, arg_extra_messages)); - std::vector<std::string> extra_vec; - boost::split(extra_vec, buff, boost::is_any_of("\n"), boost::token_compress_on ); - m_extra_messages.resize(extra_vec.size()); - for(size_t i = 0; i != extra_vec.size(); i++) - { - string_tools::trim(extra_vec[i]); - if(!extra_vec[i].size()) - continue; - std::string buff = string_encoding::base64_decode(extra_vec[i]); - if(buff != "0") - m_extra_messages[i] = buff; - } - m_config_folder_path = boost::filesystem::path(command_line::get_arg(vm, arg_extra_messages)).parent_path().string(); - m_config = AUTO_VAL_INIT(m_config); - epee::serialization::load_t_from_json_file(m_config, m_config_folder_path + "/" + MINER_CONFIG_FILE_NAME); - MINFO("Loaded " << m_extra_messages.size() << " extra messages, current index " << m_config.current_extra_message_index); - } - - if(command_line::has_arg(vm, arg_start_mining)) - { - if(!cryptonote::get_account_address_from_str(m_mine_address, testnet, command_line::get_arg(vm, arg_start_mining))) - { - LOG_ERROR("Target account address " << command_line::get_arg(vm, arg_start_mining) << " has wrong format, starting daemon canceled"); - return false; - } - m_threads_total = 1; - m_do_mining = true; - if(command_line::has_arg(vm, arg_mining_threads)) - { - m_threads_total = command_line::get_arg(vm, arg_mining_threads); - } - } - - return true; - } - //----------------------------------------------------------------------------------------------------- - bool miner::is_mining() const - { - return !m_stop; - } - //----------------------------------------------------------------------------------------------------- - const account_public_address& miner::get_mining_address() const - { - return m_mine_address; - } - //----------------------------------------------------------------------------------------------------- - uint32_t miner::get_threads_count() const { - return m_threads_total; - } - //----------------------------------------------------------------------------------------------------- - bool miner::start(const account_public_address& adr, size_t threads_count, const boost::thread::attributes& attrs) - { - m_mine_address = adr; - m_threads_total = static_cast<uint32_t>(threads_count); - m_starter_nonce = crypto::rand<uint32_t>(); - CRITICAL_REGION_LOCAL(m_threads_lock); - if(is_mining()) - { - LOG_ERROR("Starting miner but it's already started"); - return false; - } - - if(!m_threads.empty()) - { - LOG_ERROR("Unable to start miner because there are active mining threads"); - return false; - } - - if(!m_template_no) - request_block_template();//lets update block template - - boost::interprocess::ipcdetail::atomic_write32(&m_stop, 0); - boost::interprocess::ipcdetail::atomic_write32(&m_thread_index, 0); - - for(size_t i = 0; i != threads_count; i++) - { - m_threads.push_back(boost::thread(attrs, boost::bind(&miner::worker_thread, this))); - } - - LOG_PRINT_L0("Mining has started with " << threads_count << " threads, good luck!" ); - return true; - } - //----------------------------------------------------------------------------------------------------- - uint64_t miner::get_speed() const - { - if(is_mining()) { - return m_current_hash_rate; - } - else { - return 0; - } - } - //----------------------------------------------------------------------------------------------------- - void miner::send_stop_signal() - { - boost::interprocess::ipcdetail::atomic_write32(&m_stop, 1); - } - //----------------------------------------------------------------------------------------------------- - bool miner::stop() - { - MTRACE("Miner has received stop signal"); - - if (!is_mining()) - { - MDEBUG("Not mining - nothing to stop" ); - return true; - } - - send_stop_signal(); - CRITICAL_REGION_LOCAL(m_threads_lock); - - for(boost::thread& th: m_threads) - th.join(); - - MINFO("Mining has been stopped, " << m_threads.size() << " finished" ); - m_threads.clear(); - return true; - } - //----------------------------------------------------------------------------------------------------- - bool miner::find_nonce_for_given_block(block& bl, const difficulty_type& diffic, uint64_t height) - { - for(; bl.nonce != std::numeric_limits<uint32_t>::max(); bl.nonce++) - { - crypto::hash h; - get_block_longhash(bl, h, height); - - if(check_hash(h, diffic)) - { - return true; - } - } - return false; - } - //----------------------------------------------------------------------------------------------------- - void miner::on_synchronized() - { - if(m_do_mining) - { - boost::thread::attributes attrs; - attrs.set_stack_size(THREAD_STACK_SIZE); - - start(m_mine_address, m_threads_total, attrs); - } - } - //----------------------------------------------------------------------------------------------------- - void miner::pause() - { - CRITICAL_REGION_LOCAL(m_miners_count_lock); - ++m_pausers_count; - if(m_pausers_count == 1 && is_mining()) - MDEBUG("MINING PAUSED"); - } - //----------------------------------------------------------------------------------------------------- - void miner::resume() - { - CRITICAL_REGION_LOCAL(m_miners_count_lock); - --m_pausers_count; - if(m_pausers_count < 0) - { - m_pausers_count = 0; - MERROR("Unexpected miner::resume() called"); - } - if(!m_pausers_count && is_mining()) - MDEBUG("MINING RESUMED"); - } - //----------------------------------------------------------------------------------------------------- - bool miner::worker_thread() - { - uint32_t th_local_index = boost::interprocess::ipcdetail::atomic_inc32(&m_thread_index); - MGINFO("Miner thread was started ["<< th_local_index << "]"); - MLOG_SET_THREAD_NAME(std::string("[miner ") + std::to_string(th_local_index) + "]"); - uint32_t nonce = m_starter_nonce + th_local_index; - uint64_t height = 0; - difficulty_type local_diff = 0; - uint32_t local_template_ver = 0; - block b; - slow_hash_allocate_state(); - while(!m_stop) - { - if(m_pausers_count)//anti split workaround - { - misc_utils::sleep_no_w(100); - continue; - } - - if(local_template_ver != m_template_no) - { - CRITICAL_REGION_BEGIN(m_template_lock); - b = m_template; - local_diff = m_diffic; - height = m_height; - CRITICAL_REGION_END(); - local_template_ver = m_template_no; - nonce = m_starter_nonce + th_local_index; - } - - if(!local_template_ver)//no any set_block_template call - { - LOG_PRINT_L2("Block template not set yet"); - epee::misc_utils::sleep_no_w(1000); - continue; - } - - b.nonce = nonce; - crypto::hash h; - get_block_longhash(b, h, height); - - if(check_hash(h, local_diff)) - { - //we lucky! - ++m_config.current_extra_message_index; - MGINFO_GREEN("Found block for difficulty: " << local_diff); - if(!m_phandler->handle_block_found(b)) - { - --m_config.current_extra_message_index; - }else - { - //success update, lets update config - if (!m_config_folder_path.empty()) - epee::serialization::store_t_to_json_file(m_config, m_config_folder_path + "/" + MINER_CONFIG_FILE_NAME); - } - } - nonce+=m_threads_total; - ++m_hashes; - } - slow_hash_free_state(); - MGINFO("Miner thread stopped ["<< th_local_index << "]"); - return true; - } - //----------------------------------------------------------------------------------------------------- -} - diff --git a/src/cryptonote_core/miner.h b/src/cryptonote_core/miner.h deleted file mode 100644 index f24f6e960..000000000 --- a/src/cryptonote_core/miner.h +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright (c) 2014-2016, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - -#pragma once - -#include <boost/program_options.hpp> -#include <atomic> -#include "cryptonote_basic.h" -#include "difficulty.h" -#include "math_helper.h" - - -namespace cryptonote -{ - - struct i_miner_handler - { - virtual bool handle_block_found(block& b) = 0; - virtual bool get_block_template(block& b, const account_public_address& adr, difficulty_type& diffic, uint64_t& height, const blobdata& ex_nonce) = 0; - protected: - ~i_miner_handler(){}; - }; - - /************************************************************************/ - /* */ - /************************************************************************/ - class miner - { - public: - miner(i_miner_handler* phandler); - ~miner(); - bool init(const boost::program_options::variables_map& vm, bool testnet); - static void init_options(boost::program_options::options_description& desc); - bool set_block_template(const block& bl, const difficulty_type& diffic, uint64_t height); - bool on_block_chain_update(); - bool start(const account_public_address& adr, size_t threads_count, const boost::thread::attributes& attrs); - uint64_t get_speed() const; - uint32_t get_threads_count() const; - void send_stop_signal(); - bool stop(); - bool is_mining() const; - const account_public_address& get_mining_address() const; - bool on_idle(); - void on_synchronized(); - //synchronous analog (for fast calls) - static bool find_nonce_for_given_block(block& bl, const difficulty_type& diffic, uint64_t height); - void pause(); - void resume(); - void do_print_hashrate(bool do_hr); - - private: - bool worker_thread(); - bool request_block_template(); - void merge_hr(); - - struct miner_config - { - uint64_t current_extra_message_index; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(current_extra_message_index) - END_KV_SERIALIZE_MAP() - }; - - - volatile uint32_t m_stop; - epee::critical_section m_template_lock; - block m_template; - std::atomic<uint32_t> m_template_no; - std::atomic<uint32_t> m_starter_nonce; - difficulty_type m_diffic; - uint64_t m_height; - volatile uint32_t m_thread_index; - volatile uint32_t m_threads_total; - std::atomic<int32_t> m_pausers_count; - epee::critical_section m_miners_count_lock; - - std::list<boost::thread> m_threads; - epee::critical_section m_threads_lock; - i_miner_handler* m_phandler; - account_public_address m_mine_address; - epee::math_helper::once_a_time_seconds<5> m_update_block_template_interval; - epee::math_helper::once_a_time_seconds<2> m_update_merge_hr_interval; - std::vector<blobdata> m_extra_messages; - miner_config m_config; - std::string m_config_folder_path; - std::atomic<uint64_t> m_last_hr_merge_time; - std::atomic<uint64_t> m_hashes; - std::atomic<uint64_t> m_current_hash_rate; - epee::critical_section m_last_hash_rates_lock; - std::list<uint64_t> m_last_hash_rates; - bool m_do_print_hashrate; - bool m_do_mining; - - }; -} - - - diff --git a/src/cryptonote_core/tx_extra.h b/src/cryptonote_core/tx_extra.h deleted file mode 100644 index 6f5fbe466..000000000 --- a/src/cryptonote_core/tx_extra.h +++ /dev/null @@ -1,182 +0,0 @@ -// Copyright (c) 2014-2016, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - -#pragma once - - -#define TX_EXTRA_PADDING_MAX_COUNT 255 -#define TX_EXTRA_NONCE_MAX_COUNT 255 - -#define TX_EXTRA_TAG_PADDING 0x00 -#define TX_EXTRA_TAG_PUBKEY 0x01 -#define TX_EXTRA_NONCE 0x02 -#define TX_EXTRA_MERGE_MINING_TAG 0x03 -#define TX_EXTRA_MYSTERIOUS_MINERGATE_TAG 0xDE - -#define TX_EXTRA_NONCE_PAYMENT_ID 0x00 -#define TX_EXTRA_NONCE_ENCRYPTED_PAYMENT_ID 0x01 - -namespace cryptonote -{ - struct tx_extra_padding - { - size_t size; - - // load - template <template <bool> class Archive> - bool do_serialize(Archive<false>& ar) - { - // size - 1 - because of variant tag - for (size = 1; size <= TX_EXTRA_PADDING_MAX_COUNT; ++size) - { - std::ios_base::iostate state = ar.stream().rdstate(); - bool eof = EOF == ar.stream().peek(); - ar.stream().clear(state); - - if (eof) - break; - - uint8_t zero; - if (!::do_serialize(ar, zero)) - return false; - - if (0 != zero) - return false; - } - - return size <= TX_EXTRA_PADDING_MAX_COUNT; - } - - // store - template <template <bool> class Archive> - bool do_serialize(Archive<true>& ar) - { - if(TX_EXTRA_PADDING_MAX_COUNT < size) - return false; - - // i = 1 - because of variant tag - for (size_t i = 1; i < size; ++i) - { - uint8_t zero = 0; - if (!::do_serialize(ar, zero)) - return false; - } - return true; - } - }; - - struct tx_extra_pub_key - { - crypto::public_key pub_key; - - BEGIN_SERIALIZE() - FIELD(pub_key) - END_SERIALIZE() - }; - - struct tx_extra_nonce - { - std::string nonce; - - BEGIN_SERIALIZE() - FIELD(nonce) - if(TX_EXTRA_NONCE_MAX_COUNT < nonce.size()) return false; - END_SERIALIZE() - }; - - struct tx_extra_merge_mining_tag - { - struct serialize_helper - { - tx_extra_merge_mining_tag& mm_tag; - - serialize_helper(tx_extra_merge_mining_tag& mm_tag_) : mm_tag(mm_tag_) - { - } - - BEGIN_SERIALIZE() - VARINT_FIELD_N("depth", mm_tag.depth) - FIELD_N("merkle_root", mm_tag.merkle_root) - END_SERIALIZE() - }; - - size_t depth; - crypto::hash merkle_root; - - // load - template <template <bool> class Archive> - bool do_serialize(Archive<false>& ar) - { - std::string field; - if(!::do_serialize(ar, field)) - return false; - - std::istringstream iss(field); - binary_archive<false> iar(iss); - serialize_helper helper(*this); - return ::serialization::serialize(iar, helper); - } - - // store - template <template <bool> class Archive> - bool do_serialize(Archive<true>& ar) - { - std::ostringstream oss; - binary_archive<true> oar(oss); - serialize_helper helper(*this); - if(!::do_serialize(oar, helper)) - return false; - - std::string field = oss.str(); - return ::serialization::serialize(ar, field); - } - }; - - struct tx_extra_mysterious_minergate - { - std::string data; - - BEGIN_SERIALIZE() - FIELD(data) - END_SERIALIZE() - }; - - // tx_extra_field format, except tx_extra_padding and tx_extra_pub_key: - // varint tag; - // varint size; - // varint data[]; - typedef boost::variant<tx_extra_padding, tx_extra_pub_key, tx_extra_nonce, tx_extra_merge_mining_tag, tx_extra_mysterious_minergate> tx_extra_field; -} - -VARIANT_TAG(binary_archive, cryptonote::tx_extra_padding, TX_EXTRA_TAG_PADDING); -VARIANT_TAG(binary_archive, cryptonote::tx_extra_pub_key, TX_EXTRA_TAG_PUBKEY); -VARIANT_TAG(binary_archive, cryptonote::tx_extra_nonce, TX_EXTRA_NONCE); -VARIANT_TAG(binary_archive, cryptonote::tx_extra_merge_mining_tag, TX_EXTRA_MERGE_MINING_TAG); -VARIANT_TAG(binary_archive, cryptonote::tx_extra_mysterious_minergate, TX_EXTRA_MYSTERIOUS_MINERGATE_TAG); diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp index e37ddec0d..9188f8329 100644 --- a/src/cryptonote_core/tx_pool.cpp +++ b/src/cryptonote_core/tx_pool.cpp @@ -34,8 +34,8 @@ #include <vector> #include "tx_pool.h" -#include "cryptonote_format_utils.h" -#include "cryptonote_boost_serialization.h" +#include "cryptonote_tx_utils.h" +#include "cryptonote_basic/cryptonote_boost_serialization.h" #include "cryptonote_config.h" #include "blockchain.h" #include "common/boost_serialization_helper.h" diff --git a/src/cryptonote_core/tx_pool.h b/src/cryptonote_core/tx_pool.h index 2712f75bb..e9c9e3f36 100644 --- a/src/cryptonote_core/tx_pool.h +++ b/src/cryptonote_core/tx_pool.h @@ -41,8 +41,8 @@ #include "string_tools.h" #include "syncobj.h" #include "math_helper.h" -#include "cryptonote_basic_impl.h" -#include "verification_context.h" +#include "cryptonote_basic/cryptonote_basic_impl.h" +#include "cryptonote_basic/verification_context.h" #include "crypto/hash.h" #include "rpc/core_rpc_server_commands_defs.h" diff --git a/src/cryptonote_core/verification_context.h b/src/cryptonote_core/verification_context.h deleted file mode 100644 index 0bb635e84..000000000 --- a/src/cryptonote_core/verification_context.h +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (c) 2014-2016, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers - -#pragma once -namespace cryptonote -{ - /************************************************************************/ - /* */ - /************************************************************************/ - struct tx_verification_context - { - bool m_should_be_relayed; - bool m_verifivation_failed; //bad tx, should drop connection - bool m_verifivation_impossible; //the transaction is related with an alternative blockchain - bool m_added_to_pool; - bool m_low_mixin; - bool m_double_spend; - bool m_invalid_input; - bool m_invalid_output; - bool m_too_big; - bool m_overspend; - bool m_fee_too_low; - bool m_not_rct; - }; - - struct block_verification_context - { - bool m_added_to_main_chain; - bool m_verifivation_failed; //bad block, should drop connection - bool m_marked_as_orphaned; - bool m_already_exists; - bool m_partial_block_reward; - }; -} |