diff options
author | Oran Juice <oranjuices@hotmail.com> | 2014-09-28 15:52:05 +0530 |
---|---|---|
committer | Oran Juice <oranjuices@hotmail.com> | 2014-09-28 15:52:05 +0530 |
commit | 4f693d715c036346b642298cc94bd4d87c5f35e2 (patch) | |
tree | c7f764d9f9d90de3947eff7910901ee3a56212b1 /src | |
parent | Minor comment changes and code clean-up (diff) | |
parent | Revert "low risk, potentially varint overflow bug patched thanks to BBR" (diff) | |
download | monero-4f693d715c036346b642298cc94bd4d87c5f35e2.tar.xz |
Merge with origin/master
Diffstat (limited to 'src')
-rw-r--r-- | src/CMakeLists.txt | 12 | ||||
-rw-r--r-- | src/common/dns_utils.cpp | 231 | ||||
-rw-r--r-- | src/common/dns_utils.h | 122 | ||||
-rw-r--r-- | src/crypto/slow-hash.c | 16 | ||||
-rw-r--r-- | src/cryptonote_core/checkpoints.cpp | 9 | ||||
-rw-r--r-- | src/cryptonote_core/checkpoints.h | 1 | ||||
-rw-r--r-- | src/cryptonote_core/checkpoints_create.h | 67 | ||||
-rw-r--r-- | src/cryptonote_core/difficulty.cpp | 2 | ||||
-rw-r--r-- | src/daemon/daemon.cpp | 5 | ||||
-rw-r--r-- | src/daemon/daemon_commands_handler.h | 2 | ||||
-rw-r--r-- | src/p2p/net_node.h | 7 | ||||
-rw-r--r-- | src/p2p/net_node.inl | 55 | ||||
-rw-r--r-- | src/p2p/net_peerlist.h | 4 | ||||
-rw-r--r-- | src/p2p/p2p_protocol_defs.h | 2 | ||||
-rw-r--r-- | src/rpc/core_rpc_server.cpp | 2 | ||||
-rw-r--r-- | src/simplewallet/simplewallet.cpp | 58 | ||||
-rw-r--r-- | src/version.cmake | 79 | ||||
-rw-r--r-- | src/wallet/wallet2.cpp | 63 | ||||
-rw-r--r-- | src/wallet/wallet2.h | 3 | ||||
-rw-r--r-- | src/wallet/wallet_errors.h | 18 |
20 files changed, 700 insertions, 58 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8138df3f3..32115c8f6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -65,18 +65,22 @@ add_library(mnemonics ${MNEMONICS}) add_executable(daemon ${DAEMON} ${P2P} ${CRYPTONOTE_PROTOCOL}) add_executable(connectivity_tool ${CONN_TOOL}) add_executable(simpleminer ${MINER}) -target_link_libraries(daemon rpc cryptonote_core crypto common ${UPNP_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES}) -target_link_libraries(connectivity_tool cryptonote_core crypto common ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES}) -target_link_libraries(simpleminer cryptonote_core crypto common ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES}) +target_link_libraries(daemon rpc cryptonote_core crypto common ${UNBOUND_LIBRARIES} ${UPNP_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES}) +target_link_libraries(connectivity_tool cryptonote_core crypto common ${UNBOUND_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES}) +target_link_libraries(simpleminer cryptonote_core crypto common ${UNBOUND_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES}) add_library(rpc ${RPC}) add_library(wallet ${WALLET}) target_link_libraries(wallet mnemonics) add_executable(simplewallet ${SIMPLEWALLET} ) -target_link_libraries(simplewallet wallet rpc cryptonote_core crypto common mnemonics ${UPNP_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES}) +target_link_libraries(simplewallet wallet rpc cryptonote_core crypto common mnemonics ${UNBOUND_LIBRARIES} ${UPNP_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES}) add_dependencies(daemon version) add_dependencies(rpc version) add_dependencies(simplewallet version) set_property(TARGET common crypto cryptonote_core rpc wallet PROPERTY FOLDER "libs") set_property(TARGET daemon simplewallet connectivity_tool simpleminer PROPERTY FOLDER "prog") +if (STATIC) + set_property(TARGET daemon simplewallet connectivity_tool simpleminer PROPERTY LINK_SEARCH_START_STATIC 1) + set_property(TARGET daemon simplewallet connectivity_tool simpleminer PROPERTY LINK_SEARCH_END_STATIC 1) +endif() set_property(TARGET daemon PROPERTY OUTPUT_NAME "bitmonerod") diff --git a/src/common/dns_utils.cpp b/src/common/dns_utils.cpp new file mode 100644 index 000000000..346761e74 --- /dev/null +++ b/src/common/dns_utils.cpp @@ -0,0 +1,231 @@ +// Copyright (c) 2014, 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 "common/dns_utils.h" +#include <cstring> +#include <sstream> +#include <unbound.h> + +namespace tools +{ + +// fuck it, I'm tired of dealing with getnameinfo()/inet_ntop/etc +std::string ipv4_to_string(const char* src) +{ + std::stringstream ss; + unsigned int bytes[4]; + for (int i = 0; i < 4; i++) + { + unsigned char a = src[i]; + bytes[i] = a; + } + ss << bytes[0] << "." + << bytes[1] << "." + << bytes[2] << "." + << bytes[3]; + return ss.str(); +} + +// this obviously will need to change, but is here to reflect the above +// stop-gap measure and to make the tests pass at least... +std::string ipv6_to_string(const char* src) +{ + std::stringstream ss; + unsigned int bytes[8]; + for (int i = 0; i < 8; i++) + { + unsigned char a = src[i]; + bytes[i] = a; + } + ss << bytes[0] << ":" + << bytes[1] << ":" + << bytes[2] << ":" + << bytes[3] << ":" + << bytes[4] << ":" + << bytes[5] << ":" + << bytes[6] << ":" + << bytes[7]; + return ss.str(); +} + +// custom smart pointer. +// TODO: see if std::auto_ptr and the like support custom destructors +class ub_result_ptr +{ +public: + ub_result_ptr() + { + ptr = nullptr; + } + ~ub_result_ptr() + { + ub_resolve_free(ptr); + } + ub_result* ptr; +}; + +struct DNSResolverData +{ + ub_ctx* m_ub_context; +}; + +DNSResolver::DNSResolver() : m_data(new DNSResolverData()) +{ + // init libunbound context + m_data->m_ub_context = ub_ctx_create(); + + char empty_string = '\0'; + + // look for "/etc/resolv.conf" and "/etc/hosts" or platform equivalent + ub_ctx_resolvconf(m_data->m_ub_context, &empty_string); + ub_ctx_hosts(m_data->m_ub_context, &empty_string); +} + +DNSResolver::~DNSResolver() +{ + if (m_data) + { + if (m_data->m_ub_context != NULL) + { + ub_ctx_delete(m_data->m_ub_context); + } + delete m_data; + } +} + +std::vector<std::string> DNSResolver::get_ipv4(const std::string& url) +{ + std::vector<std::string> addresses; + char urlC[1000]; // waaaay too big, but just in case... + + strncpy(urlC, url.c_str(), 999); + urlC[999] = '\0'; + if (!check_address_syntax(urlC)) + { + return addresses; + } + + // destructor takes care of cleanup + ub_result_ptr result; + + // call DNS resolver, blocking. if return value not zero, something went wrong + if (!ub_resolve(m_data->m_ub_context, urlC, DNS_TYPE_A, DNS_CLASS_IN, &(result.ptr))) + { + if (result.ptr->havedata) + { + for (size_t i=0; result.ptr->data[i] != NULL; i++) + { + addresses.push_back(ipv4_to_string(result.ptr->data[i])); + } + } + } + + return addresses; +} + +std::vector<std::string> DNSResolver::get_ipv6(const std::string& url) +{ + std::vector<std::string> addresses; + char urlC[1000]; // waaaay too big, but just in case... + + strncpy(urlC, url.c_str(), 999); + urlC[999] = '\0'; + + if (!check_address_syntax(urlC)) + { + return addresses; + } + + ub_result_ptr result; + + // call DNS resolver, blocking. if return value not zero, something went wrong + if (!ub_resolve(m_data->m_ub_context, urlC, DNS_TYPE_AAAA, DNS_CLASS_IN, &(result.ptr))) + { + if (result.ptr->havedata) + { + for (size_t i=0; result.ptr->data[i] != NULL; i++) + { + addresses.push_back(ipv6_to_string(result.ptr->data[i])); + } + } + } + + return addresses; +} + +std::vector<std::string> DNSResolver::get_txt_record(const std::string& url) +{ + std::vector<std::string> records; + char urlC[1000]; // waaaay too big, but just in case... + + strncpy(urlC, url.c_str(), 999); + urlC[999] = '\0'; + + if (!check_address_syntax(urlC)) + { + return records; + } + + ub_result_ptr result; + + // call DNS resolver, blocking. if return value not zero, something went wrong + if (!ub_resolve(m_data->m_ub_context, urlC, DNS_TYPE_TXT, DNS_CLASS_IN, &(result.ptr))) + { + if (result.ptr->havedata) + { + for (size_t i=0; result.ptr->data[i] != NULL; i++) + { + records.push_back(result.ptr->data[i]); + } + } + } + + return records; +} + +DNSResolver& DNSResolver::instance() +{ + static DNSResolver* staticInstance = NULL; + if (staticInstance == NULL) + { + staticInstance = new DNSResolver(); + } + return *staticInstance; +} + +bool DNSResolver::check_address_syntax(const std::string& addr) +{ + // if string doesn't contain a dot, we won't consider it a url for now. + if (addr.find(".") == std::string::npos) + { + return false; + } + return true; +} + +} // namespace tools diff --git a/src/common/dns_utils.h b/src/common/dns_utils.h new file mode 100644 index 000000000..dd6946dc4 --- /dev/null +++ b/src/common/dns_utils.h @@ -0,0 +1,122 @@ +// Copyright (c) 2014, 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 <vector> +#include <string> + +namespace tools +{ + +// RFC defines for record types and classes for DNS, gleaned from ldns source +const static int DNS_CLASS_IN = 1; +const static int DNS_TYPE_A = 1; +const static int DNS_TYPE_TXT = 16; +const static int DNS_TYPE_AAAA = 8; + +struct DNSResolverData; + +/** + * @brief Provides high-level access to DNS resolution + * + * This class is designed to provide a high-level abstraction to DNS resolution + * functionality, including access to TXT records and such. It will also + * handle DNSSEC validation of the results. + */ +class DNSResolver +{ +public: + + /** + * @brief Constructs an instance of DNSResolver + * + * Constructs a class instance and does setup stuff for the backend resolver. + */ + DNSResolver(); + + /** + * @brief takes care of freeing C pointers and such + */ + ~DNSResolver(); + + /** + * @brief gets ipv4 addresses from DNS query of a URL + * + * returns a vector of all IPv4 "A" records for given URL. + * If no "A" records found, returns an empty vector. + * + * @param url A string containing a URL to query for + * + * @return vector of strings containing ipv4 addresses + */ + std::vector<std::string> get_ipv4(const std::string& url); + + /** + * @brief gets ipv6 addresses from DNS query + * + * returns a vector of all IPv6 "A" records for given URL. + * If no "A" records found, returns an empty vector. + * + * @param url A string containing a URL to query for + * + * @return vector of strings containing ipv6 addresses + */ + std::vector<std::string> get_ipv6(const std::string& url); + + /** + * @brief gets all TXT records from a DNS query for the supplied URL; + * if no TXT record present returns an empty vector. + * + * @param url A string containing a URL to query for + * + * @return A vector of strings containing a TXT record; or an empty vector + */ + // TODO: modify this to accomodate DNSSEC + std::vector<std::string> get_txt_record(const std::string& url); + + /** + * @brief Gets the singleton instance of DNSResolver + * + * @return returns a pointer to the singleton + */ + static DNSResolver& instance(); + +private: + + /** + * @brief Checks a string to see if it looks like a URL + * + * @param addr the string to be checked + * + * @return true if it looks enough like a URL, false if not + */ + bool check_address_syntax(const std::string& addr); + + DNSResolverData *m_data; +}; // class DNSResolver + +} // namespace tools diff --git a/src/crypto/slow-hash.c b/src/crypto/slow-hash.c index 3aff7bd5d..d4f27e1e1 100644 --- a/src/crypto/slow-hash.c +++ b/src/crypto/slow-hash.c @@ -41,12 +41,20 @@ #if defined(_MSC_VER) #include <intrin.h> -#include <Windows.h> +#include <windows.h> #define STATIC #define INLINE __inline #if !defined(RDATA_ALIGN16) #define RDATA_ALIGN16 __declspec(align(16)) #endif +#elif defined(__MINGW32__) +#include <intrin.h> +#include <windows.h> +#define STATIC static +#define INLINE inline +#if !defined(RDATA_ALIGN16) +#define RDATA_ALIGN16 __attribute__ ((aligned(16))) +#endif #else #include <wmmintrin.h> #include <sys/mman.h> @@ -287,7 +295,7 @@ STATIC INLINE void aes_pseudo_round_xor(const uint8_t *in, uint8_t *out, } } -#if defined(_MSC_VER) +#if defined(_MSC_VER) || defined(__MINGW32__) BOOL SetLockPagesPrivilege(HANDLE hProcess, BOOL bEnable) { struct @@ -325,7 +333,7 @@ void slow_hash_allocate_state(void) if(hp_state != NULL) return; -#if defined(_MSC_VER) +#if defined(_MSC_VER) || defined(__MINGW32__) SetLockPagesPrivilege(GetCurrentProcess(), TRUE); hp_state = (uint8_t *) VirtualAlloc(hp_state, MEMORY, MEM_LARGE_PAGES | MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); @@ -357,7 +365,7 @@ void slow_hash_free_state(void) free(hp_state); else { -#if defined(_MSC_VER) +#if defined(_MSC_VER) || defined(__MINGW32__) VirtualFree(hp_state, MEMORY, MEM_RELEASE); #else munmap(hp_state, MEMORY); diff --git a/src/cryptonote_core/checkpoints.cpp b/src/cryptonote_core/checkpoints.cpp index 3669a7217..c76a23841 100644 --- a/src/cryptonote_core/checkpoints.cpp +++ b/src/cryptonote_core/checkpoints.cpp @@ -93,4 +93,13 @@ namespace cryptonote uint64_t checkpoint_height = it->first; return checkpoint_height < block_height; } + uint64_t checkpoints::get_max_height() + { + 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; + } + } diff --git a/src/cryptonote_core/checkpoints.h b/src/cryptonote_core/checkpoints.h index 11c4b5eb7..3dee48682 100644 --- a/src/cryptonote_core/checkpoints.h +++ b/src/cryptonote_core/checkpoints.h @@ -44,6 +44,7 @@ namespace cryptonote bool check_block(uint64_t height, const crypto::hash& h) const; bool check_block(uint64_t height, const crypto::hash& h, bool& is_a_checkpoint) const; bool is_alternative_block_allowed(uint64_t blockchain_height, uint64_t block_height) const; + uint64_t get_max_height(); private: std::map<uint64_t, crypto::hash> m_points; diff --git a/src/cryptonote_core/checkpoints_create.h b/src/cryptonote_core/checkpoints_create.h index 9d65dc243..7512ddd95 100644 --- a/src/cryptonote_core/checkpoints_create.h +++ b/src/cryptonote_core/checkpoints_create.h @@ -34,18 +34,79 @@ #include "misc_log_ex.h" #define ADD_CHECKPOINT(h, hash) CHECK_AND_ASSERT(checkpoints.add_checkpoint(h, hash), false); +#define JSON_HASH_FILE_NAME "checkpoints.json" + +struct t_hashline +{ + uint64_t height; + std::string hash; + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(height) + KV_SERIALIZE(hash) + END_KV_SERIALIZE_MAP() +}; + +struct t_hash_json { + std::vector<t_hashline> hashlines; + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(hashlines) + END_KV_SERIALIZE_MAP() +}; namespace cryptonote { inline bool create_checkpoints(cryptonote::checkpoints& 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"); // from chainradar; verify this - ADD_CHECKPOINT(202614, "c29e3dc37d8da3e72e506e31a213a58771b24450144305bcba9e70fa4d6ea6fb"); // from chainradar; verify this - ADD_CHECKPOINT(205000, "5d3d7a26e6dc7535e34f03def711daa8c263785f73ec1fadef8a45880fde8063"); // from chainradar; verify this + 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"); + + return true; + } + + inline bool load_checkpoins_from_json(cryptonote::checkpoints& checkpoints, std::string json_hashfile_fullpath) + { + boost::system::error_code errcode; + if (! (boost::filesystem::exists(json_hashfile_fullpath, errcode))) + { + LOG_PRINT_L0("Blockchain checkpoints file not found"); + return true; + } + + LOG_PRINT_L0("Adding checkpoints from blockchain hashfile"); + + uint64_t prev_max_height = checkpoints.get_max_height(); + LOG_PRINT_L0("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_L0("ignoring checkpoint height " << height); + } else { + std::string blockhash = it->hash; + LOG_PRINT_L0("Adding checkpoint height " << height << ", hash=" << blockhash); + ADD_CHECKPOINT(height, blockhash); + } + ++it; + } + return true; } } diff --git a/src/cryptonote_core/difficulty.cpp b/src/cryptonote_core/difficulty.cpp index c26f8d909..d4d733e69 100644 --- a/src/cryptonote_core/difficulty.cpp +++ b/src/cryptonote_core/difficulty.cpp @@ -45,7 +45,7 @@ namespace cryptonote { using std::uint64_t; using std::vector; -#if defined(_MSC_VER) +#if defined(_MSC_VER) || defined(__MINGW32__) #include <windows.h> #include <winnt.h> diff --git a/src/daemon/daemon.cpp b/src/daemon/daemon.cpp index 5eda6cb69..5c209482e 100644 --- a/src/daemon/daemon.cpp +++ b/src/daemon/daemon.cpp @@ -44,6 +44,7 @@ using namespace epee; #include "p2p/net_node.h" #include "cryptonote_config.h" #include "cryptonote_core/checkpoints_create.h" +#include "cryptonote_core/checkpoints.h" #include "cryptonote_core/cryptonote_core.h" #include "rpc/core_rpc_server.h" #include "cryptonote_protocol/cryptonote_protocol_handler.h" @@ -203,6 +204,10 @@ int main(int argc, char* argv[]) cryptonote::checkpoints checkpoints; res = cryptonote::create_checkpoints(checkpoints); CHECK_AND_ASSERT_MES(res, 1, "Failed to initialize checkpoints"); + boost::filesystem::path json(JSON_HASH_FILE_NAME); + boost::filesystem::path checkpoint_json_hashfile_fullpath = data_dir / json; + res = cryptonote::load_checkpoins_from_json(checkpoints, checkpoint_json_hashfile_fullpath.string().c_str()); + CHECK_AND_ASSERT_MES(res, 1, "Failed to load initial checkpoints"); //create objects and link them cryptonote::core ccore(NULL); diff --git a/src/daemon/daemon_commands_handler.h b/src/daemon/daemon_commands_handler.h index 58112e166..869c2adf7 100644 --- a/src/daemon/daemon_commands_handler.h +++ b/src/daemon/daemon_commands_handler.h @@ -55,7 +55,7 @@ public: , bool testnet ) : m_srv(srv) - , m_testnet {testnet} + , m_testnet(testnet) { m_cmd_binder.set_handler("help", boost::bind(&daemon_cmmands_handler::help, this, _1), "Show this help"); m_cmd_binder.set_handler("print_pl", boost::bind(&daemon_cmmands_handler::print_pl, this, _1), "Print peer list"); diff --git a/src/p2p/net_node.h b/src/p2p/net_node.h index 759b21fcf..53a13f327 100644 --- a/src/p2p/net_node.h +++ b/src/p2p/net_node.h @@ -112,6 +112,13 @@ namespace nodetool size_t get_outgoing_connections_count(); peerlist_manager& get_peerlist_manager(){return m_peerlist;} private: + const std::vector<std::string> m_seed_nodes_list = + { "seeds.moneroseeds.se" + , "seeds.moneroseeds.ae.org" + , "seeds.moneroseeds.ch" + , "seeds.moneroseeds.li" + }; + typedef COMMAND_REQUEST_STAT_INFO_T<typename t_payload_net_handler::stat_info> COMMAND_REQUEST_STAT_INFO; CHAIN_LEVIN_INVOKE_MAP2(p2p_connection_context); //move levin_commands_handler interface invoke(...) callbacks into invoke map diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl index 870e7572e..08fd1d1e6 100644 --- a/src/p2p/net_node.inl +++ b/src/p2p/net_node.inl @@ -35,6 +35,7 @@ #include "version.h" #include "string_tools.h" #include "common/util.h" +#include "common/dns_utils.h" #include "net/net_helper.h" #include "math_helper.h" #include "p2p_protocol_defs.h" @@ -195,7 +196,7 @@ namespace nodetool return true; } //----------------------------------------------------------------------------------- - inline void add_hardcoded_seed_node( + inline void append_net_address( std::vector<net_address> & seed_nodes , std::string const & addr ) @@ -239,23 +240,39 @@ namespace nodetool { if (testnet) { - add_hardcoded_seed_node(m_seed_nodes, "107.152.187.202:28080"); - add_hardcoded_seed_node(m_seed_nodes, "197.242.158.240:28080"); - add_hardcoded_seed_node(m_seed_nodes, "107.152.130.98:28080"); + append_net_address(m_seed_nodes, "107.152.187.202:28080"); + append_net_address(m_seed_nodes, "197.242.158.240:28080"); + append_net_address(m_seed_nodes, "107.152.130.98:28080"); } else { - add_hardcoded_seed_node(m_seed_nodes, "62.210.78.186:18080"); - add_hardcoded_seed_node(m_seed_nodes, "195.12.60.154:18080"); - add_hardcoded_seed_node(m_seed_nodes, "54.241.246.125:18080"); - add_hardcoded_seed_node(m_seed_nodes, "107.170.157.169:18080"); - add_hardcoded_seed_node(m_seed_nodes, "54.207.112.216:18080"); - add_hardcoded_seed_node(m_seed_nodes, "78.27.112.54:18080"); - add_hardcoded_seed_node(m_seed_nodes, "209.222.30.57:18080"); - add_hardcoded_seed_node(m_seed_nodes, "80.71.13.55:18080"); - add_hardcoded_seed_node(m_seed_nodes, "107.178.112.126:18080"); - add_hardcoded_seed_node(m_seed_nodes, "107.158.233.98:18080"); - add_hardcoded_seed_node(m_seed_nodes, "64.22.111.2:18080"); + // for each hostname in the seed nodes list, attempt to DNS resolve and + // add the result addresses as seed nodes + // TODO: at some point add IPv6 support, but that won't be relevant + // for some time yet. + for (const std::string& addr_str : m_seed_nodes_list) + { + std::vector<std::string> addr_list = tools::DNSResolver::instance().get_ipv4(addr_str); + for (const std::string& a : addr_list) + { + append_net_address(m_seed_nodes, a + ":18080"); + } + } + + if (!m_seed_nodes.size()) + { + append_net_address(m_seed_nodes, "62.210.78.186:18080"); + append_net_address(m_seed_nodes, "195.12.60.154:18080"); + append_net_address(m_seed_nodes, "54.241.246.125:18080"); + append_net_address(m_seed_nodes, "107.170.157.169:18080"); + append_net_address(m_seed_nodes, "54.207.112.216:18080"); + append_net_address(m_seed_nodes, "78.27.112.54:18080"); + append_net_address(m_seed_nodes, "209.222.30.57:18080"); + append_net_address(m_seed_nodes, "80.71.13.55:18080"); + append_net_address(m_seed_nodes, "107.178.112.126:18080"); + append_net_address(m_seed_nodes, "107.158.233.98:18080"); + append_net_address(m_seed_nodes, "64.22.111.2:18080"); + } } bool res = handle_command_line(vm, testnet); @@ -624,7 +641,9 @@ namespace nodetool peerlist_entry pe_local = AUTO_VAL_INIT(pe_local); pe_local.adr = na; pe_local.id = pi; - time(&pe_local.last_seen); + time_t last_seen; + time(&last_seen); + pe_local.last_seen = static_cast<int64_t>(last_seen); m_peerlist.append_with_peer_white(pe_local); //update last seen and push it to peerlist manager @@ -1102,7 +1121,9 @@ namespace nodetool peerlist_entry pe; pe.adr.ip = context.m_remote_ip; pe.adr.port = port_l; - time(&pe.last_seen); + time_t last_seen; + time(&last_seen); + pe.last_seen = static_cast<int64_t>(last_seen); pe.id = peer_id_l; this->m_peerlist.append_with_peer_white(pe); LOG_PRINT_CCONTEXT_L2("PING SUCCESS " << epee::string_tools::get_ip_string_from_int32(context.m_remote_ip) << ":" << port_l); diff --git a/src/p2p/net_peerlist.h b/src/p2p/net_peerlist.h index b02326905..e3e387bbc 100644 --- a/src/p2p/net_peerlist.h +++ b/src/p2p/net_peerlist.h @@ -128,7 +128,7 @@ namespace nodetool // access by peerlist_entry::net_adress boost::multi_index::ordered_unique<boost::multi_index::tag<by_addr>, boost::multi_index::member<peerlist_entry,net_address,&peerlist_entry::adr> >, // sort by peerlist_entry::last_seen< - boost::multi_index::ordered_non_unique<boost::multi_index::tag<by_time>, boost::multi_index::member<peerlist_entry,time_t,&peerlist_entry::last_seen> > + boost::multi_index::ordered_non_unique<boost::multi_index::tag<by_time>, boost::multi_index::member<peerlist_entry,int64_t,&peerlist_entry::last_seen> > > > peers_indexed; @@ -140,7 +140,7 @@ namespace nodetool // access by peerlist_entry::net_adress boost::multi_index::ordered_unique<boost::multi_index::tag<by_addr>, boost::multi_index::member<peerlist_entry,net_address,&peerlist_entry::adr> >, // sort by peerlist_entry::last_seen< - boost::multi_index::ordered_non_unique<boost::multi_index::tag<by_time>, boost::multi_index::member<peerlist_entry,time_t,&peerlist_entry::last_seen> > + boost::multi_index::ordered_non_unique<boost::multi_index::tag<by_time>, boost::multi_index::member<peerlist_entry,int64_t,&peerlist_entry::last_seen> > > > peers_indexed_old; public: diff --git a/src/p2p/p2p_protocol_defs.h b/src/p2p/p2p_protocol_defs.h index a14d00dcd..44b8c5b50 100644 --- a/src/p2p/p2p_protocol_defs.h +++ b/src/p2p/p2p_protocol_defs.h @@ -53,7 +53,7 @@ namespace nodetool { net_address adr; peerid_type id; - time_t last_seen; + int64_t last_seen; }; struct connection_entry diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index 22e95a1fc..e80451cda 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -79,7 +79,7 @@ namespace cryptonote ) : m_core(cr) , m_p2p(p2p) - , m_testnet {testnet} + , m_testnet(testnet) {} //------------------------------------------------------------------------------------------------------------------------------ bool core_rpc_server::handle_command_line( diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 7a47dead0..b10feb929 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -36,6 +36,7 @@ #include <thread> #include <iostream> +#include <sstream> #include <boost/lexical_cast.hpp> #include <boost/program_options.hpp> #include <boost/algorithm/string.hpp> @@ -999,8 +1000,61 @@ bool simple_wallet::transfer(const std::vector<std::string> &args_) cryptonote::tx_destination_entry de; if(!get_account_address_from_str(de.addr, m_wallet->testnet(), local_args[i])) { - fail_msg_writer() << "wrong address: " << local_args[i]; - return true; + // if treating as an address fails, try as url + bool dnssec_ok = false; + std::string url = local_args[i]; + + // attempt to get address from dns query + auto addresses_from_dns = tools::wallet2::addresses_from_url(url, dnssec_ok); + + // for now, move on only if one address found + if (addresses_from_dns.size() == 1) + { + if (get_account_address_from_str(de.addr, m_wallet->testnet(), addresses_from_dns[0])) + { + // if it was an address, prompt user for confirmation. + // inform user of DNSSEC validation status as well. + + std::string dnssec_str; + if (dnssec_ok) + { + dnssec_str = "DNSSEC validation PASSED!"; + } + else + { + dnssec_str = "DNSSEC validation FAILED!"; + } + std::stringstream prompt; + prompt << "For URL: " << url + << "," << dnssec_str << std::endl + << " Monero Address = " << addresses_from_dns[0] + << std::endl + << "Is this OK? (Y/n) " + ; + + // prompt the user for confirmation given the dns query and dnssec status + std::string confirm_dns_ok = command_line::input_line(prompt.str()); + if (confirm_dns_ok != "Y" && confirm_dns_ok != "y" && confirm_dns_ok != "Yes" && confirm_dns_ok != "yes") + { + fail_msg_writer() << "User terminated transfer request, disagreed with dns result from url: " << url; + return true; + } + } + else + { + fail_msg_writer() << "Failed to get a monero address from: " << local_args[i]; + return true; + } + } + else if (addresses_from_dns.size() > 1) + { + fail_msg_writer() << "Multiple Monero addresses found for given URL: " << url << ", this is not yet supported."; + } + else + { + fail_msg_writer() << "wrong address: " << local_args[i]; + return true; + } } bool ok = cryptonote::parse_amount(de.amount, local_args[i + 1]); diff --git a/src/version.cmake b/src/version.cmake index e851cdf01..2f3aa0b25 100644 --- a/src/version.cmake +++ b/src/version.cmake @@ -1,30 +1,83 @@ +# Copyright (c) 2014, 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 + +# Check what commit we're on execute_process(COMMAND "${GIT}" rev-parse --short HEAD RESULT_VARIABLE RET OUTPUT_VARIABLE COMMIT OUTPUT_STRIP_TRAILING_WHITESPACE) if(RET) + # Something went wrong, set the version tag to -unknown + message(WARNING "Cannot determine current commit. Make sure that you are building either from a Git working tree or from a source archive.") set(VERSIONTAG "unknown") configure_file("src/version.h.in" "${TO}") else() message(STATUS "You are currently on commit ${COMMIT}") + + # Get all the tags execute_process(COMMAND "${GIT}" show-ref --tags -d --abbrev RESULT_VARIABLE RET OUTPUT_VARIABLE TAGGEDCOMMITOUT OUTPUT_STRIP_TRAILING_WHITESPACE) - string(REPLACE " refs/" "\n" TAGGEDCOMMITOUT2 ${TAGGEDCOMMITOUT}) - string(REPLACE "\n" ";" TAGGEDCOMMITLIST ${TAGGEDCOMMITOUT2}) - list(GET TAGGEDCOMMITLIST -2 TAGGEDCOMMIT) + # Make sure we actually got some tags + if(TAGGEDCOMMITOUT) + string(LENGTH ${TAGGEDCOMMITOUT} TLEN) + else() + set(TLEN 1) + endif() - if(RET OR NOT TAGGEDCOMMIT) + if(RET OR TLEN LESS 5) message(WARNING "Cannot determine most recent tag. Make sure that you are building either from a Git working tree or from a source archive.") - set(VERSIONTAG "${COMMIT}") + set(VERSIONTAG "${COMMIT}") else() - message(STATUS "The most recent tag was at ${TAGGEDCOMMIT}") - if(${COMMIT} MATCHES ${TAGGEDCOMMIT}) - message(STATUS "You are building a tagged release") - set(VERSIONTAG "release") + # Replace a bunch of things so we end up with a semi-colon separated list + string(REPLACE " refs/" "\n" TAGGEDCOMMITOUT2 ${TAGGEDCOMMITOUT}) + string(REPLACE "\n" ";" TAGGEDCOMMITLIST ${TAGGEDCOMMITOUT2}) + + # Grab the second-last item in the list, as that will be the hash of our most recent commit + list(GET TAGGEDCOMMITLIST -2 TAGGEDCOMMIT) + + if(NOT TAGGEDCOMMIT) + message(WARNING "Cannot determine most recent tag. Make sure that you are building either from a Git working tree or from a source archive.") + set(VERSIONTAG "${COMMIT}") else() - message(STATUS "You are ahead or behind of a tagged release") - set(VERSIONTAG "${COMMIT}") - endif() - endif() + message(STATUS "The most recent tag was at ${TAGGEDCOMMIT}") + + # Check if we're building that tagged commit or a different one + if(${COMMIT} MATCHES ${TAGGEDCOMMIT}) + message(STATUS "You are building a tagged release") + set(VERSIONTAG "release") + else() + message(STATUS "You are ahead or behind of a tagged release") + set(VERSIONTAG "${COMMIT}") + endif() + endif() + + endif() configure_file("src/version.h.in" "${TO}") endif()
\ No newline at end of file diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 6222b0c03..b8f793d7c 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -47,6 +47,7 @@ using namespace epee; #include "serialization/binary_utils.h" #include "cryptonote_protocol/blobdatatype.h" #include "mnemonics/electrum-words.h" +#include "common/dns_utils.h" extern "C" { @@ -751,6 +752,7 @@ void wallet2::add_unconfirmed_tx(const cryptonote::transaction& tx, uint64_t cha utd.m_sent_time = time(NULL); utd.m_tx = tx; } + //---------------------------------------------------------------------------------------------------- void wallet2::transfer(const std::vector<cryptonote::tx_destination_entry>& dsts, size_t fake_outputs_count, uint64_t unlock_time, uint64_t fee, const std::vector<uint8_t>& extra, cryptonote::transaction& tx, pending_tx& ptx) @@ -815,6 +817,67 @@ std::vector<std::vector<cryptonote::tx_destination_entry>> split_amounts( } } // anonymous namespace +/** + * @brief gets a monero address from the TXT record of a DNS entry + * + * gets the monero address from the TXT record of the DNS entry associated + * with <url>. If this lookup fails, or the TXT record does not contain an + * XMR address in the correct format, returns an empty string. <dnssec_valid> + * will be set true or false according to whether or not the DNS query passes + * DNSSEC validation. + * + * @param url the url to look up + * @param dnssec_valid return-by-reference for DNSSEC status of query + * + * @return a monero address (as a string) or an empty string + */ +std::vector<std::string> wallet2::addresses_from_url(const std::string& url, bool& dnssec_valid) +{ + // TODO: update this correctly once DNSResolver::get_txt_record() supports it. + dnssec_valid = false; + + std::vector<std::string> addresses; + // get txt records + auto records = tools::DNSResolver::instance().get_txt_record(url); + + // for each txt record, try to find a monero address in it. + for (auto& rec : records) + { + std::string addr = address_from_txt_record(rec); + if (addr.size()) + { + addresses.push_back(addr); + } + } + + return addresses; +} + +//---------------------------------------------------------------------------------------------------- +// TODO: parse the string in a less stupid way, probably with regex +std::string wallet2::address_from_txt_record(const std::string& s) +{ + // make sure the txt record has "oa1:xmr" and find it + auto pos = s.find("oa1:xmr"); + + // search from there to find "recipient_address=" + pos = s.find("recipient_address=", pos); + + pos += 18; // move past "recipient_address=" + + // find the next semicolon + auto pos2 = s.find(";", pos); + if (pos2 != std::string::npos) + { + // length of address == 95, we can at least validate that much here + if (pos2 - pos == 95) + { + return s.substr(pos, 95); + } + } + return std::string(); +} + //---------------------------------------------------------------------------------------------------- // take a pending tx and actually send it to the daemon void wallet2::commit_tx(pending_tx& ptx) diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 3311e3438..90918677e 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -196,6 +196,9 @@ namespace tools static bool parse_payment_id(const std::string& payment_id_str, crypto::hash& payment_id); + static std::vector<std::string> addresses_from_url(const std::string& url, bool& dnssec_valid); + + static std::string address_from_txt_record(const std::string& s); private: bool store_keys(const std::string& keys_file_name, const std::string& password); void load_keys(const std::string& keys_file_name, const std::string& password); diff --git a/src/wallet/wallet_errors.h b/src/wallet/wallet_errors.h index 7914ff8e1..ebec931e4 100644 --- a/src/wallet/wallet_errors.h +++ b/src/wallet/wallet_errors.h @@ -383,11 +383,11 @@ namespace tools , uint64_t unlock_time , bool testnet ) - : transfer_error {std::move(loc), "transaction was not constructed"} - , m_sources {sources} - , m_destinations {destinations} - , m_unlock_time {unlock_time} - , m_testnet {testnet} + : transfer_error(std::move(loc), "transaction was not constructed") + , m_sources(sources) + , m_destinations(destinations) + , m_unlock_time(unlock_time) + , m_testnet(testnet) { } @@ -471,10 +471,10 @@ namespace tools , uint64_t fee , bool testnet ) - : transfer_error {std::move(loc), "transaction sum + fee exceeds " + cryptonote::print_money(std::numeric_limits<uint64_t>::max())} - , m_destinations {destinations} - , m_fee {fee} - , m_testnet {testnet} + : transfer_error(std::move(loc), "transaction sum + fee exceeds " + cryptonote::print_money(std::numeric_limits<uint64_t>::max())) + , m_destinations(destinations) + , m_fee(fee) + , m_testnet(testnet) { } |