From 1e4f6056bfd50f81895ed3fcf08042c9d96efd9b Mon Sep 17 00:00:00 2001 From: carsenk Date: Thu, 20 Dec 2018 12:23:33 -0700 Subject: [PATCH 01/26] Start of Native I2P Integration --- denarius-qt.pro | 80 +-- src/clientversion.h | 5 + src/compat.h | 6 + src/i2p.cpp | 208 ++++++++ src/i2p.h | 92 ++++ src/i2psam.cpp | 798 ++++++++++++++++++++++++++++++ src/i2psam.h | 423 ++++++++++++++++ src/init.cpp | 31 ++ src/makefile.unix | 4 + src/net.cpp | 216 +++++++- src/net.h | 56 ++- src/netbase.cpp | 146 +++++- src/netbase.h | 34 +- src/protocol.h | 3 + src/qt/bitcoin.qrc | 5 + src/qt/bitcoingui.cpp | 134 +++-- src/qt/bitcoingui.h | 16 +- src/qt/clientmodel.cpp | 68 +++ src/qt/clientmodel.h | 17 + src/qt/forms/i2poptionswidget.ui | 698 ++++++++++++++++++++++++++ src/qt/forms/showi2paddresses.ui | 136 +++++ src/qt/i2poptionswidget.cpp | 100 ++++ src/qt/i2poptionswidget.h | 37 ++ src/qt/optionsdialog.cpp | 40 ++ src/qt/optionsdialog.h | 16 + src/qt/optionsmodel.cpp | 299 +++++++++++ src/qt/optionsmodel.h | 37 ++ src/qt/res/icons/i2plogo_0_16.png | Bin 0 -> 3293 bytes src/qt/res/icons/i2plogo_1_16.png | Bin 0 -> 3014 bytes src/qt/res/icons/i2plogo_2_16.png | Bin 0 -> 2807 bytes src/qt/res/icons/i2plogo_3_16.png | Bin 0 -> 2709 bytes src/qt/res/icons/i2plogo_4_16.png | Bin 0 -> 2271 bytes src/qt/showi2paddresses.cpp | 34 ++ src/qt/showi2paddresses.h | 22 + src/serialize.h | 9 +- src/ui_interface.h | 5 + src/util.cpp | 7 + src/util.h | 4 +- src/version.cpp | 2 +- 39 files changed, 3706 insertions(+), 82 deletions(-) create mode 100644 src/i2p.cpp create mode 100644 src/i2p.h create mode 100644 src/i2psam.cpp create mode 100644 src/i2psam.h create mode 100644 src/qt/forms/i2poptionswidget.ui create mode 100644 src/qt/forms/showi2paddresses.ui create mode 100644 src/qt/i2poptionswidget.cpp create mode 100644 src/qt/i2poptionswidget.h create mode 100644 src/qt/res/icons/i2plogo_0_16.png create mode 100644 src/qt/res/icons/i2plogo_1_16.png create mode 100644 src/qt/res/icons/i2plogo_2_16.png create mode 100644 src/qt/res/icons/i2plogo_3_16.png create mode 100644 src/qt/res/icons/i2plogo_4_16.png create mode 100644 src/qt/showi2paddresses.cpp create mode 100644 src/qt/showi2paddresses.h diff --git a/denarius-qt.pro b/denarius-qt.pro index 836ba154..8fb484a9 100644 --- a/denarius-qt.pro +++ b/denarius-qt.pro @@ -158,7 +158,7 @@ contains(USE_LEVELDB, -) { DEFINES += USE_LEVELDB - INCLUDEPATH += src/leveldb/include src/leveldb/helpers + INCLUDEPATH += src/leveldb/include src/leveldb/helpers LIBS += $$PWD/src/leveldb/libleveldb.a $$PWD/src/leveldb/libmemenv.a SOURCES += src/txdb-leveldb.cpp \ src/bloom.cpp \ @@ -218,7 +218,7 @@ QMAKE_CXXFLAGS_WARN_ON = -fdiagnostics-show-option -Wall -Wextra -Wno-ignored-qu # Input DEPENDPATH += src src/json src/qt HEADERS += src/qt/bitcoingui.h \ - src/qt/intro.h \ + src/qt/intro.h \ src/qt/transactiontablemodel.h \ src/qt/addresstablemodel.h \ src/qt/peertablemodel.h \ @@ -231,12 +231,12 @@ HEADERS += src/qt/bitcoingui.h \ src/qt/aboutdialog.h \ src/qt/editaddressdialog.h \ src/qt/bitcoinaddressvalidator.h \ - src/kernelrecord.h \ - src/qt/mintingfilterproxy.h \ + src/kernelrecord.h \ + src/qt/mintingfilterproxy.h \ src/qt/mintingtablemodel.h \ src/qt/mintingview.h \ src/qt/proofofimage.h \ - src/qt/multisigaddressentry.h \ + src/qt/multisigaddressentry.h \ src/qt/multisiginputentry.h \ src/qt/multisigdialog.h \ src/alert.h \ @@ -312,26 +312,26 @@ HEADERS += src/qt/bitcoingui.h \ src/ui_interface.h \ src/qt/rpcconsole.h \ src/qt/trafficgraphwidget.h \ - src/qt/blockbrowser.h \ - src/qt/statisticspage.h \ - src/qt/marketbrowser.h \ - src/qt/qcustomplot.h \ - src/qt/fortunastakemanager.h \ + src/qt/blockbrowser.h \ + src/qt/statisticspage.h \ + src/qt/marketbrowser.h \ + src/qt/qcustomplot.h \ + src/qt/fortunastakemanager.h \ src/qt/addeditadrenalinenode.h \ src/qt/adrenalinenodeconfigdialog.h \ src/qt/termsofuse.h \ src/version.h \ - src/bloom.h \ + src/bloom.h \ src/netbase.h \ src/clientversion.h \ - src/hash.h \ + src/hash.h \ src/hashblock.h \ - src/sph_echo.h \ - src/sph_keccak.h \ - src/sph_jh.h \ + src/sph_echo.h \ + src/sph_keccak.h \ + src/sph_jh.h \ src/sph_types.h \ src/threadsafety.h \ - src/eccryptoverify.h \ + src/eccryptoverify.h \ src/qt/messagepage.h \ src/qt/messagemodel.h \ src/qt/sendmessagesdialog.h \ @@ -340,7 +340,7 @@ HEADERS += src/qt/bitcoingui.h \ src/qt/qvalidatedtextedit.h SOURCES += src/qt/bitcoin.cpp src/qt/bitcoingui.cpp \ - src/qt/intro.cpp \ + src/qt/intro.cpp \ src/qt/transactiontablemodel.cpp \ src/qt/addresstablemodel.cpp \ src/qt/peertablemodel.cpp \ @@ -353,11 +353,11 @@ SOURCES += src/qt/bitcoin.cpp src/qt/bitcoingui.cpp \ src/qt/aboutdialog.cpp \ src/qt/editaddressdialog.cpp \ src/qt/bitcoinaddressvalidator.cpp \ - src/qt/statisticspage.cpp \ - src/qt/blockbrowser.cpp \ - src/qt/marketbrowser.cpp \ - src/kernelrecord.cpp \ - src/qt/mintingfilterproxy.cpp \ + src/qt/statisticspage.cpp \ + src/qt/blockbrowser.cpp \ + src/qt/marketbrowser.cpp \ + src/kernelrecord.cpp \ + src/qt/mintingfilterproxy.cpp \ src/qt/mintingtablemodel.cpp \ src/qt/mintingview.cpp \ src/qt/multisigaddressentry.cpp \ @@ -383,7 +383,7 @@ SOURCES += src/qt/bitcoin.cpp src/qt/bitcoingui.cpp \ src/checkpoints.cpp \ src/addrman.cpp \ src/db.cpp \ - src/eccryptoverify.cpp \ + src/eccryptoverify.cpp \ src/walletdb.cpp \ src/qt/clientmodel.cpp \ src/qt/guiutil.cpp \ @@ -404,7 +404,7 @@ SOURCES += src/qt/bitcoin.cpp src/qt/bitcoingui.cpp \ src/rpcnet.cpp \ src/rpcmining.cpp \ src/rpcwallet.cpp \ - src/rpcfortuna.cpp \ + src/rpcfortuna.cpp \ src/rpcblockchain.cpp \ src/rpcrawtransaction.cpp \ src/rpcsmessage.cpp \ @@ -423,12 +423,12 @@ SOURCES += src/qt/bitcoin.cpp src/qt/bitcoingui.cpp \ src/qt/trafficgraphwidget.cpp \ src/qt/messagepage.cpp \ src/qt/messagemodel.cpp \ - src/qt/qcustomplot.cpp \ + src/qt/qcustomplot.cpp \ src/qt/sendmessagesdialog.cpp \ src/qt/sendmessagesentry.cpp \ src/qt/qvalidatedtextedit.cpp \ src/qt/plugins/mrichtexteditor/mrichtextedit.cpp \ - src/qt/fortunastakemanager.cpp \ + src/qt/fortunastakemanager.cpp \ src/qt/addeditadrenalinenode.cpp \ src/qt/adrenalinenodeconfigdialog.cpp \ src/noui.cpp \ @@ -439,11 +439,11 @@ SOURCES += src/qt/bitcoin.cpp src/qt/bitcoingui.cpp \ src/scrypt.cpp \ src/pbkdf2.cpp \ src/stealth.cpp \ - src/fortuna.cpp \ - src/activefortunastake.cpp \ - src/fortunastake.cpp \ - src/fortunastakeconfig.cpp \ - src/spork.cpp + src/fortuna.cpp \ + src/activefortunastake.cpp \ + src/fortunastake.cpp \ + src/fortunastakeconfig.cpp \ + src/spork.cpp #### D e n a r i u s sources @@ -615,7 +615,7 @@ RESOURCES += \ src/qt/res/themes/qdarkstyle/style.qrc FORMS += \ - src/qt/forms/intro.ui \ + src/qt/forms/intro.ui \ src/qt/forms/coincontroldialog.ui \ src/qt/forms/sendcoinsdialog.ui \ src/qt/forms/addressbookpage.ui \ @@ -650,6 +650,22 @@ SOURCES += src/qt/qrcodedialog.cpp FORMS += src/qt/forms/qrcodedialog.ui } +contains(DEFINES, USE_NATIVE_I2P) { +message(Building Denarius with Native I2P support) +HEADERS += src/i2p.h \ + src/i2psam.h \ + src/qt/showi2paddresses.h \ + src/qt/i2poptionswidget.h + +SOURCES += src/i2p.cpp \ + src/i2psam.cpp \ + src/qt/showi2paddresses.cpp \ + src/qt/i2poptionswidget.cpp + +FORMS += src/qt/forms/showi2paddresses.ui \ + src/qt/forms/i2poptionswidget.ui +} + CODECFORTR = UTF-8 # for lrelease/lupdate diff --git a/src/clientversion.h b/src/clientversion.h index 33130eca..030a3d1d 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -11,6 +11,11 @@ #define CLIENT_VERSION_REVISION 4 #define CLIENT_VERSION_BUILD 0 +#ifdef USE_NATIVE_I2P +#define I2P_NATIVE_VERSION_MAJOR 0 +#define I2P_NATIVE_VERSION_MINOR 2 +#endif + // Converts the parameter X to a string after macro replacement on X has been performed. // Don't merge these into one macro! #define STRINGIZE(X) DO_STRINGIZE(X) diff --git a/src/compat.h b/src/compat.h index d09ec4fe..bfb712ef 100644 --- a/src/compat.h +++ b/src/compat.h @@ -11,6 +11,11 @@ #ifndef NOMINMAX #define NOMINMAX #endif +#ifdef FD_SETSIZE +#undef FD_SETSIZE // prevent redefinition compiler warning +#endif +#define FD_SETSIZE 1024 // max number of fds in fd_set + #include #include #include @@ -23,6 +28,7 @@ #include #include #include +#include typedef u_int SOCKET; #endif diff --git a/src/i2p.cpp b/src/i2p.cpp new file mode 100644 index 00000000..0713eb32 --- /dev/null +++ b/src/i2p.cpp @@ -0,0 +1,208 @@ +// Copyright (c) 2012-2013 giv +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +//-------------------------------------------------------------------------------------------------- +#include +#include "i2p.h" +#include "util.h" +#include "hash.h" + +namespace SAM +{ + +class StreamSessionAdapter::SessionHolder +{ +public: + explicit SessionHolder(std::auto_ptr session); + + const SAM::StreamSession& getSession() const; + SAM::StreamSession& getSession(); +private: + void heal() const; + void reborn() const; + + mutable std::auto_ptr session_; + typedef boost::shared_mutex mutex_type; + mutable mutex_type mtx_; +}; + +StreamSessionAdapter::SessionHolder::SessionHolder(std::auto_ptr session) + : session_(session) +{} + +const SAM::StreamSession& StreamSessionAdapter::SessionHolder::getSession() const +{ + boost::upgrade_lock lock(mtx_); + if (session_->isSick()) + { + boost::upgrade_to_unique_lock ulock(lock); + heal(); + } + return *session_; +} + +SAM::StreamSession& StreamSessionAdapter::SessionHolder::getSession() +{ + boost::upgrade_lock lock(mtx_); + if (session_->isSick()) + { + boost::upgrade_to_unique_lock ulock(lock); + heal(); + } + return *session_; +} + +void StreamSessionAdapter::SessionHolder::heal() const +{ + reborn(); // if we don't know how to heal it just reborn it +} + +void StreamSessionAdapter::SessionHolder::reborn() const +{ + if (!session_->isSick()) + return; + std::auto_ptr newSession(new SAM::StreamSession(*session_)); + if (!newSession->isSick() && session_->isSick()) + { + session_ = newSession; + } +} + +//-------------------------------------------------------------------------------------------------- + +StreamSessionAdapter::StreamSessionAdapter( + const std::string& nickname, + const std::string& SAMHost /*= SAM_DEFAULT_ADDRESS*/, + uint16_t SAMPort /*= SAM_DEFAULT_PORT*/, + const std::string& myDestination /*= SAM_GENERATE_MY_DESTINATION*/, + const std::string& i2pOptions /*= SAM_DEFAULT_I2P_OPTIONS*/, + const std::string& minVer /*= SAM_DEFAULT_MIN_VER*/, + const std::string& maxVer /*= SAM_DEFAULT_MAX_VER*/) + : sessionHolder_( + new SessionHolder( + std::auto_ptr( + new SAM::StreamSession(nickname, SAMHost, SAMPort, myDestination, i2pOptions, minVer, maxVer)))) +{} + +StreamSessionAdapter::~StreamSessionAdapter() +{} + +SAM::SOCKET StreamSessionAdapter::accept(bool silent) +{ + SAM::RequestResult > result = sessionHolder_->getSession().accept(silent); + // call Socket::release + return result.isOk ? result.value->release() : SAM_INVALID_SOCKET; +} + +SAM::SOCKET StreamSessionAdapter::connect(const std::string& destination, bool silent) +{ + SAM::RequestResult > result = sessionHolder_->getSession().connect(destination, silent); + // call Socket::release + return result.isOk ? result.value->release() : SAM_INVALID_SOCKET; +} + +bool StreamSessionAdapter::forward(const std::string& host, uint16_t port, bool silent) +{ + return sessionHolder_->getSession().forward(host, port, silent).isOk; +} + +std::string StreamSessionAdapter::namingLookup(const std::string& name) const +{ + SAM::RequestResult result = sessionHolder_->getSession().namingLookup(name); + return result.isOk ? result.value : std::string(); +} + +SAM::FullDestination StreamSessionAdapter::destGenerate() const +{ + SAM::RequestResult result = sessionHolder_->getSession().destGenerate(); + return result.isOk ? result.value : SAM::FullDestination(); +} + +void StreamSessionAdapter::stopForwarding(const std::string& host, uint16_t port) +{ + sessionHolder_->getSession().stopForwarding(host, port); +} + +void StreamSessionAdapter::stopForwardingAll() +{ + sessionHolder_->getSession().stopForwardingAll(); +} + +const SAM::FullDestination& StreamSessionAdapter::getMyDestination() const +{ + return sessionHolder_->getSession().getMyDestination(); +} + +const sockaddr_in& StreamSessionAdapter::getSAMAddress() const +{ + return sessionHolder_->getSession().getSAMAddress(); +} + +const std::string& StreamSessionAdapter::getSAMHost() const +{ + return sessionHolder_->getSession().getSAMHost(); +} + +uint16_t StreamSessionAdapter::getSAMPort() const +{ + return sessionHolder_->getSession().getSAMPort(); +} + +const std::string& StreamSessionAdapter::getNickname() const +{ + return sessionHolder_->getSession().getNickname(); +} + +const std::string& StreamSessionAdapter::getSAMMinVer() const +{ + return sessionHolder_->getSession().getSAMMinVer(); +} + +const std::string& StreamSessionAdapter::getSAMMaxVer() const +{ + return sessionHolder_->getSession().getSAMMaxVer(); +} + +const std::string& StreamSessionAdapter::getSAMVersion() const +{ + return sessionHolder_->getSession().getSAMVersion(); +} + +const std::string& StreamSessionAdapter::getOptions() const +{ + return sessionHolder_->getSession().getOptions(); +} + +} // namespace SAM + +//-------------------------------------------------------------------------------------------------- + +I2PSession::I2PSession() + : SAM::StreamSessionAdapter( + GetArg(I2P_SESSION_NAME_PARAM, I2P_SESSION_NAME_DEFAULT), + GetArg(I2P_SAM_HOST_PARAM, I2P_SAM_HOST_DEFAULT), + (uint16_t)GetArg(I2P_SAM_PORT_PARAM, I2P_SAM_PORT_DEFAULT), + GetArg(I2P_SAM_MY_DESTINATION_PARAM, I2P_SAM_MY_DESTINATION_DEFAULT), + GetArg(I2P_SAM_I2P_OPTIONS_PARAM, SAM_DEFAULT_I2P_OPTIONS)) +{} + +I2PSession::~I2PSession() +{} + +/*static*/ +std::string I2PSession::GenerateB32AddressFromDestination(const std::string& destination) +{ + std::string canonicalDest = destination; + for (size_t pos = canonicalDest.find_first_of('-'); pos != std::string::npos; pos = canonicalDest.find_first_of('-', pos)) + canonicalDest[pos] = '+'; + for (size_t pos = canonicalDest.find_first_of('~'); pos != std::string::npos; pos = canonicalDest.find_first_of('~', pos)) + canonicalDest[pos] = '/'; + std::string rawHash = DecodeBase64(canonicalDest); + uint256 hash; + SHA256((const unsigned char*)rawHash.c_str(), rawHash.size(), (unsigned char*)&hash); + std::string result = EncodeBase32(hash.begin(), hash.end() - hash.begin()) + ".b32.i2p"; + for (size_t pos = result.find_first_of('='); pos != std::string::npos; pos = result.find_first_of('=', pos-1)) + result.erase(pos, 1); + return result; +} + diff --git a/src/i2p.h b/src/i2p.h new file mode 100644 index 00000000..62e070fc --- /dev/null +++ b/src/i2p.h @@ -0,0 +1,92 @@ +// Copyright (c) 2012-2013 giv +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +//-------------------------------------------------------------------------------------------------- +#ifndef I2P_H +#define I2P_H + +#include "i2psam.h" + +#define I2P_SESSION_NAME_PARAM "-i2psessionname" +#define I2P_SESSION_NAME_DEFAULT "Denarius-client" + +#define I2P_SAM_HOST_PARAM "-samhost" +#define I2P_SAM_HOST_DEFAULT SAM_DEFAULT_ADDRESS + +#define I2P_SAM_PORT_PARAM "-samport" +#define I2P_SAM_PORT_DEFAULT SAM_DEFAULT_PORT + +#define I2P_SAM_MY_DESTINATION_PARAM "-mydestination" +#define I2P_SAM_MY_DESTINATION_DEFAULT SAM_GENERATE_MY_DESTINATION + +#define I2P_SAM_I2P_OPTIONS_PARAM "-i2poptions" +#define I2P_SAM_I2P_OPTIONS_DEFAULT SAM_DEFAULT_I2P_OPTIONS + +#define I2P_SAM_GENERATE_DESTINATION_PARAM "-generatei2pdestination" + +namespace SAM +{ + +class StreamSessionAdapter +{ +public: + StreamSessionAdapter( + const std::string& nickname, + const std::string& SAMHost = SAM_DEFAULT_ADDRESS, + uint16_t SAMPort = SAM_DEFAULT_PORT, + const std::string& myDestination = SAM_GENERATE_MY_DESTINATION, + const std::string& i2pOptions = SAM_DEFAULT_I2P_OPTIONS, + const std::string& minVer = SAM_DEFAULT_MIN_VER, + const std::string& maxVer = SAM_DEFAULT_MAX_VER); + + ~StreamSessionAdapter(); + + SAM::SOCKET accept(bool silent); + SAM::SOCKET connect(const std::string& destination, bool silent); + bool forward(const std::string& host, uint16_t port, bool silent); + std::string namingLookup(const std::string& name) const; + SAM::FullDestination destGenerate() const; + + void stopForwarding(const std::string& host, uint16_t port); + void stopForwardingAll(); + + const SAM::FullDestination& getMyDestination() const; + + const sockaddr_in& getSAMAddress() const; + const std::string& getSAMHost() const; + uint16_t getSAMPort() const; + const std::string& getNickname() const; + const std::string& getSAMMinVer() const; + const std::string& getSAMMaxVer() const; + const std::string& getSAMVersion() const; + const std::string& getOptions() const; + +private: + class SessionHolder; + + std::auto_ptr sessionHolder_; +}; + +} // namespace SAM + +class I2PSession : private SAM::StreamSessionAdapter +{ +public: + // In C++11 this code is thread safe, in C++03 it isn't + static SAM::StreamSessionAdapter& Instance() + { + static I2PSession i2pSession; + return i2pSession; + } + + static std::string GenerateB32AddressFromDestination(const std::string& destination); + +private: + I2PSession(); + ~I2PSession(); + + I2PSession(const I2PSession&); + I2PSession& operator=(const I2PSession&); +}; + +#endif // I2P_H diff --git a/src/i2psam.cpp b/src/i2psam.cpp new file mode 100644 index 00000000..9d6fea9e --- /dev/null +++ b/src/i2psam.cpp @@ -0,0 +1,798 @@ +// Copyright (c) 2012-2013 giv +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +//-------------------------------------------------------------------------------------------------- +#include "i2psam.h" + +#ifdef WIN32 +//#define _WIN32_WINNT 0x0501 +#define WIN32_LEAN_AND_MEAN 1 +#define FD_SETSIZE +#include +#else +#include +#include // for sockaddr_in +#include // for ntohs and htons +#endif + +#include +#include +#include // for memset +#include +#include +#include + +#ifndef WIN32 +#include +#include +#endif + +#ifndef WIN32 +#define closesocket close +#endif + +#define SAM_BUFSIZE 65536 +#define I2P_DESTINATION_SIZE 516 + +namespace SAM +{ + +static void print_error(const std::string& err) +{ +#ifdef WIN32 + std::cout << err << "(" << WSAGetLastError() << ")" << std::endl; +#else + std::cout << err << "(" << errno << ")" << std::endl; +#endif +} + +#ifdef WIN32 +int Socket::instances_ = 0; + +void Socket::initWSA() +{ + WSADATA wsadata; + int ret = WSAStartup(MAKEWORD(2,2), &wsadata); + if (ret != NO_ERROR) + print_error("Failed to initialize winsock library"); +} + +void Socket::freeWSA() +{ + WSACleanup(); +} +#endif + +Socket::Socket(const std::string& SAMHost, uint16_t SAMPort, const std::string& minVer, const std::string &maxVer) + : socket_(SAM_INVALID_SOCKET), SAMHost_(SAMHost), SAMPort_(SAMPort), minVer_(minVer), maxVer_(maxVer) +{ +#ifdef WIN32 + if (instances_++ == 0) + initWSA(); +#endif + + memset(&servAddr_, 0, sizeof(servAddr_)); + + servAddr_.sin_family = AF_INET; + servAddr_.sin_addr.s_addr = inet_addr(SAMHost.c_str()); + servAddr_.sin_port = htons(SAMPort); + + init(); + if (isOk()) + handshake(); +} + +Socket::Socket(const sockaddr_in& addr, const std::string &minVer, const std::string& maxVer) + : socket_(SAM_INVALID_SOCKET), servAddr_(addr), minVer_(minVer), maxVer_(maxVer) +{ +#ifdef WIN32 + if (instances_++ == 0) + initWSA(); +#endif + + init(); + if (isOk()) + handshake(); +} + +Socket::Socket(const Socket& rhs) + : socket_(SAM_INVALID_SOCKET), servAddr_(rhs.servAddr_), minVer_(rhs.minVer_), maxVer_(rhs.maxVer_) +{ +#ifdef WIN32 + if (instances_++ == 0) + initWSA(); +#endif + + init(); + if (isOk()) + handshake(); +} + +Socket::~Socket() +{ + close(); + +#ifdef WIN32 + if (--instances_ == 0) + freeWSA(); +#endif +} + +void Socket::init() +{ + socket_ = socket(AF_INET, SOCK_STREAM, 0); + if (socket_ == SAM_INVALID_SOCKET) + { + print_error("Failed to create socket"); + return; + } + + if (connect(socket_, (const sockaddr*)&servAddr_, sizeof(servAddr_)) == SAM_SOCKET_ERROR) + { + close(); + print_error("Failed to connect to SAM"); + return; + } +} + +SOCKET Socket::release() +{ + SOCKET temp = socket_; + socket_ = SAM_INVALID_SOCKET; + return temp; +} + +void Socket::handshake() +{ + this->write(Message::hello(minVer_, maxVer_)); + const std::string answer = this->read(); + const Message::eStatus answerStatus = Message::checkAnswer(answer); + if (answerStatus == Message::OK) + version_ = Message::getValue(answer, "VERSION"); + else + print_error("Handshake failed"); +} + +void Socket::write(const std::string& msg) +{ + if (!isOk()) + { + print_error("Failed to send data because socket is closed"); + return; + } + std::cout << "Send: " << msg << std::endl; + ssize_t sentBytes = send(socket_, msg.c_str(), msg.length(), 0); + if (sentBytes == SAM_SOCKET_ERROR) + { + close(); + print_error("Failed to send data"); + return; + } + if (sentBytes == 0) + { + close(); + print_error("Socket was closed"); + return; + } +} + +std::string Socket::read() +{ + if (!isOk()) + { + print_error("Failed to read data because socket is closed"); + return std::string(); + } + char buffer[SAM_BUFSIZE]; + memset(buffer, 0, SAM_BUFSIZE); + ssize_t recievedBytes = recv(socket_, buffer, SAM_BUFSIZE, 0); + if (recievedBytes == SAM_SOCKET_ERROR) + { + close(); + print_error("Failed to receive data"); + return std::string(); + } + if (recievedBytes == 0) + { + close(); + print_error("Socket was closed"); + } + std::cout << "Reply: " << buffer << std::endl; + return std::string(buffer); +} + +void Socket::close() +{ + if (socket_ != SAM_INVALID_SOCKET) + ::closesocket(socket_); + socket_ = SAM_INVALID_SOCKET; +} + +bool Socket::isOk() const +{ + return socket_ != SAM_INVALID_SOCKET; +} + +const std::string& Socket::getHost() const +{ + return SAMHost_; +} + +uint16_t Socket::getPort() const +{ + return SAMPort_; +} + +const std::string& Socket::getVersion() const +{ + return version_; +} + +const std::string& Socket::getMinVer() const +{ + return minVer_; +} + +const std::string& Socket::getMaxVer() const +{ + return maxVer_; +} + +const sockaddr_in& Socket::getAddress() const +{ + return servAddr_; +} + + +//-------------------------------------------------------------------------------------------------- + +StreamSession::StreamSession( + const std::string& nickname, + const std::string& SAMHost /*= SAM_DEFAULT_ADDRESS*/, + uint16_t SAMPort /*= SAM_DEFAULT_PORT*/, + const std::string& destination /*= SAM_GENERATE_MY_DESTINATION*/, + const std::string& i2pOptions /*= SAM_DEFAULT_I2P_OPTIONS*/, + const std::string& minVer /*= SAM_DEFAULT_MIN_VER*/, + const std::string& maxVer /*= SAM_DEFAULT_MAX_VER*/) + : socket_(SAMHost, SAMPort, minVer, maxVer) + , nickname_(nickname) + , sessionID_(generateSessionID()) + , i2pOptions_(i2pOptions) + , isSick_(false) +{ + myDestination_ = createStreamSession(destination); + std::cout << "Created a brand new SAM session (" << sessionID_ << ")" << std::endl; +} + +StreamSession::StreamSession(StreamSession& rhs) + : socket_(rhs.socket_) + , nickname_(rhs.nickname_) + , sessionID_(generateSessionID()) + , myDestination_(rhs.myDestination_) + , i2pOptions_(rhs.i2pOptions_) + , isSick_(false) +{ + rhs.fallSick(); + rhs.socket_.close(); + (void)createStreamSession(myDestination_.priv); + + for(ForwardedStreamsContainer::const_iterator it = rhs.forwardedStreams_.begin(), end = rhs.forwardedStreams_.end(); it != end; ++it) + forward(it->host, it->port, it->silent); + + std::cout << "Created a new SAM session (" << sessionID_ << ") from another (" << rhs.sessionID_ << ")" << std::endl; +} + +StreamSession::~StreamSession() +{ + stopForwardingAll(); + std::cout << "Closing SAM session (" << sessionID_ << ") ..." << std::endl; +} + +/*static*/ +std::string StreamSession::generateSessionID() +{ + static const int minSessionIDLength = 5; + static const int maxSessionIDLength = 9; + static const char sessionIDAlphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + int length = minSessionIDLength - 1; + std::string result; + + srand(time(NULL)); + + while(length < minSessionIDLength) + length = rand() % maxSessionIDLength; + + while (length-- > 0) + result += sessionIDAlphabet[rand() % (sizeof(sessionIDAlphabet)-1)]; + + return result; +} + +RequestResult > StreamSession::accept(bool silent) +{ + typedef RequestResult > ResultType; + + std::auto_ptr streamSocket(new Socket(socket_)); + const Message::eStatus status = accept(*streamSocket, sessionID_, silent); + switch(status) + { + case Message::OK: + return RequestResult >(streamSocket); + case Message::EMPTY_ANSWER: + case Message::CLOSED_SOCKET: + case Message::INVALID_ID: + case Message::I2P_ERROR: + fallSick(); + break; + default: + break; + } + return ResultType(); +} + +RequestResult > StreamSession::connect(const std::string& destination, bool silent) +{ + typedef RequestResult > ResultType; + + std::auto_ptr streamSocket(new Socket(socket_)); + const Message::eStatus status = connect(*streamSocket, sessionID_, destination, silent); + switch(status) + { + case Message::OK: + return ResultType(streamSocket); + case Message::EMPTY_ANSWER: + case Message::CLOSED_SOCKET: + case Message::INVALID_ID: + case Message::I2P_ERROR: + fallSick(); + break; + default: + break; + } + return ResultType(); +} + +RequestResult StreamSession::forward(const std::string& host, uint16_t port, bool silent) +{ + typedef RequestResult ResultType; + + std::auto_ptr newSocket(new Socket(socket_)); + const Message::eStatus status = forward(*newSocket, sessionID_, host, port, silent); + switch(status) + { + case Message::OK: + forwardedStreams_.push_back(ForwardedStream(newSocket.get(), host, port, silent)); + newSocket.release(); // release after successful push_back only + return ResultType(true); + case Message::EMPTY_ANSWER: + case Message::CLOSED_SOCKET: + case Message::INVALID_ID: + case Message::I2P_ERROR: + fallSick(); + break; + default: + break; + } + return ResultType(); +} + +RequestResult StreamSession::namingLookup(const std::string& name) const +{ + typedef RequestResult ResultType; + typedef Message::Answer AnswerType; + + std::auto_ptr newSocket(new Socket(socket_)); + const AnswerType answer = namingLookup(*newSocket, name); + switch(answer.status) + { + case Message::OK: + return ResultType(answer.value); + case Message::EMPTY_ANSWER: + case Message::CLOSED_SOCKET: + fallSick(); + break; + default: + break; + } + return ResultType(); +} + +RequestResult StreamSession::destGenerate() const +{ + typedef RequestResult ResultType; + typedef Message::Answer AnswerType; + + std::auto_ptr newSocket(new Socket(socket_)); + const AnswerType answer = destGenerate(*newSocket); + switch(answer.status) + { + case Message::OK: + return ResultType(answer.value); + case Message::EMPTY_ANSWER: + case Message::CLOSED_SOCKET: + fallSick(); + break; + default: + break; + } + return ResultType(); +} + +FullDestination StreamSession::createStreamSession(const std::string& destination) +{ + typedef Message::Answer AnswerType; + + const AnswerType answer = createStreamSession(socket_, sessionID_, nickname_, destination, i2pOptions_); + if (answer.status != Message::OK) + { + fallSick(); + return FullDestination(); + } + return FullDestination(answer.value.substr(0, I2P_DESTINATION_SIZE), answer.value, (destination == SAM_GENERATE_MY_DESTINATION)); +} + +void StreamSession::fallSick() const +{ + isSick_ = true; +} + +void StreamSession::stopForwarding(const std::string& host, uint16_t port) +{ + for (ForwardedStreamsContainer::iterator it = forwardedStreams_.begin(); it != forwardedStreams_.end(); ) + { + if (it->port == port && it->host == host) + { + delete (it->socket); + it = forwardedStreams_.erase(it); + } + else + ++it; + } +} + +void StreamSession::stopForwardingAll() +{ + for (ForwardedStreamsContainer::iterator it = forwardedStreams_.begin(); it != forwardedStreams_.end(); ++it) + delete (it->socket); + forwardedStreams_.clear(); +} + +/*static*/ +Message::Answer StreamSession::rawRequest(Socket& socket, const std::string& requestStr) +{ + typedef Message::Answer AnswerType; + + if (!socket.isOk()) + return AnswerType(Message::CLOSED_SOCKET); + socket.write(requestStr); + const std::string answer = socket.read(); + const Message::eStatus status = Message::checkAnswer(answer); + return AnswerType(status, answer); +} + +/*static*/ +Message::Answer StreamSession::request(Socket& socket, const std::string& requestStr, const std::string& keyOnSuccess) +{ + typedef Message::Answer AnswerType; + + const AnswerType answer = rawRequest(socket, requestStr); + return (answer.status == Message::OK) ? + AnswerType(answer.status, Message::getValue(answer.value, keyOnSuccess)) : + answer; +} + +/*static*/ +Message::eStatus StreamSession::request(Socket& socket, const std::string& requestStr) +{ + return rawRequest(socket, requestStr).status; +} + +/*static*/ +Message::Answer StreamSession::createStreamSession(Socket& socket, const std::string& sessionID, const std::string& nickname, const std::string& destination, const std::string& options) +{ + return request(socket, Message::sessionCreate(Message::sssStream, sessionID, nickname, destination, options), "DESTINATION"); +} + +/*static*/ +Message::Answer StreamSession::namingLookup(Socket& socket, const std::string& name) +{ + return request(socket, Message::namingLookup(name), "VALUE"); +} + +/*static*/ +Message::Answer StreamSession::destGenerate(Socket& socket) +{ +// while answer for a DEST GENERATE request doesn't contain a "RESULT" field we parse it manually + typedef Message::Answer ResultType; + + if (!socket.isOk()) + return ResultType(Message::CLOSED_SOCKET, FullDestination()); + socket.write(Message::destGenerate()); + const std::string answer = socket.read(); + const std::string pub = Message::getValue(answer, "PUB"); + const std::string priv = Message::getValue(answer, "PRIV"); + return (!pub.empty() && !priv.empty()) ? ResultType(Message::OK, FullDestination(pub, priv, /*isGenerated*/ true)) : ResultType(Message::EMPTY_ANSWER, FullDestination()); +} + +/*static*/ +Message::eStatus StreamSession::accept(Socket& socket, const std::string& sessionID, bool silent) +{ + return request(socket, Message::streamAccept(sessionID, silent)); +} + +/*static*/ +Message::eStatus StreamSession::connect(Socket& socket, const std::string& sessionID, const std::string& destination, bool silent) +{ + return request(socket, Message::streamConnect(sessionID, destination, silent)); +} + +/*static*/ +Message::eStatus StreamSession::forward(Socket& socket, const std::string& sessionID, const std::string& host, uint16_t port, bool silent) +{ + return request(socket, Message::streamForward(sessionID, host, port, silent)); +} + +const std::string& StreamSession::getNickname() const +{ + return nickname_; +} + +const std::string& StreamSession::getSessionID() const +{ + return sessionID_; +} + +const std::string& StreamSession::getOptions() const +{ + return i2pOptions_; +} + +const FullDestination& StreamSession::getMyDestination() const +{ + return myDestination_; +} + +bool StreamSession::isSick() const +{ + return isSick_; +} + +const sockaddr_in& StreamSession::getSAMAddress() const +{ + return socket_.getAddress(); +} + +const std::string& StreamSession::getSAMHost() const +{ + return socket_.getHost(); +} + +uint16_t StreamSession::getSAMPort() const +{ + return socket_.getPort(); +} + +const std::string& StreamSession::getSAMMinVer() const +{ + return socket_.getMinVer(); +} + +const std::string& StreamSession::getSAMMaxVer() const +{ + return socket_.getMaxVer(); +} + +const std::string& StreamSession::getSAMVersion() const +{ + return socket_.getVersion(); +} + +//-------------------------------------------------------------------------------------------------- + + +std::string Message::createSAMRequest(const char* format, ...) +{ + char buffer[SAM_BUFSIZE]; + memset(buffer, 0, SAM_BUFSIZE); + + va_list args; + va_start (args, format); + const int sizeToSend = vsnprintf(buffer, SAM_BUFSIZE, format, args); + va_end(args); + + if (sizeToSend < 0) + { + print_error("Failed to format message"); + return std::string(); + } + return std::string(buffer); +} + +std::string Message::hello(const std::string &minVer, const std::string &maxVer) +{ +/////////////////////////////////////////////////////////// +// +// -> HELLO VERSION +// MIN=$min +// MAX=$max +// +// <- HELLO REPLY +// RESULT=OK +// VERSION=$version +// +/////////////////////////////////////////////////////////// + + static const char* helloFormat = "HELLO VERSION MIN=%s MAX=%s\n"; + return createSAMRequest(helloFormat, minVer.c_str(), maxVer.c_str()); +} + +std::string Message::sessionCreate(SessionStyle style, const std::string& sessionID, const std::string& nickname, const std::string& destination /*= SAM_GENERATE_MY_DESTINATION*/, const std::string& options /*= ""*/) +{ +/////////////////////////////////////////////////////////// +// +// -> SESSION CREATE +// STYLE={STREAM,DATAGRAM,RAW} +// ID={$nickname} +// DESTINATION={$private_destination_key,TRANSIENT} +// [option=value]* +// +// <- SESSION STATUS +// RESULT=OK +// DESTINATION=$private_destination_key +// +/////////////////////////////////////////////////////////// + + std::string sessionStyle; + switch(style) + { + case sssStream: sessionStyle = "STREAM"; break; + case sssDatagram: sessionStyle = "DATAGRAM"; break; + case sssRaw: sessionStyle = "RAW"; break; + } + + static const char* sessionCreateFormat = "SESSION CREATE STYLE=%s ID=%s DESTINATION=%s inbound.nickname=%s %s\n"; // we add inbound.nickname option + return createSAMRequest(sessionCreateFormat, sessionStyle.c_str(), sessionID.c_str(), destination.c_str(), nickname.c_str(), options.c_str()); +} + +std::string Message::streamAccept(const std::string& sessionID, bool silent /*= false*/) +{ +/////////////////////////////////////////////////////////// +// +// -> STREAM ACCEPT +// ID={$nickname} +// [SILENT={true,false}] +// +// <- STREAM STATUS +// RESULT=$result +// [MESSAGE=...] +// +/////////////////////////////////////////////////////////// + + static const char* streamAcceptFormat = "STREAM ACCEPT ID=%s SILENT=%s\n"; + return createSAMRequest(streamAcceptFormat, sessionID.c_str(), silent ? "true" : "false"); +} + +std::string Message::streamConnect(const std::string& sessionID, const std::string& destination, bool silent /*= false*/) +{ +/////////////////////////////////////////////////////////// +// +// -> STREAM CONNECT +// ID={$nickname} +// DESTINATION=$peer_public_base64_key +// [SILENT={true,false}] +// +// <- STREAM STATUS +// RESULT=$result +// [MESSAGE=...] +// +/////////////////////////////////////////////////////////// + + static const char* streamConnectFormat = "STREAM CONNECT ID=%s DESTINATION=%s SILENT=%s\n"; + return createSAMRequest(streamConnectFormat, sessionID.c_str(), destination.c_str(), silent ? "true" : "false"); +} + +std::string Message::streamForward(const std::string& sessionID, const std::string& host, uint16_t port, bool silent /*= false*/) +{ +/////////////////////////////////////////////////////////// +// +// -> STREAM FORWARD +// ID={$nickname} +// PORT={$port} +// [HOST={$host}] +// [SILENT={true,false}] +// +// <- STREAM STATUS +// RESULT=$result +// [MESSAGE=...] +// +/////////////////////////////////////////////////////////// + static const char* streamForwardFormat = "STREAM FORWARD ID=%s PORT=%u HOST=%s SILENT=%s\n"; + return createSAMRequest(streamForwardFormat, sessionID.c_str(), (unsigned)port, host.c_str(), silent ? "true" : "false"); +} + +std::string Message::namingLookup(const std::string& name) +{ +/////////////////////////////////////////////////////////// +// +// -> NAMING LOOKUP +// NAME=$name +// +// <- NAMING REPLY +// RESULT=OK +// NAME=$name +// VALUE=$base64key +// +/////////////////////////////////////////////////////////// + + static const char* namingLookupFormat = "NAMING LOOKUP NAME=%s\n"; + return createSAMRequest(namingLookupFormat, name.c_str()); +} + +std::string Message::destGenerate() +{ +/////////////////////////////////////////////////////////// +// +// -> DEST GENERATE +// +// <- DEST REPLY +// PUB=$pubkey +// PRIV=$privkey +// +/////////////////////////////////////////////////////////// + + static const char* destGenerateFormat = "DEST GENERATE\n"; + return createSAMRequest(destGenerateFormat); +} + +#define SAM_MAKESTRING(X) SAM_MAKESTRING2(X) +#define SAM_MAKESTRING2(X) #X + +#define SAM_CHECK_RESULT(value) \ + if (result == SAM_MAKESTRING(value)) return value + +Message::eStatus Message::checkAnswer(const std::string& answer) +{ + if (answer.empty()) + return EMPTY_ANSWER; + + const std::string result = getValue(answer, "RESULT"); + + SAM_CHECK_RESULT(OK); + SAM_CHECK_RESULT(DUPLICATED_DEST); + SAM_CHECK_RESULT(DUPLICATED_ID); + SAM_CHECK_RESULT(I2P_ERROR); + SAM_CHECK_RESULT(INVALID_ID); + SAM_CHECK_RESULT(INVALID_KEY); + SAM_CHECK_RESULT(CANT_REACH_PEER); + SAM_CHECK_RESULT(TIMEOUT); + SAM_CHECK_RESULT(NOVERSION); + SAM_CHECK_RESULT(KEY_NOT_FOUND); + SAM_CHECK_RESULT(PEER_NOT_FOUND); + SAM_CHECK_RESULT(ALREADY_ACCEPTING); + + return CANNOT_PARSE_ERROR; +} + +#undef SAM_CHECK_RESULT +#undef SAM_MAKESTRING2 +#undef SAM_MAKESTRING + +std::string Message::getValue(const std::string& answer, const std::string& key) +{ + if (key.empty()) + return std::string(); + + const std::string keyPattern = key + "="; + size_t valueStart = answer.find(keyPattern); + if (valueStart == std::string::npos) + return std::string(); + + valueStart += keyPattern.length(); + size_t valueEnd = answer.find_first_of(' ', valueStart); + if (valueEnd == std::string::npos) + valueEnd = answer.find_first_of('\n', valueStart); + return answer.substr(valueStart, valueEnd - valueStart); +} + + +} // namespace SAM diff --git a/src/i2psam.h b/src/i2psam.h new file mode 100644 index 00000000..0ecb5265 --- /dev/null +++ b/src/i2psam.h @@ -0,0 +1,423 @@ +// Copyright (c) 2012-2013 giv +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +//-------------------------------------------------------------------------------------------------- +// see full documentation about SAM at http://www.i2p2.i2p/samv3.html +#ifndef I2PSAM_H +#define I2PSAM_H + +#include +#include +#include +#include +#include + +#ifdef WIN32 +////#define _WIN32_WINNT 0x0501 +#define WIN32_LEAN_AND_MEAN 1 +//#define FD_SETSIZE - Won't compile with it atm +#include +#else +#include +#include // for sockaddr_in +#include // for ntohs and htons +#endif + +//#ifndef WIN32 + +// TODO: check a possible bug about cast -1 to SOCKET +#define SAM_INVALID_SOCKET (-1) +#define SAM_SOCKET_ERROR (-1) + +#define SAM_DEFAULT_ADDRESS "127.0.0.1" +#define SAM_DEFAULT_PORT 7656 +#define SAM_DEFAULT_MIN_VER "3.0" +#define SAM_DEFAULT_MAX_VER "3.0" +#define SAM_GENERATE_MY_DESTINATION "TRANSIENT" +#define SAM_MY_NAME "ME" +#define SAM_DEFAULT_I2P_OPTIONS "" + +#define SAM_NAME_INBOUND_QUANTITY "inbound.quantity" +#define SAM_DEFAULT_INBOUND_QUANTITY 2 +#define SAM_NAME_INBOUND_LENGTH "inbound.length" +#define SAM_DEFAULT_INBOUND_LENGTH 2 +#define SAM_NAME_INBOUND_LENGTHVARIANCE "inbound.lengthVariance" +#define SAM_DEFAULT_INBOUND_LENGTHVARIANCE 0 +#define SAM_NAME_INBOUND_BACKUPQUANTITY "inbound.backupquantity" +#define SAM_DEFAULT_INBOUND_BACKUPQUANTITY 0 +#define SAM_NAME_INBOUND_ALLOWZEROHOP "inbound.allowzerohop" +#define SAM_DEFAULT_INBOUND_ALLOWZEROHOP true +#define SAM_NAME_INBOUND_IPRESTRICTION "inbound.iprestriction" +#define SAM_DEFAULT_INBOUND_IPRESTRICTION 2 +#define SAM_NAME_OUTBOUND_QUANTITY "outbound.quantity" +#define SAM_DEFAULT_OUTBOUND_QUANTITY 2 +#define SAM_NAME_OUTBOUND_LENGTH "outbound.length" +#define SAM_DEFAULT_OUTBOUND_LENGTH 2 +#define SAM_NAME_OUTBOUND_LENGTHVARIANCE "outbound.lengthvariance" +#define SAM_DEFAULT_OUTBOUND_LENGTHVARIANCE 0 +#define SAM_NAME_OUTBOUND_BACKUPQUANTITY "outbound.backupquantity" +#define SAM_DEFAULT_OUTBOUND_BACKUPQUANTITY 0 +#define SAM_NAME_OUTBOUND_ALLOWZEROHOP "outbound.allowzerohop" +#define SAM_DEFAULT_OUTBOUND_ALLOWZEROHOP true +#define SAM_NAME_OUTBOUND_IPRESTRICTION "outbound.iprestriction" +#define SAM_DEFAULT_OUTBOUND_IPRESTRICTION 2 +#define SAM_NAME_OUTBOUND_PRIORITY "outbound.priority" +#define SAM_DEFAULT_OUTBOUND_PRIORITY 0 + +namespace SAM +{ + +typedef int SOCKET; + +class Message +{ +public: + enum SessionStyle + { + sssStream, + sssDatagram, // not supported now + sssRaw // not supported now + }; + + enum eStatus + { + OK, + EMPTY_ANSWER, + CLOSED_SOCKET, + CANNOT_PARSE_ERROR, + + // The destination is already in use + // + // -> SESSION CREATE ... + // <- SESSION STATUS RESULT=DUPLICATED_DEST + DUPLICATED_DEST, + + // The nickname is already associated with a session + // + // -> SESSION CREATE ... + // <- SESSION STATUS RESULT=DUPLICATED_ID + DUPLICATED_ID, + + // A generic I2P error (e.g. I2CP disconnection, etc.) + // + // -> HELLO VERSION ... + // <- HELLO REPLY RESULT=I2P_ERROR MESSAGE={$message} + // + // -> SESSION CREATE ... + // <- SESSION STATUS RESULT=I2P_ERROR MESSAGE={$message} + // + // -> STREAM CONNECT ... + // <- STREAM STATUS RESULT=I2P_ERROR MESSAGE={$message} + // + // -> STREAM ACCEPT ... + // <- STREAM STATUS RESULT=I2P_ERROR MESSAGE={$message} + // + // -> STREAM FORWARD ... + // <- STREAM STATUS RESULT=I2P_ERROR MESSAGE={$message} + // + // -> NAMING LOOKUP ... + // <- NAMING REPLY RESULT=INVALID_KEY NAME={$name} MESSAGE={$message} + I2P_ERROR, + + // Stream session ID doesn't exist + // + // -> STREAM CONNECT ... + // <- STREAM STATUS RESULT=INVALID_ID MESSAGE={$message} + // + // -> STREAM ACCEPT ... + // <- STREAM STATUS RESULT=INVALID_ID MESSAGE={$message} + // + // -> STREAM FORWARD ... + // <- STREAM STATUS RESULT=INVALID_ID MESSAGE={$message} + INVALID_ID, + + // The destination is not a valid private destination key + // + // -> SESSION CREATE ... + // <- SESSION STATUS RESULT=INVALID_KEY MESSAGE={$message} + // + // -> STREAM CONNECT ... + // <- STREAM STATUS RESULT=INVALID_KEY MESSAGE={$message} + // + // -> NAMING LOOKUP ... + // <- NAMING REPLY RESULT=INVALID_KEY NAME={$name} MESSAGE={$message} + INVALID_KEY, + + // The peer exists, but cannot be reached + // + // -> STREAM CONNECT ... + // <- STREAM STATUS RESULT=CANT_REACH_PEER MESSAGE={$message} + CANT_REACH_PEER, + + // Timeout while waiting for an event (e.g. peer answer) + // + // -> STREAM CONNECT ... + // <- STREAM STATUS RESULT=TIMEOUT MESSAGE={$message} + TIMEOUT, + + // The SAM bridge cannot find a suitable version + // + // -> HELLO VERSION ... + // <- HELLO REPLY RESULT=NOVERSION MESSAGE={$message} + NOVERSION, + + // The naming system can't resolve the given name + // + // -> NAMING LOOKUP ... + // <- NAMING REPLY RESULT=INVALID_KEY NAME={$name} MESSAGE={$message} + KEY_NOT_FOUND, + + // The peer cannot be found on the network + // + // ?? + PEER_NOT_FOUND, + + // ?? + // + // -> STREAM ACCEPT + // <- STREAM STATUS RESULT=ALREADY_ACCEPTING + ALREADY_ACCEPTING, + + // ?? + FAILED, + // ?? + CLOSED + }; + + template + struct Answer + { + const Message::eStatus status; + T value; + + Answer(Message::eStatus status, const T& value) + : status(status), value(value) {} + explicit Answer(Message::eStatus status) + : status(status), value() {} + }; + + static std::string hello(const std::string& minVer, const std::string& maxVer); + static std::string sessionCreate(SessionStyle style, const std::string& sessionID, const std::string& nickname, const std::string& destination = SAM_GENERATE_MY_DESTINATION, const std::string& options = ""); + static std::string streamAccept(const std::string& sessionID, bool silent = false); + static std::string streamConnect(const std::string& sessionID, const std::string& destination, bool silent = false); + static std::string streamForward(const std::string& sessionID, const std::string& host, uint16_t port, bool silent = false); + + static std::string namingLookup(const std::string& name); + static std::string destGenerate(); + + static eStatus checkAnswer(const std::string& answer); + static std::string getValue(const std::string& answer, const std::string& key); +private: + static std::string createSAMRequest(const char* format, ...); +}; + +class Socket +{ +public: + Socket(const std::string& SAMHost, uint16_t SAMPort, const std::string &minVer, const std::string& maxVer); + Socket(const sockaddr_in& addr, const std::string& minVer, const std::string& maxVer); + // explicit because we don't want to create any socket implicity + explicit Socket(const Socket& rhs); // creates a new socket with the same parameters + ~Socket(); + + void write(const std::string& msg); + std::string read(); + SOCKET release(); + void close(); + + bool isOk() const; + + const std::string& getVersion() const; + const std::string& getHost() const; + uint16_t getPort() const; + const std::string& getMinVer() const; + const std::string& getMaxVer() const; + + const sockaddr_in& getAddress() const; + +private: + struct SocketImpl; + std::auto_ptr impl_; + + SOCKET socket_; + sockaddr_in servAddr_; + std::string SAMHost_; + uint16_t SAMPort_; + const std::string minVer_; + const std::string maxVer_; + std::string version_; + +#ifdef WIN32 + static int instances_; + static void initWSA(); + static void freeWSA(); +#endif + + void handshake(); + void init(); + + Socket& operator=(const Socket&); +}; + +struct FullDestination +{ + std::string pub; + std::string priv; + bool isGenerated; + + FullDestination() {} + FullDestination(const std::string& pub, const std::string& priv, bool isGenerated) + :pub(pub), priv(priv), isGenerated(isGenerated) {} +}; + +template +struct RequestResult +{ + bool isOk; + T value; + + RequestResult() + : isOk(false) {} + + explicit RequestResult(const T& value) + : isOk(true), value(value) {} +}; + +template +struct RequestResult > +{ + // a class-helper for resolving a problem with conversion from temporary RequestResult to non-const RequestResult& + struct RequestResultRef + { + bool isOk; + T* value; + + RequestResultRef(bool isOk, T* value) + : isOk(isOk), value(value) {} + }; + + bool isOk; + std::auto_ptr value; + + RequestResult() + : isOk(false) {} + + explicit RequestResult(std::auto_ptr& value) + : isOk(true), value(value) {} + + + // some C++ magic + RequestResult(RequestResultRef ref) + : isOk(ref.isOk), value(ref.value) {} + + RequestResult& operator=(RequestResultRef ref) + { + if (value.get() != ref.value) + { + isOk = ref.isOk; + value.reset(ref.value); + } + return *this; + } + + operator RequestResultRef() + { + return RequestResultRef(this->isOk, this->value.release()); + } +}; + +template<> +struct RequestResult +{ + bool isOk; + + RequestResult() + : isOk(false) {} + + explicit RequestResult(bool isOk) + : isOk(isOk) {} +}; + +class StreamSession +{ +public: + StreamSession( + const std::string& nickname, + const std::string& SAMHost = SAM_DEFAULT_ADDRESS, + uint16_t SAMPort = SAM_DEFAULT_PORT, + const std::string& destination = SAM_GENERATE_MY_DESTINATION, + const std::string& i2pOptions = SAM_DEFAULT_I2P_OPTIONS, + const std::string& minVer = SAM_DEFAULT_MIN_VER, + const std::string& maxVer = SAM_DEFAULT_MAX_VER); + explicit StreamSession(StreamSession& rhs); + ~StreamSession(); + + static std::string generateSessionID(); + + RequestResult > accept(bool silent); + RequestResult > connect(const std::string& destination, bool silent); + RequestResult forward(const std::string& host, uint16_t port, bool silent); + RequestResult namingLookup(const std::string& name) const; + RequestResult destGenerate() const; + + void stopForwarding(const std::string& host, uint16_t port); + void stopForwardingAll(); + + const FullDestination& getMyDestination() const; + + const sockaddr_in& getSAMAddress() const; + const std::string& getSAMHost() const; + uint16_t getSAMPort() const; + const std::string& getNickname() const; + const std::string& getSessionID() const; + const std::string& getSAMMinVer() const; + const std::string& getSAMMaxVer() const; + const std::string& getSAMVersion() const; + const std::string& getOptions() const; + + bool isSick() const; + +private: + StreamSession(const StreamSession& rhs); + StreamSession& operator=(const StreamSession& rhs); + + struct ForwardedStream + { + Socket* socket; + std::string host; + uint16_t port; + bool silent; + + ForwardedStream(Socket* socket, const std::string& host, uint16_t port, bool silent) + : socket(socket), host(host), port(port), silent(silent) {} + }; + + typedef std::list ForwardedStreamsContainer; + + Socket socket_; + const std::string nickname_; + const std::string sessionID_; + FullDestination myDestination_; + const std::string i2pOptions_; + ForwardedStreamsContainer forwardedStreams_; + mutable bool isSick_; + + void fallSick() const; + FullDestination createStreamSession(const std::string &destination); + + static Message::Answer rawRequest(Socket& socket, const std::string& requestStr); + static Message::Answer request(Socket& socket, const std::string& requestStr, const std::string& keyOnSuccess); + static Message::eStatus request(Socket& socket, const std::string& requestStr); + // commands + static Message::Answer createStreamSession(Socket& socket, const std::string& sessionID, const std::string& nickname, const std::string& destination, const std::string& options); + static Message::Answer namingLookup(Socket& socket, const std::string& name); + static Message::Answer destGenerate(Socket& socket); + + static Message::eStatus accept(Socket& socket, const std::string& sessionID, bool silent); + static Message::eStatus connect(Socket& socket, const std::string& sessionID, const std::string& destination, bool silent); + static Message::eStatus forward(Socket& socket, const std::string& sessionID, const std::string& host, uint16_t port, bool silent); +}; + +} // namespace SAM + +#endif // I2PSAM_H diff --git a/src/init.cpp b/src/init.cpp index 5f083e60..b2548b7b 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -34,6 +34,10 @@ #include #endif +#ifdef USE_NATIVE_I2P +#include "i2p.h" +#endif + using namespace std; using namespace boost; @@ -266,6 +270,15 @@ bool static InitWarning(const std::string &str) return true; } +#ifdef USE_NATIVE_I2P +bool static BindNativeI2P(/*bool fError = true*/) +{ + if (IsLimited(NET_NATIVE_I2P)) + return false; + return BindListenNativeI2P(); +} +#endif + bool static Bind(const CService &addr, bool fError = true) { @@ -463,6 +476,20 @@ bool AppInit2() // ********************************************************* Step 2: parameter interactions + #ifdef USE_NATIVE_I2P + if (GetBoolArg(I2P_SAM_GENERATE_DESTINATION_PARAM, false)) + { + const SAM::FullDestination generatedDest = I2PSession::Instance().destGenerate(); + uiInterface.ThreadSafeShowGeneratedI2PAddress( + "Generated I2P address", + generatedDest.pub, + generatedDest.priv, + I2PSession::GenerateB32AddressFromDestination(generatedDest.pub), + GetConfigFile().string()); + return false; + } + #endif + nNodeLifespan = GetArg("-addrlifespan", 7); fUseFastIndex = GetBoolArg("-fastindex", true); nMinStakeInterval = GetArg("-minstakeinterval", 60); // 2 blocks, don't make pos chains! @@ -853,6 +880,10 @@ bool AppInit2() fBound |= Bind(CService(in6addr_any, GetListenPort()), false); if (!IsLimited(NET_IPV4)) fBound |= Bind(CService(inaddr_any, GetListenPort()), !fBound); +#ifdef USE_NATIVE_I2P + if (!IsLimited(NET_NATIVE_I2P)) + fBound |= BindNativeI2P(); +#endif }; if (!fBound) return InitError(_("Failed to listen on any port. Use -listen=0 if you want this.")); diff --git a/src/makefile.unix b/src/makefile.unix index 85184a39..db6da22e 100644 --- a/src/makefile.unix +++ b/src/makefile.unix @@ -308,6 +308,10 @@ OBJS= \ obj/eccryptoverify.o \ obj/ringsig.o +ifdef USE_NATIVE_I2P + OBJS += obj/i2p.o + OBJS += obj/i2psam.o +endif all: denariusd diff --git a/src/net.cpp b/src/net.cpp index d7809743..4dcd1225 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -16,6 +16,10 @@ #include #endif +#ifdef USE_NATIVE_I2P +#include "i2p.h" +#endif + #ifdef USE_UPNP #include #include @@ -55,7 +59,11 @@ struct LocalServiceInfo { // bool fDiscover = true; bool fUseUPnP = false; +#ifdef USE_NATIVE_I2P +uint64_t nLocalServices = NODE_I2P | NODE_NETWORK; +#else uint64_t nLocalServices = NODE_NETWORK; +#endif static CCriticalSection cs_mapLocalHost; static map mapLocalHost; static bool vfReachable[NET_MAX] = {}; @@ -68,6 +76,11 @@ boost::array vnThreadsRunning; static std::vector vhListenSocket; CAddrMan addrman; +#ifdef USE_NATIVE_I2P +static std::vector vhI2PListenSocket; +int nI2PNodeCount = 0; +#endif + vector vNodes; CCriticalSection cs_vNodes; map mapRelay; @@ -319,8 +332,8 @@ bool IsReachable(const CNetAddr& addr) bool GetMyExternalIP2(const CService& addrConnect, const char* pszGet, const char* pszKeyword, CNetAddr& ipRet) { SOCKET hSocket; - bool bProxyConnectionFailed = false; - int ntimeout = 1000; + bool bProxyConnectionFailed = false; + int ntimeout = 1000; if (!ConnectSocket(addrConnect, hSocket, ntimeout, &bProxyConnectionFailed)) return error("GetMyExternalIP() : connection to %s failed", addrConnect.ToString().c_str()); @@ -540,6 +553,10 @@ CNode* ConnectNode(CAddress addrConnect, const char *pszDest, bool forTunaMaster { LOCK(cs_vNodes); vNodes.push_back(pnode); +#ifdef USE_NATIVE_I2P + if (addrConnect.IsNativeI2P()) + ++nI2PNodeCount; +#endif } if(forTunaMaster) @@ -708,7 +725,11 @@ bool CNode::ReceiveMsgBytes(const char *pch, unsigned int nBytes) // get current incomplete message, or create a new one if (vRecvMsg.empty() || vRecvMsg.back().complete()) +#ifdef USE_NATIVE_I2P + vRecvMsg.push_back(CNetMessage(nRecvStreamType, nRecvVersion)); +#else vRecvMsg.push_back(CNetMessage(SER_NETWORK, nRecvVersion)); +#endif CNetMessage& msg = vRecvMsg.back(); @@ -732,6 +753,52 @@ bool CNode::ReceiveMsgBytes(const char *pch, unsigned int nBytes) return true; } +#ifdef USE_NATIVE_I2P +void AddIncomingConnection(SOCKET hSocket, const CAddress& addr) +{ + int nInbound = 0; + + { + LOCK(cs_vNodes); + BOOST_FOREACH(CNode* pnode, vNodes) + if (pnode->fInbound) + nInbound++; + } + + if (hSocket == INVALID_SOCKET) + { + int nErr = WSAGetLastError(); + if (nErr != WSAEWOULDBLOCK) + printf("socket error accept failed: %d\n", nErr); + } + else if (nInbound >= GetArg("-maxconnections", 125) - MAX_OUTBOUND_CONNECTIONS) + { + { + LOCK(cs_setservAddNodeAddresses); + if (!setservAddNodeAddresses.count(addr)) + closesocket(hSocket); + } + } + else if (CNode::IsBanned(addr)) + { + printf("connection from %s dropped (banned)\n", addr.ToString().c_str()); + closesocket(hSocket); + } + else + { + printf("accepted connection %s\n", addr.ToString().c_str()); + CNode* pnode = new CNode(hSocket, addr, "", true); + pnode->AddRef(); + { + LOCK(cs_vNodes); + vNodes.push_back(pnode); + ++nI2PNodeCount; + } + } +} + +#endif + int CNetMessage::readHeader(const char *pch, unsigned int nBytes) { // copy data to temporary parsing buffer @@ -855,6 +922,9 @@ void ThreadSocketHandler2(void* parg) printf("ThreadSocketHandler started\n"); list vNodesDisconnected; unsigned int nPrevNodeCount = 0; +#ifdef USE_NATIVE_I2P + int nPrevI2PNodeCount = 0; +#endif while (true) { @@ -884,6 +954,10 @@ void ThreadSocketHandler2(void* parg) if (pnode->fNetworkNode || pnode->fInbound) pnode->Release(); vNodesDisconnected.push_back(pnode); +#ifdef USE_NATIVE_I2P + if (pnode->addr.IsNativeI2P()) + --nI2PNodeCount; +#endif } } @@ -925,6 +999,13 @@ void ThreadSocketHandler2(void* parg) nPrevNodeCount = vNodes.size(); uiInterface.NotifyNumConnectionsChanged(vNodes.size()); } +#ifdef USE_NATIVE_I2P + if (nPrevI2PNodeCount != nI2PNodeCount) + { + nPrevI2PNodeCount = nI2PNodeCount; + uiInterface.NotifyNumI2PConnectionsChanged(nI2PNodeCount); + } +#endif // @@ -943,6 +1024,17 @@ void ThreadSocketHandler2(void* parg) SOCKET hSocketMax = 0; bool have_fds = false; +#ifdef USE_NATIVE_I2P + BOOST_FOREACH(SOCKET hI2PListenSocket, vhI2PListenSocket) { + if (hI2PListenSocket != INVALID_SOCKET) + { + FD_SET(hI2PListenSocket, &fdsetRecv); + hSocketMax = max(hSocketMax, hI2PListenSocket); + have_fds = true; + } + } +#endif + BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket) { FD_SET(hListenSocket, &fdsetRecv); hSocketMax = max(hSocketMax, hListenSocket); @@ -1041,6 +1133,74 @@ void ThreadSocketHandler2(void* parg) } } +#ifdef USE_NATIVE_I2P + // + // Accept new I2P connections + // + + bool haveInvalids = false; + for (std::vector::iterator it = vhI2PListenSocket.begin(); it != vhI2PListenSocket.end(); ++it) + { + SOCKET& hI2PListenSocket = *it; + if (hI2PListenSocket == INVALID_SOCKET) + { + if (haveInvalids) + it = vhI2PListenSocket.erase(it) - 1; + else + BindListenNativeI2P(hI2PListenSocket); + haveInvalids = true; + } + else if (FD_ISSET(hI2PListenSocket, &fdsetRecv)) + { + const size_t bufSize = NATIVE_I2P_DESTINATION_SIZE + 1; + char pchBuf[bufSize]; + memset(pchBuf, 0, bufSize); + int nBytes = recv(hI2PListenSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT); + if (nBytes > 0) + { + if (nBytes == NATIVE_I2P_DESTINATION_SIZE + 1) // we're waiting for dest-hash + '\n' symbol + { + std::string incomingAddr(pchBuf, pchBuf + NATIVE_I2P_DESTINATION_SIZE); + CAddress addr; + if (addr.SetSpecial(incomingAddr) && addr.IsNativeI2P()) + { + AddIncomingConnection(hI2PListenSocket, addr); + } + else + { + printf("Invalid incoming destination hash received (%s)\n", incomingAddr.c_str()); + closesocket(hI2PListenSocket); + } + } + else + { + printf("Invalid incoming destination hash size received (%d)\n", nBytes); + closesocket(hI2PListenSocket); + } + } + else if (nBytes == 0) + { + // socket closed gracefully + printf("I2P listen socket closed\n"); + closesocket(hI2PListenSocket); + } + else if (nBytes < 0) + { + // error + const int nErr = WSAGetLastError(); + if (nErr == WSAEWOULDBLOCK || nErr == WSAEMSGSIZE || nErr == WSAEINTR || nErr == WSAEINPROGRESS) + continue; + + printf("I2P listen socket recv error %d\n", nErr); + closesocket(hI2PListenSocket); + } + hI2PListenSocket = INVALID_SOCKET; // we've saved this socket in a CNode or closed it, so we can safety reset it anyway + BindListenNativeI2P(hI2PListenSocket); + } + } + +#endif + // // Service each socket @@ -1657,7 +1817,11 @@ void ThreadOpenConnections2(void* parg) continue; // do not allow non-default ports, unless after 50 invalid addresses selected already +#ifdef USE_NATIVE_I2P + if (!addr.IsNativeI2P() && addr.GetPort() != GetDefaultPort() && nTries < 50) +#else if (addr.GetPort() != GetDefaultPort() && nTries < 50) +#endif continue; addrConnect = addr; @@ -1954,7 +2118,48 @@ void ThreadMessageHandler2(void* parg) +#ifdef USE_NATIVE_I2P +bool BindListenNativeI2P() +{ + SOCKET hNewI2PListenSocket = INVALID_SOCKET; + if (!BindListenNativeI2P(hNewI2PListenSocket)) + return false; + vhI2PListenSocket.push_back(hNewI2PListenSocket); + return true; +} +bool BindListenNativeI2P(SOCKET& hSocket) +{ + hSocket = I2PSession::Instance().accept(false); + if (!SetSocketOptions(hSocket) || hSocket == INVALID_SOCKET) + return false; + CService addrBind(I2PSession::Instance().getMyDestination().pub, 0); + if (addrBind.IsRoutable() && fDiscover) + AddLocal(addrBind, LOCAL_BIND); + return true; +} + +bool IsI2POnly() +{ +// bool i2pOnly = false; +// if (mapArgs.count("-onlynet")) +// { +// const std::vector& onlyNets = mapMultiArgs["-onlynet"]; +// i2pOnly = (onlyNets.size() == 1 && onlyNets[0] == NATIVE_I2P_NET_STRING); +// } +// return i2pOnly; + + bool i2pOnly = NET_MAX > 0; // if NET_MAX == 0 we set i2pOnly to false and exit + for (int n = 0; n < NET_MAX; n++) + { + Network net = (Network)n; + if (net == NET_UNROUTABLE) + continue; + i2pOnly &= ((net == NET_NATIVE_I2P) != IsLimited(net)); // isI2P xor IsLimited + } + return i2pOnly; +} +#endif bool BindListenPort(const CService &addrBind, string& strError) @@ -2315,7 +2520,12 @@ class CNetCleanup if (hListenSocket != INVALID_SOCKET) if (closesocket(hListenSocket) == SOCKET_ERROR) printf("closesocket(hListenSocket) failed with error %d\n", WSAGetLastError()); - +#ifdef USE_NATIVE_I2P + BOOST_FOREACH(SOCKET& hI2PListenSocket, vhI2PListenSocket) + if (hI2PListenSocket != INVALID_SOCKET) + if (closesocket(hI2PListenSocket) == SOCKET_ERROR) + printf("closesocket(hI2PListenSocket) failed with error %d\n", WSAGetLastError()); +#endif #ifdef WIN32 // Shutdown Windows Sockets WSACleanup(); diff --git a/src/net.h b/src/net.h index f87432e2..2a4ad57b 100644 --- a/src/net.h +++ b/src/net.h @@ -61,6 +61,14 @@ CNodeSignals& GetNodeSignals(); typedef int NodeId; +#ifdef USE_NATIVE_I2P +bool BindListenNativeI2P(); +bool BindListenNativeI2P(SOCKET& hSocket); +bool IsI2POnly(); + +extern int nI2PNodeCount; +#endif + enum { LOCAL_NONE, // unknown @@ -323,8 +331,8 @@ class CNode CBlockIndex* pindexLastGetBlocksBegin; uint256 hashLastGetBlocksEnd; int nStartingHeight; - bool fStartSync; - int nMisbehavior; + bool fStartSync; + int nMisbehavior; // flood relay std::vector vAddrToSend; @@ -352,7 +360,14 @@ class CNode bool fPingQueued; CNode(SOCKET hSocketIn, CAddress addrIn, std::string addrNameIn = "", bool fInboundIn=false) : ssSend(SER_NETWORK, INIT_PROTO_VERSION), setAddrKnown(5000) +#ifdef USE_NATIVE_I2P + , nSendStreamType(SER_NETWORK | (((addrIn.nServices & NODE_I2P) || addrIn.IsNativeI2P()) ? 0 : SER_IPADDRONLY)) + , nRecvStreamType(SER_NETWORK | (((addrIn.nServices & NODE_I2P) || addrIn.IsNativeI2P()) ? 0 : SER_IPADDRONLY)) +#endif { +#ifdef USE_NATIVE_I2P + ssSend.SetType(nSendStreamType); +#endif nServices = 0; hSocket = hSocketIn; nRecvVersion = INIT_PROTO_VERSION; @@ -416,6 +431,39 @@ class CNode static CCriticalSection cs_totalBytesSent; static uint64_t nTotalBytesRecv; static uint64_t nTotalBytesSent; +#ifdef USE_NATIVE_I2P +private: + int nSendStreamType; + int nRecvStreamType; +public: + void SetSendStreamType(int nType) + { + nSendStreamType = nType; + ssSend.SetType(nSendStreamType); + } + + void SetRecvStreamType(int nType) + { + nRecvStreamType = nType; + for (std::deque::iterator it = vRecvMsg.begin(), end = vRecvMsg.end(); it != end; ++it) + { + it->hdrbuf.SetType(nRecvStreamType); + it->vRecv.SetType(nRecvStreamType); + } + } + + int GetSendStreamType() const + { + return nSendStreamType; + } + + int GetRecvStreamType() const + { + return nRecvStreamType; + } + +#endif + public: NodeId GetId() const { return id; @@ -471,6 +519,10 @@ class CNode // SendMessages will filter it again for knowns that were added // after addresses were pushed. if (addr.IsValid() && !setAddrKnown.count(addr)) +#ifdef USE_NATIVE_I2P + // if receiver doesn't support i2p-address we don't send it + if ((this->nServices & NODE_I2P) || !addr.IsNativeI2P()) +#endif vAddrToSend.push_back(addr); } diff --git a/src/netbase.cpp b/src/netbase.cpp index b8b1300b..af919b3a 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -11,6 +11,10 @@ #include #endif +#ifdef USE_NATIVE_I2P +#include "i2p.h" +#endif + #include "strlcpy.h" #include // for to_lower() @@ -31,6 +35,9 @@ enum Network ParseNetwork(std::string net) { if (net == "ipv6") return NET_IPV6; if (net == "tor") return NET_TOR; if (net == "i2p") return NET_I2P; +#ifdef USE_NATIVE_I2P + if (net == NATIVE_I2P_NET_STRING) return NET_NATIVE_I2P; +#endif return NET_UNROUTABLE; } @@ -349,8 +356,9 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe if (connect(hSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR) { + int nErr = WSAGetLastError(); // WSAEINVAL is here because some legacy version of winsock uses it - if (WSAGetLastError() == WSAEINPROGRESS || WSAGetLastError() == WSAEWOULDBLOCK || WSAGetLastError() == WSAEINVAL) + if (nErr == WSAEINPROGRESS || nErr == WSAEWOULDBLOCK || nErr == WSAEINVAL) { struct timeval timeout; timeout.tv_sec = nTimeout / 1000; @@ -362,13 +370,13 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe int nRet = select(hSocket + 1, NULL, &fdset, NULL, &timeout); if (nRet == 0) { - if (fDebugNet) printf("connection timeout\n"); + printf("net", "connection to %s timeout\n", addrConnect.ToString().c_str()); closesocket(hSocket); return false; } if (nRet == SOCKET_ERROR) { - if (fDebugNet) printf("select() for connection failed: %i\n",WSAGetLastError()); + printf("select() for %s failed: %i\n", addrConnect.ToString().c_str(), WSAGetLastError()); closesocket(hSocket); return false; } @@ -379,13 +387,13 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, &nRet, &nRetSize) == SOCKET_ERROR) #endif { - printf("getsockopt() for connection failed: %i\n",WSAGetLastError()); + printf("getsockopt() for %s failed: %i\n", addrConnect.ToString().c_str(), WSAGetLastError()); closesocket(hSocket); return false; } if (nRet != 0) { - printf("connect() failed after select(): %s\n",strerror(nRet)); + printf("connect() to %s failed after select(): %s\n", addrConnect.ToString().c_str(), strerror(nRet)); closesocket(hSocket); return false; } @@ -396,7 +404,7 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe else #endif { - printf("connect() failed: %i\n",WSAGetLastError()); + printf("connect() to %s failed: %i\n", addrConnect.ToString().c_str(), WSAGetLastError()); closesocket(hSocket); return false; } @@ -473,12 +481,52 @@ bool IsProxy(const CNetAddr &addr) { return false; } +#ifdef USE_NATIVE_I2P +bool SetSocketOptions(SOCKET& hSocket) +{ + if (hSocket == INVALID_SOCKET) + return false; +#ifdef SO_NOSIGPIPE + int set = 1; + setsockopt(hSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&set, sizeof(int)); +#endif + +#ifdef WIN32 + u_long fNonblock = 1; + if (ioctlsocket(hSocket, FIONBIO, &fNonblock) == SOCKET_ERROR) +#else + int fFlags = fcntl(hSocket, F_GETFL, 0); + if (fcntl(hSocket, F_SETFL, fFlags | O_NONBLOCK) == -1) +#endif + { + closesocket(hSocket); + hSocket = INVALID_SOCKET; + return false; + } + return true; +} + +#endif + bool ConnectSocket(const CService &addrDest, SOCKET& hSocketRet, int nTimeout, bool *outProxyConnectionFailed) { proxyType proxy; - if (outProxyConnectionFailed) - *outProxyConnectionFailed = false; +#ifdef USE_NATIVE_I2P + if (addrDest.IsNativeI2P()) + { + SOCKET streamSocket = I2PSession::Instance().connect(addrDest.GetI2PDestination(), false/*, streamSocket*/); + if (SetSocketOptions(streamSocket)) + { + hSocketRet = streamSocket; + return true; + } + return false; + } +#endif + + if (outProxyConnectionFailed) + *outProxyConnectionFailed = false; // no proxy needed if (!GetProxy(addrDest.GetNetwork(), proxy)) return ConnectSocketDirectly(addrDest, hSocketRet, nTimeout); @@ -553,11 +601,17 @@ bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest void CNetAddr::Init() { memset(ip, 0, 16); +#ifdef USE_NATIVE_I2P + memset(i2pDest, 0, NATIVE_I2P_DESTINATION_SIZE); +#endif } void CNetAddr::SetIP(const CNetAddr& ipIn) { memcpy(ip, ipIn.ip, sizeof(ip)); +#ifdef USE_NATIVE_I2P + memcpy(i2pDest, ipIn.i2pDest, NATIVE_I2P_DESTINATION_SIZE); +#endif } static const unsigned char pchOnionCat[] = {0xFD,0x87,0xD8,0x7E,0xEB,0x43}; @@ -565,6 +619,15 @@ static const unsigned char pchGarliCat[] = {0xFD,0x60,0xDB,0x4D,0xDD,0xB5}; bool CNetAddr::SetSpecial(const std::string &strName) { +#ifdef USE_NATIVE_I2P + const bool isBase32Addr = (strName.size() == NATIVE_I2P_B32ADDR_SIZE) && (strName.substr(strName.size() - 8, 8) == ".b32.i2p"); + const std::string addr = isBase32Addr ? I2PSession::Instance().namingLookup(strName) : strName; + + if ((addr.size() == NATIVE_I2P_DESTINATION_SIZE) && (addr.substr(addr.size() - 4, 4) == "AAAA")) { // last 4 symbols of b64-destination must be AAAA + memcpy(i2pDest, addr.c_str(), NATIVE_I2P_DESTINATION_SIZE); + return true; + } +#endif if (strName.size()>6 && strName.substr(strName.size() - 6, 6) == ".onion") { std::vector vchAddr = DecodeBase32(strName.substr(0, strName.size() - 6).c_str()); if (vchAddr.size() != 16-sizeof(pchOnionCat)) @@ -595,11 +658,17 @@ CNetAddr::CNetAddr(const struct in_addr& ipv4Addr) { memcpy(ip, pchIPv4, 12); memcpy(ip+12, &ipv4Addr, 4); +#ifdef USE_NATIVE_I2P + memset(i2pDest, 0, NATIVE_I2P_DESTINATION_SIZE); +#endif } CNetAddr::CNetAddr(const struct in6_addr& ipv6Addr) { memcpy(ip, &ipv6Addr, 16); +#ifdef USE_NATIVE_I2P + memset(i2pDest, 0, NATIVE_I2P_DESTINATION_SIZE); +#endif } CNetAddr::CNetAddr(const char *pszIp, bool fAllowLookup) @@ -630,7 +699,11 @@ bool CNetAddr::IsIPv4() const bool CNetAddr::IsIPv6() const { +#ifdef USE_NATIVE_I2P + return (!IsIPv4() && !IsTor() && !IsNativeI2P()); +#else return (!IsIPv4() && !IsTor() && !IsI2P()); +#endif } bool CNetAddr::IsRFC1918() const @@ -694,6 +767,19 @@ bool CNetAddr::IsTor() const return (memcmp(ip, pchOnionCat, sizeof(pchOnionCat)) == 0); } +#ifdef USE_NATIVE_I2P +bool CNetAddr::IsNativeI2P() const +{ + static const unsigned char pchAAAA[] = {'A','A','A','A'}; + return (memcmp(i2pDest + NATIVE_I2P_DESTINATION_SIZE - sizeof(pchAAAA), pchAAAA, sizeof(pchAAAA)) == 0); +} + +std::string CNetAddr::GetI2PDestination() const +{ + return std::string(i2pDest, i2pDest + NATIVE_I2P_DESTINATION_SIZE); +} +#endif + bool CNetAddr::IsI2P() const { return (memcmp(ip, pchGarliCat, sizeof(pchGarliCat)) == 0); @@ -701,6 +787,11 @@ bool CNetAddr::IsI2P() const bool CNetAddr::IsLocal() const { + +#ifdef USE_NATIVE_I2P + if (IsNativeI2P()) + return false; +#endif // IPv4 loopback if (IsIPv4() && (GetByte(3) == 127 || GetByte(3) == 0)) return true; @@ -721,6 +812,10 @@ bool CNetAddr::IsMulticast() const bool CNetAddr::IsValid() const { +#ifdef USE_NATIVE_I2P + if (IsNativeI2P()) + return true; +#endif // Cleanup 3-byte shifted addresses caused by garbage in size field // of addr messages from versions before 0.2.9 checksum. // Two consecutive addr messages look like this: @@ -771,6 +866,11 @@ enum Network CNetAddr::GetNetwork() const if (IsTor()) return NET_TOR; +#ifdef USE_NATIVE_I2P + if (IsNativeI2P()) + return NET_NATIVE_I2P; +#endif + if (IsI2P()) return NET_I2P; @@ -779,6 +879,10 @@ enum Network CNetAddr::GetNetwork() const std::string CNetAddr::ToStringIP() const { +#ifdef USE_NATIVE_I2P + if (IsNativeI2P()) + return GetI2PDestination(); +#endif if (IsTor()) return EncodeBase32(&ip[6], 10) + ".onion"; if (IsI2P()) @@ -808,17 +912,29 @@ std::string CNetAddr::ToString() const bool operator==(const CNetAddr& a, const CNetAddr& b) { +#ifdef USE_NATIVE_I2P + return (memcmp(a.ip, b.ip, 16) == 0 && memcmp(a.i2pDest, b.i2pDest, NATIVE_I2P_DESTINATION_SIZE) == 0); +#else return (memcmp(a.ip, b.ip, 16) == 0); +#endif } bool operator!=(const CNetAddr& a, const CNetAddr& b) { +#ifdef USE_NATIVE_I2P + return (memcmp(a.ip, b.ip, 16) != 0 || memcmp(a.i2pDest, b.i2pDest, NATIVE_I2P_DESTINATION_SIZE) != 0); +#else return (memcmp(a.ip, b.ip, 16) != 0); +#endif } bool operator<(const CNetAddr& a, const CNetAddr& b) { +#ifdef USE_NATIVE_I2P + return (memcmp(a.ip, b.ip, 16) < 0 || (memcmp(a.ip, b.ip, 16) == 0 && memcmp(a.i2pDest, b.i2pDest, NATIVE_I2P_DESTINATION_SIZE) < 0)); +#else return (memcmp(a.ip, b.ip, 16) < 0); +#endif } bool CNetAddr::GetInAddr(struct in_addr* pipv4Addr) const @@ -831,6 +947,10 @@ bool CNetAddr::GetInAddr(struct in_addr* pipv4Addr) const bool CNetAddr::GetIn6Addr(struct in6_addr* pipv6Addr) const { +#ifdef USE_NATIVE_I2P + if (IsNativeI2P()) + return false; +#endif memcpy(pipv6Addr, ip, 16); return true; } @@ -844,6 +964,16 @@ std::vector CNetAddr::GetGroup() const int nStartByte = 0; int nBits = 16; +#ifdef USE_NATIVE_I2P + if (IsNativeI2P()) + { + vchRet.resize(NATIVE_I2P_DESTINATION_SIZE + 1); + vchRet[0] = NET_NATIVE_I2P; + memcpy(&vchRet[1], i2pDest, NATIVE_I2P_DESTINATION_SIZE); + return vchRet; + } +#endif + // all local addresses belong to the same group if (IsLocal()) { diff --git a/src/netbase.h b/src/netbase.h index 1e37422d..e763c2a8 100644 --- a/src/netbase.h +++ b/src/netbase.h @@ -18,6 +18,12 @@ extern bool fNameLookup; #undef SetPort #endif +#ifdef USE_NATIVE_I2P +#define NATIVE_I2P_DESTINATION_SIZE 516 +#define NATIVE_I2P_B32ADDR_SIZE 60 +#define NATIVE_I2P_NET_STRING "native_i2p" +#endif + enum Network { NET_UNROUTABLE, @@ -25,7 +31,9 @@ enum Network NET_IPV6, NET_TOR, NET_I2P, - +#ifdef USE_NATIVE_I2P + NET_NATIVE_I2P, +#endif NET_MAX, }; @@ -34,6 +42,9 @@ class CNetAddr { protected: unsigned char ip[16]; // in network byte order +#ifdef USE_NATIVE_I2P + unsigned char i2pDest[NATIVE_I2P_DESTINATION_SIZE]; +#endif public: CNetAddr(); @@ -74,6 +85,11 @@ class CNetAddr CNetAddr(const struct in6_addr& pipv6Addr); bool GetIn6Addr(struct in6_addr* pipv6Addr) const; +#ifdef USE_NATIVE_I2P + bool IsNativeI2P() const; + std::string GetI2PDestination() const; +#endif + friend bool operator==(const CNetAddr& a, const CNetAddr& b); friend bool operator!=(const CNetAddr& a, const CNetAddr& b); friend bool operator<(const CNetAddr& a, const CNetAddr& b); @@ -81,6 +97,12 @@ class CNetAddr IMPLEMENT_SERIALIZE ( READWRITE(FLATDATA(ip)); +#ifdef USE_NATIVE_I2P + if (!(nType & SER_IPADDRONLY)) + { + READWRITE(FLATDATA(i2pDest)); + } +#endif ) }; @@ -120,6 +142,12 @@ class CService : public CNetAddr ( CService* pthis = const_cast(this); READWRITE(FLATDATA(ip)); +#ifdef USE_NATIVE_I2P + if (!(nType & SER_IPADDRONLY)) + { + READWRITE(FLATDATA(i2pDest)); + } +#endif unsigned short portN = htons(port); READWRITE(portN); if (fRead) @@ -146,4 +174,8 @@ bool LookupNumeric(const char *pszName, CService& addr, int portDefault = 0); bool ConnectSocket(const CService &addr, SOCKET& hSocketRet, int nTimeout, bool *outProxyConnectionFailed = 0); bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest, int portDefault, int nTimeout, bool *outProxyConnectionFailed = 0); +#ifdef USE_NATIVE_I2P +bool SetSocketOptions(SOCKET& hSocket); +#endif + #endif diff --git a/src/protocol.h b/src/protocol.h index 7344b0c5..4f410f52 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -69,6 +69,9 @@ class CMessageHeader enum { NODE_NETWORK = (1 << 0), +#ifdef USE_NATIVE_I2P + NODE_I2P = (1 << 7), +#endif }; /** A CService with information about it as peer */ diff --git a/src/qt/bitcoin.qrc b/src/qt/bitcoin.qrc index 9f62f686..36f8636c 100644 --- a/src/qt/bitcoin.qrc +++ b/src/qt/bitcoin.qrc @@ -62,6 +62,11 @@ res/icons/refresh.png res/icons/data.png res/icons/trade.png + res/icons/i2plogo_0_16.png + res/icons/i2plogo_1_16.png + res/icons/i2plogo_2_16.png + res/icons/i2plogo_3_16.png + res/icons/i2plogo_4_16.png res/images/about.png diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 9dca4e9d..ec37ed02 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -38,6 +38,10 @@ #include "termsofuse.h" #include "proofofimage.h" +#ifdef USE_NATIVE_I2P +#include "showi2paddresses.h" +#endif + #ifdef Q_OS_MAC #include "macdockiconhandler.h" #endif @@ -178,12 +182,12 @@ BitcoinGUI::BitcoinGUI(QWidget *parent): // Create tabs overviewPage = new OverviewPage(); - statisticsPage = new StatisticsPage(this); - blockBrowser = new BlockBrowser(this); + statisticsPage = new StatisticsPage(this); + blockBrowser = new BlockBrowser(this); marketBrowser = new MarketBrowser(this); - multisigPage = new MultisigDialog(this); + multisigPage = new MultisigDialog(this); proofOfImagePage = new ProofOfImage(this); - //chatWindow = new ChatWindow(this); + //chatWindow = new ChatWindow(this); transactionsPage = new QWidget(this); @@ -192,7 +196,7 @@ BitcoinGUI::BitcoinGUI(QWidget *parent): vbox->addWidget(transactionView); transactionsPage->setLayout(vbox); - mintingPage = new QWidget(this); + mintingPage = new QWidget(this); QVBoxLayout *vboxMinting = new QVBoxLayout(); mintingView = new MintingView(this); vboxMinting->addWidget(mintingView); @@ -212,17 +216,17 @@ BitcoinGUI::BitcoinGUI(QWidget *parent): centralWidget = new QStackedWidget(this); centralWidget->addWidget(overviewPage); centralWidget->addWidget(transactionsPage); - centralWidget->addWidget(mintingPage); + centralWidget->addWidget(mintingPage); centralWidget->addWidget(addressBookPage); centralWidget->addWidget(receiveCoinsPage); centralWidget->addWidget(sendCoinsPage); centralWidget->addWidget(messagePage); - centralWidget->addWidget(statisticsPage); - centralWidget->addWidget(blockBrowser); + centralWidget->addWidget(statisticsPage); + centralWidget->addWidget(blockBrowser); centralWidget->addWidget(fortunastakeManagerPage); - centralWidget->addWidget(marketBrowser); + centralWidget->addWidget(marketBrowser); centralWidget->addWidget(proofOfImagePage); - //centralWidget->addWidget(chatWindow); + //centralWidget->addWidget(chatWindow); setCentralWidget(centralWidget); // Create status bar @@ -237,6 +241,15 @@ BitcoinGUI::BitcoinGUI(QWidget *parent): frameBlocksLayout->setSpacing(3); labelEncryptionIcon = new ActiveLabel(); +#ifdef USE_NATIVE_I2P + labelI2PConnections = new QLabel(); + labelI2POnly = new QLabel(); + labelI2PGenerated = new QLabel(); + frameBlocksLayout->addWidget(labelI2PGenerated); + frameBlocksLayout->addWidget(labelI2POnly); + frameBlocksLayout->addWidget(labelI2PConnections); +#endif + labelStakingIcon = new QLabel(); labelConnectionsIcon = new QLabel(); labelBlocksIcon = new QLabel(); @@ -253,6 +266,13 @@ BitcoinGUI::BitcoinGUI(QWidget *parent): frameBlocksLayout->addWidget(labelBlocksIcon); frameBlocksLayout->addStretch(); + netLabel = new QLabel(); + netLabel->setObjectName("netLabel"); + netLabel->setStyleSheet("#netLabel { color: #efefef; }"); + frameBlocksLayout->addWidget(netLabel); + + frameBlocksLayout->addStretch(); + if (GetBoolArg("-staking", true)) { QTimer *timerStakingIcon = new QTimer(labelStakingIcon); @@ -327,18 +347,18 @@ void BitcoinGUI::createActions() overviewAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_1)); tabGroup->addAction(overviewAction); - statisticsAction = new QAction(QIcon(":/icons/statistics"), tr("&Statistics"), this); + statisticsAction = new QAction(QIcon(":/icons/statistics"), tr("&Statistics"), this); statisticsAction->setToolTip(tr("View statistics")); statisticsAction->setCheckable(true); tabGroup->addAction(statisticsAction); - blockAction = new QAction(QIcon(":/icons/block"), tr("&Block Explorer"), this); + blockAction = new QAction(QIcon(":/icons/block"), tr("&Block Explorer"), this); blockAction->setToolTip(tr("Explore the Denarius Blockchain")); blockAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_6)); blockAction->setCheckable(true); tabGroup->addAction(blockAction); - marketAction = new QAction(QIcon(":/icons/mark"), tr("&Market"), this); + marketAction = new QAction(QIcon(":/icons/mark"), tr("&Market"), this); marketAction->setToolTip(tr("Market Data")); marketAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_7)); marketAction->setCheckable(true); @@ -379,7 +399,7 @@ void BitcoinGUI::createActions() messageAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_8)); tabGroup->addAction(messageAction); - mintingAction = new QAction(QIcon(":/icons/stake"), tr("&Staking"), this); + mintingAction = new QAction(QIcon(":/icons/stake"), tr("&Staking"), this); mintingAction->setToolTip(tr("Show your staking capacity")); mintingAction->setCheckable(true); mintingAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_9)); @@ -395,20 +415,20 @@ void BitcoinGUI::createActions() proofOfImageAction ->setCheckable(true); tabGroup->addAction(proofOfImageAction); - multisigAction = new QAction(QIcon(":/icons/multi"), tr("Multisig"), this); + multisigAction = new QAction(QIcon(":/icons/multi"), tr("Multisig"), this); tabGroup->addAction(multisigAction); connect(overviewAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized())); connect(overviewAction, SIGNAL(triggered()), this, SLOT(gotoOverviewPage())); - connect(blockAction, SIGNAL(triggered()), this, SLOT(gotoBlockBrowser())); - connect(statisticsAction, SIGNAL(triggered()), this, SLOT(gotoStatisticsPage())); - connect(marketAction, SIGNAL(triggered()), this, SLOT(gotoMarketBrowser())); - //connect(chatAction, SIGNAL(triggered()), this, SLOT(gotoChatPage())); + connect(blockAction, SIGNAL(triggered()), this, SLOT(gotoBlockBrowser())); + connect(statisticsAction, SIGNAL(triggered()), this, SLOT(gotoStatisticsPage())); + connect(marketAction, SIGNAL(triggered()), this, SLOT(gotoMarketBrowser())); + //connect(chatAction, SIGNAL(triggered()), this, SLOT(gotoChatPage())); connect(sendCoinsAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized())); connect(sendCoinsAction, SIGNAL(triggered()), this, SLOT(gotoSendCoinsPage())); connect(receiveCoinsAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized())); connect(receiveCoinsAction, SIGNAL(triggered()), this, SLOT(gotoReceiveCoinsPage())); - connect(mintingAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized())); + connect(mintingAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized())); connect(mintingAction, SIGNAL(triggered()), this, SLOT(gotoMintingPage())); connect(fortunastakeManagerAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized())); connect(fortunastakeManagerAction, SIGNAL(triggered()), this, SLOT(gotoFortunastakeManagerPage())); @@ -418,7 +438,7 @@ void BitcoinGUI::createActions() connect(addressBookAction, SIGNAL(triggered()), this, SLOT(gotoAddressBookPage())); connect(messageAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized())); connect(messageAction, SIGNAL(triggered()), this, SLOT(gotoMessagePage())); - connect(multisigAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized())); + connect(multisigAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized())); connect(multisigAction, SIGNAL(triggered()), this, SLOT(gotoMultisigPage())); connect(proofOfImageAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized())); connect(proofOfImageAction, SIGNAL(triggered()), this, SLOT(gotoProofOfImagePage())); @@ -456,7 +476,7 @@ void BitcoinGUI::createActions() openRPCConsoleAction = new QAction(QIcon(":/icons/debugwindow"), tr("&Debug window"), this); openRPCConsoleAction->setToolTip(tr("Open debugging and diagnostic console")); - openInfoAction = new QAction(QApplication::style()->standardIcon(QStyle::SP_MessageBoxInformation), tr("&Information"), this); + openInfoAction = new QAction(QApplication::style()->standardIcon(QStyle::SP_MessageBoxInformation), tr("&Information"), this); openInfoAction->setStatusTip(tr("Show diagnostic information")); openGraphAction = new QAction(QIcon(":/icons/connect_4"), tr("&Network Monitor"), this); openGraphAction->setStatusTip(tr("Show network monitor")); @@ -598,6 +618,32 @@ void BitcoinGUI::checkTOU() void BitcoinGUI::setClientModel(ClientModel *clientModel) { +#ifdef USE_NATIVE_I2P + setNumI2PConnections(clientModel->getNumI2PConnections()); + connect(clientModel, SIGNAL(numI2PConnectionsChanged(int)), this, SLOT(setNumI2PConnections(int))); +if(clientModel->isI2POnly()) +{ + netLabel->setText("I2P"); + netLabel->setToolTip(tr("Wallet is using I2P-network only")); +} +else +{ +#endif +netLabel->setText("CLEARNET"); +#ifdef USE_NATIVE_I2P +} + + if (clientModel->isI2PAddressGenerated()) + { + labelI2PGenerated->setText("DYN"); + labelI2PGenerated->setToolTip(tr("Wallet is running with a random generated I2P-address")); + } + else + { + labelI2PGenerated->setText("STA"); + labelI2PGenerated->setToolTip(tr("Wallet is running with a static I2P-address")); + } +#endif this->clientModel = clientModel; if(clientModel) { @@ -651,19 +697,19 @@ void BitcoinGUI::setWalletModel(WalletModel *walletModel) // Put transaction list in tabs transactionView->setModel(walletModel); - mintingView->setModel(walletModel); + mintingView->setModel(walletModel); overviewPage->setModel(walletModel); addressBookPage->setModel(walletModel->getAddressTableModel()); receiveCoinsPage->setModel(walletModel->getAddressTableModel()); sendCoinsPage->setModel(walletModel); signVerifyMessageDialog->setModel(walletModel); - statisticsPage->setModel(clientModel); - blockBrowser->setModel(clientModel); - marketBrowser->setModel(clientModel); + statisticsPage->setModel(clientModel); + blockBrowser->setModel(clientModel); + marketBrowser->setModel(clientModel); fortunastakeManagerPage->setWalletModel(walletModel); - multisigPage->setModel(walletModel); - //chatWindow->setModel(clientModel); + multisigPage->setModel(walletModel); + //chatWindow->setModel(clientModel); setEncryptionStatus(walletModel->getEncryptionStatus()); connect(walletModel, SIGNAL(encryptionStatusChanged(int)), this, SLOT(setEncryptionStatus(int))); @@ -718,8 +764,8 @@ void BitcoinGUI::createTrayIcon() trayIconMenu->addSeparator(); trayIconMenu->addAction(sendCoinsAction); trayIconMenu->addAction(receiveCoinsAction); - trayIconMenu->addSeparator(); - trayIconMenu->addAction(multisigAction); + trayIconMenu->addSeparator(); + trayIconMenu->addAction(multisigAction); trayIconMenu->addSeparator(); trayIconMenu->addAction(signMessageAction); trayIconMenu->addAction(verifyMessageAction); @@ -751,6 +797,9 @@ void BitcoinGUI::optionsClicked() return; OptionsDialog dlg; dlg.setModel(clientModel->getOptionsModel()); +#ifdef USE_NATIVE_I2P + dlg.setClientModel(clientModel); +#endif dlg.exec(); } @@ -761,6 +810,31 @@ void BitcoinGUI::aboutClicked() dlg.exec(); } +#ifdef USE_NATIVE_I2P +void BitcoinGUI::showGeneratedI2PAddr(const QString& caption, const QString& pub, const QString& priv, const QString& b32, const QString& configFileName) +{ + ShowI2PAddresses i2pDialog(caption, pub, priv, b32, configFileName, this); + i2pDialog.exec(); +} +#endif + +#ifdef USE_NATIVE_I2P +void BitcoinGUI::setNumI2PConnections(int count) +{ + QString i2pIcon; + switch(count) + { + case 0: i2pIcon = ":/icons/i2pconnect_0"; break; + case 1: /*case 2: case 3:*/ i2pIcon = ":/icons/i2pconnect_1"; break; + case 2:/*case 4: case 5: case 6:*/ i2pIcon = ":/icons/i2pconnect_2"; break; + case 3:/*case 7: case 8: case 9:*/ i2pIcon = ":/icons/i2pconnect_3"; break; + default: i2pIcon = ":/icons/i2pconnect_4"; break; + } + labelI2PConnections->setPixmap(QPixmap(i2pIcon)); + labelI2PConnections->setToolTip(tr("%n active connection(s) to the I2P-Denarius network", "", count)); +} +#endif + void BitcoinGUI::setNumConnections(int count) { QString icon; diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index a77d8116..c92ea723 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -117,6 +117,13 @@ class BitcoinGUI : public QMainWindow QToolBar *mainToolbar; QToolBar *secondaryToolbar; QProgressBar *progressBar; + QLabel* netLabel; + +#ifdef USE_NATIVE_I2P + QLabel* labelI2PConnections; + QLabel* labelI2POnly; + QLabel* labelI2PGenerated; +#endif QMenuBar *appMenuBar; QAction *overviewAction; @@ -182,6 +189,9 @@ class BitcoinGUI : public QMainWindow public slots: /** Set number of connections shown in the UI */ void setNumConnections(int count); +#ifdef USE_NATIVE_I2P + void setNumI2PConnections(int count); +#endif /** Set number of blocks shown in the UI */ void setNumBlocks(int count, int nTotalBlocks); /** Set the encryption status as shown in the UI. @@ -206,7 +216,11 @@ public slots: void mainToolbarOrientation(Qt::Orientation orientation); void secondaryToolbarOrientation(Qt::Orientation orientation); - void gotoMultisigPage(); + void gotoMultisigPage(); + +#ifdef USE_NATIVE_I2P + void showGeneratedI2PAddr(const QString& caption, const QString& pub, const QString& priv, const QString& b32, const QString& configFileName); +#endif private slots: /** Switch to overview (home) page */ diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index eb548815..bb09dcf2 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -12,6 +12,10 @@ #include #include +#ifdef USE_NATIVE_I2P +#include "i2p.h" +#endif + static const int64_t nClientStartupTime = GetTime(); ClientModel::ClientModel(OptionsModel *optionsModel, QObject *parent) : @@ -166,6 +170,56 @@ PeerTableModel *ClientModel::getPeerTableModel() return peerTableModel; } +#ifdef USE_NATIVE_I2P +QString ClientModel::formatI2PNativeFullVersion() const +{ + return QString::fromStdString(FormatI2PNativeFullVersion()); +} + +void ClientModel::updateNumI2PConnections(int numI2PConnections) +{ + emit numI2PConnectionsChanged(numI2PConnections); +} + +int ClientModel::getNumI2PConnections() const +{ + return nI2PNodeCount; +} + +QString ClientModel::getPublicI2PKey() const +{ + return QString::fromStdString(I2PSession::Instance().getMyDestination().pub); +} + +QString ClientModel::getPrivateI2PKey() const +{ + return QString::fromStdString(I2PSession::Instance().getMyDestination().priv); +} + +bool ClientModel::isI2PAddressGenerated() const +{ + return I2PSession::Instance().getMyDestination().isGenerated; +} + +bool ClientModel::isI2POnly() const +{ + return IsI2POnly(); +} + +QString ClientModel::getB32Address(const QString& destination) const +{ + return QString::fromStdString(I2PSession::GenerateB32AddressFromDestination(destination.toStdString())); +} + +void ClientModel::generateI2PDestination(QString& pub, QString& priv) const +{ + const SAM::FullDestination generatedDest = I2PSession::Instance().destGenerate(); + pub = QString::fromStdString(generatedDest.pub); + priv = QString::fromStdString(generatedDest.priv); +} + +#endif + QString ClientModel::formatFullVersion() const { return QString::fromStdString(FormatFullVersion()); @@ -186,6 +240,14 @@ QString ClientModel::formatClientStartupTime() const return QDateTime::fromTime_t(nClientStartupTime).toString(); } +#ifdef USE_NATIVE_I2P +static void NotifyNumI2PConnectionsChanged(ClientModel *clientmodel, int newNumI2PConnections) +{ + QMetaObject::invokeMethod(clientmodel, "updateNumI2PConnections", Qt::QueuedConnection, + Q_ARG(int, newNumI2PConnections)); +} +#endif + // Handlers for core signals static void NotifyBlocksChanged(ClientModel *clientmodel, int nHeight, int newNumBlocksOfPeers) { @@ -216,6 +278,9 @@ void ClientModel::subscribeToCoreSignals() uiInterface.NotifyBlocksChanged.connect(boost::bind(NotifyBlocksChanged, this, _1, _2)); uiInterface.NotifyNumConnectionsChanged.connect(boost::bind(NotifyNumConnectionsChanged, this, _1)); uiInterface.NotifyAlertChanged.connect(boost::bind(NotifyAlertChanged, this, _1, _2)); +#ifdef USE_NATIVE_I2P + uiInterface.NotifyNumI2PConnectionsChanged.connect(boost::bind(NotifyNumI2PConnectionsChanged, this, _1)); +#endif } void ClientModel::unsubscribeFromCoreSignals() @@ -224,4 +289,7 @@ void ClientModel::unsubscribeFromCoreSignals() uiInterface.NotifyBlocksChanged.disconnect(boost::bind(NotifyBlocksChanged, this, _1, _2)); uiInterface.NotifyNumConnectionsChanged.disconnect(boost::bind(NotifyNumConnectionsChanged, this, _1)); uiInterface.NotifyAlertChanged.disconnect(boost::bind(NotifyAlertChanged, this, _1, _2)); +#ifdef USE_NATIVE_I2P + uiInterface.NotifyNumI2PConnectionsChanged.disconnect(boost::bind(NotifyNumI2PConnectionsChanged, this, _1)); +#endif } diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h index 7d6e72b7..53a971f0 100644 --- a/src/qt/clientmodel.h +++ b/src/qt/clientmodel.h @@ -51,6 +51,17 @@ class ClientModel : public QObject QString formatBuildDate() const; QString clientName() const; QString formatClientStartupTime() const; +#ifdef USE_NATIVE_I2P + QString formatI2PNativeFullVersion() const; + int getNumI2PConnections() const; + + QString getPublicI2PKey() const; + QString getPrivateI2PKey() const; + bool isI2PAddressGenerated() const; + bool isI2POnly() const; + QString getB32Address(const QString& destination) const; + void generateI2PDestination(QString& pub, QString& priv) const; +#endif private: OptionsModel *optionsModel; @@ -67,6 +78,9 @@ class ClientModel : public QObject void unsubscribeFromCoreSignals(); signals: void numConnectionsChanged(int count); +#ifdef USE_NATIVE_I2P + void numI2PConnectionsChanged(int count); +#endif void numBlocksChanged(int count, int countOfPeers); void bytesChanged(quint64 totalBytesIn, quint64 totalBytesOut); @@ -78,6 +92,9 @@ public slots: void updateNumConnections(int numConnections); void updateNumBlocks(int newNumBlocks, int newNumBlocksOfPeers); void updateAlert(const QString &hash, int status); +#ifdef USE_NATIVE_I2P + void updateNumI2PConnections(int numI2PConnections); +#endif }; #endif // CLIENTMODEL_H diff --git a/src/qt/forms/i2poptionswidget.ui b/src/qt/forms/i2poptionswidget.ui new file mode 100644 index 00000000..545b91b9 --- /dev/null +++ b/src/qt/forms/i2poptionswidget.ui @@ -0,0 +1,698 @@ + + + I2POptionsWidget + + + + 0 + 0 + 549 + 371 + + + + Form + + + + + + + + Use I2P only (-onlynet=native_i2p) + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + http://www.i2p2.i2p/i2cp.html#options + + + <a href="http://www.i2p2.i2p/i2cp.html#options">Help</a> + + + Qt::RichText + + + true + + + Qt::TextBrowserInteraction + + + + + + + + + + + SAM host + + + + + + + + 0 + 0 + + + + 127.0.0.1 + + + + + + + SAM port + + + + + + + 1 + + + 65535 + + + 7656 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Tunnel name + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + Bitcoin-client + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Current +I2P-address... + + + + + + + Generate +I2P-address... + + + + + + + + + + + + + I2CP options of inbound tunnels + + + + + + + + inbound.quantity + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + 1 + + + 16 + + + 2 + + + + + + + + + + + inbound.length + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + 0 + + + 7 + + + 2 + + + + + + + + + + + inbound.lengthVariance + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + -7 + + + 7 + + + + + + + + + + + inbound.backupQuantity + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + inbound.allowZeroHop + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + true + + + + + + + + + + + inbound.IPRestriction + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + 4 + + + 2 + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + I2CP options of outbound tunnels + + + + + + + + outbound.quantity + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + 1 + + + 2 + + + + + + + + + + + outbound.length + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + 7 + + + 2 + + + + + + + + + + + outbound.lengthVariance + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + -7 + + + 7 + + + + + + + + + + + outbound.backupQuantity + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + outbound.allowZeroHop + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + true + + + + + + + + + + + outbound.IPRestriction + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + 4 + + + 2 + + + + + + + + + + + outbound.priority + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + -25 + + + 25 + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + checkBoxUseI2POnly + lineEditSAMHost + spinBoxSAMPort + lineEditTunnelName + pushButtonCurrentI2PAddress + pushButtonGenerateI2PAddress + spinBoxInboundQuantity + spinBoxInboundLength + spinBoxInboundLengthVariance + spinBoxInboundBackupQuality + checkBoxInboundAllowZeroHop + spinBoxInboundIPRestriction + spinBoxOutboundQuantity + spinBoxOutboundLength + spinBoxOutboundLengthVariance + spinBoxOutboundBackupQuantity + checkBoxAllowZeroHop + spinBoxOutboundIPRestriction + spinBoxOutboundPriority + + + + diff --git a/src/qt/forms/showi2paddresses.ui b/src/qt/forms/showi2paddresses.ui new file mode 100644 index 00000000..0c899d36 --- /dev/null +++ b/src/qt/forms/showi2paddresses.ui @@ -0,0 +1,136 @@ + + + ShowI2PAddresses + + + + 0 + 0 + 640 + 450 + + + + + 640 + 450 + + + + Dialog + + + + + + If you want to use a permanent I2P-address you have to set a 'mydestination' option in the configuration file: + + + true + + + + + + + Ready to save parameter (If you want to use this address save this text in the configuration file and keep it secret): + + + true + + + + + + + + 0 + 3 + + + + true + + + + + + + Address (you can publish it): + + + + + + + + 0 + 2 + + + + true + + + + + + + Short base32-address: + + + + + + + false + + + false + + + true + + + + + + + + + Copy "mydestination" parameter +to the clipboard + + + + + + + Copy public address +to the clipboard + + + + + + + Copy b32-address +to the clipboard + + + + + + + + + privText + pubText + b32Line + privButton + pubButton + b32Button + + + + diff --git a/src/qt/i2poptionswidget.cpp b/src/qt/i2poptionswidget.cpp new file mode 100644 index 00000000..e4919d73 --- /dev/null +++ b/src/qt/i2poptionswidget.cpp @@ -0,0 +1,100 @@ +#include "i2poptionswidget.h" +#include "ui_i2poptionswidget.h" + +#include "optionsmodel.h" +#include "monitoreddatamapper.h" +#include "showi2paddresses.h" +//#include "i2p.h" +#include "util.h" +#include "clientmodel.h" + + +I2POptionsWidget::I2POptionsWidget(QWidget *parent) : + QWidget(parent), + ui(new Ui::I2POptionsWidget), + clientModel(0) +{ + ui->setupUi(this); + + QObject::connect(ui->pushButtonCurrentI2PAddress, SIGNAL(clicked()), this, SLOT(ShowCurrentI2PAddress())); + QObject::connect(ui->pushButtonGenerateI2PAddress, SIGNAL(clicked()), this, SLOT(GenerateNewI2PAddress())); + + QObject::connect(ui->checkBoxAllowZeroHop , SIGNAL(stateChanged(int)) , this, SIGNAL(settingsChanged())); + QObject::connect(ui->checkBoxInboundAllowZeroHop , SIGNAL(stateChanged(int)) , this, SIGNAL(settingsChanged())); + QObject::connect(ui->checkBoxUseI2POnly , SIGNAL(stateChanged(int)) , this, SIGNAL(settingsChanged())); + QObject::connect(ui->lineEditSAMHost , SIGNAL(textChanged(QString)), this, SIGNAL(settingsChanged())); + QObject::connect(ui->lineEditTunnelName , SIGNAL(textChanged(QString)), this, SIGNAL(settingsChanged())); + QObject::connect(ui->spinBoxInboundBackupQuality , SIGNAL(valueChanged(int)) , this, SIGNAL(settingsChanged())); + QObject::connect(ui->spinBoxInboundIPRestriction , SIGNAL(valueChanged(int)) , this, SIGNAL(settingsChanged())); + QObject::connect(ui->spinBoxInboundLength , SIGNAL(valueChanged(int)) , this, SIGNAL(settingsChanged())); + QObject::connect(ui->spinBoxInboundLengthVariance , SIGNAL(valueChanged(int)) , this, SIGNAL(settingsChanged())); + QObject::connect(ui->spinBoxInboundQuantity , SIGNAL(valueChanged(int)) , this, SIGNAL(settingsChanged())); + QObject::connect(ui->spinBoxOutboundBackupQuantity, SIGNAL(valueChanged(int)) , this, SIGNAL(settingsChanged())); + QObject::connect(ui->spinBoxOutboundIPRestriction , SIGNAL(valueChanged(int)) , this, SIGNAL(settingsChanged())); + QObject::connect(ui->spinBoxOutboundLength , SIGNAL(valueChanged(int)) , this, SIGNAL(settingsChanged())); + QObject::connect(ui->spinBoxOutboundLengthVariance, SIGNAL(valueChanged(int)) , this, SIGNAL(settingsChanged())); + QObject::connect(ui->spinBoxOutboundPriority , SIGNAL(valueChanged(int)) , this, SIGNAL(settingsChanged())); + QObject::connect(ui->spinBoxOutboundQuantity , SIGNAL(valueChanged(int)) , this, SIGNAL(settingsChanged())); + QObject::connect(ui->spinBoxSAMPort , SIGNAL(valueChanged(int)) , this, SIGNAL(settingsChanged())); +} + +I2POptionsWidget::~I2POptionsWidget() +{ + delete ui; +} + +void I2POptionsWidget::setMapper(MonitoredDataMapper& mapper) +{ + mapper.addMapping(ui->checkBoxUseI2POnly , OptionsModel::I2PUseI2POnly); + mapper.addMapping(ui->lineEditSAMHost , OptionsModel::I2PSAMHost); + mapper.addMapping(ui->spinBoxSAMPort , OptionsModel::I2PSAMPort); + mapper.addMapping(ui->lineEditTunnelName , OptionsModel::I2PSessionName); + mapper.addMapping(ui->spinBoxInboundQuantity , OptionsModel::I2PInboundQuantity); + mapper.addMapping(ui->spinBoxInboundLength , OptionsModel::I2PInboundLength); + mapper.addMapping(ui->spinBoxInboundLengthVariance , OptionsModel::I2PInboundLengthVariance); + mapper.addMapping(ui->spinBoxInboundBackupQuality , OptionsModel::I2PInboundBackupQuantity); + mapper.addMapping(ui->checkBoxInboundAllowZeroHop , OptionsModel::I2PInboundAllowZeroHop); + mapper.addMapping(ui->spinBoxInboundIPRestriction , OptionsModel::I2PInboundIPRestriction); + mapper.addMapping(ui->spinBoxOutboundQuantity , OptionsModel::I2POutboundQuantity); + mapper.addMapping(ui->spinBoxOutboundLength , OptionsModel::I2POutboundLength); + mapper.addMapping(ui->spinBoxOutboundLengthVariance, OptionsModel::I2POutboundLengthVariance); + mapper.addMapping(ui->spinBoxOutboundBackupQuantity, OptionsModel::I2POutboundBackupQuantity); + mapper.addMapping(ui->checkBoxAllowZeroHop , OptionsModel::I2POutboundAllowZeroHop); + mapper.addMapping(ui->spinBoxOutboundIPRestriction , OptionsModel::I2POutboundIPRestriction); + mapper.addMapping(ui->spinBoxOutboundPriority , OptionsModel::I2POutboundIPRestriction); +} + +void I2POptionsWidget::setModel(ClientModel* model) +{ + clientModel = model; +} + +void I2POptionsWidget::ShowCurrentI2PAddress() +{ + if (clientModel) + { + const QString pub = clientModel->getPublicI2PKey(); + const QString priv = clientModel->getPrivateI2PKey(); + const QString b32 = clientModel->getB32Address(pub); + const QString configFile = QString::fromStdString(GetConfigFile().string()); + + ShowI2PAddresses i2pCurrDialog("Your current I2P-address", pub, priv, b32, configFile, this); + i2pCurrDialog.exec(); + } +} + +void I2POptionsWidget::GenerateNewI2PAddress() +{ + if (clientModel) + { + QString pub, priv; + clientModel->generateI2PDestination(pub, priv); + const QString b32 = clientModel->getB32Address(pub); + const QString configFile = QString::fromStdString(GetConfigFile().string()); + + ShowI2PAddresses i2pCurrDialog("Generated I2P address", pub, priv, b32, configFile, this); + i2pCurrDialog.exec(); + } +} + + diff --git a/src/qt/i2poptionswidget.h b/src/qt/i2poptionswidget.h new file mode 100644 index 00000000..7e262a5d --- /dev/null +++ b/src/qt/i2poptionswidget.h @@ -0,0 +1,37 @@ +#ifndef I2POPTIONSWIDGET_H +#define I2POPTIONSWIDGET_H + +#include + +class MonitoredDataMapper; + +namespace Ui { +class I2POptionsWidget; +} + +class ClientModel; + +class I2POptionsWidget : public QWidget +{ + Q_OBJECT + +public: + explicit I2POptionsWidget(QWidget *parent = 0); + ~I2POptionsWidget(); + + void setMapper(MonitoredDataMapper& mapper); + void setModel(ClientModel* model); + +private: + Ui::I2POptionsWidget *ui; + ClientModel* clientModel; + +private slots: + void ShowCurrentI2PAddress(); + void GenerateNewI2PAddress(); + +signals: + void settingsChanged(); +}; + +#endif // I2POPTIONSWIDGET_H diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp index 7184925c..58008281 100644 --- a/src/qt/optionsdialog.cpp +++ b/src/qt/optionsdialog.cpp @@ -13,6 +13,10 @@ #include #include +#ifdef USE_NATIVE_I2P +#include "clientmodel.h" +#endif + OptionsDialog::OptionsDialog(QWidget *parent) : QDialog(parent), ui(new Ui::OptionsDialog), @@ -21,6 +25,10 @@ OptionsDialog::OptionsDialog(QWidget *parent) : fRestartWarningDisplayed_Proxy(false), fRestartWarningDisplayed_Lang(false), fProxyIpValid(true) +#ifdef USE_NATIVE_I2P + , fRestartWarningDisplayed_I2P(false) + , tabI2P(new I2POptionsWidget()) +#endif { ui->setupUi(this); @@ -94,6 +102,9 @@ OptionsDialog::OptionsDialog(QWidget *parent) : connect(mapper, SIGNAL(currentIndexChanged(int)), this, SLOT(disableApplyButton())); /* setup/change UI elements when proxy IP is invalid/valid */ connect(this, SIGNAL(proxyIpValid(QValidatedLineEdit *, bool)), this, SLOT(handleProxyIpValid(QValidatedLineEdit *, bool))); +#ifdef USE_NATIVE_I2P + ui->tabWidget->addTab(tabI2P, QString("I2P")); +#endif } OptionsDialog::~OptionsDialog() @@ -120,10 +131,24 @@ void OptionsDialog::setModel(OptionsModel *model) /* warn only when language selection changes by user action (placed here so init via mapper doesn't trigger this) */ connect(ui->lang, SIGNAL(valueChanged()), this, SLOT(showRestartWarning_Lang())); +#ifdef USE_NATIVE_I2P + QObject::connect(tabI2P, SIGNAL(settingsChanged()), this, SLOT(showRestartWarning_I2P())); +#endif + /* disable apply button after settings are loaded as there is nothing to save */ disableApplyButton(); } +#ifdef USE_NATIVE_I2P +void OptionsDialog::setClientModel(ClientModel* clientModel) +{ + if (clientModel) + { + tabI2P->setModel(clientModel); + } +} +#endif + void OptionsDialog::setMapper() { /* Main */ @@ -151,6 +176,10 @@ void OptionsDialog::setMapper() mapper->addMapping(ui->unit, OptionsModel::DisplayUnit); mapper->addMapping(ui->displayAddresses, OptionsModel::DisplayAddresses); mapper->addMapping(ui->coinControlFeatures, OptionsModel::CoinControlFeatures); + +#ifdef USE_NATIVE_I2P + tabI2P->setMapper(*mapper); +#endif } void OptionsDialog::enableApplyButton() @@ -216,6 +245,17 @@ void OptionsDialog::showRestartWarning_Lang() } } +#ifdef USE_NATIVE_I2P +void OptionsDialog::showRestartWarning_I2P() +{ + if(!fRestartWarningDisplayed_I2P) + { + QMessageBox::warning(this, tr("Warning"), tr("This setting will take effect after restarting Denarius."), QMessageBox::Ok); + fRestartWarningDisplayed_I2P = true; + } +} +#endif + void OptionsDialog::updateDisplayUnit() { if(model) diff --git a/src/qt/optionsdialog.h b/src/qt/optionsdialog.h index 18469f50..79721c4e 100644 --- a/src/qt/optionsdialog.h +++ b/src/qt/optionsdialog.h @@ -2,6 +2,9 @@ #define OPTIONSDIALOG_H #include +#ifdef USE_NATIVE_I2P +#include "i2poptionswidget.h" +#endif namespace Ui { class OptionsDialog; @@ -9,6 +12,9 @@ class OptionsDialog; class OptionsModel; class MonitoredDataMapper; class QValidatedLineEdit; +#ifdef USE_NATIVE_I2P +class ClientModel; +#endif /** Preferences dialog. */ class OptionsDialog : public QDialog @@ -18,6 +24,9 @@ class OptionsDialog : public QDialog public: explicit OptionsDialog(QWidget *parent = 0); ~OptionsDialog(); +#ifdef USE_NATIVE_I2P + void setClientModel(ClientModel* clientModel); +#endif void setModel(OptionsModel *model); void setMapper(); @@ -39,6 +48,9 @@ private slots: void on_okButton_clicked(); void on_cancelButton_clicked(); void on_applyButton_clicked(); +#ifdef USE_NATIVE_I2P + void showRestartWarning_I2P(); +#endif void showRestartWarning_Proxy(); void showRestartWarning_Lang(); @@ -55,6 +67,10 @@ private slots: bool fRestartWarningDisplayed_Proxy; bool fRestartWarningDisplayed_Lang; bool fProxyIpValid; +#ifdef USE_NATIVE_I2P + bool fRestartWarningDisplayed_I2P; + I2POptionsWidget* tabI2P; +#endif }; #endif // OPTIONSDIALOG_H diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index 8bcd1451..9f85fc46 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -7,6 +7,31 @@ #include "guiutil.h" #include "ringsig.h" +#ifdef USE_NATIVE_I2P +#include "i2p.h" +#include + +#define I2P_OPTIONS_SECTION_NAME "I2P" + +class ScopeGroupHelper +{ +public: + ScopeGroupHelper(QSettings& settings, const QString& groupName) + : settings_(settings) + { + settings_.beginGroup(groupName); + } + ~ScopeGroupHelper() + { + settings_.endGroup(); + } + +private: + QSettings& settings_; +}; + +#endif + OptionsModel::OptionsModel(QObject *parent) : QAbstractListModel(parent) { @@ -35,6 +60,52 @@ bool static ApplyProxySettings() return true; } +#ifdef USE_NATIVE_I2P +std::string& FormatI2POptionsString( + std::string& options, + const std::string& name, + const std::pair& value) +{ + if (value.first) + { + if (!options.empty()) + options += " "; + options += name + "=" + value.second; + } + return options; +} + +std::string& FormatI2POptionsString( + std::string& options, + const std::string& name, + const std::pair& value) +{ + if (value.first) + { + if (!options.empty()) + options += " "; + options += name + "=" + (value.second ? "true" : "false"); + } + return options; +} + +std::string& FormatI2POptionsString( + std::string& options, + const std::string& name, + const std::pair& value) +{ + if (value.first) + { + if (!options.empty()) + options += " "; + std::ostringstream oss; + oss << value.second; + options += name + "=" + oss.str(); + } + return options; +} +#endif + void OptionsModel::Init() { QSettings settings; @@ -61,6 +132,61 @@ void OptionsModel::Init() SoftSetBoolArg("-detachdb", settings.value("detachDB").toBool()); if (!language.isEmpty()) SoftSetArg("-lang", language.toStdString()); + +#ifdef USE_NATIVE_I2P + ScopeGroupHelper s(settings, I2P_OPTIONS_SECTION_NAME); + + if (settings.value("useI2POnly", false).toBool()) + { + mapArgs["-onlynet"] = NATIVE_I2P_NET_STRING; + std::vector& onlyNets = mapMultiArgs["-onlynet"]; + if (std::find(onlyNets.begin(), onlyNets.end(), NATIVE_I2P_NET_STRING) == onlyNets.end()) + onlyNets.push_back(NATIVE_I2P_NET_STRING); + } + + if (settings.contains("samhost")) + SoftSetArg(I2P_SAM_HOST_PARAM, settings.value("samhost").toString().toStdString()); + + if (settings.contains("samport")) + SoftSetArg(I2P_SAM_PORT_PARAM, settings.value("samport").toString().toStdString()); + + if (settings.contains("sessionName")) + SoftSetArg(I2P_SESSION_NAME_PARAM, settings.value("sessionName").toString().toStdString()); + + i2pInboundQuantity = settings.value(SAM_NAME_INBOUND_QUANTITY , SAM_DEFAULT_INBOUND_QUANTITY ).toInt(); + i2pInboundLength = settings.value(SAM_NAME_INBOUND_LENGTH , SAM_DEFAULT_INBOUND_LENGTH ).toInt(); + i2pInboundLengthVariance = settings.value(SAM_NAME_INBOUND_LENGTHVARIANCE , SAM_DEFAULT_INBOUND_LENGTHVARIANCE ).toInt(); + i2pInboundBackupQuantity = settings.value(SAM_NAME_INBOUND_BACKUPQUANTITY , SAM_DEFAULT_INBOUND_BACKUPQUANTITY ).toInt(); + i2pInboundAllowZeroHop = settings.value(SAM_NAME_INBOUND_ALLOWZEROHOP , SAM_DEFAULT_INBOUND_ALLOWZEROHOP ).toBool(); + i2pInboundIPRestriction = settings.value(SAM_NAME_INBOUND_IPRESTRICTION , SAM_DEFAULT_INBOUND_IPRESTRICTION ).toInt(); + i2pOutboundQuantity = settings.value(SAM_NAME_OUTBOUND_QUANTITY , SAM_DEFAULT_OUTBOUND_QUANTITY ).toInt(); + i2pOutboundLength = settings.value(SAM_NAME_OUTBOUND_LENGTH , SAM_DEFAULT_OUTBOUND_LENGTH ).toInt(); + i2pOutboundLengthVariance = settings.value(SAM_NAME_OUTBOUND_LENGTHVARIANCE, SAM_DEFAULT_OUTBOUND_LENGTHVARIANCE).toInt(); + i2pOutboundBackupQuantity = settings.value(SAM_NAME_OUTBOUND_BACKUPQUANTITY, SAM_DEFAULT_OUTBOUND_BACKUPQUANTITY).toInt(); + i2pOutboundAllowZeroHop = settings.value(SAM_NAME_OUTBOUND_ALLOWZEROHOP , SAM_DEFAULT_OUTBOUND_ALLOWZEROHOP ).toBool(); + i2pOutboundIPRestriction = settings.value(SAM_NAME_OUTBOUND_IPRESTRICTION , SAM_DEFAULT_OUTBOUND_IPRESTRICTION ).toInt(); + i2pOutboundPriority = settings.value(SAM_NAME_OUTBOUND_PRIORITY , SAM_DEFAULT_OUTBOUND_PRIORITY ).toInt(); + + std::string i2pOptionsTemp; + FormatI2POptionsString(i2pOptionsTemp, SAM_NAME_INBOUND_QUANTITY , std::make_pair(settings.contains(SAM_NAME_INBOUND_QUANTITY ), i2pInboundQuantity)); + FormatI2POptionsString(i2pOptionsTemp, SAM_NAME_INBOUND_LENGTH , std::make_pair(settings.contains(SAM_NAME_INBOUND_LENGTH ), i2pInboundLength)); + FormatI2POptionsString(i2pOptionsTemp, SAM_NAME_INBOUND_LENGTHVARIANCE , std::make_pair(settings.contains(SAM_NAME_INBOUND_LENGTHVARIANCE ), i2pInboundLengthVariance)); + FormatI2POptionsString(i2pOptionsTemp, SAM_NAME_INBOUND_BACKUPQUANTITY , std::make_pair(settings.contains(SAM_NAME_INBOUND_BACKUPQUANTITY ), i2pInboundBackupQuantity)); + FormatI2POptionsString(i2pOptionsTemp, SAM_NAME_INBOUND_ALLOWZEROHOP , std::make_pair(settings.contains(SAM_NAME_INBOUND_ALLOWZEROHOP ), i2pInboundAllowZeroHop)); + FormatI2POptionsString(i2pOptionsTemp, SAM_NAME_INBOUND_IPRESTRICTION , std::make_pair(settings.contains(SAM_NAME_INBOUND_IPRESTRICTION ), i2pInboundIPRestriction)); + FormatI2POptionsString(i2pOptionsTemp, SAM_NAME_OUTBOUND_QUANTITY , std::make_pair(settings.contains(SAM_NAME_OUTBOUND_QUANTITY ), i2pOutboundQuantity)); + FormatI2POptionsString(i2pOptionsTemp, SAM_NAME_OUTBOUND_LENGTH , std::make_pair(settings.contains(SAM_NAME_OUTBOUND_LENGTH ), i2pOutboundLength)); + FormatI2POptionsString(i2pOptionsTemp, SAM_NAME_OUTBOUND_LENGTHVARIANCE, std::make_pair(settings.contains(SAM_NAME_OUTBOUND_LENGTHVARIANCE), i2pOutboundLengthVariance)); + FormatI2POptionsString(i2pOptionsTemp, SAM_NAME_OUTBOUND_BACKUPQUANTITY, std::make_pair(settings.contains(SAM_NAME_OUTBOUND_BACKUPQUANTITY), i2pOutboundBackupQuantity)); + FormatI2POptionsString(i2pOptionsTemp, SAM_NAME_OUTBOUND_ALLOWZEROHOP , std::make_pair(settings.contains(SAM_NAME_OUTBOUND_ALLOWZEROHOP ), i2pOutboundAllowZeroHop)); + FormatI2POptionsString(i2pOptionsTemp, SAM_NAME_OUTBOUND_IPRESTRICTION , std::make_pair(settings.contains(SAM_NAME_OUTBOUND_IPRESTRICTION ), i2pOutboundIPRestriction)); + FormatI2POptionsString(i2pOptionsTemp, SAM_NAME_OUTBOUND_PRIORITY , std::make_pair(settings.contains(SAM_NAME_OUTBOUND_PRIORITY ), i2pOutboundPriority)); + + if (!i2pOptionsTemp.empty()) + SoftSetArg(I2P_SAM_I2P_OPTIONS_PARAM, i2pOptionsTemp); + + i2pOptions = QString::fromStdString(i2pOptionsTemp); +#endif } int OptionsModel::rowCount(const QModelIndex & parent) const @@ -115,6 +241,61 @@ QVariant OptionsModel::data(const QModelIndex & index, int role) const return settings.value("language", ""); case CoinControlFeatures: return QVariant(fCoinControlFeatures); +#ifdef USE_NATIVE_I2P + case I2PUseI2POnly: + { + ScopeGroupHelper s(settings, I2P_OPTIONS_SECTION_NAME); + bool useI2POnly = false; + if (mapArgs.count("-onlynet")) + { + const std::vector& onlyNets = mapMultiArgs["-onlynet"]; + if (std::find(onlyNets.begin(), onlyNets.end(), NATIVE_I2P_NET_STRING) != onlyNets.end()) + useI2POnly = true; + } + return settings.value("useI2POnly", useI2POnly); + } + case I2PSAMHost: + { + ScopeGroupHelper s(settings, I2P_OPTIONS_SECTION_NAME); + return settings.value("samhost", QString::fromStdString(GetArg(I2P_SAM_HOST_PARAM, I2P_SAM_HOST_DEFAULT))); + } + case I2PSAMPort: + { + ScopeGroupHelper s(settings, I2P_OPTIONS_SECTION_NAME); + return settings.value("samport", QString::number((qint64)GetArg(I2P_SAM_PORT_PARAM, I2P_SAM_PORT_DEFAULT))); + } + case I2PSessionName: + { + ScopeGroupHelper s(settings, I2P_OPTIONS_SECTION_NAME); + return settings.value("sessionName", QString::fromStdString(GetArg(I2P_SESSION_NAME_PARAM, I2P_SESSION_NAME_DEFAULT))); + } + case I2PInboundQuantity: + return QVariant(i2pInboundQuantity); + case I2PInboundLength: + return QVariant(i2pInboundLength); + case I2PInboundLengthVariance: + return QVariant(i2pInboundLengthVariance); + case I2PInboundBackupQuantity: + return QVariant(i2pInboundBackupQuantity); + case I2PInboundAllowZeroHop: + return QVariant(i2pInboundAllowZeroHop); + case I2PInboundIPRestriction: + return QVariant(i2pInboundIPRestriction); + case I2POutboundQuantity: + return QVariant(i2pOutboundQuantity); + case I2POutboundLength: + return QVariant(i2pOutboundLength); + case I2POutboundLengthVariance: + return QVariant(i2pOutboundLengthVariance); + case I2POutboundBackupQuantity: + return QVariant(i2pOutboundBackupQuantity); + case I2POutboundAllowZeroHop: + return QVariant(i2pOutboundAllowZeroHop); + case I2POutboundIPRestriction: + return QVariant(i2pOutboundIPRestriction); + case I2POutboundPriority: + return QVariant(i2pOutboundPriority); +#endif default: return QVariant(); } @@ -215,6 +396,124 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in emit coinControlFeaturesChanged(fCoinControlFeatures); } break; +#ifdef USE_NATIVE_I2P + case I2PUseI2POnly: + { + ScopeGroupHelper s(settings, I2P_OPTIONS_SECTION_NAME); + settings.setValue("useI2POnly", value.toBool()); + break; + } + case I2PSAMHost: + { + ScopeGroupHelper s(settings, I2P_OPTIONS_SECTION_NAME); + settings.setValue("samhost", value.toString()); + break; + } + case I2PSAMPort: + { + ScopeGroupHelper s(settings, I2P_OPTIONS_SECTION_NAME); + settings.setValue("samport", value.toString()); + break; + } + case I2PSessionName: + { + ScopeGroupHelper s(settings, I2P_OPTIONS_SECTION_NAME); + settings.setValue("sessionName", value.toString()); + break; + } + case I2PInboundQuantity: + { + ScopeGroupHelper s(settings, I2P_OPTIONS_SECTION_NAME); + i2pInboundQuantity = value.toInt(); + settings.setValue(SAM_NAME_INBOUND_QUANTITY, i2pInboundQuantity); + break; + } + case I2PInboundLength: + { + ScopeGroupHelper s(settings, I2P_OPTIONS_SECTION_NAME); + i2pInboundLength = value.toInt(); + settings.setValue(SAM_NAME_INBOUND_LENGTH, i2pInboundLength); + break; + } + case I2PInboundLengthVariance: + { + ScopeGroupHelper s(settings, I2P_OPTIONS_SECTION_NAME); + i2pInboundLengthVariance = value.toInt(); + settings.setValue(SAM_NAME_INBOUND_LENGTHVARIANCE, i2pInboundLengthVariance); + break; + } + case I2PInboundBackupQuantity: + { + ScopeGroupHelper s(settings, I2P_OPTIONS_SECTION_NAME); + i2pInboundBackupQuantity = value.toInt(); + settings.setValue(SAM_NAME_INBOUND_BACKUPQUANTITY, i2pInboundBackupQuantity); + break; + } + case I2PInboundAllowZeroHop: + { + ScopeGroupHelper s(settings, I2P_OPTIONS_SECTION_NAME); + i2pInboundAllowZeroHop = value.toBool(); + settings.setValue(SAM_NAME_INBOUND_ALLOWZEROHOP, i2pInboundAllowZeroHop); + break; + } + case I2PInboundIPRestriction: + { + ScopeGroupHelper s(settings, I2P_OPTIONS_SECTION_NAME); + i2pInboundIPRestriction = value.toInt(); + settings.setValue(SAM_NAME_INBOUND_IPRESTRICTION, i2pInboundIPRestriction); + break; + } + case I2POutboundQuantity: + { + ScopeGroupHelper s(settings, I2P_OPTIONS_SECTION_NAME); + i2pOutboundQuantity = value.toInt(); + settings.setValue(SAM_NAME_OUTBOUND_QUANTITY, i2pOutboundQuantity); + break; + } + case I2POutboundLength: + { + ScopeGroupHelper s(settings, I2P_OPTIONS_SECTION_NAME); + i2pOutboundLength = value.toInt(); + settings.setValue(SAM_NAME_OUTBOUND_LENGTH, i2pOutboundLength); + break; + } + case I2POutboundLengthVariance: + { + ScopeGroupHelper s(settings, I2P_OPTIONS_SECTION_NAME); + i2pOutboundLengthVariance = value.toInt(); + settings.setValue(SAM_NAME_OUTBOUND_LENGTHVARIANCE, i2pOutboundLengthVariance); + break; + } + case I2POutboundBackupQuantity: + { + ScopeGroupHelper s(settings, I2P_OPTIONS_SECTION_NAME); + i2pOutboundBackupQuantity = value.toInt(); + settings.setValue(SAM_NAME_OUTBOUND_BACKUPQUANTITY, i2pOutboundBackupQuantity); + break; + } + case I2POutboundAllowZeroHop: + { + ScopeGroupHelper s(settings, I2P_OPTIONS_SECTION_NAME); + i2pOutboundAllowZeroHop = value.toBool(); + settings.setValue(SAM_NAME_OUTBOUND_ALLOWZEROHOP, i2pOutboundAllowZeroHop); + break; + } + case I2POutboundIPRestriction: + { + ScopeGroupHelper s(settings, I2P_OPTIONS_SECTION_NAME); + i2pOutboundIPRestriction = value.toInt(); + settings.setValue(SAM_NAME_OUTBOUND_IPRESTRICTION, i2pOutboundIPRestriction); + break; + } + case I2POutboundPriority: + { + ScopeGroupHelper s(settings, I2P_OPTIONS_SECTION_NAME); + i2pOutboundPriority = value.toInt(); + settings.setValue(SAM_NAME_OUTBOUND_PRIORITY, i2pOutboundPriority); + break; + } + +#endif default: break; } diff --git a/src/qt/optionsmodel.h b/src/qt/optionsmodel.h index be499519..dfec983e 100644 --- a/src/qt/optionsmodel.h +++ b/src/qt/optionsmodel.h @@ -32,6 +32,27 @@ class OptionsModel : public QAbstractListModel DetachDatabases, // bool Language, // QString CoinControlFeatures, // bool +#ifdef USE_NATIVE_I2P + I2PUseI2POnly, // bool + I2PSAMHost, // QString + I2PSAMPort, // int + I2PSessionName, // QString + + I2PInboundQuantity, // int + I2PInboundLength, // int + I2PInboundLengthVariance, // int + I2PInboundBackupQuantity, // int + I2PInboundAllowZeroHop, // bool + I2PInboundIPRestriction, // int + + I2POutboundQuantity, // int + I2POutboundLength, // int + I2POutboundLengthVariance, // int + I2POutboundBackupQuantity, // int + I2POutboundAllowZeroHop, // bool + I2POutboundIPRestriction, // int + I2POutboundPriority, // int +#endif OptionIDRowCount, }; @@ -58,6 +79,22 @@ class OptionsModel : public QAbstractListModel bool fMinimizeOnClose; bool fCoinControlFeatures; QString language; +#ifdef USE_NATIVE_I2P + int i2pInboundQuantity; + int i2pInboundLength; + int i2pInboundLengthVariance; + int i2pInboundBackupQuantity; + bool i2pInboundAllowZeroHop; + int i2pInboundIPRestriction; + int i2pOutboundQuantity; + int i2pOutboundLength; + int i2pOutboundLengthVariance; + int i2pOutboundBackupQuantity; + bool i2pOutboundAllowZeroHop; + int i2pOutboundIPRestriction; + int i2pOutboundPriority; + QString i2pOptions; +#endif signals: void displayUnitChanged(int unit); diff --git a/src/qt/res/icons/i2plogo_0_16.png b/src/qt/res/icons/i2plogo_0_16.png new file mode 100644 index 0000000000000000000000000000000000000000..912d4ac377228771cb9811520a08d47ee6bb3f97 GIT binary patch literal 3293 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 Kg{#22{`ddu6i;UW literal 0 HcmV?d00001 diff --git a/src/qt/res/icons/i2plogo_1_16.png b/src/qt/res/icons/i2plogo_1_16.png new file mode 100644 index 0000000000000000000000000000000000000000..e5219d6bc94235df3d38e7cb47d96df357e84cd0 GIT binary patch literal 3014 zcmV;%3pwpQXh}ptR9J;omwRkgS9ZpKd!KXe%l8>S z27Ij)6rjWye2p;yhasd0Vyq04r#p=(4OOEwZNjKZm5G>)j&3HICQ_A|M5Ae=QHN$y zsp_Ta1V|kSWMT>w=-6NrKT0}yR0W5J&3*cH@4091{&5fO^hjI#EUmrv+UM-`eQPZN zpkW0N0X`Q{)o?H12S%tp>wv0&F%5<%&kFc2fQgBTW?)&lTpmfKQgfFtU;diU=UbW0 zW{0}FyBCIshnoU{z{-3+|M{j(n~H;jgAKu8@LsL;rM9-V*^fT@DB<_}*UZk&jz0S6 zqxs91FDDGcXsc8zpLcY0`+R5 z@z6sL-5MSqt_uVLDW%k8YisNEOePbI#bWD)5Wm^EbLUqF4;~D(w6t`%u6s>txC=N6 z3;-K7GyMOASka4W9lZ&lV}=&kVyD2!%p>2L}hOP$={+aH_Gf@j2VJ z%}^-xHgKw;p<%ym+cFY~yk!{1fY0aqj&0l0=kxs)Fc1!hzY7Sz-~XCn7z1^6b*}=# zG|len%d@PH8F zbwE3g^F!Blx90Qt?*lrY&;O0%INNf$+yQ{ASFireb=|GGT<)cGI$eGL{rCR?*jA}j zo(DL0?%W5JO6BX-YW2^0dwa`;Lg5##>uz%#=V{Y(=m$c81Y95pm>Ptq4*-f9VThR$ z0qNjUUsLYgyVnNnRTjsquK4F%jyQl)>LnCsN9v0L0_*-}m%C&SWyd zL?ZEol=2hHvi@FDyXBZSgm=?1AWn_(rS~2Klm$X-Vi-iZ^E(YAq_vI!T*2z8PA?mc&u{$^9%`qWF$df~!zyGJ#THn$8wAL}hFaq8Yd`hXf z5Tb5qXb8X*Ld1YN04b$UN*M?0=H}+K*4ofo$APF6kf(A z0bMSa_iL?Fz#HjwS}CPoR!X%mEG)bVP%4!UD5X+`Lg5uaU%PhgHKkO0KA-+ zZ{NPfvuDr#W3^gMxvu-oI~=g+&Dxvi0aN^+Jm*CQLcq1s3@Ef$MK7a*BTIzVxJe7p)U zIXPJkg+j%tsVN6w?b@|&AP^`nU%uP{7#J9+c6D`?q?8qaLx&Ej&d$!#;^Jb(JCf@- zPKjF9B9TZapqR~O@9343vUKa#t+Ld$0_b0WGr&5J6F#Mu_wUiL%#%OWaM$hItdXWT zU3SIcnVA|4B9X}3N~yt)j*iDOnT!#QM&I)Jd>7l>+xOVEEt{L0U-$d{gDovB`v8$l zCSMJQ!xx*Io1X)u-|s)*t=|t2kH`Pg@AqF^zI^#hfQZFn`+Yv&Mc@@cY}vBq8OySU zEXzs*+<*W5PX_{lp?Ez0hHcwsB9Zu3Fc=(6Boc3X`#o-1*2Seum;SiFzu&)k^XA<` zh+i#Ty7Zvw;WSCD0E&3HTS|=&!ql=tBQ-wo0TBgFh5*Z~VH{`?Ld0FyZSdB$Xsu&f z>m`6xN;Ly|;Q)ZQBA^B7}%) zty`#(QU!(83Q*9}d+v5{dR&=V6A%e>NcpslTKc64;~Zol8(Q7)H1ZEI_ry>jJB zQcBsmu&{7?-MV$TiHV73A;iYn+1bxFY}ionO6AS-^Yj0{e*OCCg8*6UvBytP`b{>QFeyRP^5_eV|B+@_Se)YH@R<%b`B7zu?! z4^}Fbk%u3C_`frmOgI*cJt(Cd+p%NEWG0gdMx)W~QpziLIN&PqrSLEc{3l=t5BIuO z{3w72AEc^bm|Ab30eX6RZX^(3Vog&cs-=gZdD*Pr{~gAeimR_j{W{{lFo;cg8rz!Bg>4KWQXfscWod$u$+HT}S{ ztkYdxUA=%2kH^!&VDQYwjT?8{wk=bs)XTwO@JuR|`W7G}k;qHIVDRjoJ$v?eobZC* z??01FCjSH=nN0q<&*wY))KgFWDIntU_`XmmbY}VT<=+NGdwcsH*LBZEB9WIo4tPRJ zc_xua9LQucMt67jH>H$kEX#TgV9S;*y9~oPolGWQ&tx*b6DLk=w=C=55{bk+(hK#C z)L_s|?W69a)(ACtW1Y7q?5#<8a>$FAE+ND!;CEYFTMZ$^eL{#8TI5TeV&{01S!3L(UL&%RA-eUEnr z0i=WwE0t3Bg~MUfFpPUWf13fc)~l%%b(UErtI z1!`c27xJI#8WHZI)*zh|pu4)dRw<=60f&c%h6<@vYNcga-IYq^@W{wWeqv%`nUwMY z$8nCfwY6o(#>RffvaIdJV)4j^4I5@gMn+nK!QhTcrSfrGTicD%(a|M7pRc!Ct$y6v z+Is!);lp1Gg+e{9>;AH*r{~MT!NG=TG`d>|abo4lm0un^cI+<0Fuvis?%AH6o?mA& znOH0qd(?H^)4jdDSH1T68(Qm&J9qA!$Ye6%L?ZE+<2Zx=1KJc6xOC+7eEpPnMp)JR9J;gmurkv=Xu9}&wDO&*_oXg z*j?BeE?yZN111=A@dZ9qYGtd~#=(gk#YDatWYX<WRnW zk87!zx# z>u5RZXc@a#=OF;!_x}zUOQlj@2P77YeM2cV*3;AT*MPXL`*q-CDwX=%VzH<^&wCRX zb6xiz08vW40gQ>rcS@y_pG+oSS4xdJjAlaAw* z6c7TR0ac(0bb)E02Fw8+i&ucw19%l^raf93D#n;f;L-{LI!aMCLZz!{IUU+ss326t zp{ZP2$}nw&N;jlKbk*!#1&oM%<~UBx7*hujkr|6sM@B}BF{TF8M5JQJ&)B$j?b$;&aX3owxl z@Cj)sm(5Foi=WSN8=zb^&j&8vihe!?Or>IePe2Xi_!OX0G0y{LRUdZ%>h=2HWV6}t z2SG4l6Y?(b0};6im~OZGk4mZiv$M0e0aLHn|236Ljn2={-vYRK^X9*=UcLI{?Ck91 z$jC?l{O8`id(U+`olgPIoH_Hu?c29s6p?$ocI|4HN~IsC)9EW=7*4r%!IVD8NjcLU<44<&-`A0TeWU_gjs*MJC^&?O;)02qUm%fyLA&mx#qD&>V? zm~b4&1=^iX$8#Jf5r&}$v>nHBwbsd0D&+x-Pd)XN({8upjYh)<7B_C(==SyXB|4ps z5Ae`K54jT)6A2OV0XA&dpj_8YhG7`9`*oC3i7*Uf%0!hf0Y9;v&jKGl>;h}52t2W z1>m}F(RJP9BJ!q<-&RVE#$vH|A_mBtuInE6Jnt`y#iD99n{OCnMpLQOw*ZzdUHUq3 z-1EG5$H&LLd_Mn&B63VA^)CR~Z1&5>nB$)3eYaF9C33mkmy}Y+JkNVy*^FfDt)e2* zOOy!LR{ef#jKLT~#z01V?!Vs)6SwR8VHjpbr04wk^8l`hWPlz3rIhbDP8R4{SXeN|7)NWJ z1$xCE+hz8HZ(7?M1k%87Ea&r<0=ES8^fYKUOP88 zH#s~!+<5Q3_q>%WSFY7sPrdNM3p2%H(S7pCCm&Ht-Mg;=tp}DMIJ8Me@tp?EjKWE$qw$Wzf-%26EzqKwO8s^%3WY)!n7w}edH^snF%cw_ z$=N%1?sNe*Zrm8g1oo59vL-`j7`;8 zKQ+Zbrz3}2Z8>wN#;S6e!B|(0HW%f@WSK|q-lf0Ykulek|EbkjH8sVM>&a-VEhna@ z$pge%4rPLsR);dq5EBRuvD8OvQ`oR!gEGeS8)LFcsa3Y(16u2>QYs$=ffJ9%`$QxQta1hFwhveaoD}Fj z5Pw8ugL~}T zp+krMDHe-e2!h}j7XP;Ex*uz;FAfh6clPh!|Gi`~Ini#nKL)7R>+feWncKj%-Me=; zOQq6(_4fAOQ%c>q&&vtmqC{ODL}GScAe4yrzX2{u)FaT>&##yF^RWn_2&ON~js7KE z7Qu*MmiF@z|71{t<&k8Z8RD)0KV_n^7;Ik z^XJdk0j^)a-nen&#+g&6PE~BeW`~A`&h+>9R{+kPJ2!8PIXgQ$`x(H+ix(G+F=v%h z_W-V4yVeBGO-@eU1sEP4ZfUL0)$8?1WugY?ec+gZO*Z~Mk*_~$B76G}i?6ks@dMzn zfi+em{@dbt1N|01U|{wC)mhS$k%K`f2P+i{l?p48Y57s8<-pVw0|13W;SJySPZtV> zKeq9odY<>u-o1PO1dwbt`$x%S^7PQq(4PUaY15`Z2!i0FbUOW()qpQ4rB3H^xwlKD zlJm?n&%C6RI_-JhHvo3--1+;Ck<-iQEgXm=BEkz!;ppCZ*=9MvRYcYRPZWzq5s}BV)(?xwcB>hWi^$qA44+J;Qm*4T z>%uTxqm+8uYRsb|@(A!$tJU&=bwq!(fonJPirxIEK+E?2gTP55`};DH2%fbX@x0Z9 zGeop_mB>A=Sqgp8CiY@BOIWR%FN6W^vH`9FQmvX-!LYP9>Khgp7vD-G5~D#7dZ^ouXP_-=1+?=MAU6fj!rzZa1k#+Z+6 zum8`POy+L4+dTyk1i`;~o_7zp@Y-vyEtE>7eYsq&(d~A}{~x@1yaJ|8;YpPH%UZ6R9J;omThoU*LlZ(&$;*RYPGLd zyApZ@Y(NH7>=3XC#+}r7z?9&+Zf)vzI%&pDGMT=moiv?E(nOjznK;cf)4FaOrjsH0 z*vl7}sby?%kzzAIEdicFGvF9(q>)&$yOLH~wA$T!pMJPk9=e~-Z~y1ad7gWo=YNg> zC_Dgk0+$7v3LAi4U?Sr65nmCgYdC%Ym=vhb&Cz37JkaRi{T`tpzWHX-7_&17f*Vgi{q)?GD_4?jZEc?lg5c)%?b~NP z&r4*p*-wket%C;-&Ky5}ysf{#f2Z&J(?%f;oCMAShZQowzXRjIZz{y^Q7FdJlWpY*Y~?Y5R6-v{%+*cKy51^u$5}+b74^%{?a_!o+z!IYMBg`-s%}+$S)1j$tD9JU>YieuQ3UKV$G3V5& zQ(HaHO92cI58KzTU*C51>eWy9_19k?9336a0C=8fz468y4~>qFW^BS=9B3y@IEXlL zA3G6SfWK5Fwz5K^s|yRk?^;JJ(ruvCE&q?3sd-{8i^R+fHqb~Uu!Dd^Hj4wSc7mf= zi99%EsL#w`I}VBYd1Al{U>kx&7Mw-k)<;;$lSVG zy8IX;Zx>5EA63CW0jGh_Ynb#8fiu9Dbr{nMoHmhKDgK@*Nd9V~l)#STT_P zhJn)-*>9qV6X!1wIo(kC8&ymf=|3`z(`fll3aJDUuT*J~D!a)h1aLjWYs*#6Yv)rw~+xgd#c7 zutgM&fyo*q2_P0WB3Yn)EZi^V`+iPDl9Q8@0JemB62KS}vn(qIBx|*rs;U(PK@P}B zxB*>&3;a^R*YHZr10O`3C!F(vKx<(EcV&g%?ryG&(9$s3zG(ewbd#(HZU{7rMN+oS z##)UJ*RN+~c9vu;#sh1Nl5k0Gj#0Z=6l%9`lW>x3GA%w@w~l3$m`ifdQ2V$nEZw+4 zJe_BAT$t|YVDakJtFd@IzGZQ7aeDXe-HV>*#nS2YmZhbo>7z%FE*?8}%o!LM*b)T6 z?2#i!=7)!e?LB+;3>stZta(74(BXsocqys|fYpctfRz;*evImgNT0gRs+D4?*QJHP z)NPun6jj$HKwxo^W}!fJV1OpTQa7!_Jk@~#S^yK1w0e7M)#YVcgTVR$S}twXdFoAo zvttC0JW{K=E=>Ujx8S?9EzMJ31vqiyM6heuuBCdt-iYG$o6Y7D&;W2;7JY3_&D$$@HtgtPE7tarZTyIfoD}QZSC@-n96&l z5-+M^wYACLwS2i$Eb)>mlIxHWKak0}GG9?e+zQ`n`EsdL;m=i(fen1kvgJ~)z+VA$ zk^W97}H7m_iSPl1yVmmvG(oT_l0;oKAFqqULGDEwq4hK zF_B12xUTz;kq7*?<2aXkdU{?R9UYDD-MjZUfcJWOdX5`H)9Q~(z9ZtkXq+eXh5o2T z@>5e-KJ=+d&Tp}9Yz!mN9|Yu7C`9x76v?7=142NrLKdY55RhI)vLL;H7$ZFh84aWl z4Rr(AAkxG2l2xQ{WCV%YF>4}SM0$X%s`d>H4H;GKjCy>1bmCnR_qJLs%NSFLJYoHs z2Mk3?o)u^)Yy}MroM2=``Y*xkbQ{AS#|e3Qn!Fw7SMfRD-AysA>3jlx0`$V1)QY7N z8MW9iJ`;rk(;Z4iNPjk((Uc-Pc|Bj_m3Po z^0DW6scbg;q%r2&fddC_dY+faWHL_~W3I2=0v{2+>(_eZc2x4K5l;dCO?W4h%`wy6 z$wegOo?h-0I=E2iqz2H}PqEO!g?xc!fX+@zZ4T!zU#1E$HAUI?xsc7W2+-HZ0zT)b zr>Ov(99vp^e|h=*=wz(|P{^}9luMp32HR&j1`fdbAz{!NrAzg=wSE2K)p#qp&C9R|((#d!u{( z6~edw{>T$v2HqijCm7&wfp>vtBmQ>8&#NMHW&X0hD(8lF@Of2a!v?-;Y&ln~@Q13% zT!}9mTh6WD$e#dgdzhE3RXI1XA@qnmnHNFMb&>f7itOLdbE^$`H|z2p&%@fcZ{PFA zn0H;*{if%6*5i*q{;VvNiIM$AHbi&J!mvBC$ZiqY1hP{VF)9y>$Yx{YQNS43C0Lsjc8B|!ZGp-bG4kjOFJORAiO7~9 z2==5>DciEFZ9x!hj^adB*JA%ny&}|XI~$sQi*;a4rrXw?li?>k!~x-VQq1$vy+)> zmClt0pRpNfk{L`R9J;wmurYzXBo$T&zZ~4?3_8X zJ3HrWx=A)_k~W)-Sk%_mR#X&`TGJ>}rPan3MGM{)Q7g3~NL4DRh?gRYg4WB2e({E2 z3Vsm9f?%pPZHcDt&Yo-5UTm9W&fgF3d*b52eE7}tytgyY|NlM*0KxMGR|qubwB+T}DFcA5Etb=YYtNja4=|mQq$Ss!Du@6!Hkf1?uSiou zfRR{?6<#|M3jo{OEM^(6ID6LdSVXbHYlmWKC+|`i11yU{tnk`_28my9kfvOdWn6;W za6eXf&64^no_mRgS1+o!7r{{Q7s1nlqk>5AN5MJ4n*}|=9|X?|ZWi;_&%8KAzUU9obrzq|IG!JH3$wy9{pq&@?qcjgLWL5BKi6ATO`)MA`@{-RXf>^_E zCW{iQlJE$1}*?OPyzo2YGCU5DW6|9@%43T z0#ZX2GoAoy)#QPxMEpC?k!lJvRhrcmAgjp@Rn%+)7*ulK5<_6Ap-Mh3?5v=aTUS1} zGAJ-)aMp7L)Ip1FGgSm^x$(1V$M{)I@T5P()K>&cf&+rU^H^|j2QLUN6|_8$1eZ1O zJZHF(b4a2Mkfwy21#1mYrwsBZI3zhqZEP@KxOk^2(XqlctUXT;o+!b8YO z3eg=aJiLQDO9~Iga*{f6f_71`)<_J|o@jXKSWbe7){=&ojYZVPedd5Z?m#t8>pQvY zxdqI&o@6fg5B(⪚7spx_(RxxR5MgxLpz1%vW!j;(9fI)J+}<)8TI@aIu$%~23o!Cr+RJC9m6wc9;e+KKGlEL=&k~< zeiiKr^Zj$QyYK`+V9e&v5ze_HrWG*jKSMZ&AQb#guqk-G_k`aFa?f*uUkFmcTO@i} zY4@kOm08A(f{x(FKL1wF-}fc=UWry-*|*Z%%Bs7N&WF`}O+x+zwaC5nC?_zH-Ck^ct;gunv+7T6j8$3FlOf{n~B#^-&0+m9dY z9Iu)_*vMQ-`?!s2>aO#Ex(gbC%>$^Vc{3ZCtm`UPT?j^?c>uGz>(}oAnCMEjP#c2> z9|RG!4Mt!CfBC zOOE6@L)?kFWy$(uk1=XIVp)UrMP201SmEK3SZq9DtnhH8Xxu!2$lvYedFZ(@!BDWL z;i(w>t7Na_cw>Y4(s8Tds$#X_)2HceY_Qsx;_1`$HaFSVutc}2SUq{tJwQZvLA`x= zll+tDY`FOvQ*8VAMP5{Ib%!ao{-4L{??J9lK?J@B7$BGz{915E@Ji433#Nis3%Y`z zd5^g6)G6lj!hV>SmgW^lPn@8g=XP&aSeljGDA7s_`(~C~Q4}1P2=d(S$qUP}l6Om3 zR`A6%x3VaB|7Si!ke7B>mRpgRd<;ivb`P)wj6JUai~hG3u(#oZ z2MK`Pb#03hNgNXh_DC$KX7bQOv|P2=XeM?&@Bl##E45fa>~fN|-Cz;e%3XH>Vg)0j zwo4Eepxs6gfm|n7+lsK!3|j#Vw96n8vpp_9xFmp)q1`}Gqd0&CL#xhXNCH^Ejc?U3 zF<7Xv)kXsAg4gZP@S5Pdrq%WSaGl&$NSbnBn)AjpzQoR+<#}1f_07FoRjlR}H#A%n z?9MBW{&U-DFwa@p$~jh5PNUN)NuG1V<|Z+~K!YSvcq~*n0odMVyp?mTX>CUuEhY+Y zm}veIaIJBo;n79)_5v)4;gW_&7u4Ga5Q}hG!#5@xy}%#1Khf~|iG~N82QUy!@E>G^wtzskJ;bp+oLJmfv0Blw!& zVZmzzEy0%se-~Wu`EJ1@f@2avR&Zxt+Nr$aW(g|_?#K&!w5Yhnd%}nF!XC*>-V2Zw zd@w8Q(X`-w2%9K;SEBHdSi_Iu#vjj1dn7BkqtSSx=v1uXUG8CpZ%P!MN)&y`#fNW5 z6g?a(x(CrsGFe=hYY*a+&Mc!Yq-|_s;1;$B6w?~alwlP zZ`1!?f7b;!$u&6mJO1r*4HI&c-6Gd4A@?3}T&~$*dY0#<1;@9y83Sxq?8^#n+t_fj zd%R#zT5xNcvI`(h*_9RC)@VM_U^&+Cc%$)+4JKK^ZDq+`fJo6e*6?_&=m5Z?7{waC tGgh?!e;yItJXW~YctWhsetupUi(this); + this->setWindowTitle(caption); + ui->pubText->setPlainText(pub); + ui->privText->setText("mydestination=" + priv); + ui->b32Line->setText(b32); + ui->label->setText(ui->label->text() + "\n" + configFileName); + + QObject::connect(ui->privButton, SIGNAL(clicked()), + ui->privText, SLOT(selectAll())); + QObject::connect(ui->privButton, SIGNAL(clicked()), + ui->privText, SLOT(copy())); + + QObject::connect(ui->pubButton, SIGNAL(clicked()), + ui->pubText, SLOT(selectAll())); + QObject::connect(ui->pubButton, SIGNAL(clicked()), + ui->pubText, SLOT(copy())); + + QObject::connect(ui->b32Button, SIGNAL(clicked()), + ui->b32Line, SLOT(selectAll())); + QObject::connect(ui->b32Button, SIGNAL(clicked()), + ui->b32Line, SLOT(copy())); +} + +ShowI2PAddresses::~ShowI2PAddresses() +{ + delete ui; +} diff --git a/src/qt/showi2paddresses.h b/src/qt/showi2paddresses.h new file mode 100644 index 00000000..bcd21a10 --- /dev/null +++ b/src/qt/showi2paddresses.h @@ -0,0 +1,22 @@ +#ifndef SHOWI2PADDRESSES_H +#define SHOWI2PADDRESSES_H + +#include + +namespace Ui { +class ShowI2PAddresses; +} + +class ShowI2PAddresses : public QDialog +{ + Q_OBJECT + +public: + explicit ShowI2PAddresses(const QString& caption, const QString& pub, const QString& priv, const QString& b32, const QString& configFileName, QWidget *parent = 0); + ~ShowI2PAddresses(); + +private: + Ui::ShowI2PAddresses *ui; +}; + +#endif // SHOWI2PADDRESSES_H diff --git a/src/serialize.h b/src/serialize.h index a11afd5b..0d4b093a 100644 --- a/src/serialize.h +++ b/src/serialize.h @@ -46,7 +46,7 @@ inline T* NCONST_PTR(const T* val) return const_cast(val); } -/** +/** * Get begin pointer of vector (non-const version). * @note These functions avoid the undefined case of indexing into an empty * vector, as well as that of indexing after the end of the vector. @@ -92,6 +92,9 @@ enum // modifiers SER_SKIPSIG = (1 << 16), SER_BLOCKHEADERONLY = (1 << 17), +#ifdef USE_NATIVE_I2P + SER_IPADDRONLY = (1 << 18), +#endif }; #define IMPLEMENT_SERIALIZE(statements) \ @@ -136,11 +139,11 @@ enum #define READWRITES(obj) (::SerReadWrite(s, (obj), nType, nVersion, ser_action)) -/** +/** * Implement three methods for serializable objects. These are actually wrappers over * "SerializationOp" template, which implements the body of each class' serialization * code. Adding "ADD_SERIALIZE_METHODS" in the body of the class causes these wrappers to be - * added as members. + * added as members. */ #define ADD_SERIALIZE_METHODS \ size_t GetSerializeSize(int nType, int nVersion) const { \ diff --git a/src/ui_interface.h b/src/ui_interface.h index e6e61980..5e5ac1eb 100644 --- a/src/ui_interface.h +++ b/src/ui_interface.h @@ -96,6 +96,11 @@ class CClientUIInterface * @note called with lock cs_mapAlerts held. */ boost::signals2::signal NotifyAlertChanged; +#ifdef USE_NATIVE_I2P + boost::signals2::signal ThreadSafeShowGeneratedI2PAddress; + + boost::signals2::signal NotifyNumI2PConnectionsChanged; +#endif }; extern CClientUIInterface uiInterface; diff --git a/src/util.cpp b/src/util.cpp index 6c777ce7..f530c6c9 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -1295,6 +1295,13 @@ string FormatFullVersion() return CLIENT_BUILD; } +#ifdef USE_NATIVE_I2P +std::string FormatI2PNativeFullVersion() +{ + return; +} +#endif + // Format the subversion field according to BIP 14 spec (https://en.bitcoin.it/wiki/BIP_0014) std::string FormatSubVersion(const std::string& name, int nClientVersion, const std::vector& comments) { diff --git a/src/util.h b/src/util.h index 0999c807..f862c012 100644 --- a/src/util.h +++ b/src/util.h @@ -241,7 +241,9 @@ std::string FormatSubVersion(const std::string& name, int nClientVersion, const void AddTimeData(const CNetAddr& ip, int64_t nTime); void runCommand(std::string strCommand); - +#ifdef USE_NATIVE_I2P +std::string FormatI2PNativeFullVersion(); +#endif diff --git a/src/version.cpp b/src/version.cpp index ae2d5f2e..366713c6 100644 --- a/src/version.cpp +++ b/src/version.cpp @@ -33,7 +33,7 @@ const std::string CLIENT_NAME("Satoshi"); # include "build.h" #endif -// git will put "#define GIT_ARCHIVE 1" on the next line inside archives. +// git will put "#define GIT_ARCHIVE 1" on the next line inside archives. #define GIT_ARCHIVE 0 #ifdef GIT_ARCHIVE # define GIT_COMMIT_ID "" From 555adee539c4fe99e86dd41f37cc275c45ef7b82 Mon Sep 17 00:00:00 2001 From: carsenk Date: Fri, 21 Jun 2019 22:03:39 -0600 Subject: [PATCH 02/26] FS Protocol Update and Renamings --- src/fortuna.cpp | 2 +- src/init.cpp | 2 +- src/miner.cpp | 2 +- src/version.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/fortuna.cpp b/src/fortuna.cpp index a66f2ee1..5c12ec46 100644 --- a/src/fortuna.cpp +++ b/src/fortuna.cpp @@ -40,7 +40,7 @@ CActiveFortunastake activeFortunastake; int RequestedFortunaStakeList = 0; //MIN_MN_PROTO_VERSION -int MIN_MN_PROTO_VERSION = 31000; +int MIN_MN_PROTO_VERSION = 31005; // Since block 1.5m it is 31005 /* *** BEGIN FORTUNA MAGIC ********** Copyright 2014, Darkcoin Developers diff --git a/src/init.cpp b/src/init.cpp index e21a807e..0337487d 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -489,7 +489,7 @@ bool AppInit2() // Fee-per-kilobyte amount considered the same as "free" // Be careful setting this: if you set it to zero then // a transaction spammer can cheaply fill blocks using - // 1-satoshi-fee transactions. It should be set above the real + // 1-denarii-fee transactions. It should be set above the real // cost to you of processing a transaction. if (mapArgs.count("-mintxfee")) ParseMoney(mapArgs["-mintxfee"], nMinTxFee); diff --git a/src/miner.cpp b/src/miner.cpp index 3727ea9a..d0e20cff 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -193,7 +193,7 @@ CBlock* CreateNewBlock(CWallet* pwallet, bool fProofOfStake, int64_t* pFees) // Fee-per-kilobyte amount considered the same as "free" // Be careful setting this: if you set it to zero then // a transaction spammer can cheaply fill blocks using - // 1-satoshi-fee transactions. It should be set above the real + // 1-denarii-fee transactions. It should be set above the real // cost to you of processing a transaction. int64_t nMinTxFee = MIN_TX_FEE; if (mapArgs.count("-mintxfee")) diff --git a/src/version.cpp b/src/version.cpp index ae2d5f2e..3f2c0c09 100644 --- a/src/version.cpp +++ b/src/version.cpp @@ -8,7 +8,7 @@ // Name of client reported in the 'version' message. Report the same name // for both bitcoind and bitcoin-qt, to make it harder for attackers to // target servers or GUI users specifically. -const std::string CLIENT_NAME("Satoshi"); +const std::string CLIENT_NAME("Denarii"); // Client version number #define CLIENT_VERSION_SUFFIX "" From 5d5d9777782dd863ced7a0d5068b8e1f5a96f113 Mon Sep 17 00:00:00 2001 From: carsenk Date: Mon, 29 Jul 2019 12:49:48 -0600 Subject: [PATCH 03/26] Resolve Out of Sync FS Payments & dFPS cleanup --- src/bitcoinrpc.cpp | 9 ++++----- src/bitcoinrpc.h | 1 - src/fortunastake.h | 4 ++-- src/main.cpp | 8 ++++---- src/rpcblockchain.cpp | 39 --------------------------------------- src/spork.h | 4 ++-- 6 files changed, 12 insertions(+), 53 deletions(-) diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp index e107047b..fbbf2367 100644 --- a/src/bitcoinrpc.cpp +++ b/src/bitcoinrpc.cpp @@ -301,7 +301,7 @@ static const CRPCCommand vRPCCommands[] = { "addredeemscript", &addredeemscript, false, false }, { "getrawmempool", &getrawmempool, true, false }, { "getblock", &getblock, false, false }, - { "getblockheader", &getblockheader, false, false }, + { "getblockheader", &getblockheader, false, false }, { "getblock_old", &getblock_old, false, false }, { "getblockbynumber", &getblockbynumber, false, false }, { "getblockhash", &getblockhash, false, false }, @@ -359,7 +359,6 @@ static const CRPCCommand vRPCCommands[] = /* Fortunastake features */ { "getpoolinfo", &getpoolinfo, true, false}, - { "spork", &spork, true, false}, { "masternode", &masternode, true, false}, { "fortunastake", &fortunastake, true, false}, @@ -1314,7 +1313,7 @@ Array RPCConvertValues(const std::string &strMethod, const std::vector 1) ConvertTo(params[1]); if (strMethod == "getbalance" && n > 2) ConvertTo(params[2]); if (strMethod == "getblock" && n > 1) ConvertTo(params[1]); - if (strMethod == "getblockheader" && n > 1) ConvertTo(params[1]); + if (strMethod == "getblockheader" && n > 1) ConvertTo(params[1]); if (strMethod == "getblock_old" && n > 1) ConvertTo(params[1]); if (strMethod == "getblockbynumber" && n > 0) ConvertTo(params[0]); if (strMethod == "getblockbynumber" && n > 1) ConvertTo(params[1]); @@ -1365,8 +1364,8 @@ Array RPCConvertValues(const std::string &strMethod, const std::vector 2) ConvertTo(params[2]); if (strMethod == "sendanontod" && n > 1) ConvertTo(params[1]); if (strMethod == "sendanontod" && n > 2) ConvertTo(params[2]); - if (strMethod == "estimateanonfee" && n > 0) ConvertTo(params[0]); - if (strMethod == "estimateanonfee" && n > 1) ConvertTo(params[1]); + if (strMethod == "estimateanonfee" && n > 0) ConvertTo(params[0]); + if (strMethod == "estimateanonfee" && n > 1) ConvertTo(params[1]); if (strMethod == "getpoolinfo" && n > 0) ConvertTo(params[0]); diff --git a/src/bitcoinrpc.h b/src/bitcoinrpc.h index d469bda3..7a2f4a5d 100644 --- a/src/bitcoinrpc.h +++ b/src/bitcoinrpc.h @@ -251,7 +251,6 @@ extern json_spirit::Value reloadanondata(const json_spirit::Array& params, bool extern json_spirit::Value txnreport(const json_spirit::Array& params, bool fHelp); //rpcfortuna.cpp -extern json_spirit::Value spork(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value getpoolinfo(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value masternode(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value fortunastake(const json_spirit::Array& params, bool fHelp); diff --git a/src/fortunastake.h b/src/fortunastake.h index b67e90b0..b9437ca2 100644 --- a/src/fortunastake.h +++ b/src/fortunastake.h @@ -342,8 +342,8 @@ class CFortunastakePayments public: CFortunastakePayments() { - strMainPubKey = "04af2b6c63d5e5937266a4ce630ab6ced73a0f6a5ff5611ef9b5cfc4f9e264e4a8a4840ab4da4d3ded243ef9f80f114d335dad9a87a50431004b35c01b2c68ea49"; - strTestPubKey = "0406d6c9580d20c4daaacbade0f5bbe4448c511c5860f6dc27a1bf2a8c043b2ad27f3831f8e24750488f0c715100cc5a5811ffd578029f3af62633d9e1c51be384"; + strMainPubKey = ""; + strTestPubKey = ""; enabled = false; } diff --git a/src/main.cpp b/src/main.cpp index 7a17b677..25b4b5c9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2641,12 +2641,12 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex, bool fJustCheck) if (!fIsInitialDownload) { if (!CheckFSPayment(pindex, vtx[1].vout[i].nValue, mn)) // if MN is being paid and it's bottom 50% ranked, don't let it be paid. { - if (pindexBest->nHeight >= MN_ENFORCEMENT_ACTIVE_HEIGHT) { - return error("CheckBlock-POS() : Out-of-cycle fortunastake payment detected, rejecting block."); + if (pindexBest->nHeight >= MN_ENFORCEMENT_ACTIVE_HEIGHT) { //Update PoS FS Payments to not go out of sync + if (fDebug) printf("CheckBlock-POS() : This payment has been determined as legitimate, and will be allowed."); } else { - if (fDebug) printf("WARNING: This fortunastake payment is too aggressive and will not be accepted after block %d\n", MN_ENFORCEMENT_ACTIVE_HEIGHT); + if (fDebug) printf("CheckBlock-POS(): This fortunastake payment is too aggressive and will be accepted after block %d\n", MN_ENFORCEMENT_ACTIVE_HEIGHT); } - break; + //break; } else { if (fDebug) printf("CheckBlock-POS() : Payment meets rate requirement: payee has earnt %s against average %s\n",FormatMoney(mn.payValue).c_str(),FormatMoney(nAverageFSIncome).c_str()); } diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp index 2e35bc15..b669b341 100644 --- a/src/rpcblockchain.cpp +++ b/src/rpcblockchain.cpp @@ -541,45 +541,6 @@ Value getcheckpoint(const Array& params, bool fHelp) return result; } -/* - Used for updating/reading spork settings on the network -*/ -Value spork(const Array& params, bool fHelp) -{ - if(params.size() == 1 && params[0].get_str() == "show"){ - std::map::iterator it = mapSporksActive.begin(); - - Object ret; - while(it != mapSporksActive.end()) { - ret.push_back(Pair(sporkManager.GetSporkNameByID(it->second.nSporkID), it->second.nValue)); - it++; - } - return ret; - } else if (params.size() == 2){ - int nSporkID = sporkManager.GetSporkIDByName(params[0].get_str()); - if(nSporkID == -1){ - return "Invalid spork name"; - } - - // SPORK VALUE - int64_t nValue = params[1].get_int(); - - //broadcast new spork - if(sporkManager.UpdateSpork(nSporkID, nValue)){ - return "success"; - } else { - return "failure"; - } - - } - - throw runtime_error( - "spork []\n" - " is the corresponding spork name, or 'show' to show all current spork settings" - " is a epoch datetime to enable or disable spork" - + HelpRequiringPassphrase()); -} - Value gettxout(const Array& params, bool fHelp) { if (fHelp || params.size() < 2 || params.size() > 3) diff --git a/src/spork.h b/src/spork.h index 70d4647b..59120810 100644 --- a/src/spork.h +++ b/src/spork.h @@ -95,8 +95,8 @@ class CSporkManager public: CSporkManager() { - strMainPubKey = "0417d4b095e451d08bd83111d9ddc7f648af93d8f72e4391940bfa97bde644c0504e1f04a9e7e89be7e1c54c8995f8905be76f50d43fb4a31a7abba5e5291fbc63"; - strTestPubKey = "0417d4b095e451d08bd83111d9ddc7f648af93d8f72e4391940bfa97bde644c0504e1f04a9e7e89be7e1c54c8995f8905be76f50d43fb4a31a7abba5e5291fbc63"; + strMainPubKey = "invalid"; //Sporks deprecated for dFPS Decentralized Denarius Fortuna Stake system + strTestPubKey = "invalid"; } std::string GetSporkNameByID(int id); From 3bdf06dd6c5122b66d467c6348a0fae2391bedbf Mon Sep 17 00:00:00 2001 From: carsenk Date: Mon, 29 Jul 2019 13:20:30 -0600 Subject: [PATCH 04/26] Version bump v3.3.9.2 --- denarius-qt.pro | 2 +- src/clientversion.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/denarius-qt.pro b/denarius-qt.pro index 8a94108d..20162d1e 100644 --- a/denarius-qt.pro +++ b/denarius-qt.pro @@ -1,6 +1,6 @@ TEMPLATE = app TARGET = Denarius -VERSION = 3.3.9.1 +VERSION = 3.3.9.2 INCLUDEPATH += src src/json src/qt src/qt/plugins/mrichtexteditor DEFINES += QT_GUI BOOST_THREAD_USE_LIB BOOST_SPIRIT_THREADSAFE CONFIG += no_include_pwd diff --git a/src/clientversion.h b/src/clientversion.h index 4cc32c11..b785d310 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -10,7 +10,7 @@ #define CLIENT_VERSION_MAJOR 3 #define CLIENT_VERSION_MINOR 3 #define CLIENT_VERSION_REVISION 9 -#define CLIENT_VERSION_BUILD 1 +#define CLIENT_VERSION_BUILD 2 // Converts the parameter X to a string after macro replacement on X has been performed. // Don't merge these into one macro! From eae8cc4b239565677f652607c0c0cd28f724eaf6 Mon Sep 17 00:00:00 2001 From: carsenk Date: Mon, 29 Jul 2019 22:56:05 -0600 Subject: [PATCH 05/26] LastSeen Update & FS Updates --- src/fortunastake.cpp | 3 ++- src/fortunastake.h | 2 +- src/main.cpp | 7 +++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/fortunastake.cpp b/src/fortunastake.cpp index add0ef40..7eb07205 100644 --- a/src/fortunastake.cpp +++ b/src/fortunastake.cpp @@ -139,7 +139,8 @@ void ProcessMessageFortunastake(CNode* pfrom, std::string& strCommand, CDataStre // mn.pubkey = pubkey, IsVinAssociatedWithPubkey is validated once below, // after that they just need to match if(count == -1 && mn.pubkey == pubkey && !mn.UpdatedWithin(FORTUNASTAKE_MIN_DSEE_SECONDS)){ - mn.UpdateLastSeen(); // update last seen without the sigTime since it's a new entry + mn.UpdateLastSeen(sigTime); // Updated UpdateLastSeen with sigTime + //mn.UpdateLastSeen(); // update last seen without the sigTime since it's a new entry if(mn.now < sigTime){ //take the newest entry if (fDebugFS & fDebugNet) printf("dsee - Got updated entry for %s\n", addr.ToString().c_str()); diff --git a/src/fortunastake.h b/src/fortunastake.h index b9437ca2..c8a6d76b 100644 --- a/src/fortunastake.h +++ b/src/fortunastake.h @@ -203,7 +203,7 @@ class CFortunaStake void UpdateLastSeen(int64_t override=0) { - if (override == 0) { + if (override == 0 || override > GetAdjustedTime()) { lastTimeSeen = GetAdjustedTime(); } else { lastTimeSeen = override; diff --git a/src/main.cpp b/src/main.cpp index 25b4b5c9..4bc6fc63 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2642,11 +2642,11 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex, bool fJustCheck) if (!CheckFSPayment(pindex, vtx[1].vout[i].nValue, mn)) // if MN is being paid and it's bottom 50% ranked, don't let it be paid. { if (pindexBest->nHeight >= MN_ENFORCEMENT_ACTIVE_HEIGHT) { //Update PoS FS Payments to not go out of sync - if (fDebug) printf("CheckBlock-POS() : This payment has been determined as legitimate, and will be allowed."); + return error("CheckBlock-POS() : Out-of-cycle fortunastake payment detected, rejecting block."); } else { if (fDebug) printf("CheckBlock-POS(): This fortunastake payment is too aggressive and will be accepted after block %d\n", MN_ENFORCEMENT_ACTIVE_HEIGHT); } - //break; + //break; No more breaking out of the checks } else { if (fDebug) printf("CheckBlock-POS() : Payment meets rate requirement: payee has earnt %s against average %s\n",FormatMoney(mn.payValue).c_str(),FormatMoney(nAverageFSIncome).c_str()); } @@ -2769,8 +2769,7 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex, bool fJustCheck) if (pindexBest->nHeight >= MN_ENFORCEMENT_ACTIVE_HEIGHT) { return error("CheckBlock-POW() : Fortunastake overpayment detected, rejecting block. rank:%d value:%s avg:%s payRate:%s",mn.nRank,FormatMoney(mn.payValue).c_str(),FormatMoney(nAverageFSIncome).c_str(),FormatMoney(mn.payRate).c_str()); - } else - { + } else { if (fDebug) printf("WARNING: This fortunastake payment is too aggressive and will not be accepted after block %d\n", MN_ENFORCEMENT_ACTIVE_HEIGHT); } } else { From 580e054d284403655cd8634efe307d09a6d59d0a Mon Sep 17 00:00:00 2001 From: carsenk Date: Wed, 31 Jul 2019 11:40:15 -0600 Subject: [PATCH 06/26] Update makefile.arm for boost chrono --- src/makefile.arm | 1 + 1 file changed, 1 insertion(+) diff --git a/src/makefile.arm b/src/makefile.arm index a0ddc544..e1925b78 100644 --- a/src/makefile.arm +++ b/src/makefile.arm @@ -32,6 +32,7 @@ endif LIBS += \ -Wl,-B$(LMODE) \ -l boost_system$(BOOST_LIB_SUFFIX) \ + -l boost_chrono$(BOOST_LIB_SUFFIX) \ -l boost_filesystem$(BOOST_LIB_SUFFIX) \ -l boost_program_options$(BOOST_LIB_SUFFIX) \ -l boost_thread$(BOOST_LIB_SUFFIX) \ From a8438e29cd4eed075b8dc3df514851258d7e680a Mon Sep 17 00:00:00 2001 From: carsenk Date: Tue, 6 Aug 2019 15:14:26 -0600 Subject: [PATCH 07/26] Full Native I2P Integration and other updates --- .gitignore | 1 + denarius-qt.pro | 2 +- src/activefortunastake.cpp | 2 +- src/clientversion.h | 2 +- src/init.cpp | 53 ++++--- src/main.cpp | 127 +--------------- src/net.cpp | 79 +++++----- src/net.h | 19 ++- src/netbase.cpp | 93 +++++++----- src/qt/bitcoingui.cpp | 106 ++++++++----- src/qt/bitcoingui.h | 1 + src/qt/clientmodel.cpp | 5 + src/qt/clientmodel.h | 5 +- src/qt/forms/i2poptionswidget.ui | 27 ++-- src/qt/forms/rpcconsole.ui | 245 ++++++++++++++++-------------- src/qt/forms/showi2paddresses.ui | 4 +- src/qt/i2poptionswidget.cpp | 2 +- src/qt/optionsdialog.cpp | 10 +- src/qt/res/icons/i2plogo_0_16.png | Bin 3293 -> 2797 bytes src/qt/res/icons/i2plogo_1_16.png | Bin 3014 -> 3242 bytes src/qt/res/icons/i2plogo_2_16.png | Bin 2807 -> 3411 bytes src/qt/res/icons/i2plogo_3_16.png | Bin 2709 -> 3558 bytes src/qt/res/icons/i2plogo_4_16.png | Bin 2271 -> 3598 bytes src/qt/rpcconsole.cpp | 1 + src/rpcwallet.cpp | 3 +- src/util.cpp | 6 +- src/util.h | 2 + src/wallet.cpp | 115 -------------- 28 files changed, 391 insertions(+), 519 deletions(-) diff --git a/.gitignore b/.gitignore index f20b0b92..a7ba5cc6 100644 --- a/.gitignore +++ b/.gitignore @@ -42,4 +42,5 @@ dist *.app *.dmg .idea +*.vscode diff --git a/denarius-qt.pro b/denarius-qt.pro index 928b5f2f..ceba75b9 100644 --- a/denarius-qt.pro +++ b/denarius-qt.pro @@ -1,6 +1,6 @@ TEMPLATE = app TARGET = Denarius -VERSION = 3.3.9.2 +VERSION = 3.3.9.3 INCLUDEPATH += src src/json src/qt src/qt/plugins/mrichtexteditor DEFINES += QT_GUI BOOST_THREAD_USE_LIB BOOST_SPIRIT_THREADSAFE CONFIG += no_include_pwd diff --git a/src/activefortunastake.cpp b/src/activefortunastake.cpp index 7868bed4..758f7630 100644 --- a/src/activefortunastake.cpp +++ b/src/activefortunastake.cpp @@ -484,7 +484,7 @@ vector CActiveFortunastake::SelectCoinsFortunastake(bool fSelectUnlocke vector confLockedCoins; // Temporary unlock MN coins from fortunastake.conf - if(fSelectUnlocked && GetBoolArg("-mnconflock", true) || fSelectUnlocked && GetBoolArg("-fsconflock", true)) { + if(fSelectUnlocked && GetBoolArg("-fsconflock", true)) { uint256 mnTxHash; BOOST_FOREACH(CFortunastakeConfig::CFortunastakeEntry mne, fortunastakeConfig.getEntries()) { mnTxHash.SetHex(mne.getTxHash()); diff --git a/src/clientversion.h b/src/clientversion.h index d715bb2d..0776ce47 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -10,7 +10,7 @@ #define CLIENT_VERSION_MAJOR 3 #define CLIENT_VERSION_MINOR 3 #define CLIENT_VERSION_REVISION 9 -#define CLIENT_VERSION_BUILD 2 +#define CLIENT_VERSION_BUILD 3 #ifdef USE_NATIVE_I2P #define I2P_NATIVE_VERSION_MAJOR 0 diff --git a/src/init.cpp b/src/init.cpp index c80a88b9..d1027e60 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -394,8 +394,7 @@ std::string HelpMessage() "\n" + _("Fortunastake options:") + "\n" + " -fortunastake= " + _("Enable the client to act as a fortunastake (0-1, default: 0)") + "\n" + - " -mnconf= " + _("Specify fortunastake configuration file (default: fortunastake.conf)") + "\n" + - " -mnconflock= " + _("Lock fortunastakes from fortunastake configuration file (default: 1)") + + " -fsconf= " + _("Specify fortunastake configuration file (default: fortunastake.conf)") + "\n" + " -fsconflock= " + _("Lock fortunastakes from fortunastake configuration file (default: 1)") + " -fortunastakeprivkey= " + _("Set the fortunastake private key") + "\n" + " -fortunastakeaddr= " + _("Set external address:port to get to this fortunastake (example: address:port)") + "\n" + @@ -479,19 +478,22 @@ bool AppInit2() // ********************************************************* Step 2: parameter interactions - #ifdef USE_NATIVE_I2P - if (GetBoolArg(I2P_SAM_GENERATE_DESTINATION_PARAM, false)) - { - const SAM::FullDestination generatedDest = I2PSession::Instance().destGenerate(); - uiInterface.ThreadSafeShowGeneratedI2PAddress( - "Generated I2P address", - generatedDest.pub, - generatedDest.priv, - I2PSession::GenerateB32AddressFromDestination(generatedDest.pub), - GetConfigFile().string()); - return false; - } - #endif +#ifdef USE_NATIVE_I2P + if(fNativeI2P) + { + if (GetBoolArg(I2P_SAM_GENERATE_DESTINATION_PARAM, false)) + { + const SAM::FullDestination generatedDest = I2PSession::Instance().destGenerate(); + uiInterface.ThreadSafeShowGeneratedI2PAddress( + "Generated I2P address", + generatedDest.pub, + generatedDest.priv, + I2PSession::GenerateB32AddressFromDestination(generatedDest.pub), + GetConfigFile().string()); + return false; + } + } +#endif nNodeLifespan = GetArg("-addrlifespan", 7); fUseFastIndex = GetBoolArg("-fastindex", true); @@ -540,6 +542,8 @@ bool AppInit2() fTestNet = GetBoolArg("-testnet"); fNativeTor = GetBoolArg("-nativetor"); + fNativeI2P = GetBoolArg("-nativei2p"); + fFSLock = GetBoolArg("-fsconflock"); //if (fTestNet) @@ -708,13 +712,13 @@ bool AppInit2() CFortunaStake::minProtoVersion = GetArg("-fortunastakeminprotocol", MIN_MN_PROTO_VERSION); if (fDaemon) - fprintf(stdout, "Denarius server starting\n"); + fprintf(stdout, "Denarius (D) server starting\n"); int64_t nStart; // Anonymous Ring Signatures ~ D e n a r i u s - v3.0.0.0 if (initialiseRingSigs() != 0) - return InitError("initialiseRingSigs() failed."); + return InitError("initializeRingSigs() failed."); // ********************************************************* Step 5: verify database integrity @@ -851,7 +855,7 @@ bool AppInit2() }; // see Step 2: parameter interactions for more information about these - if(!fNativeTor) // Available if nativetor is disabled + if(!fNativeTor) // Available if nativetor and nativei2p are disabled { fNoListen = !GetBoolArg("-listen", true); fDiscover = GetBoolArg("-discover", true); @@ -885,8 +889,10 @@ bool AppInit2() if (!IsLimited(NET_IPV4)) fBound |= Bind(CService(inaddr_any, GetListenPort()), !fBound); #ifdef USE_NATIVE_I2P - if (!IsLimited(NET_NATIVE_I2P)) - fBound |= BindNativeI2P(); + if(fNativeI2P) { + if (!IsLimited(NET_NATIVE_I2P)) + fBound |= BindNativeI2P(); + } #endif }; if (!fBound) @@ -1206,7 +1212,7 @@ bool AppInit2() } if (pwalletMain) { - if(GetBoolArg("-fsconflock", true) & GetBoolArg("-mnconflock", true)) { + if(GetBoolArg("-fsconflock", true)) { LOCK(pwalletMain->cs_wallet); printf("Locking Fortunastakes:\n"); uint256 mnTxHash; @@ -1283,6 +1289,11 @@ bool AppInit2() else printf("Native Tor Onion Relay Disabled, Using Regular Peers..."); + if(fNativeI2P) + printf("Native I2P Node Enabled"); + else + printf("Native I2P Disabled, Using Regular Peers..."); + if (fDebug) printf("Debugging is Enabled."); else diff --git a/src/main.cpp b/src/main.cpp index 4bc6fc63..a8b72769 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -67,7 +67,7 @@ bool fAddrIndex = false; CMedianFilter cPeerBlockCounts(5, 0); // Amount of blocks that other nodes claim to have std::map mapAnonOutputStats; -//map mapAnonOutputStats; // display only, not 100% accurate, height could become inaccurate due to undos + map mapOrphanBlocks; multimap mapOrphanBlocksByPrev; set > setStakeSeenOrphan; @@ -208,13 +208,6 @@ void static UpdatedTransaction(const uint256& hashTx) BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) pwallet->UpdatedTransaction(hashTx); } -/* -// dump all wallets -void static PrintWallets(const CBlock& block) -{ - BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) - pwallet->PrintWallet(block); -} */ // notify wallets about an incoming inventory (for request counts) void static Inventory(const uint256& hash) @@ -257,11 +250,6 @@ bool Finalise() bool AbortNode(const std::string &strMessage, const std::string &userMessage) { strMiscWarning = strMessage; printf("*** %s\n", strMessage.c_str()); - /* - uiInterface.ThreadSafeMessageBox( - userMessage.empty() ? _("Error: A fatal internal error occured, see debug.log for details") : userMessage, - "", CClientUIInterface::MSG_ERROR); - */ StartShutdown(); return false; } @@ -338,12 +326,6 @@ unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans) return nEvicted; } - - - - - - ////////////////////////////////////////////////////////////////////////////// // // CTransaction and CTxIndex @@ -377,54 +359,6 @@ bool CTransaction::ReadFromDisk(COutPoint prevout) return ReadFromDisk(txdb, prevout, txindex); } -// bool CTransaction::IsStandard() const -// { -// if (nVersion > CTransaction::CURRENT_VERSION) -// return false; - -// BOOST_FOREACH(const CTxIn& txin, vin) -// { -// // Biggest 'standard' txin is a 3-signature 3-of-3 CHECKMULTISIG -// // pay-to-script-hash, which is 3 ~80-byte signatures, 3 -// // ~65-byte public keys, plus a few script ops. -// if (txin.scriptSig.size() > 500) -// return false; -// if (!txin.scriptSig.IsPushOnly()) -// return false; -// if (fEnforceCanonical && !txin.scriptSig.HasCanonicalPushes()) { -// return false; -// } -// } - -// unsigned int nDataOut = 0; -// unsigned int nTxnOut = 0; - -// txnouttype whichType; -// BOOST_FOREACH(const CTxOut& txout, vout) { -// if (!::IsStandard(txout.scriptPubKey, whichType)) -// return false; -// if (whichType == TX_NULL_DATA) -// { -// nDataOut++; -// } else -// { -// if (txout.nValue == 0) -// return false; -// nTxnOut++; -// } -// if (fEnforceCanonical && !txout.scriptPubKey.HasCanonicalPushes()) { -// return false; -// } -// } - -// // only one OP_RETURN txout per txn out is permitted -// if (nDataOut > nTxnOut) { -// return false; -// } - -// return true; -// } - bool IsStandardTx(const CTransaction& tx, string& reason) { if (tx.nVersion > CTransaction::CURRENT_VERSION && tx.nVersion != ANON_TXN_VERSION) { @@ -732,12 +666,6 @@ int CMerkleTx::SetMerkleBranch(const CBlock* pblock) return pindexBest->nHeight - pindex->nHeight + 1; } - - - - - - bool CTransaction::CheckTransaction() const { // Basic checks that don't depend on any context @@ -1372,7 +1300,6 @@ bool CMerkleTx::AcceptToMemoryPool() bool CWalletTx::AcceptWalletTransaction(CTxDB& txdb) { - { // Add previous supporting transactions first BOOST_FOREACH(CMerkleTx& tx, vtxPrev) @@ -1739,10 +1666,6 @@ void CBlock::UpdateTime(const CBlockIndex* pindexPrev) nTime = max(GetBlockTime(), GetAdjustedTime()); } - - - - // Requires cs_main. void Misbehaving(NodeId pnode, int howmuch) { @@ -1769,10 +1692,6 @@ void Misbehaving(NodeId pnode, int howmuch) } } - - - - bool CTransaction::DisconnectInputs(CTxDB& txdb) { // Relinquish previous transactions' spent pointers @@ -1808,7 +1727,6 @@ bool CTransaction::DisconnectInputs(CTxDB& txdb) return true; } - bool CTransaction::FetchInputs(CTxDB& txdb, const map& mapTestPool, bool fBlock, bool fMiner, MapPrevTx& inputsRet, bool& fInvalid) { @@ -2398,17 +2316,6 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex, bool fJustCheck) unsigned int flags = SCRIPT_VERIFY_NOCACHE; - /* // Currently don't need - if(V3(nTime)) - { - flags |= SCRIPT_VERIFY_NULLDUMMY | - SCRIPT_VERIFY_STRICTENC | - SCRIPT_VERIFY_ALLOW_EMPTY_SIG | - SCRIPT_VERIFY_FIX_HASHTYPE | - SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY; - } - */ - //// issue here: it doesn't know the version unsigned int nTxPos; if (fJustCheck) @@ -4145,13 +4052,6 @@ string GetWarnings(string strFor) return "error"; } - - - - - - - ////////////////////////////////////////////////////////////////////////////// // // Messages @@ -4234,14 +4134,6 @@ void static ProcessGetData(CNode* pfrom) { // Send stream from relay memory bool pushed = false; - /*{ - LOCK(cs_mapRelay); - map::iterator mi = mapRelay.find(inv); - if (mi != mapRelay.end()) { - pfrom->PushMessage(inv.GetCommand(), (*mi).second); - pushed = true; - } - }*/ if (!pushed && inv.type == MSG_TX) { if(mapFortunaBroadcastTxes.count(inv.hash)){ CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); @@ -4314,7 +4206,7 @@ void static ProcessGetData(CNode* pfrom) // The message start string is designed to be unlikely to occur in normal data. // The characters are rarely used upper ASCII, not valid as UTF-8, and produce // a large 4-byte int at any alignment. -unsigned char pchMessageStart[4] = { 0xfa, 0xf2, 0xef, 0xb4 }; +unsigned char pchMessageStart[4] = { 0xfa, 0xf2, 0xef, 0xb4 }; //Magic Number bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, int64_t nTimeReceived) { @@ -4354,19 +4246,10 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, printf("Partner %s using obsolete version %i; DISCONNECTING\n", pfrom->addr.ToString().c_str(), pfrom->nVersion); pfrom->fDisconnect = true; if (pfrom->fForTunaMaster) - printf("Masternode hosting node version was obsolete. This masternode should be removed from the list\n"); + printf("Masternode hosting node version is obsolete. This masternode should be removed from the list\n"); return false; } - /* - if (pfrom->nVersion < PROTO_VERSION) - { - // disconnect from peers older than this proto version - printf("partner %s using obsolete version %i; disconnecting\n", pfrom->addr.ToString().c_str(), pfrom->nVersion); - pfrom->fDisconnect = true; - return false; - }*/ - if (pfrom->nVersion == 10300) pfrom->nVersion = 300; if (!vRecv.empty()) @@ -5349,8 +5232,6 @@ bool SendMessages(CNode* pto, bool fSendTrickle) SecureMsgSendData(pto, fSendTrickle); } - - return true; } @@ -5360,4 +5241,4 @@ int64_t GetFortunastakePayment(int nHeight, int64_t blockValue) int64_t ret = static_cast(blockValue * 1/3); //33% return ret; -} +} \ No newline at end of file diff --git a/src/net.cpp b/src/net.cpp index 05f08326..cd878e65 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1,3 +1,4 @@ +// Copyright (c) 2019 Denarius developers // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2012 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying @@ -559,8 +560,10 @@ CNode* ConnectNode(CAddress addrConnect, const char *pszDest, bool forTunaMaster LOCK(cs_vNodes); vNodes.push_back(pnode); #ifdef USE_NATIVE_I2P - if (addrConnect.IsNativeI2P()) - ++nI2PNodeCount; + if (fNativeI2P) { + if (addrConnect.IsNativeI2P()) + ++nI2PNodeCount; + } #endif } @@ -730,11 +733,11 @@ bool CNode::ReceiveMsgBytes(const char *pch, unsigned int nBytes) // get current incomplete message, or create a new one if (vRecvMsg.empty() || vRecvMsg.back().complete()) -#ifdef USE_NATIVE_I2P + if (fNativeI2P) { vRecvMsg.push_back(CNetMessage(nRecvStreamType, nRecvVersion)); -#else + } else { vRecvMsg.push_back(CNetMessage(SER_NETWORK, nRecvVersion)); -#endif + } CNetMessage& msg = vRecvMsg.back(); @@ -960,8 +963,10 @@ void ThreadSocketHandler2(void* parg) pnode->Release(); vNodesDisconnected.push_back(pnode); #ifdef USE_NATIVE_I2P - if (pnode->addr.IsNativeI2P()) - --nI2PNodeCount; + if (fNativeI2P) { + if (pnode->addr.IsNativeI2P()) + --nI2PNodeCount; + } #endif } } @@ -1005,11 +1010,13 @@ void ThreadSocketHandler2(void* parg) uiInterface.NotifyNumConnectionsChanged(vNodes.size()); } #ifdef USE_NATIVE_I2P +if (fNativeI2P) { if (nPrevI2PNodeCount != nI2PNodeCount) { nPrevI2PNodeCount = nI2PNodeCount; uiInterface.NotifyNumI2PConnectionsChanged(nI2PNodeCount); } +} #endif @@ -1030,13 +1037,15 @@ void ThreadSocketHandler2(void* parg) bool have_fds = false; #ifdef USE_NATIVE_I2P - BOOST_FOREACH(SOCKET hI2PListenSocket, vhI2PListenSocket) { - if (hI2PListenSocket != INVALID_SOCKET) - { - FD_SET(hI2PListenSocket, &fdsetRecv); - hSocketMax = max(hSocketMax, hI2PListenSocket); - have_fds = true; - } + if (fNativeI2P) { + BOOST_FOREACH(SOCKET hI2PListenSocket, vhI2PListenSocket) { + if (hI2PListenSocket != INVALID_SOCKET) + { + FD_SET(hI2PListenSocket, &fdsetRecv); + hSocketMax = max(hSocketMax, hI2PListenSocket); + have_fds = true; + } + } } #endif @@ -1142,7 +1151,7 @@ void ThreadSocketHandler2(void* parg) // // Accept new I2P connections // - +if (fNativeI2P) { bool haveInvalids = false; for (std::vector::iterator it = vhI2PListenSocket.begin(); it != vhI2PListenSocket.end(); ++it) { @@ -1203,7 +1212,7 @@ void ThreadSocketHandler2(void* parg) BindListenNativeI2P(hI2PListenSocket); } } - +} #endif @@ -1820,12 +1829,14 @@ void ThreadOpenConnections2(void* parg) continue; // do not allow non-default ports, unless after 50 invalid addresses selected already -#ifdef USE_NATIVE_I2P - if (!addr.IsNativeI2P() && addr.GetPort() != GetDefaultPort() && nTries < 50) -#else - if (addr.GetPort() != GetDefaultPort() && nTries < 50) -#endif - continue; + + if (fNativeI2P) { + if (!addr.IsNativeI2P() && addr.GetPort() != GetDefaultPort() && nTries < 50) + continue; + } else { + if (addr.GetPort() != GetDefaultPort() && nTries < 50) + continue; + } addrConnect = addr; break; @@ -2424,7 +2435,7 @@ void StartNode(void* parg) // Start threads // - if(!fNativeTor) + if(!fNativeTor && !fNativeI2P) { if (!GetBoolArg("-dnsseed", true)) printf("DNS seeding disabled\n"); @@ -2479,6 +2490,7 @@ bool StopNode() { printf("StopNode()\n"); fShutdown = true; + //MapPort(false); mempool.AddTransactionsUpdated(1); int64_t nStart = GetTime(); if (semOutbound) @@ -2531,10 +2543,12 @@ class CNetCleanup if (closesocket(hListenSocket) == SOCKET_ERROR) printf("closesocket(hListenSocket) failed with error %d\n", WSAGetLastError()); #ifdef USE_NATIVE_I2P - BOOST_FOREACH(SOCKET& hI2PListenSocket, vhI2PListenSocket) - if (hI2PListenSocket != INVALID_SOCKET) - if (closesocket(hI2PListenSocket) == SOCKET_ERROR) - printf("closesocket(hI2PListenSocket) failed with error %d\n", WSAGetLastError()); + if (fNativeI2P) { + BOOST_FOREACH(SOCKET& hI2PListenSocket, vhI2PListenSocket) + if (hI2PListenSocket != INVALID_SOCKET) + if (closesocket(hI2PListenSocket) == SOCKET_ERROR) + printf("closesocket(hI2PListenSocket) failed with error %d\n", WSAGetLastError()); + } #endif #ifdef WIN32 // Shutdown Windows Sockets @@ -2629,17 +2643,6 @@ void RelayForTunaElectionEntry(const CTxIn vin, const CService addr, const std:: } } -/* -void RelayForTunaElectionEntry(const CTxIn vin, const CService addr, const std::vector vchSig, const int64 nNow, const CPubKey pubkey, const CPubKey pubkey2, const int count, const int current, const int64 lastUpdated) -{ - LOCK(cs_vNodes); - BOOST_FOREACH(CNode* pnode, vNodes) - { - pnode->PushMessage("dsee", vin, addr, vchSig, nNow, pubkey, pubkey2, count, current, lastUpdated); - } -} -*/ - void SendForTunaElectionEntry(const CTxIn vin, const CService addr, const std::vector vchSig, const int64_t nNow, const CPubKey pubkey, const CPubKey pubkey2, const int count, const int current, const int64_t lastUpdated, const int protocolVersion) { LOCK(cs_vNodes); diff --git a/src/net.h b/src/net.h index ab863388..c048d59a 100644 --- a/src/net.h +++ b/src/net.h @@ -367,6 +367,7 @@ class CNode , nRecvStreamType(SER_NETWORK | (((addrIn.nServices & NODE_I2P) || addrIn.IsNativeI2P()) ? 0 : SER_IPADDRONLY)) #endif { + // Native I2P Socket CNode structure #ifdef USE_NATIVE_I2P ssSend.SetType(nSendStreamType); #endif @@ -397,7 +398,7 @@ class CNode pindexLastGetBlocksBegin = 0; hashLastGetBlocksEnd = 0; nStartingHeight = -1; - fStartSync = false; + fStartSync = false; fGetAddr = false; nMisbehavior = 0; hashCheckpointKnown = 0; @@ -520,12 +521,16 @@ class CNode // Known checking here is only to save space from duplicates. // SendMessages will filter it again for knowns that were added // after addresses were pushed. - if (addr.IsValid() && !setAddrKnown.count(addr)) -#ifdef USE_NATIVE_I2P - // if receiver doesn't support i2p-address we don't send it - if ((this->nServices & NODE_I2P) || !addr.IsNativeI2P()) -#endif - vAddrToSend.push_back(addr); + if(fNativeI2P) { + if (addr.IsValid() && !setAddrKnown.count(addr)) { + // if receiver doesn't support i2p-address we don't send it + if ((this->nServices & NODE_I2P) || !addr.IsNativeI2P()) + vAddrToSend.push_back(addr); + } + } else { + if (addr.IsValid() && !setAddrKnown.count(addr)) + vAddrToSend.push_back(addr); + } } diff --git a/src/netbase.cpp b/src/netbase.cpp index af919b3a..36de012a 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -505,7 +505,6 @@ bool SetSocketOptions(SOCKET& hSocket) } return true; } - #endif bool ConnectSocket(const CService &addrDest, SOCKET& hSocketRet, int nTimeout, bool *outProxyConnectionFailed) @@ -513,6 +512,7 @@ bool ConnectSocket(const CService &addrDest, SOCKET& hSocketRet, int nTimeout, b proxyType proxy; #ifdef USE_NATIVE_I2P +if (fNativeI2P) { if (addrDest.IsNativeI2P()) { SOCKET streamSocket = I2PSession::Instance().connect(addrDest.GetI2PDestination(), false/*, streamSocket*/); @@ -523,6 +523,7 @@ bool ConnectSocket(const CService &addrDest, SOCKET& hSocketRet, int nTimeout, b } return false; } +} #endif if (outProxyConnectionFailed) @@ -602,7 +603,9 @@ void CNetAddr::Init() { memset(ip, 0, 16); #ifdef USE_NATIVE_I2P +if (fNativeI2P) { memset(i2pDest, 0, NATIVE_I2P_DESTINATION_SIZE); +} #endif } @@ -610,7 +613,9 @@ void CNetAddr::SetIP(const CNetAddr& ipIn) { memcpy(ip, ipIn.ip, sizeof(ip)); #ifdef USE_NATIVE_I2P +if (fNativeI2P) { memcpy(i2pDest, ipIn.i2pDest, NATIVE_I2P_DESTINATION_SIZE); +} #endif } @@ -620,6 +625,7 @@ static const unsigned char pchGarliCat[] = {0xFD,0x60,0xDB,0x4D,0xDD,0xB5}; bool CNetAddr::SetSpecial(const std::string &strName) { #ifdef USE_NATIVE_I2P +if (fNativeI2P) { const bool isBase32Addr = (strName.size() == NATIVE_I2P_B32ADDR_SIZE) && (strName.substr(strName.size() - 8, 8) == ".b32.i2p"); const std::string addr = isBase32Addr ? I2PSession::Instance().namingLookup(strName) : strName; @@ -627,6 +633,7 @@ bool CNetAddr::SetSpecial(const std::string &strName) memcpy(i2pDest, addr.c_str(), NATIVE_I2P_DESTINATION_SIZE); return true; } +} #endif if (strName.size()>6 && strName.substr(strName.size() - 6, 6) == ".onion") { std::vector vchAddr = DecodeBase32(strName.substr(0, strName.size() - 6).c_str()); @@ -659,7 +666,9 @@ CNetAddr::CNetAddr(const struct in_addr& ipv4Addr) memcpy(ip, pchIPv4, 12); memcpy(ip+12, &ipv4Addr, 4); #ifdef USE_NATIVE_I2P +if (fNativeI2P) { memset(i2pDest, 0, NATIVE_I2P_DESTINATION_SIZE); +} #endif } @@ -667,7 +676,9 @@ CNetAddr::CNetAddr(const struct in6_addr& ipv6Addr) { memcpy(ip, &ipv6Addr, 16); #ifdef USE_NATIVE_I2P +if (fNativeI2P) { memset(i2pDest, 0, NATIVE_I2P_DESTINATION_SIZE); +} #endif } @@ -699,11 +710,11 @@ bool CNetAddr::IsIPv4() const bool CNetAddr::IsIPv6() const { -#ifdef USE_NATIVE_I2P +if (fNativeI2P) { return (!IsIPv4() && !IsTor() && !IsNativeI2P()); -#else +} else { return (!IsIPv4() && !IsTor() && !IsI2P()); -#endif +} } bool CNetAddr::IsRFC1918() const @@ -789,8 +800,10 @@ bool CNetAddr::IsLocal() const { #ifdef USE_NATIVE_I2P - if (IsNativeI2P()) - return false; + if (fNativeI2P) { + if (IsNativeI2P()) + return false; + } #endif // IPv4 loopback if (IsIPv4() && (GetByte(3) == 127 || GetByte(3) == 0)) @@ -813,8 +826,10 @@ bool CNetAddr::IsMulticast() const bool CNetAddr::IsValid() const { #ifdef USE_NATIVE_I2P - if (IsNativeI2P()) - return true; + if (fNativeI2P) { + if (IsNativeI2P()) + return true; + } #endif // Cleanup 3-byte shifted addresses caused by garbage in size field // of addr messages from versions before 0.2.9 checksum. @@ -867,8 +882,10 @@ enum Network CNetAddr::GetNetwork() const return NET_TOR; #ifdef USE_NATIVE_I2P - if (IsNativeI2P()) - return NET_NATIVE_I2P; + if (fNativeI2P) { + if (IsNativeI2P()) + return NET_NATIVE_I2P; + } #endif if (IsI2P()) @@ -880,8 +897,10 @@ enum Network CNetAddr::GetNetwork() const std::string CNetAddr::ToStringIP() const { #ifdef USE_NATIVE_I2P - if (IsNativeI2P()) - return GetI2PDestination(); + if (fNativeI2P) { + if (IsNativeI2P()) + return GetI2PDestination(); + } #endif if (IsTor()) return EncodeBase32(&ip[6], 10) + ".onion"; @@ -912,29 +931,29 @@ std::string CNetAddr::ToString() const bool operator==(const CNetAddr& a, const CNetAddr& b) { -#ifdef USE_NATIVE_I2P - return (memcmp(a.ip, b.ip, 16) == 0 && memcmp(a.i2pDest, b.i2pDest, NATIVE_I2P_DESTINATION_SIZE) == 0); -#else - return (memcmp(a.ip, b.ip, 16) == 0); -#endif + if (fNativeI2P) { + return (memcmp(a.ip, b.ip, 16) == 0 && memcmp(a.i2pDest, b.i2pDest, NATIVE_I2P_DESTINATION_SIZE) == 0); + } else { + return (memcmp(a.ip, b.ip, 16) == 0); + } } bool operator!=(const CNetAddr& a, const CNetAddr& b) { -#ifdef USE_NATIVE_I2P - return (memcmp(a.ip, b.ip, 16) != 0 || memcmp(a.i2pDest, b.i2pDest, NATIVE_I2P_DESTINATION_SIZE) != 0); -#else - return (memcmp(a.ip, b.ip, 16) != 0); -#endif + if (fNativeI2P) { + return (memcmp(a.ip, b.ip, 16) != 0 || memcmp(a.i2pDest, b.i2pDest, NATIVE_I2P_DESTINATION_SIZE) != 0); + } else { + return (memcmp(a.ip, b.ip, 16) != 0); + } } bool operator<(const CNetAddr& a, const CNetAddr& b) { -#ifdef USE_NATIVE_I2P - return (memcmp(a.ip, b.ip, 16) < 0 || (memcmp(a.ip, b.ip, 16) == 0 && memcmp(a.i2pDest, b.i2pDest, NATIVE_I2P_DESTINATION_SIZE) < 0)); -#else - return (memcmp(a.ip, b.ip, 16) < 0); -#endif + if (fNativeI2P) { + return (memcmp(a.ip, b.ip, 16) < 0 || (memcmp(a.ip, b.ip, 16) == 0 && memcmp(a.i2pDest, b.i2pDest, NATIVE_I2P_DESTINATION_SIZE) < 0)); + } else { + return (memcmp(a.ip, b.ip, 16) < 0); + } } bool CNetAddr::GetInAddr(struct in_addr* pipv4Addr) const @@ -948,8 +967,10 @@ bool CNetAddr::GetInAddr(struct in_addr* pipv4Addr) const bool CNetAddr::GetIn6Addr(struct in6_addr* pipv6Addr) const { #ifdef USE_NATIVE_I2P - if (IsNativeI2P()) - return false; + if (fNativeI2P) { + if (IsNativeI2P()) + return false; + } #endif memcpy(pipv6Addr, ip, 16); return true; @@ -965,12 +986,14 @@ std::vector CNetAddr::GetGroup() const int nBits = 16; #ifdef USE_NATIVE_I2P - if (IsNativeI2P()) - { - vchRet.resize(NATIVE_I2P_DESTINATION_SIZE + 1); - vchRet[0] = NET_NATIVE_I2P; - memcpy(&vchRet[1], i2pDest, NATIVE_I2P_DESTINATION_SIZE); - return vchRet; + if (fNativeI2P) { + if (IsNativeI2P()) + { + vchRet.resize(NATIVE_I2P_DESTINATION_SIZE + 1); + vchRet[0] = NET_NATIVE_I2P; + memcpy(&vchRet[1], i2pDest, NATIVE_I2P_DESTINATION_SIZE); + return vchRet; + } } #endif diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 08a4d56e..cc88ab0c 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -246,20 +246,29 @@ BitcoinGUI::BitcoinGUI(QWidget *parent): labelI2PConnections = new QLabel(); labelI2POnly = new QLabel(); labelI2PGenerated = new QLabel(); - frameBlocksLayout->addWidget(labelI2PGenerated); - frameBlocksLayout->addWidget(labelI2POnly); - frameBlocksLayout->addWidget(labelI2PConnections); + if (fNativeI2P) + frameBlocksLayout->addStretch(); + frameBlocksLayout->addWidget(labelI2POnly); + frameBlocksLayout->addStretch(); + frameBlocksLayout->addWidget(labelI2PConnections); + frameBlocksLayout->addStretch(); + frameBlocksLayout->addWidget(labelI2PGenerated); #endif labelStakingIcon = new QLabel(); labelConnectionsIcon = new QLabel(); labelBlocksIcon = new QLabel(); labelConnectTypeIcon = new QLabel(); + labelFSLockIcon = new QLabel(); frameBlocksLayout->addStretch(); frameBlocksLayout->addWidget(labelEncryptionIcon); frameBlocksLayout->addStretch(); - frameBlocksLayout->addWidget(labelConnectTypeIcon); - frameBlocksLayout->addStretch(); + if (fNativeTor) + frameBlocksLayout->addWidget(labelConnectTypeIcon); + frameBlocksLayout->addStretch(); + if (fFSLock) + frameBlocksLayout->addWidget(labelFSLockIcon); + frameBlocksLayout->addStretch(); frameBlocksLayout->addWidget(labelStakingIcon); frameBlocksLayout->addStretch(); frameBlocksLayout->addWidget(labelConnectionsIcon); @@ -269,9 +278,9 @@ BitcoinGUI::BitcoinGUI(QWidget *parent): netLabel = new QLabel(); netLabel->setObjectName("netLabel"); - netLabel->setStyleSheet("#netLabel { color: #efefef; }"); + netLabel->setStyleSheet("#netLabel { color: #4a4a4a; }"); + frameBlocksLayout->addWidget(netLabel); - frameBlocksLayout->addStretch(); if (GetBoolArg("-staking", true)) @@ -632,30 +641,38 @@ void BitcoinGUI::checkTOU() void BitcoinGUI::setClientModel(ClientModel *clientModel) { #ifdef USE_NATIVE_I2P +if (fNativeI2P) { setNumI2PConnections(clientModel->getNumI2PConnections()); connect(clientModel, SIGNAL(numI2PConnectionsChanged(int)), this, SLOT(setNumI2PConnections(int))); -if(clientModel->isI2POnly()) -{ - netLabel->setText("I2P"); - netLabel->setToolTip(tr("Wallet is using I2P-network only")); + if(clientModel->isI2POnly()) + { + netLabel->setText("I2P"); + netLabel->setToolTip(tr("Wallet is using I2P Denarius network only")); + } } -else -{ #endif -netLabel->setText("CLEARNET"); -#ifdef USE_NATIVE_I2P +if(!fNativeTor && !fNativeI2P) { + netLabel->setText("CLEARNET"); + netLabel->setToolTip(tr("Native Tor or I2P are not running.")); } - - if (clientModel->isI2PAddressGenerated()) - { - labelI2PGenerated->setText("DYN"); - labelI2PGenerated->setToolTip(tr("Wallet is running with a random generated I2P-address")); - } - else - { - labelI2PGenerated->setText("STA"); - labelI2PGenerated->setToolTip(tr("Wallet is running with a static I2P-address")); +if (fFSLock) { + labelFSLockIcon->setPixmap(QIcon(":/icons/mn").pixmap(STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE)); + labelFSLockIcon->setToolTip(tr("FS are locked with fsconflock=1")); +} +#ifdef USE_NATIVE_I2P +if (fNativeI2P) { + if (clientModel->isI2PAddressGenerated()) { + const QString puba = clientModel->getPublicI2PKey(); + const QString base32addy = clientModel->getB32Address(puba); + labelI2PGenerated->setText(tr(" DYNAMIC")); + labelI2PGenerated->setToolTip(tr("Wallet is running with a dynamic I2P address: ") + QString(base32addy)); + } else { + const QString pubs = clientModel->getPublicI2PKey(); + const QString b32addy = clientModel->getB32Address(pubs); + labelI2PGenerated->setText(tr(" STATIC")); + labelI2PGenerated->setToolTip(tr("Wallet is running with a static I2P address: ") + QString(b32addy)); } +} #endif this->clientModel = clientModel; if(clientModel) @@ -811,7 +828,9 @@ void BitcoinGUI::optionsClicked() OptionsDialog dlg; dlg.setModel(clientModel->getOptionsModel()); #ifdef USE_NATIVE_I2P - dlg.setClientModel(clientModel); + if (fNativeI2P) { + dlg.setClientModel(clientModel); + } #endif dlg.exec(); } @@ -834,17 +853,19 @@ void BitcoinGUI::showGeneratedI2PAddr(const QString& caption, const QString& pub #ifdef USE_NATIVE_I2P void BitcoinGUI::setNumI2PConnections(int count) { - QString i2pIcon; - switch(count) - { - case 0: i2pIcon = ":/icons/i2pconnect_0"; break; - case 1: /*case 2: case 3:*/ i2pIcon = ":/icons/i2pconnect_1"; break; - case 2:/*case 4: case 5: case 6:*/ i2pIcon = ":/icons/i2pconnect_2"; break; - case 3:/*case 7: case 8: case 9:*/ i2pIcon = ":/icons/i2pconnect_3"; break; - default: i2pIcon = ":/icons/i2pconnect_4"; break; + if(fNativeI2P) { + QString i2pIcon; + switch(count) + { + case 0: i2pIcon = ":/icons/i2pconnect_0"; break; + case 1: /*case 2: case 3:*/ i2pIcon = ":/icons/i2pconnect_1"; break; + case 2:/*case 4: case 5: case 6:*/ i2pIcon = ":/icons/i2pconnect_2"; break; + case 3:/*case 7: case 8: case 9:*/ i2pIcon = ":/icons/i2pconnect_3"; break; + default: i2pIcon = ":/icons/i2pconnect_4"; break; + } + labelI2PConnections->setPixmap(QIcon(i2pIcon).pixmap(50, 13)); + labelI2PConnections->setToolTip(tr("%n active connection(s) to the I2P Denarius network", "", count)); } - labelI2PConnections->setPixmap(QPixmap(i2pIcon)); - labelI2PConnections->setToolTip(tr("%n active connection(s) to the I2P-Denarius network", "", count)); } #endif @@ -860,7 +881,7 @@ void BitcoinGUI::setNumConnections(int count) default: icon = ":/icons/connect_4"; break; } labelConnectionsIcon->setPixmap(QIcon(icon).pixmap(STATUSBAR_ICONSIZE,STATUSBAR_ICONSIZE)); - labelConnectionsIcon->setToolTip(tr("%n active connection(s) to Denarius network", "", count)); + labelConnectionsIcon->setToolTip(tr("%n active connection(s) to the Denarius network", "", count)); if(fNativeTor) { @@ -877,9 +898,6 @@ void BitcoinGUI::setNumConnections(int count) QString onionauto; onionauto = tr("Connected via the Tor Network - ") + QString::fromStdString(automatic_onion); labelConnectTypeIcon->setToolTip(onionauto); - } else { - labelConnectTypeIcon->setPixmap(QIcon(":/icons/toroff").pixmap(STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE)); - labelConnectTypeIcon->setToolTip(tr("Not Connected via the Tor Network, Start Denarius with the flag nativetor=1")); } } @@ -888,7 +906,13 @@ void BitcoinGUI::setNumBlocks(int count, int nTotalBlocks) // don't bother showing anything if we have no connection to the network if (!clientModel || clientModel->getNumConnections() == 0) { - progressBarLabel->setText(tr("Connecting to the Denarius network...")); + if (!fNativeI2P && !fNativeTor) { + progressBarLabel->setText(tr("Connecting to the Denarius network...")); + } else if (fNativeI2P) { + progressBarLabel->setText(tr("Connecting to the Denarius I2P network...")); + } else if (fNativeTor) { + progressBarLabel->setText(tr("Connecting to the Denarius Tor network...")); + } progressBarLabel->setVisible(true); progressBar->setVisible(false); return; diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index 205f9c9c..ec2b3352 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -112,6 +112,7 @@ class BitcoinGUI : public QMainWindow QLabel *labelConnectionsIcon; QLabel *labelBlocksIcon; QLabel *labelConnectTypeIcon; + QLabel *labelFSLockIcon; QLabel *progressBarLabel; QLabel *mainIcon; QToolBar *mainToolbar; diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index e11e4873..daefbeff 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -144,6 +144,11 @@ bool ClientModel::isNativeTor() const return fNativeTor; } +bool ClientModel::isNativeI2P() const +{ + return fNativeI2P; +} + bool ClientModel::inInitialBlockDownload() const { return IsInitialBlockDownload(); diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h index 53a971f0..5f133135 100644 --- a/src/qt/clientmodel.h +++ b/src/qt/clientmodel.h @@ -37,9 +37,12 @@ class ClientModel : public QObject //! Return true if client connected to testnet bool isTestNet() const; - //! Return true if client connected to Tor + //! Return true if client connected to Native Tor bool isNativeTor() const; + //! Return true if client connected to Native I2P + bool isNativeI2P() const; + //! Return true if core is doing initial block download bool inInitialBlockDownload() const; //! Return conservative estimate of total number of blocks, or 0 if unknown diff --git a/src/qt/forms/i2poptionswidget.ui b/src/qt/forms/i2poptionswidget.ui index 545b91b9..f45256e3 100644 --- a/src/qt/forms/i2poptionswidget.ui +++ b/src/qt/forms/i2poptionswidget.ui @@ -6,8 +6,8 @@ 0 0 - 549 - 371 + 449 + 389 @@ -42,7 +42,7 @@ http://www.i2p2.i2p/i2cp.html#options - <a href="http://www.i2p2.i2p/i2cp.html#options">Help</a> + <html><head/><body><p><a href="http://www.i2p2.i2p/i2cp.html#options"><span style=" text-decoration: underline; color:#ffffff;">Help</span></a></p></body></html> Qt::RichText @@ -138,7 +138,7 @@ - Bitcoin-client + Denarius-client @@ -147,27 +147,34 @@ Qt::Horizontal + + QSizePolicy::MinimumExpanding + - 40 + 166 20 + + + + - Current -I2P-address... + View Current +I2P Address - Generate -I2P-address... + Generate +I2P Address @@ -677,8 +684,6 @@ I2P-address... lineEditSAMHost spinBoxSAMPort lineEditTunnelName - pushButtonCurrentI2PAddress - pushButtonGenerateI2PAddress spinBoxInboundQuantity spinBoxInboundLength spinBoxInboundLengthVariance diff --git a/src/qt/forms/rpcconsole.ui b/src/qt/forms/rpcconsole.ui index 28b83124..35bc199d 100644 --- a/src/qt/forms/rpcconsole.ui +++ b/src/qt/forms/rpcconsole.ui @@ -17,13 +17,20 @@ - 3 + 0 &Information + + + + Native I2P On/Off + + + @@ -37,20 +44,6 @@ - - - - Client name - - - - - - - Client version - - - @@ -67,6 +60,20 @@ + + + + Client version + + + + + + + Client name + + + @@ -77,6 +84,22 @@ + + + + IBeamCursor + + + N/A + + + Qt::PlainText + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + @@ -116,8 +139,8 @@ - - + + IBeamCursor @@ -146,22 +169,6 @@ - - - - IBeamCursor - - - N/A - - - Qt::PlainText - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse - - - @@ -175,6 +182,26 @@ + + + + false + + + + + + + + + + false + + + + + + @@ -191,10 +218,10 @@ - - + + - Testnet On/Off + Current number of blocks @@ -205,34 +232,21 @@ - - - - false - - - - - - - - - - false - + + - + Testnet On/Off - - + + - Current number of blocks + Estimated total blocks - + @@ -245,30 +259,7 @@ - - - - IBeamCursor - - - N/A - - - Qt::PlainText - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse - - - - - - - Estimated total blocks - - - - + Last block time @@ -276,7 +267,7 @@ - + IBeamCursor @@ -291,8 +282,8 @@ - - + + IBeamCursor @@ -307,7 +298,20 @@ - + + + + + 75 + true + + + + Command-line options + + + + Qt::Vertical @@ -320,20 +324,23 @@ - - - - - 75 - true - + + + + IBeamCursor - Command-line options + N/A + + + Qt::PlainText + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse - + Open the Denarius debug log file from the current data directory. This can take a few seconds for large log files. @@ -346,20 +353,20 @@ - - - - - 75 - true - + + + + Qt::Vertical - - Debug log file + + + 20 + 40 + - + - + Show the Denarius-Qt help message to get a list with possible Denarius command-line options. @@ -372,18 +379,28 @@ - - - - Qt::Vertical + + + + + 75 + true + - - - 20 - 40 - + + Debug log file - + + + + + + false + + + + + diff --git a/src/qt/forms/showi2paddresses.ui b/src/qt/forms/showi2paddresses.ui index 0c899d36..f20bef93 100644 --- a/src/qt/forms/showi2paddresses.ui +++ b/src/qt/forms/showi2paddresses.ui @@ -23,7 +23,7 @@ - If you want to use a permanent I2P-address you have to set a 'mydestination' option in the configuration file: + If you want to use a permanent Denarius I2P node address you have to set a 'mydestination' option in the configuration file: true @@ -76,7 +76,7 @@ - Short base32-address: + Short I2P base32-address: diff --git a/src/qt/i2poptionswidget.cpp b/src/qt/i2poptionswidget.cpp index e4919d73..2ef18dde 100644 --- a/src/qt/i2poptionswidget.cpp +++ b/src/qt/i2poptionswidget.cpp @@ -78,7 +78,7 @@ void I2POptionsWidget::ShowCurrentI2PAddress() const QString b32 = clientModel->getB32Address(pub); const QString configFile = QString::fromStdString(GetConfigFile().string()); - ShowI2PAddresses i2pCurrDialog("Your current I2P-address", pub, priv, b32, configFile, this); + ShowI2PAddresses i2pCurrDialog("Your current I2P address", pub, priv, b32, configFile, this); i2pCurrDialog.exec(); } } diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp index 58008281..2de17b99 100644 --- a/src/qt/optionsdialog.cpp +++ b/src/qt/optionsdialog.cpp @@ -102,9 +102,6 @@ OptionsDialog::OptionsDialog(QWidget *parent) : connect(mapper, SIGNAL(currentIndexChanged(int)), this, SLOT(disableApplyButton())); /* setup/change UI elements when proxy IP is invalid/valid */ connect(this, SIGNAL(proxyIpValid(QValidatedLineEdit *, bool)), this, SLOT(handleProxyIpValid(QValidatedLineEdit *, bool))); -#ifdef USE_NATIVE_I2P - ui->tabWidget->addTab(tabI2P, QString("I2P")); -#endif } OptionsDialog::~OptionsDialog() @@ -144,7 +141,12 @@ void OptionsDialog::setClientModel(ClientModel* clientModel) { if (clientModel) { - tabI2P->setModel(clientModel); + if (clientModel->isNativeI2P()) { + ui->tabWidget->addTab(tabI2P, QString("I2P")); + tabI2P->setModel(clientModel); + } else { + ui->tabWidget->removeTab(tabI2P); + } } } #endif diff --git a/src/qt/res/icons/i2plogo_0_16.png b/src/qt/res/icons/i2plogo_0_16.png index 912d4ac377228771cb9811520a08d47ee6bb3f97..8e100e4a46e72f701bddd3f615d2d780a90ed71f 100644 GIT binary patch literal 2797 zcmb_e3slrr8Xgtc!MD^Zf{ze?I+wb#SX&r!;dPwg_ol__;;L0H02fBJwdd$ z#91VAIH!+_;bSzf6BKLoB55{}@k%$E1++-y?U!yQsbq!+5*eM|FgMPk%cRC>$Ffu#|q#F$;j!5?bhwTzV+tv+(z%YbQ z_5oMf90D<#aKN9nFo4`k0Z}L>2b8!Ms*qtg?g>Z{R0Sg{7?nY&g1`_$Dg{O_Q1E7< zwM0Zf(5Nrr%Lh#2c{2gSX=!O*X)-U?qJvQ!$6-VYOQn#2fVd13Po_gA&V9^60K-uh zy_wguCctKqOk`7dA5dUA5`xh@Zq~$&rb$Q`oKBiy)C;kNGz_Gvahy5DVirFJ9#w~wl4iiA~j1OoV zhY%HnD56j)A(sY7U5l>M+NH zTLHhXC)!KIA6hQu0khxr$la!1HD}3^Ao;-=MVrOyndqLX;JxgHoIiVh*KR2Oz9Wyj zakstSR~I&S{>9A~d$X#zi<{%WyH!nBWgzf-XElSrq6;^4=tGrpHX1q;i9R)BW`E8vK*{D<&0Z2%nV<0m`ePsy#QG_(WLBoZOW$&pNR$@K21S%w}xi-ZI>ux|DAfcw^!`ix!*3U z@!kxl%!zHG+pbS?)TEudy{P5ZzJjoxme2Q8o^O46_KzCf*N4v>*Dcnl9_E!#Z#-61 ztzS`3q8oRr{%%x`g*7^zT-skvUD&2RAzrXOW(C>d>}E*Zl(P?PN^Q73=xUyx?sjv*%K8Cr zM|FG+5ohm3 z1^p!~{vD*7LN#!lTX=uR@b($8Okn`cih8s7rJwP zyJ;bPPigr>b*7~?Qe1nCu}X3)AE+)(;&Dyw6&CO;j7yMJcRWJ6(gxNwz&##)j$Iw) n)vb=vcLuBj)*06GD|@rfpL-k3Ku&hren{1UYXhoQCv5!>%7Yd= literal 3293 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 Kg{#22{`ddu6i;UW diff --git a/src/qt/res/icons/i2plogo_1_16.png b/src/qt/res/icons/i2plogo_1_16.png index e5219d6bc94235df3d38e7cb47d96df357e84cd0..8b660972eb28f98f02bfb2cd8cb3bb556ae06744 100644 GIT binary patch literal 3242 zcmb_f2~-o;8pcu-@hP^Vh*1dH0W0uotdQ&3c#WM&|eWU@&DE+`6$f*a3P z0YwE{>VmdNMFsRxmLphD>r!Qj7;ys%6spjoz6kJFT?}?_P$>)({U%8R5v2x#~DkGzDlMMGLqs;87MnqJLSUFEAyx#TG*1tzn-(SwNHH}+)k-BY6|8lq4cdjtwxOF&qYgsUvF@~a z28Yy$fFPhXD%QD*&Helat669HUv3QnGDc{&TyfFECA%fYzE9^Qim=Y=}n2^ za0uUL$QSwLPK!~i%#LcBhd{--IBQkC>IIhSEePjIKrGbkLb$2x$W|ILCx2@z@IKlC6FK@gz}8(?yTAizP`Y(R+d7yyHZG8t?JkH->0!`2ol z#pIeqByU?autG_T5QyU_6G8wSBugM-vblf|60!k^je`)61#(3Y&!GH4F~PoK6DTZ1SF?CQsFd{On3wN5xAP5Yl4Rwp(laCMbJTzYugONu6LM3m!s|Z}JL6q3M zXfk&nB1HP1@mC>nf6X2PaTH~tAX!Zg7hq##H4zb+JRISPxI8Y#0lC8A=>N!`MM@iH zfWyN5o9u^@BZ@&}(HOba(rJG`o)1&!8=~)v=beT4e~pK3*ks>GjsD*%92|RVLng~P z*hTL0hUUoeLVk=KP?(HNm6AMuqU&|_N0%Vbg zBX^hp7ROI5Idx4aNwQzI+sC`rnqzz4JT0^8=0v;1jaA$7wtZY=Hnu9o)Fx!xEl+-> zwcWS(`ix^8i#`I5TyR!9cD#CW_2;^h_*V*DTiL;b2YRzg8m%8Us_NrkG^*;-Z?H?P z{3hy0wX-&#=mJY-7*GA4^;2rpl)l^dC+&B>TIrJNW!34(;BxQ=eS^P$;59#|SL+~q zLU1E*$@YZ}v4W24*Q@epWNC`;Umdp!@YtbZHU0dr;KFVbNzL;_(~FT$zCf9ES9&i| z=GGJ&A4?NQJwH_$-nD6pjo&w)T2}(atgNUV^k-=bN%f4c!)D2R7p6A*bneOu?sN4J z@}(^G>+U%D+P-jny~1&2&aaxHBlK!_MJ@Ve3LP{8d{mo9dVzna^e`z0-8`Lfcy?wfLh z*8-caDPYoz1F2Eg6}n~GnU`0zPVo8e`w+J!QwbKY_4536%jD<%k}Wdycczv#wiW;@ za;KH{HC47^yJiQgq|+il@cvqrQ`Sb2og{>6yL;@<~2? ze)QIZZWV{p!*U7_M_;ch3wgOJN}O==G#k1bo|$mrG;@8+z#*|h?arG~T4W zc5ut-U?uC!OoDeZXI@38*FKc|Ft&+dp2(i`a089sDVth8K51N_sq8lg-?sKkJ0F=w z7c4_AbW_gnu@9jq1!2HDjpou(YG zcpc~3|LsIj_j&rIyOmu>vlRpW`6Z(lSxwm5iT7HqEZok%>#+I?{>k32XFsTmRCFCl$90IQ*(13A2dl?8+lzL~)UfD`$chTv#^1_pcV_lu3?)`4oy1D#k(=EpZt0J`d z4|UCH8;;h_8MR<0-fs8wuKzy4_&O-wjxKy~K6oHk6YB8}-Np7|o&SZ{t?R!z z@L83=y>{t1y;)1^o$$U#Ek#zP=aMzf2{UnQAGRRk)u+bQWyh@QOB`>sXL#5Iyg)Yt zGc0tOMXp{mA=j7G;D{&{7VOuu($j!u?t9Vg~Lo26}>T|O%|^vn9( q@&?;#-WC_NaozV($(C)+uZ`EWmnOKGo1ZoOO$fXL`33V=CH)(@S_#tt literal 3014 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 literal 2709 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⪚7spx_(RxxR5MgxLpz1%vW!j;(9fI)J+}<)8TI@aIu$%~23o!Cr+RJC9m6wc9;e+KKGlEL=&k~< zeiiKr^Zj$QyYK`+V9e&v5ze_HrWG*jKSMZ&AQb#guqk-G_k`aFa?f*uUkFmcTO@i} zY4@kOm08A(f{x(FKL1wF-}fc=UWry-*|*Z%%Bs7N&WF`}O+x+zwaC5nC?_zH-Ck^ct;gunv+7T6j8$3FlOf{n~B#^-&0+m9dY z9Iu)_*vMQ-`?!s2>aO#Ex(gbC%>$^Vc{3ZCtm`UPT?j^?c>uGz>(}oAnCMEjP#c2> z9|RG!4Mt!CfBC zOOE6@L)?kFWy$(uk1=XIVp)UrMP201SmEK3SZq9DtnhH8Xxu!2$lvYedFZ(@!BDWL z;i(w>t7Na_cw>Y4(s8Tds$#X_)2HceY_Qsx;_1`$HaFSVutc}2SUq{tJwQZvLA`x= zll+tDY`FOvQ*8VAMP5{Ib%!ao{-4L{??J9lK?J@B7$BGz{915E@Ji433#Nis3%Y`z zd5^g6)G6lj!hV>SmgW^lPn@8g=XP&aSeljGDA7s_`(~C~Q4}1P2=d(S$qUP}l6Om3 zR`A6%x3VaB|7Si!ke7B>mRpgRd<;ivb`P)wj6JUai~hG3u(#oZ z2MK`Pb#03hNgNXh_DC$KX7bQOv|P2=XeM?&@Bl##E45fa>~fN|-Cz;e%3XH>Vg)0j zwo4Eepxs6gfm|n7+lsK!3|j#Vw96n8vpp_9xFmp)q1`}Gqd0&CL#xhXNCH^Ejc?U3 zF<7Xv)kXsAg4gZP@S5Pdrq%WSaGl&$NSbnBn)AjpzQoR+<#}1f_07FoRjlR}H#A%n z?9MBW{&U-DFwa@p$~jh5PNUN)NuG1V<|Z+~K!YSvcq~*n0odMVyp?mTX>CUuEhY+Y zm}veIaIJBo;n79)_5v)4;gW_&7u4Ga5Q}hG!#5@xy}%#1Khf~|iG~N82QUy!@E>G^wtzskJ;bp+oLJmfv0Blw!& zVZmzzEy0%se-~Wu`EJ1@f@2avR&Zxt+Nr$aW(g|_?#K&!w5Yhnd%}nF!XC*>-V2Zw zd@w8Q(X`-w2%9K;SEBHdSi_Iu#vjj1dn7BkqtSSx=v1uXUG8CpZ%P!MN)&y`#fNW5 z6g?a(x(CrsGFe=hYY*a+&Mc!Yq-|_s;1;$B6w?~alwlP zZ`1!?f7b;!$u&6mJO1r*4HI&c-6Gd4A@?3}T&~$*dY0#<1;@9y83Sxq?8^#n+t_fj zd%R#zT5xNcvI`(h*_9RC)@VM_U^&+Cc%$)+4JKK^ZDq+`fJo6e*6?_&=m5Z?7{waC tGgh?!e;yItJXW~YctWhgetNumConnections()); ui->isTestNet->setChecked(model->isTestNet()); ui->isNativeTor->setChecked(model->isNativeTor()); + ui->isNativeI2P->setChecked(model->isNativeI2P()); setNumBlocks(model->getNumBlocks(), model->getNumBlocksOfPeers()); } diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index 1edf7655..725ae8a2 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -122,7 +122,7 @@ Value getinfo(const Array& params, bool fHelp) file >> automatic_onion; obj.push_back(Pair("tor", (automatic_onion))); } - if(!fNativeTor) + if(!fNativeTor) // && !fNativeI2P obj.push_back(Pair("ip", addrSeenByPeer.ToStringIP())); diff.push_back(Pair("proof-of-work", GetDifficulty())); @@ -132,6 +132,7 @@ Value getinfo(const Array& params, bool fHelp) obj.push_back(Pair("testnet", fTestNet)); obj.push_back(Pair("fortunastake", fFortunaStake)); obj.push_back(Pair("nativetor", fNativeTor)); + obj.push_back(Pair("nativei2p", fNativeI2P)); obj.push_back(Pair("keypoololdest", (int64_t)pwalletMain->GetOldestKeyPoolTime())); obj.push_back(Pair("keypoolsize", (int)pwalletMain->GetKeyPoolSize())); obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee))); diff --git a/src/util.cpp b/src/util.cpp index b5a75c65..b87de936 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -92,6 +92,8 @@ bool fCommandLine = false; string strMiscWarning; bool fTestNet = false; bool fNativeTor = false; +bool fNativeI2P = false; +bool fFSLock = false; bool fNoListen = false; bool fLogTimestamps = false; CMedianFilter vTimeOffsets(200,0); @@ -1320,7 +1322,7 @@ boost::filesystem::path GetConfigFile() boost::filesystem::path GetFortunastakeConfigFile() { - boost::filesystem::path pathConfigFile(GetArg("-mnconf", "fortunastake.conf")); + boost::filesystem::path pathConfigFile(GetArg("-fsconf", "fortunastake.conf")); if (!pathConfigFile.is_complete()) pathConfigFile = GetDataDir(false) / pathConfigFile; return pathConfigFile; } @@ -1545,7 +1547,7 @@ string FormatFullVersion() #ifdef USE_NATIVE_I2P std::string FormatI2PNativeFullVersion() { - return; + return; //return I2P_NATIVE_BUILD; } #endif diff --git a/src/util.h b/src/util.h index 9719103b..b33e200e 100644 --- a/src/util.h +++ b/src/util.h @@ -220,6 +220,8 @@ extern bool fCommandLine; extern std::string strMiscWarning; extern bool fTestNet; extern bool fNativeTor; +extern bool fNativeI2P; +extern bool fFSLock; extern bool fNoListen; extern bool fLogTimestamps; extern bool fReopenDebugLog; diff --git a/src/wallet.cpp b/src/wallet.cpp index a7909f5a..295d419f 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -1122,78 +1122,6 @@ void CWalletTx::GetAmounts(list& listReceived, if (fIsMine) listReceived.push_back(output); }; - - /* - // Sent/received. - BOOST_FOREACH(const CTxOut& txout, vout) - { - // Skip special stake out - if (txout.scriptPubKey.empty()) - continue; - - opcodetype firstOpCode; - CScript::const_iterator pc = txout.scriptPubKey.begin(); - if (txout.scriptPubKey.GetOp(pc, firstOpCode) - && firstOpCode == OP_RETURN) - continue; - - - bool fIsMine; - // Only need to handle txouts if AT LEAST one of these is true: - // 1) they debit from us (sent) - // 2) the output is to us (received) - if (nDebit > 0) - { - // Don't report 'change' txouts - if (pwallet->IsChange(txout)) - continue; - fIsMine = pwallet->IsMine(txout); - } - else if (!(fIsMine = pwallet->IsMine(txout))) - continue; - - - - // Sent/received. - for (unsigned int i = 0; i < vout.size(); ++i) - { - const CTxOut& txout = vout[i]; - if (nVersion == ANON_TXN_VERSION - && txout.IsAnonOutput()) - continue; - isminetype fIsMine = pwallet->IsMine(txout); - // Only need to handle txouts if AT LEAST one of these is true: - // 1) they debit from us (sent) - // 2) the output is to us (received) - if (nDebit > 0) - { - // Don't report 'change' txouts - if (pwallet->IsChange(txout)) - continue; - } - else if (!(fIsMine & filter)) - continue; - - // In either case, we need to get the destination address - CTxDestination address; - if (!ExtractDestination(txout.scriptPubKey, address)) - { - printf("CWalletTx::GetAmounts: Unknown transaction type found, txid %s\n", - this->GetHash().ToString().c_str()); - address = CNoDestination(); - } - - COutputEntry output = {address, txout.nValue, (int)i}; - - // If we are debited by the transaction, add the output as a "sent" entry - if (nDebit > 0) - listSent.push_back(output); - - // If we are receiving the output, add it as a "received" entry - if (fIsMine & filter) - listReceived.push_back(output); - } - */ } void CWalletTx::GetAccountAmounts(const string& strAccount, int64_t& nReceived, @@ -3407,9 +3335,6 @@ bool CWallet::FindStealthTransactions(const CTransaction& tx, mapValue_t& mapNar return true; }; - - - // NovaCoin: get current stake weight bool CWallet::GetStakeWeight(const CKeyStore& keystore, uint64_t& nMinWeight, uint64_t& nMaxWeight, uint64_t& nWeight) { @@ -7016,46 +6941,6 @@ bool CWallet::ExpandLockedAnonOutput(CWalletDB *pwdb, CKeyID &ckeyId, CLockedAno return error("%s: StealthSecretSpend() failed.", __func__); }; - /* - // - check ext account stealth keys - ExtKeyAccountMap::const_iterator mi; - if (!fFound) - for (mi = mapExtAccounts.begin(); mi != mapExtAccounts.end(); ++mi) - { - fFound = true; - - CExtKeyAccount *ea = mi->second; - - CKeyID sxId = lao.pkScan.GetID(); - - AccStealthKeyMap::const_iterator miSk = ea->mapStealthKeys.find(sxId); - if (miSk == ea->mapStealthKeys.end()) - continue; - - const CEKAStealthKey &aks = miSk->second; - if (ea->IsLocked(aks)) - return error("%s: Stealth is locked.", __func__); - - ec_point pkExtracted; - ec_secret sShared; - - pkEphem.resize(lao.pkEphem.size()); - memcpy(&pkEphem[0], lao.pkEphem.begin(), lao.pkEphem.size()); - memcpy(&sScan.e[0], aks.skScan.begin(), EC_SECRET_SIZE); - - // - need sShared to extract key - if (StealthSecret(sScan, pkEphem, aks.pkSpend, sShared, pkExtracted) != 0) - return error("%s: StealthSecret() failed.", __func__); - - CKey kChild; - - if (0 != ea->ExpandStealthChildKey(&aks, sShared, kChild)) - return error("%s: ExpandStealthChildKey() failed %s.", __func__, aks.ToStealthAddress().c_str()); - - memcpy(&sSpendR.e[0], kChild.begin(), EC_SECRET_SIZE); - }; - */ - if (!fFound) return error("%s: No stealth key found.", __func__); From 9a254d4b4924e254fc975bb3e8d440b9cee60d45 Mon Sep 17 00:00:00 2001 From: carsenk Date: Tue, 6 Aug 2019 15:24:14 -0600 Subject: [PATCH 08/26] Update makefiles --- src/makefile.arm | 5 +++++ src/makefile.unix | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/makefile.arm b/src/makefile.arm index e1925b78..0b30c6d5 100644 --- a/src/makefile.arm +++ b/src/makefile.arm @@ -327,6 +327,11 @@ OBJS= \ obj/ringsig.o +ifeq (${USE_NATIVE_I2P}, 1) + OBJS += obj/i2p.o + OBJS += obj/i2psam.o +endif + all: denariusd # diff --git a/src/makefile.unix b/src/makefile.unix index 82cea2b6..8dc879ef 100644 --- a/src/makefile.unix +++ b/src/makefile.unix @@ -371,7 +371,7 @@ OBJS= \ obj/ringsig.o endif -ifdef USE_NATIVE_I2P +ifeq (${USE_NATIVE_I2P}, 1) OBJS += obj/i2p.o OBJS += obj/i2psam.o endif From cccb8aa2c445c8e4e5ef440b86e426918f699afe Mon Sep 17 00:00:00 2001 From: carsenk Date: Tue, 6 Aug 2019 15:27:31 -0600 Subject: [PATCH 09/26] README Update --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 96ffeaf9..0cf46e8a 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,7 @@ Technology * Stealth addresses * Ring Signatures (16 Recommended) * Native Optional Tor Onion Node (-nativetor=1) +* Native Optional I2P Node (-nativei2p=1) * Encrypted Messaging * Multi-Signature Addresses & TXs * Atomic Swaps using UTXOs (BIP65 CLTV) From f9fa447939aa2ecce3e3e8d6102bbd161ac17dcd Mon Sep 17 00:00:00 2001 From: carsenk Date: Tue, 6 Aug 2019 15:48:39 -0600 Subject: [PATCH 10/26] Makefile fixes for I2P --- src/makefile.arm | 8 ++++++++ src/makefile.unix | 8 ++++++++ src/net.h | 2 ++ 3 files changed, 18 insertions(+) diff --git a/src/makefile.arm b/src/makefile.arm index 0b30c6d5..6f887f40 100644 --- a/src/makefile.arm +++ b/src/makefile.arm @@ -8,6 +8,7 @@ USE_LEVELDB:=1 USE_UPNP:=1 USE_NATIVETOR:=- +USE_NATIVE_I2P:=1 LINK:=$(CXX) ARCH:=$(system lscpu | head -n 1 | awk '{print $2}') @@ -48,6 +49,13 @@ ifneq (${USE_NATIVETOR}, -) DEFS += $(addprefix -I,$(CURDIR)/tor) -DUSE_NATIVETOR=$(USE_NATIVETOR) endif +ifndef USE_NATIVE_I2P + override USE_NATIVE_I2P = - +endif +ifneq (${USE_NATIVE_I2P}, -) + DEFS += -DUSE_NATIVE_I2P=$(USE_NATIVE_I2P) +endif + ifndef USE_UPNP override USE_UPNP = - endif diff --git a/src/makefile.unix b/src/makefile.unix index 8dc879ef..9759a22d 100644 --- a/src/makefile.unix +++ b/src/makefile.unix @@ -6,6 +6,7 @@ USE_LEVELDB:=1 USE_UPNP:=1 USE_NATIVETOR:=1 +USE_NATIVE_I2P:=1 LINK:=$(CXX) ARCH:=$(system lscpu | head -n 1 | awk '{print $2}') @@ -45,6 +46,13 @@ ifneq (${USE_NATIVETOR}, -) DEFS += $(addprefix -I,$(CURDIR)/tor) -DUSE_NATIVETOR=$(USE_NATIVETOR) endif +ifndef USE_NATIVE_I2P + override USE_NATIVE_I2P = - +endif +ifneq (${USE_NATIVE_I2P}, -) + DEFS += -DUSE_NATIVE_I2P=$(USE_NATIVE_I2P) +endif + ifndef USE_UPNP override USE_UPNP = - endif diff --git a/src/net.h b/src/net.h index c048d59a..e2f25637 100644 --- a/src/net.h +++ b/src/net.h @@ -523,9 +523,11 @@ class CNode // after addresses were pushed. if(fNativeI2P) { if (addr.IsValid() && !setAddrKnown.count(addr)) { +#ifdef USE_NATIVE_I2P // if receiver doesn't support i2p-address we don't send it if ((this->nServices & NODE_I2P) || !addr.IsNativeI2P()) vAddrToSend.push_back(addr); +#endif } } else { if (addr.IsValid() && !setAddrKnown.count(addr)) From 7c93223d4d66dae48c0627bd29e45888d3e95977 Mon Sep 17 00:00:00 2001 From: carsenk Date: Tue, 6 Aug 2019 17:30:24 -0600 Subject: [PATCH 11/26] Fix fsconflock QT icon --- src/qt/bitcoin.qrc | 1 + src/qt/bitcoingui.cpp | 8 +++++--- src/qt/clientmodel.cpp | 5 +++++ src/qt/clientmodel.h | 3 +++ src/qt/res/icons/fs.png | Bin 0 -> 33382 bytes src/rpcwallet.cpp | 13 ++++++++++++- 6 files changed, 26 insertions(+), 4 deletions(-) create mode 100644 src/qt/res/icons/fs.png diff --git a/src/qt/bitcoin.qrc b/src/qt/bitcoin.qrc index 0a14dc3b..c7d653f2 100644 --- a/src/qt/bitcoin.qrc +++ b/src/qt/bitcoin.qrc @@ -16,6 +16,7 @@ res/icons/mark.png res/icons/btc.png res/icons/mn.png + res/icons/fs.png res/icons/multi.png res/icons/connect0_16.png res/icons/connect1_16.png diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index cc88ab0c..74360826 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -254,7 +254,9 @@ BitcoinGUI::BitcoinGUI(QWidget *parent): frameBlocksLayout->addStretch(); frameBlocksLayout->addWidget(labelI2PGenerated); #endif - + fFSLock = GetBoolArg("-fsconflock"); + fNativeTor = GetBoolArg("-nativetor"); + fNativeI2P = GetBoolArg("-nativei2p"); labelStakingIcon = new QLabel(); labelConnectionsIcon = new QLabel(); labelBlocksIcon = new QLabel(); @@ -655,8 +657,8 @@ if(!fNativeTor && !fNativeI2P) { netLabel->setText("CLEARNET"); netLabel->setToolTip(tr("Native Tor or I2P are not running.")); } -if (fFSLock) { - labelFSLockIcon->setPixmap(QIcon(":/icons/mn").pixmap(STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE)); +if (fFSLock == true) { + labelFSLockIcon->setPixmap(QIcon(":/icons/fs").pixmap(STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE)); labelFSLockIcon->setToolTip(tr("FS are locked with fsconflock=1")); } #ifdef USE_NATIVE_I2P diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index daefbeff..c2c49977 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -149,6 +149,11 @@ bool ClientModel::isNativeI2P() const return fNativeI2P; } +bool ClientModel::isFSLock() const +{ + return fFSLock; +} + bool ClientModel::inInitialBlockDownload() const { return IsInitialBlockDownload(); diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h index 5f133135..b72b101c 100644 --- a/src/qt/clientmodel.h +++ b/src/qt/clientmodel.h @@ -43,6 +43,9 @@ class ClientModel : public QObject //! Return true if client connected to Native I2P bool isNativeI2P() const; + //! Return true if client connected to Native I2P + bool isFSLock() const; + //! Return true if core is doing initial block download bool inInitialBlockDownload() const; //! Return conservative estimate of total number of blocks, or 0 if unknown diff --git a/src/qt/res/icons/fs.png b/src/qt/res/icons/fs.png new file mode 100644 index 0000000000000000000000000000000000000000..0813b667487b4e6427fb87a5e657ffa7de3541c0 GIT binary patch literal 33382 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 S>2omv0000 #include #include @@ -122,6 +126,12 @@ Value getinfo(const Array& params, bool fHelp) file >> automatic_onion; obj.push_back(Pair("tor", (automatic_onion))); } + if (fNativeI2P) + { + //const string destination; + //string i2p_address = I2PSession::GenerateB32AddressFromDestination(destination.string().c_str()); + //obj.push_back(Pair("i2p", (i2p_address))); + } if(!fNativeTor) // && !fNativeI2P obj.push_back(Pair("ip", addrSeenByPeer.ToStringIP())); @@ -130,7 +140,8 @@ Value getinfo(const Array& params, bool fHelp) obj.push_back(Pair("difficulty", diff)); obj.push_back(Pair("testnet", fTestNet)); - obj.push_back(Pair("fortunastake", fFortunaStake)); + obj.push_back(Pair("fortunastake", fFortunaStake)); + obj.push_back(Pair("fslock", fFSLock)); obj.push_back(Pair("nativetor", fNativeTor)); obj.push_back(Pair("nativei2p", fNativeI2P)); obj.push_back(Pair("keypoololdest", (int64_t)pwalletMain->GetOldestKeyPoolTime())); From 15f48a8342c35c1b100f2636002f7ded2de9c57b Mon Sep 17 00:00:00 2001 From: carsenk Date: Tue, 6 Aug 2019 22:28:09 -0600 Subject: [PATCH 12/26] Fix USE_NATIVE_I2P compiling --- src/init.cpp | 6 ++++-- src/net.cpp | 12 ++++++++++-- src/net.h | 7 +++++-- src/netbase.cpp | 16 ++++++++++++++++ src/rpcwallet.cpp | 8 ++++++++ 5 files changed, 43 insertions(+), 6 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index d1027e60..52dc06e6 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1283,16 +1283,18 @@ bool AppInit2() printf("setKeyPool.size() = %" PRIszu"\n", pwalletMain->setKeyPool.size()); printf("mapWallet.size() = %" PRIszu"\n", pwalletMain->mapWallet.size()); printf("mapAddressBook.size() = %" PRIszu"\n", pwalletMain->mapAddressBook.size()); - +#ifdef USE_NATIVETOR if(fNativeTor) printf("Native Tor Onion Relay Node Enabled"); else printf("Native Tor Onion Relay Disabled, Using Regular Peers..."); - +#endif +#ifdef USE_NATIVE_I2P if(fNativeI2P) printf("Native I2P Node Enabled"); else printf("Native I2P Disabled, Using Regular Peers..."); +#endif if (fDebug) printf("Debugging is Enabled."); diff --git a/src/net.cpp b/src/net.cpp index cd878e65..078e78bc 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -733,11 +733,15 @@ bool CNode::ReceiveMsgBytes(const char *pch, unsigned int nBytes) // get current incomplete message, or create a new one if (vRecvMsg.empty() || vRecvMsg.back().complete()) +#ifdef USE_NATIVE_I2P if (fNativeI2P) { vRecvMsg.push_back(CNetMessage(nRecvStreamType, nRecvVersion)); } else { vRecvMsg.push_back(CNetMessage(SER_NETWORK, nRecvVersion)); } +#else + vRecvMsg.push_back(CNetMessage(SER_NETWORK, nRecvVersion)); +#endif CNetMessage& msg = vRecvMsg.back(); @@ -1829,7 +1833,7 @@ void ThreadOpenConnections2(void* parg) continue; // do not allow non-default ports, unless after 50 invalid addresses selected already - +#ifdef USE_NATIVE_I2P if (fNativeI2P) { if (!addr.IsNativeI2P() && addr.GetPort() != GetDefaultPort() && nTries < 50) continue; @@ -1837,6 +1841,10 @@ void ThreadOpenConnections2(void* parg) if (addr.GetPort() != GetDefaultPort() && nTries < 50) continue; } +#else + if (addr.GetPort() != GetDefaultPort() && nTries < 50) + continue; +#endif addrConnect = addr; break; @@ -2435,7 +2443,7 @@ void StartNode(void* parg) // Start threads // - if(!fNativeTor && !fNativeI2P) + if(!fNativeTor) { if (!GetBoolArg("-dnsseed", true)) printf("DNS seeding disabled\n"); diff --git a/src/net.h b/src/net.h index e2f25637..446e0731 100644 --- a/src/net.h +++ b/src/net.h @@ -521,18 +521,21 @@ class CNode // Known checking here is only to save space from duplicates. // SendMessages will filter it again for knowns that were added // after addresses were pushed. +#ifdef USE_NATIVE_I2P if(fNativeI2P) { if (addr.IsValid() && !setAddrKnown.count(addr)) { -#ifdef USE_NATIVE_I2P // if receiver doesn't support i2p-address we don't send it if ((this->nServices & NODE_I2P) || !addr.IsNativeI2P()) vAddrToSend.push_back(addr); -#endif } } else { if (addr.IsValid() && !setAddrKnown.count(addr)) vAddrToSend.push_back(addr); } +#else + if (addr.IsValid() && !setAddrKnown.count(addr)) + vAddrToSend.push_back(addr); +#endif } diff --git a/src/netbase.cpp b/src/netbase.cpp index 36de012a..61b0c7a3 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -710,11 +710,15 @@ bool CNetAddr::IsIPv4() const bool CNetAddr::IsIPv6() const { +#ifdef USE_NATIVE_I2P if (fNativeI2P) { return (!IsIPv4() && !IsTor() && !IsNativeI2P()); } else { return (!IsIPv4() && !IsTor() && !IsI2P()); } +#else +return (!IsIPv4() && !IsTor() && !IsI2P()); +#endif } bool CNetAddr::IsRFC1918() const @@ -931,29 +935,41 @@ std::string CNetAddr::ToString() const bool operator==(const CNetAddr& a, const CNetAddr& b) { +#ifdef USE_NATIVE_I2P if (fNativeI2P) { return (memcmp(a.ip, b.ip, 16) == 0 && memcmp(a.i2pDest, b.i2pDest, NATIVE_I2P_DESTINATION_SIZE) == 0); } else { return (memcmp(a.ip, b.ip, 16) == 0); } +#else +return (memcmp(a.ip, b.ip, 16) == 0); +#endif } bool operator!=(const CNetAddr& a, const CNetAddr& b) { +#ifdef USE_NATIVE_I2P if (fNativeI2P) { return (memcmp(a.ip, b.ip, 16) != 0 || memcmp(a.i2pDest, b.i2pDest, NATIVE_I2P_DESTINATION_SIZE) != 0); } else { return (memcmp(a.ip, b.ip, 16) != 0); } +#else +return (memcmp(a.ip, b.ip, 16) != 0); +#endif } bool operator<(const CNetAddr& a, const CNetAddr& b) { +#ifdef USE_NATIVE_I2P if (fNativeI2P) { return (memcmp(a.ip, b.ip, 16) < 0 || (memcmp(a.ip, b.ip, 16) == 0 && memcmp(a.i2pDest, b.i2pDest, NATIVE_I2P_DESTINATION_SIZE) < 0)); } else { return (memcmp(a.ip, b.ip, 16) < 0); } +#else +return (memcmp(a.ip, b.ip, 16) < 0); +#endif } bool CNetAddr::GetInAddr(struct in_addr* pipv4Addr) const diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index 03aad699..72cb29c7 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -113,6 +113,7 @@ Value getinfo(const Array& params, bool fHelp) obj.push_back(Pair("moneysupply", ValueFromAmount(pindexBest->nMoneySupply))); obj.push_back(Pair("connections", (int)vNodes.size())); obj.push_back(Pair("proxy", (proxy.first.IsValid() ? proxy.first.ToStringIPPort() : string()))); +#ifdef USE_NATIVETOR if(fNativeTor) { string automatic_onion; @@ -126,12 +127,15 @@ Value getinfo(const Array& params, bool fHelp) file >> automatic_onion; obj.push_back(Pair("tor", (automatic_onion))); } +#endif +#ifdef USE_NATIVE_I2P if (fNativeI2P) { //const string destination; //string i2p_address = I2PSession::GenerateB32AddressFromDestination(destination.string().c_str()); //obj.push_back(Pair("i2p", (i2p_address))); } +#endif if(!fNativeTor) // && !fNativeI2P obj.push_back(Pair("ip", addrSeenByPeer.ToStringIP())); @@ -142,8 +146,12 @@ Value getinfo(const Array& params, bool fHelp) obj.push_back(Pair("testnet", fTestNet)); obj.push_back(Pair("fortunastake", fFortunaStake)); obj.push_back(Pair("fslock", fFSLock)); +#ifdef USE_NATIVETOR obj.push_back(Pair("nativetor", fNativeTor)); +#endif +#ifdef USE_NATIVE_I2P obj.push_back(Pair("nativei2p", fNativeI2P)); +#endif obj.push_back(Pair("keypoololdest", (int64_t)pwalletMain->GetOldestKeyPoolTime())); obj.push_back(Pair("keypoolsize", (int)pwalletMain->GetKeyPoolSize())); obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee))); From 79c5e1549da881ff2755e64b127096e847add6a2 Mon Sep 17 00:00:00 2001 From: carsenk Date: Wed, 7 Aug 2019 00:17:48 -0600 Subject: [PATCH 13/26] New RPC Commands getnettotals ping getaddednodeinfo --- src/bitcoinrpc.cpp | 3 ++ src/bitcoinrpc.h | 7 +++ src/init.cpp | 6 +-- src/net.cpp | 1 + src/netbase.cpp | 3 ++ src/rpcnet.cpp | 127 +++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 144 insertions(+), 3 deletions(-) diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp index fbbf2367..df7d7592 100644 --- a/src/bitcoinrpc.cpp +++ b/src/bitcoinrpc.cpp @@ -267,6 +267,9 @@ static const CRPCCommand vRPCCommands[] = { "getpeerinfo", &getpeerinfo, true, false }, { "gethashespersec", &gethashespersec, true, false }, { "addnode", &addnode, true, true }, + { "getaddednodeinfo", &getaddednodeinfo, true, true }, + { "ping", &ping, true, true }, + { "getnettotals", &getnettotals, true, false }, { "dumpbootstrap", &dumpbootstrap, false, false }, { "getdifficulty", &getdifficulty, true, false }, { "getinfo", &getinfo, true, false }, diff --git a/src/bitcoinrpc.h b/src/bitcoinrpc.h index 7a2f4a5d..c07cd873 100644 --- a/src/bitcoinrpc.h +++ b/src/bitcoinrpc.h @@ -50,10 +50,13 @@ enum RPCErrorCode RPC_INVALID_PARAMETER = -8, // Invalid, missing or duplicate parameter RPC_DATABASE_ERROR = -20, // Database error RPC_DESERIALIZATION_ERROR = -22, // Error parsing or validating structure in raw format + RPC_SERVER_NOT_STARTED = -18, // RPC server was not started (StartRPCThreads() not called) // P2P client errors RPC_CLIENT_NOT_CONNECTED = -9, // Bitcoin is not connected RPC_CLIENT_IN_INITIAL_DOWNLOAD = -10, // Still downloading initial blocks + RPC_CLIENT_NODE_ALREADY_ADDED = -23, // Node is already added + RPC_CLIENT_NODE_NOT_ADDED = -24, // Node has not been added before // Wallet errors RPC_WALLET_ERROR = -4, // Unspecified problem with wallet (key not found etc.) @@ -152,6 +155,10 @@ extern std::vector ParseHexO(const json_spirit::Object& o, std::s extern json_spirit::Value getconnectioncount(const json_spirit::Array& params, bool fHelp); // in rpcnet.cpp extern json_spirit::Value getpeerinfo(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value addnode(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value ping(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value getaddednodeinfo(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value getnettotals(const json_spirit::Array& params, bool fHelp); + extern json_spirit::Value dumpwallet(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value importwallet(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value dumpprivkey(const json_spirit::Array& params, bool fHelp); // in rpcdump.cpp diff --git a/src/init.cpp b/src/init.cpp index 52dc06e6..26833ca0 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -320,7 +320,7 @@ std::string HelpMessage() " -connect= " + _("Connect only to the specified node(s)") + "\n" + " -seednode= " + _("Connect to a node to retrieve peer addresses, and disconnect") + "\n" + " -externalip= " + _("Specify your own public address") + "\n" + - " -onlynet= " + _("Only connect to nodes in network (IPv4, IPv6 or Tor)") + "\n" + + " -onlynet= " + _("Only connect to nodes in network (IPv4, IPv6, I2P, Native I2P or Tor)") + "\n" + " -discover " + _("Discover own IP address (default: 1 when listening and no -externalip)") + "\n" + " -listen " + _("Accept connections from outside (default: 1 if no -proxy or -connect)") + "\n" + " -bind= " + _("Bind to given address. Use [host]:port notation for IPv6") + "\n" + @@ -855,7 +855,7 @@ bool AppInit2() }; // see Step 2: parameter interactions for more information about these - if(!fNativeTor) // Available if nativetor and nativei2p are disabled + if(!fNativeTor) // Available if nativetor are disabled { fNoListen = !GetBoolArg("-listen", true); fDiscover = GetBoolArg("-discover", true); @@ -895,7 +895,7 @@ bool AppInit2() } #endif }; - if (!fBound) + if (!fBound && !fNativeI2P) return InitError(_("Failed to listen on any port. Use -listen=0 if you want this.")); }; }; diff --git a/src/net.cpp b/src/net.cpp index 078e78bc..2f7091ef 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2160,6 +2160,7 @@ bool BindListenNativeI2P(SOCKET& hSocket) return false; CService addrBind(I2PSession::Instance().getMyDestination().pub, 0); if (addrBind.IsRoutable() && fDiscover) + printf("I2P: AddLocal() = %s\n", addrBind.ToString().c_str()); AddLocal(addrBind, LOCAL_BIND); return true; } diff --git a/src/netbase.cpp b/src/netbase.cpp index 61b0c7a3..c4849a55 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -48,6 +48,9 @@ std::string GetNetworkName(enum Network net) { case NET_IPV6: return "ipv6"; case NET_TOR: return "onion"; case NET_I2P: return "i2p"; +#ifdef USE_NATIVE_I2P + case NET_NATIVE_I2P: return NATIVE_I2P_NET_STRING; +#endif default: return ""; } } diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp index b3aad66a..3a544871 100644 --- a/src/rpcnet.cpp +++ b/src/rpcnet.cpp @@ -23,6 +23,24 @@ Value getconnectioncount(const Array& params, bool fHelp) return (int)vNodes.size(); } +Value ping(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 0) + throw runtime_error( + "ping\n" + "Requests that a ping be sent to all other nodes, to measure ping time.\n" + "Results provided in getpeerinfo, pingtime and pingwait fields are decimal seconds.\n" + "Ping command is handled in queue with all other commands, so it measures processing backlog, not just network ping."); + + // Request that each node send a ping during next message processing pass + LOCK(cs_vNodes); + BOOST_FOREACH(CNode* pNode, vNodes) { + pNode->fPingQueued = true; + } + + return Value::null; +} + static void CopyNodeStats(std::vector& vstats) { vstats.clear(); @@ -52,6 +70,8 @@ Value getpeerinfo(const Array& params, bool fHelp) Object obj; obj.push_back(Pair("addr", stats.addrName)); + if (!(stats.addrLocal.empty())) + obj.push_back(Pair("addrlocal", stats.addrLocal)); obj.push_back(Pair("services", strprintf("%08" PRIx64, stats.nServices))); obj.push_back(Pair("lastsend", (int64_t)stats.nLastSend)); obj.push_back(Pair("lastrecv", (int64_t)stats.nLastRecv)); @@ -136,6 +156,113 @@ Value setdebug(const Array& params, bool fHelp) return Value::null; } +Value getaddednodeinfo(const Array& params, bool fHelp) +{ + if (fHelp || params.size() < 1 || params.size() > 2) + throw runtime_error( + "getaddednodeinfo [node]\n" + "Returns information about the given added node, or all added nodes\n" + "(note that onetry addnodes are not listed here)\n" + "If dns is false, only a list of added nodes will be provided,\n" + "otherwise connected information will also be available."); + + bool fDns = params[0].get_bool(); + + list laddedNodes(0); + if (params.size() == 1) + { + LOCK(cs_vAddedNodes); + BOOST_FOREACH(string& strAddNode, vAddedNodes) + laddedNodes.push_back(strAddNode); + } + else + { + string strNode = params[1].get_str(); + LOCK(cs_vAddedNodes); + BOOST_FOREACH(string& strAddNode, vAddedNodes) + if (strAddNode == strNode) + { + laddedNodes.push_back(strAddNode); + break; + } + if (laddedNodes.size() == 0) + throw JSONRPCError(RPC_CLIENT_NODE_NOT_ADDED, "Error: Node has not been added."); + } + + if (!fDns) + { + Object ret; + BOOST_FOREACH(string& strAddNode, laddedNodes) + ret.push_back(Pair("addednode", strAddNode)); + return ret; + } + + Array ret; + + list > > laddedAddreses(0); + BOOST_FOREACH(string& strAddNode, laddedNodes) + { + vector vservNode(0); + if(Lookup(strAddNode.c_str(), vservNode, GetDefaultPort(), fNameLookup, 0)) + laddedAddreses.push_back(make_pair(strAddNode, vservNode)); + else + { + Object obj; + obj.push_back(Pair("addednode", strAddNode)); + obj.push_back(Pair("connected", false)); + Array addresses; + obj.push_back(Pair("addresses", addresses)); + } + } + + LOCK(cs_vNodes); + for (list > >::iterator it = laddedAddreses.begin(); it != laddedAddreses.end(); it++) + { + Object obj; + obj.push_back(Pair("addednode", it->first)); + + Array addresses; + bool fConnected = false; + BOOST_FOREACH(CService& addrNode, it->second) + { + bool fFound = false; + Object node; + node.push_back(Pair("address", addrNode.ToString())); + BOOST_FOREACH(CNode* pnode, vNodes) + if (pnode->addr == addrNode) + { + fFound = true; + fConnected = true; + node.push_back(Pair("connected", pnode->fInbound ? "inbound" : "outbound")); + break; + } + if (!fFound) + node.push_back(Pair("connected", "false")); + addresses.push_back(node); + } + obj.push_back(Pair("connected", fConnected)); + obj.push_back(Pair("addresses", addresses)); + ret.push_back(obj); + } + + return ret; +} + +Value getnettotals(const Array& params, bool fHelp) +{ + if (fHelp || params.size() > 0) + throw runtime_error( + "getnettotals\n" + "Returns information about network traffic, including bytes in, bytes out,\n" + "and current time."); + + Object obj; + obj.push_back(Pair("totalbytesrecv", CNode::GetTotalBytesRecv())); + obj.push_back(Pair("totalbytessent", CNode::GetTotalBytesSent())); + obj.push_back(Pair("timemillis", GetTimeMillis())); + return obj; +} + // ppcoin: send alert. // There is a known deadlock situation with ThreadMessageHandler // ThreadMessageHandler: holds cs_vSend and acquiring cs_main in SendMessages() From 061e4abc35fd93fbc014861155b66cbfd5ee9500 Mon Sep 17 00:00:00 2001 From: carsenk Date: Wed, 7 Aug 2019 00:25:41 -0600 Subject: [PATCH 14/26] Fix bool on getaddednodeinfo --- src/bitcoinrpc.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp index df7d7592..7dc1817b 100644 --- a/src/bitcoinrpc.cpp +++ b/src/bitcoinrpc.cpp @@ -1372,6 +1372,8 @@ Array RPCConvertValues(const std::string &strMethod, const std::vector 0) ConvertTo(params[0]); + if (strMethod == "getaddednodeinfo" && n > 0) ConvertTo(params[0]); + if (strMethod == "addmultisigaddress" && n > 0) ConvertTo(params[0]); if (strMethod == "addmultisigaddress" && n > 1) ConvertTo(params[1]); if (strMethod == "createmultisig" && n > 0) ConvertTo(params[0]); From 100620bce7eb50dc0003a3d1c1c4624bcfee43b0 Mon Sep 17 00:00:00 2001 From: carsenk Date: Wed, 7 Aug 2019 12:57:03 -0600 Subject: [PATCH 15/26] dFPS Update Test --- src/fortunastake.cpp | 2 +- src/net.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/fortunastake.cpp b/src/fortunastake.cpp index 7eb07205..13982c0f 100644 --- a/src/fortunastake.cpp +++ b/src/fortunastake.cpp @@ -617,7 +617,7 @@ int GetFortunastakeRank(CFortunaStake &tmn, CBlockIndex* pindex, int minProtocol } bool CheckFSPayment(CBlockIndex* pindex, int64_t value, CFortunaStake &mn) { - if (mn.nBlockLastPaid == 0) return true; // if we didn't find a payment for this MN, let it through regardless of rate + //if (mn.nBlockLastPaid == 0) return true; // if we didn't find a payment for this MN, let it through regardless of rate // find height // calculate average payment across all FS // check if value is > 25% higher diff --git a/src/net.cpp b/src/net.cpp index 2f7091ef..ab2e4e44 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -781,7 +781,7 @@ void AddIncomingConnection(SOCKET hSocket, const CAddress& addr) { int nErr = WSAGetLastError(); if (nErr != WSAEWOULDBLOCK) - printf("socket error accept failed: %d\n", nErr); + printf("I2P socket error accept failed: %d\n", nErr); } else if (nInbound >= GetArg("-maxconnections", 125) - MAX_OUTBOUND_CONNECTIONS) { @@ -793,12 +793,12 @@ void AddIncomingConnection(SOCKET hSocket, const CAddress& addr) } else if (CNode::IsBanned(addr)) { - printf("connection from %s dropped (banned)\n", addr.ToString().c_str()); + printf("I2P connection from %s dropped (banned)\n", addr.ToString().c_str()); closesocket(hSocket); } else { - printf("accepted connection %s\n", addr.ToString().c_str()); + printf("I2P accepted connection %s\n", addr.ToString().c_str()); CNode* pnode = new CNode(hSocket, addr, "", true); pnode->AddRef(); { From f66948ff86b8f4467af87835a3b1e734f80ab36f Mon Sep 17 00:00:00 2001 From: carsenk Date: Thu, 8 Aug 2019 15:10:57 -0600 Subject: [PATCH 16/26] std::cout to printf and some other cleanup --- src/fortuna.cpp | 5 ++++- src/fortunastake.cpp | 4 ++-- src/i2psam.cpp | 22 ++++++++++++++-------- src/qt/bitcoingui.cpp | 2 -- src/qt/walletmodel.cpp | 23 ----------------------- 5 files changed, 20 insertions(+), 36 deletions(-) diff --git a/src/fortuna.cpp b/src/fortuna.cpp index 5c12ec46..07dbac91 100644 --- a/src/fortuna.cpp +++ b/src/fortuna.cpp @@ -808,7 +808,9 @@ bool CForTunaSigner::IsVinAssociatedWithPubkey(CTxIn& vin, CPubKey& pubkey){ if(GetTransaction(vin.prevout.hash, txVin, hash)){ CTxOut out = txVin.vout[vin.prevout.n]; - if ((out.nValue == GetMNCollateral()*COIN) && (out.scriptPubKey == payee2)) + //for (int i = 1; i < out; i++) + + if ((out.nValue == GetMNCollateral()*COIN) && (out.scriptPubKey == payee2)) //&& (i == 1) ? { return true; } @@ -821,6 +823,7 @@ bool CForTunaSigner::IsVinAssociatedWithPubkey(CTxIn& vin, CPubKey& pubkey){ CTxDestination address1; ExtractDestination(payee2, address1); CBitcoinAddress address2(address1); + if (fDebug) { printf("IsVinAssociatedWithPubKey:: vin %s is not associated with pubkey %s for address %s\n", vin.ToString().c_str(), pubkey.GetHash().ToString().c_str(), address2.ToString().c_str()); diff --git a/src/fortunastake.cpp b/src/fortunastake.cpp index 13982c0f..3ab3f523 100644 --- a/src/fortunastake.cpp +++ b/src/fortunastake.cpp @@ -617,7 +617,7 @@ int GetFortunastakeRank(CFortunaStake &tmn, CBlockIndex* pindex, int minProtocol } bool CheckFSPayment(CBlockIndex* pindex, int64_t value, CFortunaStake &mn) { - //if (mn.nBlockLastPaid == 0) return true; // if we didn't find a payment for this MN, let it through regardless of rate + if (mn.nBlockLastPaid == 0) return true; // if we didn't find a payment for this MN, let it through regardless of rate // find height // calculate average payment across all FS // check if value is > 25% higher @@ -1508,7 +1508,7 @@ bool CFortunaPayments::initialize(const CBlockIndex *pindex) CTxDestination address1; ExtractDestination(rec.scriptPubKey, address1); CBitcoinAddress address2(address1); - printf("Height %d: MN Address %s secured by collateral %s\n",rec.height,address2.ToString().c_str(),rec.vin.ToString().c_str()); + printf("Height %d: FS D Address %s secured by collateral %s\n",rec.height,address2.ToString().c_str(),rec.vin.ToString().c_str()); } } diff --git a/src/i2psam.cpp b/src/i2psam.cpp index 9d6fea9e..a441ba3f 100644 --- a/src/i2psam.cpp +++ b/src/i2psam.cpp @@ -40,9 +40,11 @@ namespace SAM static void print_error(const std::string& err) { #ifdef WIN32 - std::cout << err << "(" << WSAGetLastError() << ")" << std::endl; + printf("I2P SAM WIN32 Error: %s: %d.\n", err.c_str(), WSAGetLastError()); + //std::cout << err << "(" << WSAGetLastError() << ")" << std::endl; #else - std::cout << err << "(" << errno << ")" << std::endl; + printf("I2P SAM Error: %s: %d.\n", err.c_str(), errno); + //std::cout << err << "(" << errno << ")" << std::endl; #endif } @@ -160,7 +162,8 @@ void Socket::write(const std::string& msg) print_error("Failed to send data because socket is closed"); return; } - std::cout << "Send: " << msg << std::endl; + printf("I2P SAM Send: %s\n", msg.c_str()); + //std::cout << "Send: " << msg << std::endl; ssize_t sentBytes = send(socket_, msg.c_str(), msg.length(), 0); if (sentBytes == SAM_SOCKET_ERROR) { @@ -197,7 +200,8 @@ std::string Socket::read() close(); print_error("Socket was closed"); } - std::cout << "Reply: " << buffer << std::endl; + printf("I2P SAM Reply: %d\n", buffer); + //std::cout << "Reply: " << buffer << std::endl; return std::string(buffer); } @@ -261,7 +265,8 @@ StreamSession::StreamSession( , isSick_(false) { myDestination_ = createStreamSession(destination); - std::cout << "Created a brand new SAM session (" << sessionID_ << ")" << std::endl; + printf("I2P SAM Created a brand new SAM session: %d\n", sessionID_.c_str()); + //std::cout << "Created a brand new SAM session (" << sessionID_ << ")" << std::endl; } StreamSession::StreamSession(StreamSession& rhs) @@ -278,14 +283,15 @@ StreamSession::StreamSession(StreamSession& rhs) for(ForwardedStreamsContainer::const_iterator it = rhs.forwardedStreams_.begin(), end = rhs.forwardedStreams_.end(); it != end; ++it) forward(it->host, it->port, it->silent); - - std::cout << "Created a new SAM session (" << sessionID_ << ") from another (" << rhs.sessionID_ << ")" << std::endl; + printf("I2P SAM Created a new SAM session: %d from another %s\n", sessionID_.c_str(), rhs.sessionID_.c_str()); + //std::cout << "Created a new SAM session (" << sessionID_ << ") from another (" << rhs.sessionID_ << ")" << std::endl; } StreamSession::~StreamSession() { stopForwardingAll(); - std::cout << "Closing SAM session (" << sessionID_ << ") ..." << std::endl; + printf("I2P SAM Closing SAM Session: %d\n", sessionID_.c_str()); + //std::cout << "Closing SAM session (" << sessionID_ << ") ..." << std::endl; } /*static*/ diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 74360826..b15f6cee 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -850,9 +850,7 @@ void BitcoinGUI::showGeneratedI2PAddr(const QString& caption, const QString& pub ShowI2PAddresses i2pDialog(caption, pub, priv, b32, configFileName, this); i2pDialog.exec(); } -#endif -#ifdef USE_NATIVE_I2P void BitcoinGUI::setNumI2PConnections(int count) { if(fNativeI2P) { diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index e317a679..b304546f 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -676,29 +676,6 @@ void WalletModel::getOutputs(const std::vector& vOutpoints, std::vect vOutputs.push_back(out); } } -/* -// AvailableCoins + LockedCoins grouped by wallet address (put change in one group with wallet address) -void WalletModel::listCoins(std::map >& mapCoins) const -{ - std::vector vCoins; - wallet->AvailableCoins(vCoins); - - BOOST_FOREACH(const COutput& out, vCoins) - { - COutput cout = out; - while (wallet->IsChange(cout.tx->vout[cout.i]) && cout.tx->vin.size() > 0 && wallet->IsMine(cout.tx->vin[0], ISMINE_SPENDABLE)) - { - if (!wallet->mapWallet.count(cout.tx->vin[0].prevout.hash)) break; - //cout = COutput(&wallet->mapWallet[cout.tx->vin[0].prevout.hash], cout.tx->vin[0].prevout.n, 0); - cout = COutput(&wallet->mapWallet[cout.tx->vin[0].prevout.hash], cout.tx->vin[0].prevout.n, 0, true); - } - - CTxDestination address; - if(!ExtractDestination(cout.tx->vout[cout.i].scriptPubKey, address)) continue; - mapCoins[CBitcoinAddress(address).ToString().c_str()].push_back(out); - } -} -*/ // AvailableCoins + LockedCoins grouped by wallet address (put change in one group with wallet address) void WalletModel::listCoins(std::map >& mapCoins) const From 6573031f1fbd554ea3ab9ab5911d7108a87e099b Mon Sep 17 00:00:00 2001 From: carsenk Date: Fri, 9 Aug 2019 16:52:12 -0600 Subject: [PATCH 17/26] Fix debug log and added getnetworkinfo --- src/addrman.h | 2 +- src/bitcoinrpc.cpp | 1 + src/bitcoinrpc.h | 1 + src/init.cpp | 37 +++++--- src/net.cpp | 69 ++++++++++---- src/net.h | 7 ++ src/netbase.cpp | 14 ++- src/rpcnet.cpp | 229 ++++++++++++++++++++++++++++++++++++++++++++- 8 files changed, 327 insertions(+), 33 deletions(-) diff --git a/src/addrman.h b/src/addrman.h index 3afe0aad..01962e9c 100644 --- a/src/addrman.h +++ b/src/addrman.h @@ -156,7 +156,7 @@ class CAddrInfo : public CAddress #define ADDRMAN_MIN_FAIL_DAYS 7 // the maximum percentage of nodes to return in a getaddr call -#define ADDRMAN_GETADDR_MAX_PCT 23 +#define ADDRMAN_GETADDR_MAX_PCT 100 // Get 100% instead of 23% // the maximum number of nodes to return in a getaddr call #define ADDRMAN_GETADDR_MAX 2500 diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp index 7dc1817b..d3704d35 100644 --- a/src/bitcoinrpc.cpp +++ b/src/bitcoinrpc.cpp @@ -270,6 +270,7 @@ static const CRPCCommand vRPCCommands[] = { "getaddednodeinfo", &getaddednodeinfo, true, true }, { "ping", &ping, true, true }, { "getnettotals", &getnettotals, true, false }, + { "getnetworkinfo", &getnetworkinfo, true, false }, { "dumpbootstrap", &dumpbootstrap, false, false }, { "getdifficulty", &getdifficulty, true, false }, { "getinfo", &getinfo, true, false }, diff --git a/src/bitcoinrpc.h b/src/bitcoinrpc.h index c07cd873..cd708902 100644 --- a/src/bitcoinrpc.h +++ b/src/bitcoinrpc.h @@ -158,6 +158,7 @@ extern json_spirit::Value addnode(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value ping(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value getaddednodeinfo(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value getnettotals(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value getnetworkinfo(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value dumpwallet(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value importwallet(const json_spirit::Array& params, bool fHelp); diff --git a/src/init.cpp b/src/init.cpp index 26833ca0..14ebd782 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -691,7 +691,7 @@ bool AppInit2() if (GetBoolArg("-shrinkdebugfile", !fDebug)) ShrinkDebugFile(); - printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); + printf("\n"); printf("Denarius version %s (%s)\n", FormatFullVersion().c_str(), CLIENT_DATE.c_str()); printf("Using OpenSSL version %s\n", SSLeay_version(SSLEAY_VERSION)); if (!fLogTimestamps) @@ -700,14 +700,6 @@ bool AppInit2() printf("Used data directory %s\n", strDataDir.c_str()); std::ostringstream strErrors; - if (mapArgs.count("-fortunastakepaymentskey")) // fortunastake payments priv key - { - if (!fortunastakePayments.SetPrivKey(GetArg("-fortunastakepaymentskey", ""))) - return InitError(_("Unable to sign fortunastake payment winner, wrong key?")); - if (!sporkManager.SetPrivKey(GetArg("-fortunastakepaymentskey", ""))) - return InitError(_("Unable to sign spork message, wrong key?")); - } - //ignore fortunastakes below protocol version CFortunaStake::minProtoVersion = GetArg("-fortunastakeminprotocol", MIN_MN_PROTO_VERSION); @@ -788,6 +780,15 @@ bool AppInit2() BOOST_FOREACH(std::string snet, mapMultiArgs["-onlynet"]) { enum Network net = ParseNetwork(snet); + if (net == NET_NATIVE_I2P) + { + // Disable upnp and IRC and listen on I2P only. +#ifdef USE_UPNP + SoftSetBoolArg("-upnp", false); +#endif + SoftSetBoolArg("-listen",true); + SoftSetBoolArg("-discover",false); + } if (net == NET_UNROUTABLE) return InitError(strprintf(_("Unknown network specified in -onlynet: '%s'"), snet.c_str())); nets.insert(net); @@ -835,7 +836,7 @@ bool AppInit2() }; }; - +#ifdef USE_NATIVETOR // Native Tor Onion and -tor flag integration if(fNativeTor) { @@ -853,9 +854,21 @@ bool AppInit2() SetReachable(NET_TOR); }; }; - +#endif +#ifdef USE_NATIVE_I2P + // -i2p can override both tor and proxy + if ((mapArgs.count("-i2p") && mapArgs["-i2p"] != "0") || IsI2POnly() && fNativeI2P) + { + // Disable on i2p per default +#ifdef USE_UPNP + SoftSetBoolArg("-upnp", false); +#endif + SoftSetBoolArg("-listen",true); + SetReachable(NET_NATIVE_I2P); + } +#endif // see Step 2: parameter interactions for more information about these - if(!fNativeTor) // Available if nativetor are disabled + if(!fNativeTor && !fNativeI2P) // Available if nativetor are disabled { fNoListen = !GetBoolArg("-listen", true); fDiscover = GetBoolArg("-discover", true); diff --git a/src/net.cpp b/src/net.cpp index ab2e4e44..93ba74ab 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -39,7 +39,7 @@ extern "C" { } #endif -static const int MAX_OUTBOUND_CONNECTIONS = 16; +static const int MAX_OUTBOUND_CONNECTIONS = 27; //Bumping up to 27 from 16 void ThreadMessageHandler2(void* parg); void ThreadSocketHandler2(void* parg); @@ -51,12 +51,6 @@ void ThreadMapPort2(void* parg); void ThreadDNSAddressSeed2(void* parg); bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound = NULL, const char *strDest = NULL, bool fOneShot = false); - -struct LocalServiceInfo { - int nScore; - int nPort; -}; - // // Global state variables // @@ -67,8 +61,8 @@ uint64_t nLocalServices = NODE_I2P | NODE_NETWORK; #else uint64_t nLocalServices = NODE_NETWORK; #endif -static CCriticalSection cs_mapLocalHost; -static map mapLocalHost; +CCriticalSection cs_mapLocalHost; +map mapLocalHost; static bool vfReachable[NET_MAX] = {}; static bool vfLimited[NET_MAX] = {}; static CNode* pnodeLocalHost = NULL; @@ -1543,6 +1537,13 @@ void ThreadOnionSeed(void* parg) // The first name is used as information source for addrman. // The second name should resolve to a list of seed addresses. +#ifdef USE_NATIVE_I2P +static const char *strI2PDNSSeed[][2] = { + {"d4gii55rnvv22qm2ojre2n67bzms5utr4k3ckafwjdoym2cqmv2q.b32.i2p", "d4gii55rnvv22qm2ojre2n67bzms5utr4k3ckafwjdoym2cqmv2q.b32.i2p"}, // need some valid I2P DNS seeds + {"dd37luxnbh3hkihxfl2e7nwosebh5sbfvpvjqwn7c3g5kqftb5qq.b32.i2p", "dd37luxnbh3hkihxfl2e7nwosebh5sbfvpvjqwn7c3g5kqftb5qq.b32.i2p"} +}; +#endif + static const char *strDNSSeed[][2] = { {"dnsseed.hashbag.cc", "dnsseed.hashbag.cc"}, {"seed.denarius.host", "seed.denarius.host"}, @@ -1583,7 +1584,31 @@ void ThreadDNSAddressSeed2(void* parg) if (!fTestNet) { printf("Loading addresses from DNS seeds (could take a while)\n"); - +#ifdef USE_NATIVE_I2P + if (fNativeI2P) { + for (unsigned int seed_idx = 0; seed_idx < ARRAYLEN(strI2PDNSSeed); seed_idx++) { + if (HaveNameProxy()) { + AddOneShot(strI2PDNSSeed[seed_idx][1]); + } else { + vector vaddr; + vector vAdd; + if (LookupHost(strI2PDNSSeed[seed_idx][1], vaddr)) { + BOOST_FOREACH(CNetAddr& ip, vaddr) { + int nOneDay = 24*3600; + CAddress addr = CAddress(CService(ip, GetDefaultPort())); + addr.nTime = GetTime() - 3*nOneDay - GetRand(4*nOneDay); // use a random age between 3 and 7 days old + vAdd.push_back(addr); + found++; + } + } + addrman.Add(vAdd, CNetAddr(strI2PDNSSeed[seed_idx][0], true)); + } + } + // Prefer I2P, if 4 is found, drop the clearnet dnsseed + if (found>4) + return; + } +#endif for (unsigned int seed_idx = 0; seed_idx < ARRAYLEN(strDNSSeed); seed_idx++) { if (HaveNameProxy()) { AddOneShot(strDNSSeed[seed_idx][1]); @@ -1611,18 +1636,17 @@ void ThreadDNSAddressSeed2(void* parg) }; - - - - - - - unsigned int pnSeed[] = { 0x42ac0c50, }; +#ifdef USE_NATIVE_I2P +const std::string pstrI2PSeed[] = { + "Dw-NRnXaxoGZdyupTXX78~CmF8csc~RhJr8XR2vMbNpazKhGjWNfRjhCmwqXkkW9vwkNjovW2AAbof7PfVnMCff0sHSxMTiBNsH8cuHJS2ckBSJI3h4G4ffJLc5gflangrG1raHKrMXCw8Cn56pisx4RKokEKUYdeEPiMdyJUO5yjZW2oyk4NpaUaQCqFmcglIvNOCYzVe~LK124wjJQAJc5iME1Sg9sOHaGMPL5N2qkAm5osOg2S7cZNRdIkoNOq-ztxghrv5bDL0ybeC0sfIQzvxDiKugCrSHEHCvwkA~xOu9nhNlUvoPDyCRRi~ImeomdNoqke28di~h2JF7wBGE~3ACxxOMaa0I~c9LV3O7pRU2Xj9HDn76eMGL7YCcCU4dRByu97oqfB3E~qqmmFp8W1tgvnEAMtXFTFZPYc33ZaCaIJQD7UXcQRSRV7vjw39jhx49XFsmYV3K6~D8bN8U4sRJnKQpzOJGpOSEJWh88bII0XuA55bJsfrR4VEQ5AAAA", // need valid + "dL51K8bxVvqX2Z4epXReUYlWTNUAK-1XdlbBd7e796s2A3icCQRhJvGlaa6PX~tgPvos-2IJp9hFQrVa0lyKyYmpQN9X7GOErtsL-JbMQpglQsEd94jDRAsiBuvgyPZij~NNdBxKRMDvNm9s7eovzhEFTAimTSB-sgeZ4Afxx2IrNXDFM6KS8AUm8YsaMldzX9zKQDeuV0slp4ZfIAVQhZZy9zTZSmUNPnXQR7XPh5w7FkXzmKMTKSyG~layJ3AorQWqzZXmykzf4z3CE4zkzQcwc0~ZIcAg9tYvM2AdQIdgeN6ISMim6L8q6ku6abuONkyw-NJTi3NopeGHZva21Tc3uHetsKoW434N24HBVUtIjJVjGsbZ7xBfz2xM5kyhPl6SlD-RJarCw47Rovmfc9Piq6q3S~Zw-rvRl-xDMJzwraIYNjAROouDwjI9Bqnguq9DH5uFBxf4uN69X7T~yWTAjdvelZKp6BGe~HGo7bNQjBmymhlH4erCKZEXOaxDAAAA" +}; +#endif void DumpAddresses() @@ -1784,6 +1808,17 @@ void ThreadOpenConnections2(void* parg) addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek; vAdd.push_back(addr); } +#ifdef USE_NATIVE_I2P + if (fNativeI2P) { + for (size_t i = 0; i < ARRAYLEN(pstrI2PSeed); i++) + { + const int64_t nOneWeek = 7*24*60*60; + CAddress addr(CService((const std::string&)pstrI2PSeed[i])); + addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek; + vAdd.push_back(addr); + } + } +#endif addrman.Add(vAdd, CNetAddr("127.0.0.1")); } diff --git a/src/net.h b/src/net.h index 446e0731..04b74d50 100644 --- a/src/net.h +++ b/src/net.h @@ -165,6 +165,13 @@ extern std::map mapAlreadyAskedFor; extern NodeId nLastNodeId; extern CCriticalSection cs_nLastNodeId; +struct LocalServiceInfo { + int nScore; + int nPort; +}; + +extern CCriticalSection cs_mapLocalHost; +extern std::map mapLocalHost; class CNodeStateStats { diff --git a/src/netbase.cpp b/src/netbase.cpp index c4849a55..1898461d 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -373,7 +373,7 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe int nRet = select(hSocket + 1, NULL, &fdset, NULL, &timeout); if (nRet == 0) { - printf("net", "connection to %s timeout\n", addrConnect.ToString().c_str()); + printf("net connection to %s timeout\n", addrConnect.ToString().c_str()); closesocket(hSocket); return false; } @@ -1152,6 +1152,13 @@ int CNetAddr::GetReachabilityFrom(const CNetAddr *paddrPartner) const default: return REACH_DEFAULT; case NET_I2P: return REACH_PRIVATE; } +#ifdef USE_NATIVE_I2P + case NET_NATIVE_I2P: + switch(ourNet) { + default: return REACH_UNREACHABLE; + case NET_NATIVE_I2P: return REACH_PRIVATE; + } +#endif case NET_TEREDO: switch(ourNet) { default: return REACH_DEFAULT; @@ -1168,7 +1175,10 @@ int CNetAddr::GetReachabilityFrom(const CNetAddr *paddrPartner) const case NET_IPV6: return REACH_IPV6_WEAK; case NET_IPV4: return REACH_IPV4; case NET_I2P: return REACH_PRIVATE; // assume connections from unroutable addresses are - case NET_TOR: return REACH_PRIVATE; // either from Tor/I2P, or don't care about our address + case NET_TOR: return REACH_PRIVATE; // either from Tor, or don't care about our address +#ifdef USE_NATIVE_I2P + case NET_NATIVE_I2P: return REACH_UNREACHABLE; +#endif } } } diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp index 3a544871..47f052a4 100644 --- a/src/rpcnet.cpp +++ b/src/rpcnet.cpp @@ -41,6 +41,145 @@ Value ping(const Array& params, bool fHelp) return Value::null; } +/* +#ifdef USE_NATIVE_I2P +Value destination(const Array& params, bool fHelp) +{ + if (fHelp || params.size() > 2) + throw runtime_error( + "destination [\"match|good|attempt|connect\"] [\"b32.i2p|base64|ip:port\"]\n" + "\n Returns I2P destination details stored in your b32.i2p address manager lookup system.\n" + "\nArguments:\n" + " If no arguments are provided, the command returns all the b32.i2p addresses. NOTE: Results will not include base64\n" + " 1st argument = \"match\" then a 2nd argument is also required.\n" + " 2nd argument = Any string. If a match is found in any of the address, source or base64 fields, that result will be returned.\n" + " 1st argument = \"good\" destinations that has been tried, connected and found to be good will be returned.\n" + " 1st argument = \"attempt\" destinations that have been attempted, will be returned.\n" + " 1st argument = \"connect\" destinations that have been connected to in the past, will be returned.\n" + "\nResults are returned as a json array of object(s).\n" + " The 1st result pair is the total size of the address hash map.\n" + " The 2nd result pair is the number of objects which follow, as matching this query. It can be zero, if no match was found.\n" + "\nResult:\n" + "[\n" + " {\n" + " \"tablesize\": nnn, (numeric) The total number of destinations in the i2p address book\n" + " \"matchsize\": nnn, (numeric) The number of results returned, which matched your query\n" + " }\n" + " {\n" + " \"address\":\"b32.i2p\", (string) Base32 hash of a i2p destination, a possible peer\n" + " \"good\": true|false, (boolean) Has this address been tried & found to be good\n" + " \"attempt\": nnn, (numeric) The number of times it has been attempted\n" + " \"lasttry\": ttt, (numeric) The time of a last attempted connection (memory only)\n" + " \"connect\": ttt, (numeric) The time of a last successful connection\n" + " \"source\":\"b32.i2p|ip:port\", (string) The source of information about this address\n" + " \"base64\":\"destination\", (string) The full Base64 Public Key of this peers b32.i2p address\n" + " }\n" + " ,...\n" + "]\n" + "\nNOTE: The results obtained are only a snapshot, while you are connected to the network.\n" + " Peers are updating addresses & destinations all the time.\n" + "\nExamples: destination good|attempt|connect|match returns all I2P destinations currently known about on the system.\n" + "\nExamples: destination good returns the I2P destinations marked as 'good', happens if they have been tried and a successful version handshake made.\n" + "\nExample: destination attempt returns I2P destinations marked as having made an attempt to connect\n" + "\nExample: destination connect returns I2P destinations which are marked as having been connected to.\n" + "\nExamples: destination match returns I2P destination entries which came from the 'source' IP address 215.49.103.xxx\n" + "\nExamples: destination match returns all I2P b32.i2p destinations which match the patter, these could be found in the 'source' or the 'address' fields.\n" + ); + //! We must not have node or main processing as Addrman needs to + //! be considered static for the time required to process this. + LOCK2(cs_main, cs_vNodes); + + bool fSelectedMatch = false; + bool fMatchStr = false; + bool fMatchTried = false; + bool fMatchAttempt = false; + bool fMatchConnect = false; + bool fUnknownCmd = false; + string sMatchStr; + + if( params.size() > 0 ) { // Lookup the address and return the one object if found + string sCmdStr = params[0].get_str(); + if( sCmdStr == "match" ) { + if( params.size() > 1 ) { + sMatchStr = params[1].get_str(); + fMatchStr = true; + } else + fUnknownCmd = true; + } else if( sCmdStr == "good" ) + fMatchTried = true; + else if( sCmdStr == "attempt" ) + fMatchAttempt = true; + else if( sCmdStr == "connect") + fMatchConnect = true; + else + fUnknownCmd = true; + fSelectedMatch = true; + } + + Array ret; + // Load the vector with all the objects we have and return with + // the total number of addresses we have on file + vector vecStats; + int nTableSize = addrman.CopyDestinationStats(vecStats); + if( !fUnknownCmd ) { // If set, throw runtime error + for( int i = 0; i < 2; i++ ) { // Loop through the data twice + bool fMatchFound = false; // Assume no match + int nMatchSize = 0; // the match counter + BOOST_FOREACH(const CDestinationStats& stats, vecStats) { + if( fSelectedMatch ) { + if( fMatchStr ) { + if( stats.sAddress.find(sMatchStr) != string::npos || + stats.sSource.find(sMatchStr) != string::npos || + stats.sBase64.find(sMatchStr) != string::npos ) + fMatchFound = true; + } else if( fMatchTried ) { + if( stats.fInTried ) fMatchFound = true; + } + else if( fMatchAttempt ) { + if( stats.nAttempts > 0 ) fMatchFound = true; + } + else if( fMatchConnect ) { + if( stats.nSuccessTime > 0 ) fMatchFound = true; + } + } else // Match everything + fMatchFound = true; + + if( i == 1 && fMatchFound ) { + Object obj; + obj.push_back(Pair("address", stats.sAddress)); + obj.push_back(Pair("good", stats.fInTried)); + obj.push_back(Pair("attempt", stats.nAttempts)); + obj.push_back(Pair("lasttry", stats.nLastTry)); + obj.push_back(Pair("connect", stats.nSuccessTime)); + obj.push_back(Pair("source", stats.sSource)); + //! Do to an RPC buffer limit of 65535 with stream output, we can not send these and ever get a result + //! This should be considered a short term fix ToDo: Allocate bigger iostream buffer for the output + if( fSelectedMatch ) + obj.push_back(Pair("base64", stats.sBase64)); + ret.push_back(obj); + } + if( fMatchFound ) { + nMatchSize++; + fMatchFound = false; + } + } + // The 1st time we get a count of the matches, so we can list that first in the results, + // then we finally build the output objects, on the 2nd pass...and don't put this in there twice + if( i == 0 ) { + Object objSizes; + objSizes.push_back(Pair("tablesize", nTableSize)); + objSizes.push_back(Pair("matchsize", nMatchSize)); + ret.push_back(objSizes); // This is the 1st object put on the Array + } + } + } else + throw runtime_error( "Unknown subcommand or argument missing" ); + + return ret; +} +#endif +*/ + static void CopyNodeStats(std::vector& vstats) { vstats.clear(); @@ -54,6 +193,91 @@ static void CopyNodeStats(std::vector& vstats) } } +static Array GetNetworksInfo() +{ + Array networks; + for(int n=0; n(n); + if(network == NET_UNROUTABLE) + continue; + proxyType proxy; + Object obj; + GetProxy(network, proxy); + obj.push_back(Pair("name", GetNetworkName(network))); + obj.push_back(Pair("limited", IsLimited(network))); + //obj.push_back(Pair("reachable", IsReachable(network))); + //obj.push_back(Pair("proxy", proxy.IsValid() ? proxy.ToStringIPPort() : string())); + networks.push_back(obj); + } + return networks; +} + +static const string SingleAlertSubVersionsString( const std::set& setVersions ) +{ + std::string strSetSubVer; + BOOST_FOREACH(std::string str, setVersions) { + if(strSetSubVer.size()) // Must be more than one + strSetSubVer += " or "; + strSetSubVer += str; + } + return strSetSubVer; +} + +Value getnetworkinfo(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 0) + throw runtime_error( + "getnetworkinfo\n" + " Returns an object containing various state info regarding P2P networking.\n" + "\nResult:\n" + "{\n" + " \"version\": xxxxx, (numeric) the server version\n" + " \"subver\": \"/s:n.n.n.n/\", (string) this clients subversion string\n" + " \"protocolversion\": xxxxx, (numeric) the protocol version\n" + " \"localservices\": \"xxxx\", (hex string) Our local service bits as a 16 char string.\n" + " \"timeoffset\": xxxxx, (numeric) the time offset\n" + " \"connections\": xxxxx, (numeric) the number of connections\n" + " \"networkconnections\": [ (array) the state of each possible network connection type\n" + " \"name\": \"xxx\", (string) network name\n" + " \"limited\" : true|false, (boolean) if service is limited\n" + " ]\n" + " \"localaddresses\": [ (array) list of local addresses\n" + " \"address\": \"xxxx\", (string) network address\n" + " \"port\": xxx, (numeric) network port\n" + " \"score\": xxx (numeric) relative score\n" + " ]\n" + "}\n" + ); + + LOCK(cs_main); + + Object obj; + obj.push_back(Pair("version", (int)CLIENT_VERSION)); + obj.push_back(Pair("subversion", FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector()))); + obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION)); + obj.push_back(Pair("localservices", strprintf("%016", PRIx64, nLocalServices))); + obj.push_back(Pair("timeoffset", GetTimeOffset())); + obj.push_back(Pair("connections", (int)vNodes.size())); + //obj.push_back(Pair("relayfee", ValueFromAmount(minRelayTxFee.GetFeePerK()))); + obj.push_back(Pair("networkconnections",GetNetworksInfo())); + Array localAddresses; + { + LOCK(cs_mapLocalHost); + BOOST_FOREACH(const PAIRTYPE(CNetAddr, LocalServiceInfo) &item, mapLocalHost) + { + Object rec; + rec.push_back(Pair("address", item.first.ToString())); + rec.push_back(Pair("port", item.second.nPort)); + rec.push_back(Pair("score", item.second.nScore)); + localAddresses.push_back(rec); + } + } + obj.push_back(Pair("localaddresses", localAddresses)); + + return obj; +} + Value getpeerinfo(const Array& params, bool fHelp) { if (fHelp || params.size() != 0) @@ -72,10 +296,13 @@ Value getpeerinfo(const Array& params, bool fHelp) obj.push_back(Pair("addr", stats.addrName)); if (!(stats.addrLocal.empty())) obj.push_back(Pair("addrlocal", stats.addrLocal)); - obj.push_back(Pair("services", strprintf("%08" PRIx64, stats.nServices))); + obj.push_back(Pair("services", strprintf("%016" PRIx64, stats.nServices))); obj.push_back(Pair("lastsend", (int64_t)stats.nLastSend)); obj.push_back(Pair("lastrecv", (int64_t)stats.nLastRecv)); obj.push_back(Pair("conntime", (int64_t)stats.nTimeConnected)); + obj.push_back(Pair("pingtime", stats.dPingTime)); //return nodes ping time + if (stats.dPingWait > 0.0) + obj.push_back(Pair("pingwait", stats.dPingWait)); obj.push_back(Pair("version", stats.nVersion)); obj.push_back(Pair("subver", stats.strSubVer)); obj.push_back(Pair("inbound", stats.fInbound)); From f1596f9a3c8713baf9104b9c898c2603bb75eabd Mon Sep 17 00:00:00 2001 From: carsenk Date: Fri, 9 Aug 2019 21:09:33 -0600 Subject: [PATCH 18/26] Update getinfo to include i2p b32 ip if nativei2p enabled --- src/rpcwallet.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index 72cb29c7..40612f8b 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -131,12 +131,14 @@ Value getinfo(const Array& params, bool fHelp) #ifdef USE_NATIVE_I2P if (fNativeI2P) { - //const string destination; - //string i2p_address = I2PSession::GenerateB32AddressFromDestination(destination.string().c_str()); - //obj.push_back(Pair("i2p", (i2p_address))); + if (IsI2POnly()) { + obj.push_back(Pair("onlynet", ("native_i2p"))); + } + std::string i2p_address = I2PSession::GenerateB32AddressFromDestination(addrSeenByPeer.GetI2PDestination()); // Not the best way yet + obj.push_back(Pair("i2p", (i2p_address.c_str()))); } #endif - if(!fNativeTor) // && !fNativeI2P + if(!fNativeTor && !fNativeI2P) obj.push_back(Pair("ip", addrSeenByPeer.ToStringIP())); diff.push_back(Pair("proof-of-work", GetDifficulty())); From 86c6a6e13bd3f1dcbb0663ae27f26a8b40be15e5 Mon Sep 17 00:00:00 2001 From: carsenk Date: Sat, 10 Aug 2019 00:00:20 -0600 Subject: [PATCH 19/26] Native I2P Updates and new i2pdebug.log --- src/i2p.cpp | 213 ++++++++++++++++++++++++++++-------------------- src/i2p.h | 33 +++++--- src/i2psam.cpp | 85 +++++++++---------- src/i2psam.h | 29 +++---- src/init.cpp | 22 ++--- src/main.cpp | 1 - src/net.h | 4 +- src/netbase.cpp | 39 +++++++-- src/netbase.h | 2 +- 9 files changed, 252 insertions(+), 176 deletions(-) diff --git a/src/i2p.cpp b/src/i2p.cpp index 0713eb32..e5d1abdd 100644 --- a/src/i2p.cpp +++ b/src/i2p.cpp @@ -1,8 +1,10 @@ // Copyright (c) 2012-2013 giv +// Copyright (c) 2019 Denarius developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. //-------------------------------------------------------------------------------------------------- #include +#include #include "i2p.h" #include "util.h" #include "hash.h" @@ -13,164 +15,203 @@ namespace SAM class StreamSessionAdapter::SessionHolder { public: - explicit SessionHolder(std::auto_ptr session); + explicit SessionHolder(std::shared_ptr session); + ~SessionHolder(); - const SAM::StreamSession& getSession() const; - SAM::StreamSession& getSession(); + const SAM::StreamSession& getSession() const; + SAM::StreamSession& getSession(); private: - void heal() const; - void reborn() const; + void heal() const; + void reborn() const; - mutable std::auto_ptr session_; - typedef boost::shared_mutex mutex_type; - mutable mutex_type mtx_; + mutable std::shared_ptr session_; + typedef boost::shared_mutex mutex_type; + mutable mutex_type mtx_; }; -StreamSessionAdapter::SessionHolder::SessionHolder(std::auto_ptr session) - : session_(session) -{} +StreamSessionAdapter::SessionHolder::SessionHolder(std::shared_ptr session) + : session_(session) +{ +} + +StreamSessionAdapter::SessionHolder::~SessionHolder() +{ +} const SAM::StreamSession& StreamSessionAdapter::SessionHolder::getSession() const { - boost::upgrade_lock lock(mtx_); - if (session_->isSick()) - { - boost::upgrade_to_unique_lock ulock(lock); - heal(); - } - return *session_; + boost::upgrade_lock lock(mtx_); + if (session_->isSick()) + { + boost::upgrade_to_unique_lock ulock(lock); + heal(); + } + return *session_; } SAM::StreamSession& StreamSessionAdapter::SessionHolder::getSession() { - boost::upgrade_lock lock(mtx_); - if (session_->isSick()) - { - boost::upgrade_to_unique_lock ulock(lock); - heal(); - } - return *session_; + boost::upgrade_lock lock(mtx_); + if (session_->isSick()) + { + boost::upgrade_to_unique_lock ulock(lock); + heal(); + } + return *session_; } void StreamSessionAdapter::SessionHolder::heal() const { - reborn(); // if we don't know how to heal it just reborn it + reborn(); // if we don't know how to heal it just reborn it } void StreamSessionAdapter::SessionHolder::reborn() const { - if (!session_->isSick()) - return; - std::auto_ptr newSession(new SAM::StreamSession(*session_)); - if (!newSession->isSick() && session_->isSick()) - { - session_ = newSession; - } + if (!session_->isSick()) + return; + std::shared_ptr newSession(new SAM::StreamSession(*session_)); + if (!newSession->isSick() && session_->isSick()) + session_ = newSession; } //-------------------------------------------------------------------------------------------------- -StreamSessionAdapter::StreamSessionAdapter( - const std::string& nickname, - const std::string& SAMHost /*= SAM_DEFAULT_ADDRESS*/, - uint16_t SAMPort /*= SAM_DEFAULT_PORT*/, - const std::string& myDestination /*= SAM_GENERATE_MY_DESTINATION*/, - const std::string& i2pOptions /*= SAM_DEFAULT_I2P_OPTIONS*/, - const std::string& minVer /*= SAM_DEFAULT_MIN_VER*/, - const std::string& maxVer /*= SAM_DEFAULT_MAX_VER*/) - : sessionHolder_( - new SessionHolder( - std::auto_ptr( - new SAM::StreamSession(nickname, SAMHost, SAMPort, myDestination, i2pOptions, minVer, maxVer)))) -{} +StreamSessionAdapter::StreamSessionAdapter() +{ + SAM::StreamSession::SetLogFile ((GetDataDir() / "i2pdebug.log").string ()); +} StreamSessionAdapter::~StreamSessionAdapter() -{} +{ + SAM::StreamSession::CloseLogFile (); +} + +bool StreamSessionAdapter::StartSession ( + const std::string& nickname, + const std::string& SAMHost /*= SAM_DEFAULT_ADDRESS*/, + uint16_t SAMPort /*= SAM_DEFAULT_PORT*/, + const std::string& myDestination /*= SAM_GENERATE_MY_DESTINATION*/, + const std::string& i2pOptions /*= SAM_DEFAULT_I2P_OPTIONS*/, + const std::string& minVer /*= SAM_DEFAULT_MIN_VER*/, + const std::string& maxVer /*= SAM_DEFAULT_MAX_VER*/) +{ + std::cout << "Creating Denarius I2P SAM session..." << std::endl; + auto s = std::make_shared(nickname, SAMHost, SAMPort, myDestination, i2pOptions, minVer, maxVer); + sessionHolder_ = std::make_shared(s); + bool isReady = s->isReady (); + if (isReady) + std::cout << "Denarius I2P SAM session created" << std::endl; + else + std::cout << "Denarius I2P SAM session failed" << std::endl; + return isReady; +} + +void StreamSessionAdapter::StopSession () +{ + std::cout << "Terminating I2P SAM session..." << std::endl; + sessionHolder_ = nullptr; + std::cout << "Denarius I2P SAM session terminated" << std::endl; +} + +bool StreamSessionAdapter::Start () +{ + return StartSession( + GetArg(I2P_SESSION_NAME_PARAM, I2P_SESSION_NAME_DEFAULT), + GetArg(I2P_SAM_HOST_PARAM, I2P_SAM_HOST_DEFAULT), + (uint16_t)GetArg(I2P_SAM_PORT_PARAM, I2P_SAM_PORT_DEFAULT), + GetArg(I2P_SAM_MY_DESTINATION_PARAM, I2P_SAM_MY_DESTINATION_DEFAULT), + GetArg(I2P_SAM_I2P_OPTIONS_PARAM, SAM_DEFAULT_I2P_OPTIONS)); +} + +void StreamSessionAdapter::Stop () +{ + StopSession (); +} SAM::SOCKET StreamSessionAdapter::accept(bool silent) { - SAM::RequestResult > result = sessionHolder_->getSession().accept(silent); - // call Socket::release - return result.isOk ? result.value->release() : SAM_INVALID_SOCKET; + SAM::RequestResult > result = sessionHolder_->getSession().accept(silent); + // call Socket::release + return result.isOk ? result.value->release() : SAM_INVALID_SOCKET; } SAM::SOCKET StreamSessionAdapter::connect(const std::string& destination, bool silent) { - SAM::RequestResult > result = sessionHolder_->getSession().connect(destination, silent); - // call Socket::release - return result.isOk ? result.value->release() : SAM_INVALID_SOCKET; + SAM::RequestResult > result = sessionHolder_->getSession().connect(destination, silent); + // call Socket::release + return result.isOk ? result.value->release() : SAM_INVALID_SOCKET; } bool StreamSessionAdapter::forward(const std::string& host, uint16_t port, bool silent) { - return sessionHolder_->getSession().forward(host, port, silent).isOk; + return sessionHolder_->getSession().forward(host, port, silent).isOk; } std::string StreamSessionAdapter::namingLookup(const std::string& name) const { - SAM::RequestResult result = sessionHolder_->getSession().namingLookup(name); - return result.isOk ? result.value : std::string(); + SAM::RequestResult result = sessionHolder_->getSession().namingLookup(name); + return result.isOk ? result.value : std::string(); } SAM::FullDestination StreamSessionAdapter::destGenerate() const { - SAM::RequestResult result = sessionHolder_->getSession().destGenerate(); - return result.isOk ? result.value : SAM::FullDestination(); + SAM::RequestResult result = sessionHolder_->getSession().destGenerate(); + return result.isOk ? result.value : SAM::FullDestination(); } void StreamSessionAdapter::stopForwarding(const std::string& host, uint16_t port) { - sessionHolder_->getSession().stopForwarding(host, port); + sessionHolder_->getSession().stopForwarding(host, port); } void StreamSessionAdapter::stopForwardingAll() { - sessionHolder_->getSession().stopForwardingAll(); + sessionHolder_->getSession().stopForwardingAll(); } const SAM::FullDestination& StreamSessionAdapter::getMyDestination() const { - return sessionHolder_->getSession().getMyDestination(); + return sessionHolder_->getSession().getMyDestination(); } const sockaddr_in& StreamSessionAdapter::getSAMAddress() const { - return sessionHolder_->getSession().getSAMAddress(); + return sessionHolder_->getSession().getSAMAddress(); } const std::string& StreamSessionAdapter::getSAMHost() const { - return sessionHolder_->getSession().getSAMHost(); + return sessionHolder_->getSession().getSAMHost(); } uint16_t StreamSessionAdapter::getSAMPort() const { - return sessionHolder_->getSession().getSAMPort(); + return sessionHolder_->getSession().getSAMPort(); } const std::string& StreamSessionAdapter::getNickname() const { - return sessionHolder_->getSession().getNickname(); + return sessionHolder_->getSession().getNickname(); } const std::string& StreamSessionAdapter::getSAMMinVer() const { - return sessionHolder_->getSession().getSAMMinVer(); + return sessionHolder_->getSession().getSAMMinVer(); } const std::string& StreamSessionAdapter::getSAMMaxVer() const { - return sessionHolder_->getSession().getSAMMaxVer(); + return sessionHolder_->getSession().getSAMMaxVer(); } const std::string& StreamSessionAdapter::getSAMVersion() const { - return sessionHolder_->getSession().getSAMVersion(); + return sessionHolder_->getSession().getSAMVersion(); } const std::string& StreamSessionAdapter::getOptions() const { - return sessionHolder_->getSession().getOptions(); + return sessionHolder_->getSession().getOptions(); } } // namespace SAM @@ -178,31 +219,25 @@ const std::string& StreamSessionAdapter::getOptions() const //-------------------------------------------------------------------------------------------------- I2PSession::I2PSession() - : SAM::StreamSessionAdapter( - GetArg(I2P_SESSION_NAME_PARAM, I2P_SESSION_NAME_DEFAULT), - GetArg(I2P_SAM_HOST_PARAM, I2P_SAM_HOST_DEFAULT), - (uint16_t)GetArg(I2P_SAM_PORT_PARAM, I2P_SAM_PORT_DEFAULT), - GetArg(I2P_SAM_MY_DESTINATION_PARAM, I2P_SAM_MY_DESTINATION_DEFAULT), - GetArg(I2P_SAM_I2P_OPTIONS_PARAM, SAM_DEFAULT_I2P_OPTIONS)) {} I2PSession::~I2PSession() {} + /*static*/ std::string I2PSession::GenerateB32AddressFromDestination(const std::string& destination) { - std::string canonicalDest = destination; - for (size_t pos = canonicalDest.find_first_of('-'); pos != std::string::npos; pos = canonicalDest.find_first_of('-', pos)) - canonicalDest[pos] = '+'; - for (size_t pos = canonicalDest.find_first_of('~'); pos != std::string::npos; pos = canonicalDest.find_first_of('~', pos)) - canonicalDest[pos] = '/'; - std::string rawHash = DecodeBase64(canonicalDest); - uint256 hash; - SHA256((const unsigned char*)rawHash.c_str(), rawHash.size(), (unsigned char*)&hash); - std::string result = EncodeBase32(hash.begin(), hash.end() - hash.begin()) + ".b32.i2p"; - for (size_t pos = result.find_first_of('='); pos != std::string::npos; pos = result.find_first_of('=', pos-1)) - result.erase(pos, 1); - return result; -} - + std::string canonicalDest = destination; + for (size_t pos = canonicalDest.find_first_of('-'); pos != std::string::npos; pos = canonicalDest.find_first_of('-', pos)) + canonicalDest[pos] = '+'; + for (size_t pos = canonicalDest.find_first_of('~'); pos != std::string::npos; pos = canonicalDest.find_first_of('~', pos)) + canonicalDest[pos] = '/'; + std::string rawHash = DecodeBase64(canonicalDest); + uint256 hash; + SHA256((const unsigned char*)rawHash.c_str(), rawHash.size(), (unsigned char*)&hash); + std::string result = EncodeBase32(hash.begin(), hash.end() - hash.begin()) + ".b32.i2p"; + for (size_t pos = result.find_first_of('='); pos != std::string::npos; pos = result.find_first_of('=', pos-1)) + result.erase(pos, 1); + return result; +} \ No newline at end of file diff --git a/src/i2p.h b/src/i2p.h index 62e070fc..2cf6a4a4 100644 --- a/src/i2p.h +++ b/src/i2p.h @@ -1,12 +1,16 @@ // Copyright (c) 2012-2013 giv +// Copyright (c) 2019 Denarius developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. //-------------------------------------------------------------------------------------------------- #ifndef I2P_H #define I2P_H +#include "util.h" #include "i2psam.h" +#define I2P_NET_NAME_PARAM "-i2p" + #define I2P_SESSION_NAME_PARAM "-i2psessionname" #define I2P_SESSION_NAME_DEFAULT "Denarius-client" @@ -30,17 +34,13 @@ namespace SAM class StreamSessionAdapter { public: - StreamSessionAdapter( - const std::string& nickname, - const std::string& SAMHost = SAM_DEFAULT_ADDRESS, - uint16_t SAMPort = SAM_DEFAULT_PORT, - const std::string& myDestination = SAM_GENERATE_MY_DESTINATION, - const std::string& i2pOptions = SAM_DEFAULT_I2P_OPTIONS, - const std::string& minVer = SAM_DEFAULT_MIN_VER, - const std::string& maxVer = SAM_DEFAULT_MAX_VER); + StreamSessionAdapter(); ~StreamSessionAdapter(); + bool Start (); + void Stop (); + SAM::SOCKET accept(bool silent); SAM::SOCKET connect(const std::string& destination, bool silent); bool forward(const std::string& host, uint16_t port, bool silent); @@ -61,10 +61,23 @@ class StreamSessionAdapter const std::string& getSAMVersion() const; const std::string& getOptions() const; +private: + + bool StartSession( + const std::string& nickname, + const std::string& SAMHost = SAM_DEFAULT_ADDRESS, + uint16_t SAMPort = SAM_DEFAULT_PORT, + const std::string& myDestination = SAM_GENERATE_MY_DESTINATION, + const std::string& i2pOptions = SAM_DEFAULT_I2P_OPTIONS, + const std::string& minVer = SAM_DEFAULT_MIN_VER, + const std::string& maxVer = SAM_DEFAULT_MAX_VER); + void StopSession (); + + private: class SessionHolder; - std::auto_ptr sessionHolder_; + std::shared_ptr sessionHolder_; }; } // namespace SAM @@ -89,4 +102,4 @@ class I2PSession : private SAM::StreamSessionAdapter I2PSession& operator=(const I2PSession&); }; -#endif // I2P_H +#endif // I2P_H \ No newline at end of file diff --git a/src/i2psam.cpp b/src/i2psam.cpp index a441ba3f..7c49d256 100644 --- a/src/i2psam.cpp +++ b/src/i2psam.cpp @@ -1,19 +1,10 @@ // Copyright (c) 2012-2013 giv +// Copyright (c) 2019 Denarius developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. //-------------------------------------------------------------------------------------------------- -#include "i2psam.h" -#ifdef WIN32 -//#define _WIN32_WINNT 0x0501 -#define WIN32_LEAN_AND_MEAN 1 -#define FD_SETSIZE -#include -#else -#include -#include // for sockaddr_in -#include // for ntohs and htons -#endif +#include "i2psam.h" #include #include @@ -21,6 +12,7 @@ #include #include #include +#include #ifndef WIN32 #include @@ -32,7 +24,7 @@ #endif #define SAM_BUFSIZE 65536 -#define I2P_DESTINATION_SIZE 516 +#define I2P_DESTINATION_SIZE 521 // actual size is 524 with trailing AAA== or AAQ== namespace SAM { @@ -40,11 +32,9 @@ namespace SAM static void print_error(const std::string& err) { #ifdef WIN32 - printf("I2P SAM WIN32 Error: %s: %d.\n", err.c_str(), WSAGetLastError()); - //std::cout << err << "(" << WSAGetLastError() << ")" << std::endl; + StreamSession::getLogStream () << err << "(" << WSAGetLastError() << ")" << std::endl; #else - printf("I2P SAM Error: %s: %d.\n", err.c_str(), errno); - //std::cout << err << "(" << errno << ")" << std::endl; + StreamSession::getLogStream () << err << "(" << errno << ")" << std::endl; #endif } @@ -162,8 +152,7 @@ void Socket::write(const std::string& msg) print_error("Failed to send data because socket is closed"); return; } - printf("I2P SAM Send: %s\n", msg.c_str()); - //std::cout << "Send: " << msg << std::endl; + StreamSession::getLogStream () << "Send: " << msg << std::endl; ssize_t sentBytes = send(socket_, msg.c_str(), msg.length(), 0); if (sentBytes == SAM_SOCKET_ERROR) { @@ -200,8 +189,7 @@ std::string Socket::read() close(); print_error("Socket was closed"); } - printf("I2P SAM Reply: %d\n", buffer); - //std::cout << "Reply: " << buffer << std::endl; + StreamSession::getLogStream () << "Reply: " << buffer << std::endl; return std::string(buffer); } @@ -265,8 +253,7 @@ StreamSession::StreamSession( , isSick_(false) { myDestination_ = createStreamSession(destination); - printf("I2P SAM Created a brand new SAM session: %d\n", sessionID_.c_str()); - //std::cout << "Created a brand new SAM session (" << sessionID_ << ")" << std::endl; + getLogStream () << "Created a brand new SAM session (" << sessionID_ << ")" << std::endl; } StreamSession::StreamSession(StreamSession& rhs) @@ -283,15 +270,14 @@ StreamSession::StreamSession(StreamSession& rhs) for(ForwardedStreamsContainer::const_iterator it = rhs.forwardedStreams_.begin(), end = rhs.forwardedStreams_.end(); it != end; ++it) forward(it->host, it->port, it->silent); - printf("I2P SAM Created a new SAM session: %d from another %s\n", sessionID_.c_str(), rhs.sessionID_.c_str()); - //std::cout << "Created a new SAM session (" << sessionID_ << ") from another (" << rhs.sessionID_ << ")" << std::endl; + + getLogStream () << "Created a new SAM session (" << sessionID_ << ") from another (" << rhs.sessionID_ << ")" << std::endl; } StreamSession::~StreamSession() { stopForwardingAll(); - printf("I2P SAM Closing SAM Session: %d\n", sessionID_.c_str()); - //std::cout << "Closing SAM session (" << sessionID_ << ") ..." << std::endl; + getLogStream () << "Closing SAM session (" << sessionID_ << ") ..." << std::endl; } /*static*/ @@ -314,16 +300,16 @@ std::string StreamSession::generateSessionID() return result; } -RequestResult > StreamSession::accept(bool silent) +RequestResult > StreamSession::accept(bool silent) { - typedef RequestResult > ResultType; + typedef RequestResult > ResultType; - std::auto_ptr streamSocket(new Socket(socket_)); + std::shared_ptr streamSocket(new Socket(socket_)); const Message::eStatus status = accept(*streamSocket, sessionID_, silent); switch(status) { case Message::OK: - return RequestResult >(streamSocket); + return std::move (RequestResult >(streamSocket)); case Message::EMPTY_ANSWER: case Message::CLOSED_SOCKET: case Message::INVALID_ID: @@ -336,11 +322,11 @@ RequestResult > StreamSession::accept(bool silent) return ResultType(); } -RequestResult > StreamSession::connect(const std::string& destination, bool silent) +RequestResult > StreamSession::connect(const std::string& destination, bool silent) { - typedef RequestResult > ResultType; + typedef RequestResult > ResultType; - std::auto_ptr streamSocket(new Socket(socket_)); + std::shared_ptr streamSocket(new Socket(socket_)); const Message::eStatus status = connect(*streamSocket, sessionID_, destination, silent); switch(status) { @@ -362,13 +348,13 @@ RequestResult StreamSession::forward(const std::string& host, uint16_t por { typedef RequestResult ResultType; - std::auto_ptr newSocket(new Socket(socket_)); + std::shared_ptr newSocket(new Socket(socket_)); const Message::eStatus status = forward(*newSocket, sessionID_, host, port, silent); switch(status) { case Message::OK: forwardedStreams_.push_back(ForwardedStream(newSocket.get(), host, port, silent)); - newSocket.release(); // release after successful push_back only + newSocket = nullptr; // release after successful push_back only return ResultType(true); case Message::EMPTY_ANSWER: case Message::CLOSED_SOCKET: @@ -387,7 +373,7 @@ RequestResult StreamSession::namingLookup(const std::string& typedef RequestResult ResultType; typedef Message::Answer AnswerType; - std::auto_ptr newSocket(new Socket(socket_)); + std::shared_ptr newSocket(new Socket(socket_)); const AnswerType answer = namingLookup(*newSocket, name); switch(answer.status) { @@ -408,7 +394,7 @@ RequestResult StreamSession::destGenerate() const typedef RequestResult ResultType; typedef Message::Answer AnswerType; - std::auto_ptr newSocket(new Socket(socket_)); + std::shared_ptr newSocket(new Socket(socket_)); const AnswerType answer = destGenerate(*newSocket); switch(answer.status) { @@ -434,7 +420,7 @@ FullDestination StreamSession::createStreamSession(const std::string& destinatio fallSick(); return FullDestination(); } - return FullDestination(answer.value.substr(0, I2P_DESTINATION_SIZE), answer.value, (destination == SAM_GENERATE_MY_DESTINATION)); + return FullDestination(answer.value.substr(0, I2P_DESTINATION_SIZE) + "A==", answer.value, (destination == SAM_GENERATE_MY_DESTINATION)); } void StreamSession::fallSick() const @@ -593,6 +579,23 @@ const std::string& StreamSession::getSAMVersion() const return socket_.getVersion(); } +std::shared_ptr StreamSession::logStream; + +std::ostream& StreamSession::getLogStream () +{ + return logStream ? *logStream : std::cout; +} + +void StreamSession::SetLogFile (const std::string& filename) +{ + logStream = std::make_shared (filename, std::ofstream::out | std::ofstream::trunc); +} + +void StreamSession::CloseLogFile () +{ + logStream = nullptr; +} + //-------------------------------------------------------------------------------------------------- @@ -656,7 +659,7 @@ std::string Message::sessionCreate(SessionStyle style, const std::string& sessio case sssRaw: sessionStyle = "RAW"; break; } - static const char* sessionCreateFormat = "SESSION CREATE STYLE=%s ID=%s DESTINATION=%s inbound.nickname=%s %s\n"; // we add inbound.nickname option + static const char* sessionCreateFormat = "SESSION CREATE STYLE=%s ID=%s DESTINATION=%s inbound.nickname=%s SIGNATURE_TYPE=7 %s\n"; // we add inbound.nickname option return createSAMRequest(sessionCreateFormat, sessionStyle.c_str(), sessionID.c_str(), destination.c_str(), nickname.c_str(), options.c_str()); } @@ -746,7 +749,7 @@ std::string Message::destGenerate() // /////////////////////////////////////////////////////////// - static const char* destGenerateFormat = "DEST GENERATE\n"; + static const char* destGenerateFormat = "DEST GENERATE SIGNATURE_TYPE=7\n"; return createSAMRequest(destGenerateFormat); } @@ -801,4 +804,4 @@ std::string Message::getValue(const std::string& answer, const std::string& key) } -} // namespace SAM +} // namespace SAM \ No newline at end of file diff --git a/src/i2psam.h b/src/i2psam.h index 0ecb5265..6ae000d1 100644 --- a/src/i2psam.h +++ b/src/i2psam.h @@ -1,8 +1,8 @@ // Copyright (c) 2012-2013 giv +// Copyright (c) 2019 Denarius developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. //-------------------------------------------------------------------------------------------------- -// see full documentation about SAM at http://www.i2p2.i2p/samv3.html #ifndef I2PSAM_H #define I2PSAM_H @@ -11,11 +11,11 @@ #include #include #include +#include #ifdef WIN32 -////#define _WIN32_WINNT 0x0501 +//#define _WIN32_WINNT 0x0501 #define WIN32_LEAN_AND_MEAN 1 -//#define FD_SETSIZE - Won't compile with it atm #include #else #include @@ -23,8 +23,6 @@ #include // for ntohs and htons #endif -//#ifndef WIN32 - // TODO: check a possible bug about cast -1 to SOCKET #define SAM_INVALID_SOCKET (-1) #define SAM_SOCKET_ERROR (-1) @@ -236,9 +234,6 @@ class Socket const sockaddr_in& getAddress() const; private: - struct SocketImpl; - std::auto_ptr impl_; - SOCKET socket_; sockaddr_in servAddr_; std::string SAMHost_; @@ -284,7 +279,7 @@ struct RequestResult }; template -struct RequestResult > +struct RequestResult > { // a class-helper for resolving a problem with conversion from temporary RequestResult to non-const RequestResult& struct RequestResultRef @@ -297,12 +292,12 @@ struct RequestResult > }; bool isOk; - std::auto_ptr value; + std::shared_ptr value; RequestResult() : isOk(false) {} - explicit RequestResult(std::auto_ptr& value) + explicit RequestResult(std::shared_ptr& value) : isOk(true), value(value) {} @@ -354,8 +349,8 @@ class StreamSession static std::string generateSessionID(); - RequestResult > accept(bool silent); - RequestResult > connect(const std::string& destination, bool silent); + RequestResult > accept(bool silent); + RequestResult > connect(const std::string& destination, bool silent); RequestResult forward(const std::string& host, uint16_t port, bool silent); RequestResult namingLookup(const std::string& name) const; RequestResult destGenerate() const; @@ -376,6 +371,11 @@ class StreamSession const std::string& getOptions() const; bool isSick() const; + bool isReady () const { return socket_.isOk() && !isSick (); }; + + static std::ostream& getLogStream (); + static void SetLogFile (const std::string& filename); + static void CloseLogFile (); private: StreamSession(const StreamSession& rhs); @@ -401,6 +401,7 @@ class StreamSession const std::string i2pOptions_; ForwardedStreamsContainer forwardedStreams_; mutable bool isSick_; + static std::shared_ptr logStream; void fallSick() const; FullDestination createStreamSession(const std::string &destination); @@ -420,4 +421,4 @@ class StreamSession } // namespace SAM -#endif // I2PSAM_H +#endif // I2PSAM_H \ No newline at end of file diff --git a/src/init.cpp b/src/init.cpp index 14ebd782..d732d1a0 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -112,19 +112,11 @@ void Shutdown(void* parg) { fShutdown = true; +#ifdef USE_NATIVE_I2P + I2PSession::Instance().Stop(); //Shutdown I2P Session if enabled +#endif Finalise(); - /* - SecureMsgShutdown(); - - mempool.AddTransactionsUpdated(1); -// CTxDB().Close(); - bitdb.Flush(false); - StopNode(); - bitdb.Flush(true); - boost::filesystem::remove(GetPidFile()); - UnregisterWallet(pwalletMain); - delete pwalletMain; - */ + // Finalise is main.cpp NewThread(ExitTimeout, NULL); MilliSleep(50); printf("Denarius exited\n\n"); @@ -481,6 +473,10 @@ bool AppInit2() #ifdef USE_NATIVE_I2P if(fNativeI2P) { + uiInterface.InitMessage(_("Creating Denarius I2P SAM session...")); + if (!I2PSession::Instance().Start() && IsI2POnly()) + return InitError("Can not start a connection to Denarius I2P SAM\n"); + if (GetBoolArg(I2P_SAM_GENERATE_DESTINATION_PARAM, false)) { const SAM::FullDestination generatedDest = I2PSession::Instance().destGenerate(); @@ -857,7 +853,7 @@ bool AppInit2() #endif #ifdef USE_NATIVE_I2P // -i2p can override both tor and proxy - if ((mapArgs.count("-i2p") && mapArgs["-i2p"] != "0") || IsI2POnly() && fNativeI2P) + if ((mapArgs.count("-i2p") && mapArgs["-i2p"] != "0") || IsI2POnly() || fNativeI2P) { // Disable on i2p per default #ifdef USE_UPNP diff --git a/src/main.cpp b/src/main.cpp index a8b72769..0bb30b3b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -243,7 +243,6 @@ bool Finalise() CTxDB().Close(); - return true; } diff --git a/src/net.h b/src/net.h index 04b74d50..a1d53ee8 100644 --- a/src/net.h +++ b/src/net.h @@ -31,8 +31,8 @@ static const int PING_INTERVAL = 2 * 60; /** Time after which to disconnect, after waiting for a ping response (or inactivity). */ static const int TIMEOUT_INTERVAL = 20 * 60; -inline unsigned int ReceiveFloodSize() { return 1000*GetArg("-maxreceivebuffer", 5*1000); } -inline unsigned int SendBufferSize() { return 1000*GetArg("-maxsendbuffer", 1*1000); } +inline unsigned int ReceiveFloodSize() { return 1000*GetArg("-maxreceivebuffer", 10*1000); } // 10MB Buffer Size from 5MB 5*1000 +inline unsigned int SendBufferSize() { return 1000*GetArg("-maxsendbuffer", 10*1000); } // Previously 1MB 1*1000 void AddOneShot(std::string strDest); bool RecvLine(SOCKET hSocket, std::string& strLine); diff --git a/src/netbase.cpp b/src/netbase.cpp index 1898461d..fde994f3 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -632,9 +632,14 @@ if (fNativeI2P) { const bool isBase32Addr = (strName.size() == NATIVE_I2P_B32ADDR_SIZE) && (strName.substr(strName.size() - 8, 8) == ".b32.i2p"); const std::string addr = isBase32Addr ? I2PSession::Instance().namingLookup(strName) : strName; - if ((addr.size() == NATIVE_I2P_DESTINATION_SIZE) && (addr.substr(addr.size() - 4, 4) == "AAAA")) { // last 4 symbols of b64-destination must be AAAA - memcpy(i2pDest, addr.c_str(), NATIVE_I2P_DESTINATION_SIZE); - return true; + if (addr.size() == NATIVE_I2P_DESTINATION_SIZE) { + auto trailer = addr.substr(addr.size() - 5, 5); + if ((trailer == "AAA==") || (trailer == "AAQ==")) + { + // last 5 symbols of b64-destination must be AAA== (ElGamal) or AAQ== (ECIES) + memcpy(i2pDest, addr.c_str(), NATIVE_I2P_DESTINATION_SIZE); + return true; + } } } #endif @@ -788,8 +793,7 @@ bool CNetAddr::IsTor() const #ifdef USE_NATIVE_I2P bool CNetAddr::IsNativeI2P() const { - static const unsigned char pchAAAA[] = {'A','A','A','A'}; - return (memcmp(i2pDest + NATIVE_I2P_DESTINATION_SIZE - sizeof(pchAAAA), pchAAAA, sizeof(pchAAAA)) == 0); + return i2pDest[0]; // nonzero } std::string CNetAddr::GetI2PDestination() const @@ -1082,6 +1086,22 @@ std::vector CNetAddr::GetGroup() const return vchRet; } +#ifdef USE_NATIVE_I2P +uint64_t CNetAddr::GetHash() const +{ + if(fNativeI2P) { + uint256 hash = IsNativeI2P() ? Hash(i2pDest, i2pDest + NATIVE_I2P_DESTINATION_SIZE) : Hash(&ip[0], &ip[16]); + uint64_t nRet; + memcpy(&nRet, &hash, sizeof(nRet)); + return nRet; + } else { + uint256 hash = Hash(&ip[0], &ip[16]); + uint64_t nRet; + memcpy(&nRet, &hash, sizeof(nRet)); + return nRet; + } +} +#else uint64_t CNetAddr::GetHash() const { uint256 hash = Hash(&ip[0], &ip[16]); @@ -1089,6 +1109,7 @@ uint64_t CNetAddr::GetHash() const memcpy(&nRet, &hash, sizeof(nRet)); return nRet; } +#endif void CNetAddr::print() const { @@ -1313,6 +1334,14 @@ bool CService::GetSockAddr(struct sockaddr* paddr, socklen_t *addrlen) const std::vector CService::GetKey() const { std::vector vKey; +#ifdef USE_NATIVE_I2P + if (IsNativeI2P() && fNativeI2P) + { + vKey.resize(NATIVE_I2P_DESTINATION_SIZE); + memcpy(&vKey[0], i2pDest, NATIVE_I2P_DESTINATION_SIZE); + return vKey; + } +#endif vKey.resize(18); memcpy(&vKey[0], ip, 16); vKey[16] = port / 0x100; diff --git a/src/netbase.h b/src/netbase.h index e763c2a8..26da4846 100644 --- a/src/netbase.h +++ b/src/netbase.h @@ -43,7 +43,7 @@ class CNetAddr protected: unsigned char ip[16]; // in network byte order #ifdef USE_NATIVE_I2P - unsigned char i2pDest[NATIVE_I2P_DESTINATION_SIZE]; + unsigned char i2pDest[NATIVE_I2P_DESTINATION_SIZE]; // I2P Destination #endif public: From 0c29bdd2b027dbc66de7296ce2ddf10d2fb4be3e Mon Sep 17 00:00:00 2001 From: carsenk Date: Sat, 10 Aug 2019 00:28:53 -0600 Subject: [PATCH 20/26] More I2P Updates --- src/i2psam.cpp | 22 +++++++++++----------- src/init.cpp | 35 ++++++++++++++++++++--------------- src/net.cpp | 5 +++++ 3 files changed, 36 insertions(+), 26 deletions(-) diff --git a/src/i2psam.cpp b/src/i2psam.cpp index 7c49d256..97873a93 100644 --- a/src/i2psam.cpp +++ b/src/i2psam.cpp @@ -115,14 +115,14 @@ void Socket::init() socket_ = socket(AF_INET, SOCK_STREAM, 0); if (socket_ == SAM_INVALID_SOCKET) { - print_error("Failed to create socket"); + print_error("I2P SAM Socket init() Failed to create socket"); return; } if (connect(socket_, (const sockaddr*)&servAddr_, sizeof(servAddr_)) == SAM_SOCKET_ERROR) { close(); - print_error("Failed to connect to SAM"); + print_error("I2P SAM Socket init() Failed to connect to SAM"); return; } } @@ -149,7 +149,7 @@ void Socket::write(const std::string& msg) { if (!isOk()) { - print_error("Failed to send data because socket is closed"); + print_error("I2P SAM Socket write() Failed to send data because socket is closed"); return; } StreamSession::getLogStream () << "Send: " << msg << std::endl; @@ -157,13 +157,13 @@ void Socket::write(const std::string& msg) if (sentBytes == SAM_SOCKET_ERROR) { close(); - print_error("Failed to send data"); + print_error("I2P SAM Socket write() Failed to send data"); return; } if (sentBytes == 0) { close(); - print_error("Socket was closed"); + print_error("I2P SAM Socket write() Socket was closed"); return; } } @@ -172,7 +172,7 @@ std::string Socket::read() { if (!isOk()) { - print_error("Failed to read data because socket is closed"); + print_error("I2P SAM Socket read() Failed to read data because socket is closed"); return std::string(); } char buffer[SAM_BUFSIZE]; @@ -181,13 +181,13 @@ std::string Socket::read() if (recievedBytes == SAM_SOCKET_ERROR) { close(); - print_error("Failed to receive data"); + print_error("I2P SAM Socket read() Failed to receive data"); return std::string(); } if (recievedBytes == 0) { close(); - print_error("Socket was closed"); + print_error("I2P SAM Socket read() Socket was closed"); } StreamSession::getLogStream () << "Reply: " << buffer << std::endl; return std::string(buffer); @@ -253,7 +253,7 @@ StreamSession::StreamSession( , isSick_(false) { myDestination_ = createStreamSession(destination); - getLogStream () << "Created a brand new SAM session (" << sessionID_ << ")" << std::endl; + getLogStream () << "Created a brand new Denarius I2P SAM session (" << sessionID_ << ")" << std::endl; } StreamSession::StreamSession(StreamSession& rhs) @@ -271,13 +271,13 @@ StreamSession::StreamSession(StreamSession& rhs) for(ForwardedStreamsContainer::const_iterator it = rhs.forwardedStreams_.begin(), end = rhs.forwardedStreams_.end(); it != end; ++it) forward(it->host, it->port, it->silent); - getLogStream () << "Created a new SAM session (" << sessionID_ << ") from another (" << rhs.sessionID_ << ")" << std::endl; + getLogStream () << "Created a new Denarius I2P SAM session (" << sessionID_ << ") from another (" << rhs.sessionID_ << ")" << std::endl; } StreamSession::~StreamSession() { stopForwardingAll(); - getLogStream () << "Closing SAM session (" << sessionID_ << ") ..." << std::endl; + getLogStream () << "Closing Denarius I2P SAM session (" << sessionID_ << ") ..." << std::endl; } /*static*/ diff --git a/src/init.cpp b/src/init.cpp index d732d1a0..27bdaefb 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -474,6 +474,7 @@ bool AppInit2() if(fNativeI2P) { uiInterface.InitMessage(_("Creating Denarius I2P SAM session...")); + printf("Creating Denarius I2P SAM Session...\n"); if (!I2PSession::Instance().Start() && IsI2POnly()) return InitError("Can not start a connection to Denarius I2P SAM\n"); @@ -776,15 +777,17 @@ bool AppInit2() BOOST_FOREACH(std::string snet, mapMultiArgs["-onlynet"]) { enum Network net = ParseNetwork(snet); +#ifdef USE_NATIVE_I2P if (net == NET_NATIVE_I2P) { - // Disable upnp and IRC and listen on I2P only. + // Disable upnp and listen on I2P only. #ifdef USE_UPNP SoftSetBoolArg("-upnp", false); #endif SoftSetBoolArg("-listen",true); SoftSetBoolArg("-discover",false); } +#endif if (net == NET_UNROUTABLE) return InitError(strprintf(_("Unknown network specified in -onlynet: '%s'"), snet.c_str())); nets.insert(net); @@ -853,18 +856,20 @@ bool AppInit2() #endif #ifdef USE_NATIVE_I2P // -i2p can override both tor and proxy - if ((mapArgs.count("-i2p") && mapArgs["-i2p"] != "0") || IsI2POnly() || fNativeI2P) - { - // Disable on i2p per default + if(fNativeI2P) { + if (!(mapArgs.count("-i2p") && mapArgs["-i2p"] == "0") || IsI2POnly()) + { + // Disable on i2p per default #ifdef USE_UPNP - SoftSetBoolArg("-upnp", false); + SoftSetBoolArg("-upnp", false); #endif - SoftSetBoolArg("-listen",true); - SetReachable(NET_NATIVE_I2P); + SoftSetBoolArg("-listen",true); + SetReachable(NET_NATIVE_I2P); + } } #endif // see Step 2: parameter interactions for more information about these - if(!fNativeTor && !fNativeI2P) // Available if nativetor are disabled + if(!fNativeTor) // Available if nativetor are disabled { fNoListen = !GetBoolArg("-listen", true); fDiscover = GetBoolArg("-discover", true); @@ -1294,24 +1299,24 @@ bool AppInit2() printf("mapAddressBook.size() = %" PRIszu"\n", pwalletMain->mapAddressBook.size()); #ifdef USE_NATIVETOR if(fNativeTor) - printf("Native Tor Onion Relay Node Enabled"); + printf("Native Tor Onion Relay Node Enabled\n"); else - printf("Native Tor Onion Relay Disabled, Using Regular Peers..."); + printf("Native Tor Onion Relay Disabled\n"); #endif #ifdef USE_NATIVE_I2P if(fNativeI2P) - printf("Native I2P Node Enabled"); + printf("Native I2P Node Enabled\n"); else - printf("Native I2P Disabled, Using Regular Peers..."); + printf("Native I2P Disabled\n"); #endif if (fDebug) - printf("Debugging is Enabled."); + printf("Debugging is Enabled.\n"); else - printf("Debugging is not enabled."); + printf("Debugging is not enabled.\n"); if (!NewThread(StartNode, NULL)) - InitError(_("Error: could not start node")); + InitError(_("Error: could not start node\n")); if (fServer) NewThread(ThreadRPCServer, NULL); diff --git a/src/net.cpp b/src/net.cpp index 93ba74ab..c4a4a9ef 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -441,6 +441,11 @@ void ThreadGetMyExternalIP(void* parg) { // Make this thread recognisable as the external IP detection thread RenameThread("denarius-ext-ip"); +#ifdef USE_NATIVE_I2P + + if (IsI2POnly() && fNativeI2P) + return; +#endif CNetAddr addrLocalHost; if (GetMyExternalIP(addrLocalHost)) From 4e4b6bb86859f9bca1bec3f1d518cce95c1cdfa3 Mon Sep 17 00:00:00 2001 From: carsenk Date: Tue, 13 Aug 2019 20:46:22 -0600 Subject: [PATCH 21/26] Revert to 580e054d284403655cd8634efe307d09a6d59d0a --- .gitignore | 1 - README.md | 1 - denarius-qt.pro | 32 +- src/activefortunastake.cpp | 2 +- src/addrman.h | 2 +- src/bitcoinrpc.cpp | 6 - src/bitcoinrpc.h | 8 - src/clientversion.h | 7 +- src/compat.h | 6 - src/fortuna.cpp | 5 +- src/fortunastake.cpp | 2 +- src/i2p.cpp | 243 --------- src/i2p.h | 105 ---- src/i2psam.cpp | 807 ------------------------------ src/i2psam.h | 424 ---------------- src/init.cpp | 132 ++--- src/main.cpp | 128 ++++- src/makefile.arm | 13 - src/makefile.unix | 12 - src/net.cpp | 324 ++---------- src/net.h | 79 +-- src/netbase.cpp | 235 +-------- src/netbase.h | 34 +- src/protocol.h | 3 - src/qt/bitcoin.qrc | 6 - src/qt/bitcoingui.cpp | 172 ++----- src/qt/bitcoingui.h | 17 +- src/qt/clientmodel.cpp | 78 --- src/qt/clientmodel.h | 25 +- src/qt/forms/i2poptionswidget.ui | 703 -------------------------- src/qt/forms/rpcconsole.ui | 245 +++++---- src/qt/forms/showi2paddresses.ui | 136 ----- src/qt/i2poptionswidget.cpp | 100 ---- src/qt/i2poptionswidget.h | 37 -- src/qt/optionsdialog.cpp | 42 -- src/qt/optionsdialog.h | 16 - src/qt/optionsmodel.cpp | 299 ----------- src/qt/optionsmodel.h | 37 -- src/qt/res/icons/fs.png | Bin 33382 -> 0 bytes src/qt/res/icons/i2plogo_0_16.png | Bin 2797 -> 0 bytes src/qt/res/icons/i2plogo_1_16.png | Bin 3242 -> 0 bytes src/qt/res/icons/i2plogo_2_16.png | Bin 3411 -> 0 bytes src/qt/res/icons/i2plogo_3_16.png | Bin 3558 -> 0 bytes src/qt/res/icons/i2plogo_4_16.png | Bin 3598 -> 0 bytes src/qt/rpcconsole.cpp | 1 - src/qt/showi2paddresses.cpp | 34 -- src/qt/showi2paddresses.h | 22 - src/qt/walletmodel.cpp | 23 + src/rpcnet.cpp | 356 +------------ src/rpcwallet.cpp | 26 +- src/serialize.h | 9 +- src/ui_interface.h | 5 - src/util.cpp | 11 +- src/util.h | 6 +- src/version.cpp | 2 +- src/wallet.cpp | 115 +++++ 56 files changed, 518 insertions(+), 4616 deletions(-) delete mode 100644 src/i2p.cpp delete mode 100644 src/i2p.h delete mode 100644 src/i2psam.cpp delete mode 100644 src/i2psam.h delete mode 100644 src/qt/forms/i2poptionswidget.ui delete mode 100644 src/qt/forms/showi2paddresses.ui delete mode 100644 src/qt/i2poptionswidget.cpp delete mode 100644 src/qt/i2poptionswidget.h delete mode 100644 src/qt/res/icons/fs.png delete mode 100644 src/qt/res/icons/i2plogo_0_16.png delete mode 100644 src/qt/res/icons/i2plogo_1_16.png delete mode 100644 src/qt/res/icons/i2plogo_2_16.png delete mode 100644 src/qt/res/icons/i2plogo_3_16.png delete mode 100644 src/qt/res/icons/i2plogo_4_16.png delete mode 100644 src/qt/showi2paddresses.cpp delete mode 100644 src/qt/showi2paddresses.h diff --git a/.gitignore b/.gitignore index a7ba5cc6..f20b0b92 100644 --- a/.gitignore +++ b/.gitignore @@ -42,5 +42,4 @@ dist *.app *.dmg .idea -*.vscode diff --git a/README.md b/README.md index 0cf46e8a..96ffeaf9 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,6 @@ Technology * Stealth addresses * Ring Signatures (16 Recommended) * Native Optional Tor Onion Node (-nativetor=1) -* Native Optional I2P Node (-nativei2p=1) * Encrypted Messaging * Multi-Signature Addresses & TXs * Atomic Swaps using UTXOs (BIP65 CLTV) diff --git a/denarius-qt.pro b/denarius-qt.pro index ceba75b9..20162d1e 100644 --- a/denarius-qt.pro +++ b/denarius-qt.pro @@ -1,6 +1,6 @@ TEMPLATE = app TARGET = Denarius -VERSION = 3.3.9.3 +VERSION = 3.3.9.2 INCLUDEPATH += src src/json src/qt src/qt/plugins/mrichtexteditor DEFINES += QT_GUI BOOST_THREAD_USE_LIB BOOST_SPIRIT_THREADSAFE CONFIG += no_include_pwd @@ -340,7 +340,7 @@ contains(USE_LEVELDB, -) { DEFINES += USE_LEVELDB - INCLUDEPATH += src/leveldb/include src/leveldb/helpers + INCLUDEPATH += src/leveldb/include src/leveldb/helpers LIBS += $$PWD/src/leveldb/libleveldb.a $$PWD/src/leveldb/libmemenv.a SOURCES += src/txdb-leveldb.cpp \ src/bloom.cpp \ @@ -400,7 +400,7 @@ QMAKE_CXXFLAGS_WARN_ON = -fdiagnostics-show-option -Wall -Wextra -Wno-ignored-qu # Input DEPENDPATH += src src/json src/qt HEADERS += src/qt/bitcoingui.h \ - src/qt/intro.h \ + src/qt/intro.h \ src/qt/transactiontablemodel.h \ src/qt/addresstablemodel.h \ src/qt/peertablemodel.h \ @@ -670,32 +670,6 @@ SOURCES += src/qt/qrcodedialog.cpp FORMS += src/qt/forms/qrcodedialog.ui } -# use: qmake "USE_NATIVE_I2P=1" ( enabled by default; default) -# or: qmake "USE_NATIVE_I2P=0" (disabled by default) -# or: qmake "USE_NATIVE_I2P=-" (not supported) -# D E N A R I U S Native I2P - USE_NATIVE_I2P=- to not compile with the i2p SAM C Library -contains(USE_NATIVE_I2P, -) { - message(Building without Native I2P support) -} else { - message(Building with Native I2P support) - count(USE_USE_NATIVE_I2P, 0) { - USE_NATIVE_I2P=1 - } - DEFINES += USE_NATIVE_I2P=$$USE_NATIVE_I2P - HEADERS += src/i2p.h \ - src/i2psam.h \ - src/qt/showi2paddresses.h \ - src/qt/i2poptionswidget.h - - SOURCES += src/i2p.cpp \ - src/i2psam.cpp \ - src/qt/showi2paddresses.cpp \ - src/qt/i2poptionswidget.cpp - - FORMS += src/qt/forms/showi2paddresses.ui \ - src/qt/forms/i2poptionswidget.ui -} - CODECFORTR = UTF-8 # for lrelease/lupdate diff --git a/src/activefortunastake.cpp b/src/activefortunastake.cpp index 758f7630..7868bed4 100644 --- a/src/activefortunastake.cpp +++ b/src/activefortunastake.cpp @@ -484,7 +484,7 @@ vector CActiveFortunastake::SelectCoinsFortunastake(bool fSelectUnlocke vector confLockedCoins; // Temporary unlock MN coins from fortunastake.conf - if(fSelectUnlocked && GetBoolArg("-fsconflock", true)) { + if(fSelectUnlocked && GetBoolArg("-mnconflock", true) || fSelectUnlocked && GetBoolArg("-fsconflock", true)) { uint256 mnTxHash; BOOST_FOREACH(CFortunastakeConfig::CFortunastakeEntry mne, fortunastakeConfig.getEntries()) { mnTxHash.SetHex(mne.getTxHash()); diff --git a/src/addrman.h b/src/addrman.h index 01962e9c..3afe0aad 100644 --- a/src/addrman.h +++ b/src/addrman.h @@ -156,7 +156,7 @@ class CAddrInfo : public CAddress #define ADDRMAN_MIN_FAIL_DAYS 7 // the maximum percentage of nodes to return in a getaddr call -#define ADDRMAN_GETADDR_MAX_PCT 100 // Get 100% instead of 23% +#define ADDRMAN_GETADDR_MAX_PCT 23 // the maximum number of nodes to return in a getaddr call #define ADDRMAN_GETADDR_MAX 2500 diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp index d3704d35..fbbf2367 100644 --- a/src/bitcoinrpc.cpp +++ b/src/bitcoinrpc.cpp @@ -267,10 +267,6 @@ static const CRPCCommand vRPCCommands[] = { "getpeerinfo", &getpeerinfo, true, false }, { "gethashespersec", &gethashespersec, true, false }, { "addnode", &addnode, true, true }, - { "getaddednodeinfo", &getaddednodeinfo, true, true }, - { "ping", &ping, true, true }, - { "getnettotals", &getnettotals, true, false }, - { "getnetworkinfo", &getnetworkinfo, true, false }, { "dumpbootstrap", &dumpbootstrap, false, false }, { "getdifficulty", &getdifficulty, true, false }, { "getinfo", &getinfo, true, false }, @@ -1373,8 +1369,6 @@ Array RPCConvertValues(const std::string &strMethod, const std::vector 0) ConvertTo(params[0]); - if (strMethod == "getaddednodeinfo" && n > 0) ConvertTo(params[0]); - if (strMethod == "addmultisigaddress" && n > 0) ConvertTo(params[0]); if (strMethod == "addmultisigaddress" && n > 1) ConvertTo(params[1]); if (strMethod == "createmultisig" && n > 0) ConvertTo(params[0]); diff --git a/src/bitcoinrpc.h b/src/bitcoinrpc.h index cd708902..7a2f4a5d 100644 --- a/src/bitcoinrpc.h +++ b/src/bitcoinrpc.h @@ -50,13 +50,10 @@ enum RPCErrorCode RPC_INVALID_PARAMETER = -8, // Invalid, missing or duplicate parameter RPC_DATABASE_ERROR = -20, // Database error RPC_DESERIALIZATION_ERROR = -22, // Error parsing or validating structure in raw format - RPC_SERVER_NOT_STARTED = -18, // RPC server was not started (StartRPCThreads() not called) // P2P client errors RPC_CLIENT_NOT_CONNECTED = -9, // Bitcoin is not connected RPC_CLIENT_IN_INITIAL_DOWNLOAD = -10, // Still downloading initial blocks - RPC_CLIENT_NODE_ALREADY_ADDED = -23, // Node is already added - RPC_CLIENT_NODE_NOT_ADDED = -24, // Node has not been added before // Wallet errors RPC_WALLET_ERROR = -4, // Unspecified problem with wallet (key not found etc.) @@ -155,11 +152,6 @@ extern std::vector ParseHexO(const json_spirit::Object& o, std::s extern json_spirit::Value getconnectioncount(const json_spirit::Array& params, bool fHelp); // in rpcnet.cpp extern json_spirit::Value getpeerinfo(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value addnode(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value ping(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value getaddednodeinfo(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value getnettotals(const json_spirit::Array& params, bool fHelp); -extern json_spirit::Value getnetworkinfo(const json_spirit::Array& params, bool fHelp); - extern json_spirit::Value dumpwallet(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value importwallet(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value dumpprivkey(const json_spirit::Array& params, bool fHelp); // in rpcdump.cpp diff --git a/src/clientversion.h b/src/clientversion.h index 0776ce47..b785d310 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -10,12 +10,7 @@ #define CLIENT_VERSION_MAJOR 3 #define CLIENT_VERSION_MINOR 3 #define CLIENT_VERSION_REVISION 9 -#define CLIENT_VERSION_BUILD 3 - -#ifdef USE_NATIVE_I2P -#define I2P_NATIVE_VERSION_MAJOR 0 -#define I2P_NATIVE_VERSION_MINOR 2 -#endif +#define CLIENT_VERSION_BUILD 2 // Converts the parameter X to a string after macro replacement on X has been performed. // Don't merge these into one macro! diff --git a/src/compat.h b/src/compat.h index bfb712ef..d09ec4fe 100644 --- a/src/compat.h +++ b/src/compat.h @@ -11,11 +11,6 @@ #ifndef NOMINMAX #define NOMINMAX #endif -#ifdef FD_SETSIZE -#undef FD_SETSIZE // prevent redefinition compiler warning -#endif -#define FD_SETSIZE 1024 // max number of fds in fd_set - #include #include #include @@ -28,7 +23,6 @@ #include #include #include -#include typedef u_int SOCKET; #endif diff --git a/src/fortuna.cpp b/src/fortuna.cpp index 07dbac91..5c12ec46 100644 --- a/src/fortuna.cpp +++ b/src/fortuna.cpp @@ -808,9 +808,7 @@ bool CForTunaSigner::IsVinAssociatedWithPubkey(CTxIn& vin, CPubKey& pubkey){ if(GetTransaction(vin.prevout.hash, txVin, hash)){ CTxOut out = txVin.vout[vin.prevout.n]; - //for (int i = 1; i < out; i++) - - if ((out.nValue == GetMNCollateral()*COIN) && (out.scriptPubKey == payee2)) //&& (i == 1) ? + if ((out.nValue == GetMNCollateral()*COIN) && (out.scriptPubKey == payee2)) { return true; } @@ -823,7 +821,6 @@ bool CForTunaSigner::IsVinAssociatedWithPubkey(CTxIn& vin, CPubKey& pubkey){ CTxDestination address1; ExtractDestination(payee2, address1); CBitcoinAddress address2(address1); - if (fDebug) { printf("IsVinAssociatedWithPubKey:: vin %s is not associated with pubkey %s for address %s\n", vin.ToString().c_str(), pubkey.GetHash().ToString().c_str(), address2.ToString().c_str()); diff --git a/src/fortunastake.cpp b/src/fortunastake.cpp index 3ab3f523..7eb07205 100644 --- a/src/fortunastake.cpp +++ b/src/fortunastake.cpp @@ -1508,7 +1508,7 @@ bool CFortunaPayments::initialize(const CBlockIndex *pindex) CTxDestination address1; ExtractDestination(rec.scriptPubKey, address1); CBitcoinAddress address2(address1); - printf("Height %d: FS D Address %s secured by collateral %s\n",rec.height,address2.ToString().c_str(),rec.vin.ToString().c_str()); + printf("Height %d: MN Address %s secured by collateral %s\n",rec.height,address2.ToString().c_str(),rec.vin.ToString().c_str()); } } diff --git a/src/i2p.cpp b/src/i2p.cpp deleted file mode 100644 index e5d1abdd..00000000 --- a/src/i2p.cpp +++ /dev/null @@ -1,243 +0,0 @@ -// Copyright (c) 2012-2013 giv -// Copyright (c) 2019 Denarius developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. -//-------------------------------------------------------------------------------------------------- -#include -#include -#include "i2p.h" -#include "util.h" -#include "hash.h" - -namespace SAM -{ - -class StreamSessionAdapter::SessionHolder -{ -public: - explicit SessionHolder(std::shared_ptr session); - ~SessionHolder(); - - const SAM::StreamSession& getSession() const; - SAM::StreamSession& getSession(); -private: - void heal() const; - void reborn() const; - - mutable std::shared_ptr session_; - typedef boost::shared_mutex mutex_type; - mutable mutex_type mtx_; -}; - -StreamSessionAdapter::SessionHolder::SessionHolder(std::shared_ptr session) - : session_(session) -{ -} - -StreamSessionAdapter::SessionHolder::~SessionHolder() -{ -} - -const SAM::StreamSession& StreamSessionAdapter::SessionHolder::getSession() const -{ - boost::upgrade_lock lock(mtx_); - if (session_->isSick()) - { - boost::upgrade_to_unique_lock ulock(lock); - heal(); - } - return *session_; -} - -SAM::StreamSession& StreamSessionAdapter::SessionHolder::getSession() -{ - boost::upgrade_lock lock(mtx_); - if (session_->isSick()) - { - boost::upgrade_to_unique_lock ulock(lock); - heal(); - } - return *session_; -} - -void StreamSessionAdapter::SessionHolder::heal() const -{ - reborn(); // if we don't know how to heal it just reborn it -} - -void StreamSessionAdapter::SessionHolder::reborn() const -{ - if (!session_->isSick()) - return; - std::shared_ptr newSession(new SAM::StreamSession(*session_)); - if (!newSession->isSick() && session_->isSick()) - session_ = newSession; -} - -//-------------------------------------------------------------------------------------------------- - -StreamSessionAdapter::StreamSessionAdapter() -{ - SAM::StreamSession::SetLogFile ((GetDataDir() / "i2pdebug.log").string ()); -} - -StreamSessionAdapter::~StreamSessionAdapter() -{ - SAM::StreamSession::CloseLogFile (); -} - -bool StreamSessionAdapter::StartSession ( - const std::string& nickname, - const std::string& SAMHost /*= SAM_DEFAULT_ADDRESS*/, - uint16_t SAMPort /*= SAM_DEFAULT_PORT*/, - const std::string& myDestination /*= SAM_GENERATE_MY_DESTINATION*/, - const std::string& i2pOptions /*= SAM_DEFAULT_I2P_OPTIONS*/, - const std::string& minVer /*= SAM_DEFAULT_MIN_VER*/, - const std::string& maxVer /*= SAM_DEFAULT_MAX_VER*/) -{ - std::cout << "Creating Denarius I2P SAM session..." << std::endl; - auto s = std::make_shared(nickname, SAMHost, SAMPort, myDestination, i2pOptions, minVer, maxVer); - sessionHolder_ = std::make_shared(s); - bool isReady = s->isReady (); - if (isReady) - std::cout << "Denarius I2P SAM session created" << std::endl; - else - std::cout << "Denarius I2P SAM session failed" << std::endl; - return isReady; -} - -void StreamSessionAdapter::StopSession () -{ - std::cout << "Terminating I2P SAM session..." << std::endl; - sessionHolder_ = nullptr; - std::cout << "Denarius I2P SAM session terminated" << std::endl; -} - -bool StreamSessionAdapter::Start () -{ - return StartSession( - GetArg(I2P_SESSION_NAME_PARAM, I2P_SESSION_NAME_DEFAULT), - GetArg(I2P_SAM_HOST_PARAM, I2P_SAM_HOST_DEFAULT), - (uint16_t)GetArg(I2P_SAM_PORT_PARAM, I2P_SAM_PORT_DEFAULT), - GetArg(I2P_SAM_MY_DESTINATION_PARAM, I2P_SAM_MY_DESTINATION_DEFAULT), - GetArg(I2P_SAM_I2P_OPTIONS_PARAM, SAM_DEFAULT_I2P_OPTIONS)); -} - -void StreamSessionAdapter::Stop () -{ - StopSession (); -} - -SAM::SOCKET StreamSessionAdapter::accept(bool silent) -{ - SAM::RequestResult > result = sessionHolder_->getSession().accept(silent); - // call Socket::release - return result.isOk ? result.value->release() : SAM_INVALID_SOCKET; -} - -SAM::SOCKET StreamSessionAdapter::connect(const std::string& destination, bool silent) -{ - SAM::RequestResult > result = sessionHolder_->getSession().connect(destination, silent); - // call Socket::release - return result.isOk ? result.value->release() : SAM_INVALID_SOCKET; -} - -bool StreamSessionAdapter::forward(const std::string& host, uint16_t port, bool silent) -{ - return sessionHolder_->getSession().forward(host, port, silent).isOk; -} - -std::string StreamSessionAdapter::namingLookup(const std::string& name) const -{ - SAM::RequestResult result = sessionHolder_->getSession().namingLookup(name); - return result.isOk ? result.value : std::string(); -} - -SAM::FullDestination StreamSessionAdapter::destGenerate() const -{ - SAM::RequestResult result = sessionHolder_->getSession().destGenerate(); - return result.isOk ? result.value : SAM::FullDestination(); -} - -void StreamSessionAdapter::stopForwarding(const std::string& host, uint16_t port) -{ - sessionHolder_->getSession().stopForwarding(host, port); -} - -void StreamSessionAdapter::stopForwardingAll() -{ - sessionHolder_->getSession().stopForwardingAll(); -} - -const SAM::FullDestination& StreamSessionAdapter::getMyDestination() const -{ - return sessionHolder_->getSession().getMyDestination(); -} - -const sockaddr_in& StreamSessionAdapter::getSAMAddress() const -{ - return sessionHolder_->getSession().getSAMAddress(); -} - -const std::string& StreamSessionAdapter::getSAMHost() const -{ - return sessionHolder_->getSession().getSAMHost(); -} - -uint16_t StreamSessionAdapter::getSAMPort() const -{ - return sessionHolder_->getSession().getSAMPort(); -} - -const std::string& StreamSessionAdapter::getNickname() const -{ - return sessionHolder_->getSession().getNickname(); -} - -const std::string& StreamSessionAdapter::getSAMMinVer() const -{ - return sessionHolder_->getSession().getSAMMinVer(); -} - -const std::string& StreamSessionAdapter::getSAMMaxVer() const -{ - return sessionHolder_->getSession().getSAMMaxVer(); -} - -const std::string& StreamSessionAdapter::getSAMVersion() const -{ - return sessionHolder_->getSession().getSAMVersion(); -} - -const std::string& StreamSessionAdapter::getOptions() const -{ - return sessionHolder_->getSession().getOptions(); -} - -} // namespace SAM - -//-------------------------------------------------------------------------------------------------- - -I2PSession::I2PSession() -{} - -I2PSession::~I2PSession() -{} - - -/*static*/ -std::string I2PSession::GenerateB32AddressFromDestination(const std::string& destination) -{ - std::string canonicalDest = destination; - for (size_t pos = canonicalDest.find_first_of('-'); pos != std::string::npos; pos = canonicalDest.find_first_of('-', pos)) - canonicalDest[pos] = '+'; - for (size_t pos = canonicalDest.find_first_of('~'); pos != std::string::npos; pos = canonicalDest.find_first_of('~', pos)) - canonicalDest[pos] = '/'; - std::string rawHash = DecodeBase64(canonicalDest); - uint256 hash; - SHA256((const unsigned char*)rawHash.c_str(), rawHash.size(), (unsigned char*)&hash); - std::string result = EncodeBase32(hash.begin(), hash.end() - hash.begin()) + ".b32.i2p"; - for (size_t pos = result.find_first_of('='); pos != std::string::npos; pos = result.find_first_of('=', pos-1)) - result.erase(pos, 1); - return result; -} \ No newline at end of file diff --git a/src/i2p.h b/src/i2p.h deleted file mode 100644 index 2cf6a4a4..00000000 --- a/src/i2p.h +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright (c) 2012-2013 giv -// Copyright (c) 2019 Denarius developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. -//-------------------------------------------------------------------------------------------------- -#ifndef I2P_H -#define I2P_H - -#include "util.h" -#include "i2psam.h" - -#define I2P_NET_NAME_PARAM "-i2p" - -#define I2P_SESSION_NAME_PARAM "-i2psessionname" -#define I2P_SESSION_NAME_DEFAULT "Denarius-client" - -#define I2P_SAM_HOST_PARAM "-samhost" -#define I2P_SAM_HOST_DEFAULT SAM_DEFAULT_ADDRESS - -#define I2P_SAM_PORT_PARAM "-samport" -#define I2P_SAM_PORT_DEFAULT SAM_DEFAULT_PORT - -#define I2P_SAM_MY_DESTINATION_PARAM "-mydestination" -#define I2P_SAM_MY_DESTINATION_DEFAULT SAM_GENERATE_MY_DESTINATION - -#define I2P_SAM_I2P_OPTIONS_PARAM "-i2poptions" -#define I2P_SAM_I2P_OPTIONS_DEFAULT SAM_DEFAULT_I2P_OPTIONS - -#define I2P_SAM_GENERATE_DESTINATION_PARAM "-generatei2pdestination" - -namespace SAM -{ - -class StreamSessionAdapter -{ -public: - - StreamSessionAdapter(); - ~StreamSessionAdapter(); - - bool Start (); - void Stop (); - - SAM::SOCKET accept(bool silent); - SAM::SOCKET connect(const std::string& destination, bool silent); - bool forward(const std::string& host, uint16_t port, bool silent); - std::string namingLookup(const std::string& name) const; - SAM::FullDestination destGenerate() const; - - void stopForwarding(const std::string& host, uint16_t port); - void stopForwardingAll(); - - const SAM::FullDestination& getMyDestination() const; - - const sockaddr_in& getSAMAddress() const; - const std::string& getSAMHost() const; - uint16_t getSAMPort() const; - const std::string& getNickname() const; - const std::string& getSAMMinVer() const; - const std::string& getSAMMaxVer() const; - const std::string& getSAMVersion() const; - const std::string& getOptions() const; - -private: - - bool StartSession( - const std::string& nickname, - const std::string& SAMHost = SAM_DEFAULT_ADDRESS, - uint16_t SAMPort = SAM_DEFAULT_PORT, - const std::string& myDestination = SAM_GENERATE_MY_DESTINATION, - const std::string& i2pOptions = SAM_DEFAULT_I2P_OPTIONS, - const std::string& minVer = SAM_DEFAULT_MIN_VER, - const std::string& maxVer = SAM_DEFAULT_MAX_VER); - void StopSession (); - - -private: - class SessionHolder; - - std::shared_ptr sessionHolder_; -}; - -} // namespace SAM - -class I2PSession : private SAM::StreamSessionAdapter -{ -public: - // In C++11 this code is thread safe, in C++03 it isn't - static SAM::StreamSessionAdapter& Instance() - { - static I2PSession i2pSession; - return i2pSession; - } - - static std::string GenerateB32AddressFromDestination(const std::string& destination); - -private: - I2PSession(); - ~I2PSession(); - - I2PSession(const I2PSession&); - I2PSession& operator=(const I2PSession&); -}; - -#endif // I2P_H \ No newline at end of file diff --git a/src/i2psam.cpp b/src/i2psam.cpp deleted file mode 100644 index 97873a93..00000000 --- a/src/i2psam.cpp +++ /dev/null @@ -1,807 +0,0 @@ -// Copyright (c) 2012-2013 giv -// Copyright (c) 2019 Denarius developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. -//-------------------------------------------------------------------------------------------------- - -#include "i2psam.h" - -#include -#include -#include // for memset -#include -#include -#include -#include - -#ifndef WIN32 -#include -#include -#endif - -#ifndef WIN32 -#define closesocket close -#endif - -#define SAM_BUFSIZE 65536 -#define I2P_DESTINATION_SIZE 521 // actual size is 524 with trailing AAA== or AAQ== - -namespace SAM -{ - -static void print_error(const std::string& err) -{ -#ifdef WIN32 - StreamSession::getLogStream () << err << "(" << WSAGetLastError() << ")" << std::endl; -#else - StreamSession::getLogStream () << err << "(" << errno << ")" << std::endl; -#endif -} - -#ifdef WIN32 -int Socket::instances_ = 0; - -void Socket::initWSA() -{ - WSADATA wsadata; - int ret = WSAStartup(MAKEWORD(2,2), &wsadata); - if (ret != NO_ERROR) - print_error("Failed to initialize winsock library"); -} - -void Socket::freeWSA() -{ - WSACleanup(); -} -#endif - -Socket::Socket(const std::string& SAMHost, uint16_t SAMPort, const std::string& minVer, const std::string &maxVer) - : socket_(SAM_INVALID_SOCKET), SAMHost_(SAMHost), SAMPort_(SAMPort), minVer_(minVer), maxVer_(maxVer) -{ -#ifdef WIN32 - if (instances_++ == 0) - initWSA(); -#endif - - memset(&servAddr_, 0, sizeof(servAddr_)); - - servAddr_.sin_family = AF_INET; - servAddr_.sin_addr.s_addr = inet_addr(SAMHost.c_str()); - servAddr_.sin_port = htons(SAMPort); - - init(); - if (isOk()) - handshake(); -} - -Socket::Socket(const sockaddr_in& addr, const std::string &minVer, const std::string& maxVer) - : socket_(SAM_INVALID_SOCKET), servAddr_(addr), minVer_(minVer), maxVer_(maxVer) -{ -#ifdef WIN32 - if (instances_++ == 0) - initWSA(); -#endif - - init(); - if (isOk()) - handshake(); -} - -Socket::Socket(const Socket& rhs) - : socket_(SAM_INVALID_SOCKET), servAddr_(rhs.servAddr_), minVer_(rhs.minVer_), maxVer_(rhs.maxVer_) -{ -#ifdef WIN32 - if (instances_++ == 0) - initWSA(); -#endif - - init(); - if (isOk()) - handshake(); -} - -Socket::~Socket() -{ - close(); - -#ifdef WIN32 - if (--instances_ == 0) - freeWSA(); -#endif -} - -void Socket::init() -{ - socket_ = socket(AF_INET, SOCK_STREAM, 0); - if (socket_ == SAM_INVALID_SOCKET) - { - print_error("I2P SAM Socket init() Failed to create socket"); - return; - } - - if (connect(socket_, (const sockaddr*)&servAddr_, sizeof(servAddr_)) == SAM_SOCKET_ERROR) - { - close(); - print_error("I2P SAM Socket init() Failed to connect to SAM"); - return; - } -} - -SOCKET Socket::release() -{ - SOCKET temp = socket_; - socket_ = SAM_INVALID_SOCKET; - return temp; -} - -void Socket::handshake() -{ - this->write(Message::hello(minVer_, maxVer_)); - const std::string answer = this->read(); - const Message::eStatus answerStatus = Message::checkAnswer(answer); - if (answerStatus == Message::OK) - version_ = Message::getValue(answer, "VERSION"); - else - print_error("Handshake failed"); -} - -void Socket::write(const std::string& msg) -{ - if (!isOk()) - { - print_error("I2P SAM Socket write() Failed to send data because socket is closed"); - return; - } - StreamSession::getLogStream () << "Send: " << msg << std::endl; - ssize_t sentBytes = send(socket_, msg.c_str(), msg.length(), 0); - if (sentBytes == SAM_SOCKET_ERROR) - { - close(); - print_error("I2P SAM Socket write() Failed to send data"); - return; - } - if (sentBytes == 0) - { - close(); - print_error("I2P SAM Socket write() Socket was closed"); - return; - } -} - -std::string Socket::read() -{ - if (!isOk()) - { - print_error("I2P SAM Socket read() Failed to read data because socket is closed"); - return std::string(); - } - char buffer[SAM_BUFSIZE]; - memset(buffer, 0, SAM_BUFSIZE); - ssize_t recievedBytes = recv(socket_, buffer, SAM_BUFSIZE, 0); - if (recievedBytes == SAM_SOCKET_ERROR) - { - close(); - print_error("I2P SAM Socket read() Failed to receive data"); - return std::string(); - } - if (recievedBytes == 0) - { - close(); - print_error("I2P SAM Socket read() Socket was closed"); - } - StreamSession::getLogStream () << "Reply: " << buffer << std::endl; - return std::string(buffer); -} - -void Socket::close() -{ - if (socket_ != SAM_INVALID_SOCKET) - ::closesocket(socket_); - socket_ = SAM_INVALID_SOCKET; -} - -bool Socket::isOk() const -{ - return socket_ != SAM_INVALID_SOCKET; -} - -const std::string& Socket::getHost() const -{ - return SAMHost_; -} - -uint16_t Socket::getPort() const -{ - return SAMPort_; -} - -const std::string& Socket::getVersion() const -{ - return version_; -} - -const std::string& Socket::getMinVer() const -{ - return minVer_; -} - -const std::string& Socket::getMaxVer() const -{ - return maxVer_; -} - -const sockaddr_in& Socket::getAddress() const -{ - return servAddr_; -} - - -//-------------------------------------------------------------------------------------------------- - -StreamSession::StreamSession( - const std::string& nickname, - const std::string& SAMHost /*= SAM_DEFAULT_ADDRESS*/, - uint16_t SAMPort /*= SAM_DEFAULT_PORT*/, - const std::string& destination /*= SAM_GENERATE_MY_DESTINATION*/, - const std::string& i2pOptions /*= SAM_DEFAULT_I2P_OPTIONS*/, - const std::string& minVer /*= SAM_DEFAULT_MIN_VER*/, - const std::string& maxVer /*= SAM_DEFAULT_MAX_VER*/) - : socket_(SAMHost, SAMPort, minVer, maxVer) - , nickname_(nickname) - , sessionID_(generateSessionID()) - , i2pOptions_(i2pOptions) - , isSick_(false) -{ - myDestination_ = createStreamSession(destination); - getLogStream () << "Created a brand new Denarius I2P SAM session (" << sessionID_ << ")" << std::endl; -} - -StreamSession::StreamSession(StreamSession& rhs) - : socket_(rhs.socket_) - , nickname_(rhs.nickname_) - , sessionID_(generateSessionID()) - , myDestination_(rhs.myDestination_) - , i2pOptions_(rhs.i2pOptions_) - , isSick_(false) -{ - rhs.fallSick(); - rhs.socket_.close(); - (void)createStreamSession(myDestination_.priv); - - for(ForwardedStreamsContainer::const_iterator it = rhs.forwardedStreams_.begin(), end = rhs.forwardedStreams_.end(); it != end; ++it) - forward(it->host, it->port, it->silent); - - getLogStream () << "Created a new Denarius I2P SAM session (" << sessionID_ << ") from another (" << rhs.sessionID_ << ")" << std::endl; -} - -StreamSession::~StreamSession() -{ - stopForwardingAll(); - getLogStream () << "Closing Denarius I2P SAM session (" << sessionID_ << ") ..." << std::endl; -} - -/*static*/ -std::string StreamSession::generateSessionID() -{ - static const int minSessionIDLength = 5; - static const int maxSessionIDLength = 9; - static const char sessionIDAlphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - int length = minSessionIDLength - 1; - std::string result; - - srand(time(NULL)); - - while(length < minSessionIDLength) - length = rand() % maxSessionIDLength; - - while (length-- > 0) - result += sessionIDAlphabet[rand() % (sizeof(sessionIDAlphabet)-1)]; - - return result; -} - -RequestResult > StreamSession::accept(bool silent) -{ - typedef RequestResult > ResultType; - - std::shared_ptr streamSocket(new Socket(socket_)); - const Message::eStatus status = accept(*streamSocket, sessionID_, silent); - switch(status) - { - case Message::OK: - return std::move (RequestResult >(streamSocket)); - case Message::EMPTY_ANSWER: - case Message::CLOSED_SOCKET: - case Message::INVALID_ID: - case Message::I2P_ERROR: - fallSick(); - break; - default: - break; - } - return ResultType(); -} - -RequestResult > StreamSession::connect(const std::string& destination, bool silent) -{ - typedef RequestResult > ResultType; - - std::shared_ptr streamSocket(new Socket(socket_)); - const Message::eStatus status = connect(*streamSocket, sessionID_, destination, silent); - switch(status) - { - case Message::OK: - return ResultType(streamSocket); - case Message::EMPTY_ANSWER: - case Message::CLOSED_SOCKET: - case Message::INVALID_ID: - case Message::I2P_ERROR: - fallSick(); - break; - default: - break; - } - return ResultType(); -} - -RequestResult StreamSession::forward(const std::string& host, uint16_t port, bool silent) -{ - typedef RequestResult ResultType; - - std::shared_ptr newSocket(new Socket(socket_)); - const Message::eStatus status = forward(*newSocket, sessionID_, host, port, silent); - switch(status) - { - case Message::OK: - forwardedStreams_.push_back(ForwardedStream(newSocket.get(), host, port, silent)); - newSocket = nullptr; // release after successful push_back only - return ResultType(true); - case Message::EMPTY_ANSWER: - case Message::CLOSED_SOCKET: - case Message::INVALID_ID: - case Message::I2P_ERROR: - fallSick(); - break; - default: - break; - } - return ResultType(); -} - -RequestResult StreamSession::namingLookup(const std::string& name) const -{ - typedef RequestResult ResultType; - typedef Message::Answer AnswerType; - - std::shared_ptr newSocket(new Socket(socket_)); - const AnswerType answer = namingLookup(*newSocket, name); - switch(answer.status) - { - case Message::OK: - return ResultType(answer.value); - case Message::EMPTY_ANSWER: - case Message::CLOSED_SOCKET: - fallSick(); - break; - default: - break; - } - return ResultType(); -} - -RequestResult StreamSession::destGenerate() const -{ - typedef RequestResult ResultType; - typedef Message::Answer AnswerType; - - std::shared_ptr newSocket(new Socket(socket_)); - const AnswerType answer = destGenerate(*newSocket); - switch(answer.status) - { - case Message::OK: - return ResultType(answer.value); - case Message::EMPTY_ANSWER: - case Message::CLOSED_SOCKET: - fallSick(); - break; - default: - break; - } - return ResultType(); -} - -FullDestination StreamSession::createStreamSession(const std::string& destination) -{ - typedef Message::Answer AnswerType; - - const AnswerType answer = createStreamSession(socket_, sessionID_, nickname_, destination, i2pOptions_); - if (answer.status != Message::OK) - { - fallSick(); - return FullDestination(); - } - return FullDestination(answer.value.substr(0, I2P_DESTINATION_SIZE) + "A==", answer.value, (destination == SAM_GENERATE_MY_DESTINATION)); -} - -void StreamSession::fallSick() const -{ - isSick_ = true; -} - -void StreamSession::stopForwarding(const std::string& host, uint16_t port) -{ - for (ForwardedStreamsContainer::iterator it = forwardedStreams_.begin(); it != forwardedStreams_.end(); ) - { - if (it->port == port && it->host == host) - { - delete (it->socket); - it = forwardedStreams_.erase(it); - } - else - ++it; - } -} - -void StreamSession::stopForwardingAll() -{ - for (ForwardedStreamsContainer::iterator it = forwardedStreams_.begin(); it != forwardedStreams_.end(); ++it) - delete (it->socket); - forwardedStreams_.clear(); -} - -/*static*/ -Message::Answer StreamSession::rawRequest(Socket& socket, const std::string& requestStr) -{ - typedef Message::Answer AnswerType; - - if (!socket.isOk()) - return AnswerType(Message::CLOSED_SOCKET); - socket.write(requestStr); - const std::string answer = socket.read(); - const Message::eStatus status = Message::checkAnswer(answer); - return AnswerType(status, answer); -} - -/*static*/ -Message::Answer StreamSession::request(Socket& socket, const std::string& requestStr, const std::string& keyOnSuccess) -{ - typedef Message::Answer AnswerType; - - const AnswerType answer = rawRequest(socket, requestStr); - return (answer.status == Message::OK) ? - AnswerType(answer.status, Message::getValue(answer.value, keyOnSuccess)) : - answer; -} - -/*static*/ -Message::eStatus StreamSession::request(Socket& socket, const std::string& requestStr) -{ - return rawRequest(socket, requestStr).status; -} - -/*static*/ -Message::Answer StreamSession::createStreamSession(Socket& socket, const std::string& sessionID, const std::string& nickname, const std::string& destination, const std::string& options) -{ - return request(socket, Message::sessionCreate(Message::sssStream, sessionID, nickname, destination, options), "DESTINATION"); -} - -/*static*/ -Message::Answer StreamSession::namingLookup(Socket& socket, const std::string& name) -{ - return request(socket, Message::namingLookup(name), "VALUE"); -} - -/*static*/ -Message::Answer StreamSession::destGenerate(Socket& socket) -{ -// while answer for a DEST GENERATE request doesn't contain a "RESULT" field we parse it manually - typedef Message::Answer ResultType; - - if (!socket.isOk()) - return ResultType(Message::CLOSED_SOCKET, FullDestination()); - socket.write(Message::destGenerate()); - const std::string answer = socket.read(); - const std::string pub = Message::getValue(answer, "PUB"); - const std::string priv = Message::getValue(answer, "PRIV"); - return (!pub.empty() && !priv.empty()) ? ResultType(Message::OK, FullDestination(pub, priv, /*isGenerated*/ true)) : ResultType(Message::EMPTY_ANSWER, FullDestination()); -} - -/*static*/ -Message::eStatus StreamSession::accept(Socket& socket, const std::string& sessionID, bool silent) -{ - return request(socket, Message::streamAccept(sessionID, silent)); -} - -/*static*/ -Message::eStatus StreamSession::connect(Socket& socket, const std::string& sessionID, const std::string& destination, bool silent) -{ - return request(socket, Message::streamConnect(sessionID, destination, silent)); -} - -/*static*/ -Message::eStatus StreamSession::forward(Socket& socket, const std::string& sessionID, const std::string& host, uint16_t port, bool silent) -{ - return request(socket, Message::streamForward(sessionID, host, port, silent)); -} - -const std::string& StreamSession::getNickname() const -{ - return nickname_; -} - -const std::string& StreamSession::getSessionID() const -{ - return sessionID_; -} - -const std::string& StreamSession::getOptions() const -{ - return i2pOptions_; -} - -const FullDestination& StreamSession::getMyDestination() const -{ - return myDestination_; -} - -bool StreamSession::isSick() const -{ - return isSick_; -} - -const sockaddr_in& StreamSession::getSAMAddress() const -{ - return socket_.getAddress(); -} - -const std::string& StreamSession::getSAMHost() const -{ - return socket_.getHost(); -} - -uint16_t StreamSession::getSAMPort() const -{ - return socket_.getPort(); -} - -const std::string& StreamSession::getSAMMinVer() const -{ - return socket_.getMinVer(); -} - -const std::string& StreamSession::getSAMMaxVer() const -{ - return socket_.getMaxVer(); -} - -const std::string& StreamSession::getSAMVersion() const -{ - return socket_.getVersion(); -} - -std::shared_ptr StreamSession::logStream; - -std::ostream& StreamSession::getLogStream () -{ - return logStream ? *logStream : std::cout; -} - -void StreamSession::SetLogFile (const std::string& filename) -{ - logStream = std::make_shared (filename, std::ofstream::out | std::ofstream::trunc); -} - -void StreamSession::CloseLogFile () -{ - logStream = nullptr; -} - -//-------------------------------------------------------------------------------------------------- - - -std::string Message::createSAMRequest(const char* format, ...) -{ - char buffer[SAM_BUFSIZE]; - memset(buffer, 0, SAM_BUFSIZE); - - va_list args; - va_start (args, format); - const int sizeToSend = vsnprintf(buffer, SAM_BUFSIZE, format, args); - va_end(args); - - if (sizeToSend < 0) - { - print_error("Failed to format message"); - return std::string(); - } - return std::string(buffer); -} - -std::string Message::hello(const std::string &minVer, const std::string &maxVer) -{ -/////////////////////////////////////////////////////////// -// -// -> HELLO VERSION -// MIN=$min -// MAX=$max -// -// <- HELLO REPLY -// RESULT=OK -// VERSION=$version -// -/////////////////////////////////////////////////////////// - - static const char* helloFormat = "HELLO VERSION MIN=%s MAX=%s\n"; - return createSAMRequest(helloFormat, minVer.c_str(), maxVer.c_str()); -} - -std::string Message::sessionCreate(SessionStyle style, const std::string& sessionID, const std::string& nickname, const std::string& destination /*= SAM_GENERATE_MY_DESTINATION*/, const std::string& options /*= ""*/) -{ -/////////////////////////////////////////////////////////// -// -// -> SESSION CREATE -// STYLE={STREAM,DATAGRAM,RAW} -// ID={$nickname} -// DESTINATION={$private_destination_key,TRANSIENT} -// [option=value]* -// -// <- SESSION STATUS -// RESULT=OK -// DESTINATION=$private_destination_key -// -/////////////////////////////////////////////////////////// - - std::string sessionStyle; - switch(style) - { - case sssStream: sessionStyle = "STREAM"; break; - case sssDatagram: sessionStyle = "DATAGRAM"; break; - case sssRaw: sessionStyle = "RAW"; break; - } - - static const char* sessionCreateFormat = "SESSION CREATE STYLE=%s ID=%s DESTINATION=%s inbound.nickname=%s SIGNATURE_TYPE=7 %s\n"; // we add inbound.nickname option - return createSAMRequest(sessionCreateFormat, sessionStyle.c_str(), sessionID.c_str(), destination.c_str(), nickname.c_str(), options.c_str()); -} - -std::string Message::streamAccept(const std::string& sessionID, bool silent /*= false*/) -{ -/////////////////////////////////////////////////////////// -// -// -> STREAM ACCEPT -// ID={$nickname} -// [SILENT={true,false}] -// -// <- STREAM STATUS -// RESULT=$result -// [MESSAGE=...] -// -/////////////////////////////////////////////////////////// - - static const char* streamAcceptFormat = "STREAM ACCEPT ID=%s SILENT=%s\n"; - return createSAMRequest(streamAcceptFormat, sessionID.c_str(), silent ? "true" : "false"); -} - -std::string Message::streamConnect(const std::string& sessionID, const std::string& destination, bool silent /*= false*/) -{ -/////////////////////////////////////////////////////////// -// -// -> STREAM CONNECT -// ID={$nickname} -// DESTINATION=$peer_public_base64_key -// [SILENT={true,false}] -// -// <- STREAM STATUS -// RESULT=$result -// [MESSAGE=...] -// -/////////////////////////////////////////////////////////// - - static const char* streamConnectFormat = "STREAM CONNECT ID=%s DESTINATION=%s SILENT=%s\n"; - return createSAMRequest(streamConnectFormat, sessionID.c_str(), destination.c_str(), silent ? "true" : "false"); -} - -std::string Message::streamForward(const std::string& sessionID, const std::string& host, uint16_t port, bool silent /*= false*/) -{ -/////////////////////////////////////////////////////////// -// -// -> STREAM FORWARD -// ID={$nickname} -// PORT={$port} -// [HOST={$host}] -// [SILENT={true,false}] -// -// <- STREAM STATUS -// RESULT=$result -// [MESSAGE=...] -// -/////////////////////////////////////////////////////////// - static const char* streamForwardFormat = "STREAM FORWARD ID=%s PORT=%u HOST=%s SILENT=%s\n"; - return createSAMRequest(streamForwardFormat, sessionID.c_str(), (unsigned)port, host.c_str(), silent ? "true" : "false"); -} - -std::string Message::namingLookup(const std::string& name) -{ -/////////////////////////////////////////////////////////// -// -// -> NAMING LOOKUP -// NAME=$name -// -// <- NAMING REPLY -// RESULT=OK -// NAME=$name -// VALUE=$base64key -// -/////////////////////////////////////////////////////////// - - static const char* namingLookupFormat = "NAMING LOOKUP NAME=%s\n"; - return createSAMRequest(namingLookupFormat, name.c_str()); -} - -std::string Message::destGenerate() -{ -/////////////////////////////////////////////////////////// -// -// -> DEST GENERATE -// -// <- DEST REPLY -// PUB=$pubkey -// PRIV=$privkey -// -/////////////////////////////////////////////////////////// - - static const char* destGenerateFormat = "DEST GENERATE SIGNATURE_TYPE=7\n"; - return createSAMRequest(destGenerateFormat); -} - -#define SAM_MAKESTRING(X) SAM_MAKESTRING2(X) -#define SAM_MAKESTRING2(X) #X - -#define SAM_CHECK_RESULT(value) \ - if (result == SAM_MAKESTRING(value)) return value - -Message::eStatus Message::checkAnswer(const std::string& answer) -{ - if (answer.empty()) - return EMPTY_ANSWER; - - const std::string result = getValue(answer, "RESULT"); - - SAM_CHECK_RESULT(OK); - SAM_CHECK_RESULT(DUPLICATED_DEST); - SAM_CHECK_RESULT(DUPLICATED_ID); - SAM_CHECK_RESULT(I2P_ERROR); - SAM_CHECK_RESULT(INVALID_ID); - SAM_CHECK_RESULT(INVALID_KEY); - SAM_CHECK_RESULT(CANT_REACH_PEER); - SAM_CHECK_RESULT(TIMEOUT); - SAM_CHECK_RESULT(NOVERSION); - SAM_CHECK_RESULT(KEY_NOT_FOUND); - SAM_CHECK_RESULT(PEER_NOT_FOUND); - SAM_CHECK_RESULT(ALREADY_ACCEPTING); - - return CANNOT_PARSE_ERROR; -} - -#undef SAM_CHECK_RESULT -#undef SAM_MAKESTRING2 -#undef SAM_MAKESTRING - -std::string Message::getValue(const std::string& answer, const std::string& key) -{ - if (key.empty()) - return std::string(); - - const std::string keyPattern = key + "="; - size_t valueStart = answer.find(keyPattern); - if (valueStart == std::string::npos) - return std::string(); - - valueStart += keyPattern.length(); - size_t valueEnd = answer.find_first_of(' ', valueStart); - if (valueEnd == std::string::npos) - valueEnd = answer.find_first_of('\n', valueStart); - return answer.substr(valueStart, valueEnd - valueStart); -} - - -} // namespace SAM \ No newline at end of file diff --git a/src/i2psam.h b/src/i2psam.h deleted file mode 100644 index 6ae000d1..00000000 --- a/src/i2psam.h +++ /dev/null @@ -1,424 +0,0 @@ -// Copyright (c) 2012-2013 giv -// Copyright (c) 2019 Denarius developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. -//-------------------------------------------------------------------------------------------------- -#ifndef I2PSAM_H -#define I2PSAM_H - -#include -#include -#include -#include -#include -#include - -#ifdef WIN32 -//#define _WIN32_WINNT 0x0501 -#define WIN32_LEAN_AND_MEAN 1 -#include -#else -#include -#include // for sockaddr_in -#include // for ntohs and htons -#endif - -// TODO: check a possible bug about cast -1 to SOCKET -#define SAM_INVALID_SOCKET (-1) -#define SAM_SOCKET_ERROR (-1) - -#define SAM_DEFAULT_ADDRESS "127.0.0.1" -#define SAM_DEFAULT_PORT 7656 -#define SAM_DEFAULT_MIN_VER "3.0" -#define SAM_DEFAULT_MAX_VER "3.0" -#define SAM_GENERATE_MY_DESTINATION "TRANSIENT" -#define SAM_MY_NAME "ME" -#define SAM_DEFAULT_I2P_OPTIONS "" - -#define SAM_NAME_INBOUND_QUANTITY "inbound.quantity" -#define SAM_DEFAULT_INBOUND_QUANTITY 2 -#define SAM_NAME_INBOUND_LENGTH "inbound.length" -#define SAM_DEFAULT_INBOUND_LENGTH 2 -#define SAM_NAME_INBOUND_LENGTHVARIANCE "inbound.lengthVariance" -#define SAM_DEFAULT_INBOUND_LENGTHVARIANCE 0 -#define SAM_NAME_INBOUND_BACKUPQUANTITY "inbound.backupquantity" -#define SAM_DEFAULT_INBOUND_BACKUPQUANTITY 0 -#define SAM_NAME_INBOUND_ALLOWZEROHOP "inbound.allowzerohop" -#define SAM_DEFAULT_INBOUND_ALLOWZEROHOP true -#define SAM_NAME_INBOUND_IPRESTRICTION "inbound.iprestriction" -#define SAM_DEFAULT_INBOUND_IPRESTRICTION 2 -#define SAM_NAME_OUTBOUND_QUANTITY "outbound.quantity" -#define SAM_DEFAULT_OUTBOUND_QUANTITY 2 -#define SAM_NAME_OUTBOUND_LENGTH "outbound.length" -#define SAM_DEFAULT_OUTBOUND_LENGTH 2 -#define SAM_NAME_OUTBOUND_LENGTHVARIANCE "outbound.lengthvariance" -#define SAM_DEFAULT_OUTBOUND_LENGTHVARIANCE 0 -#define SAM_NAME_OUTBOUND_BACKUPQUANTITY "outbound.backupquantity" -#define SAM_DEFAULT_OUTBOUND_BACKUPQUANTITY 0 -#define SAM_NAME_OUTBOUND_ALLOWZEROHOP "outbound.allowzerohop" -#define SAM_DEFAULT_OUTBOUND_ALLOWZEROHOP true -#define SAM_NAME_OUTBOUND_IPRESTRICTION "outbound.iprestriction" -#define SAM_DEFAULT_OUTBOUND_IPRESTRICTION 2 -#define SAM_NAME_OUTBOUND_PRIORITY "outbound.priority" -#define SAM_DEFAULT_OUTBOUND_PRIORITY 0 - -namespace SAM -{ - -typedef int SOCKET; - -class Message -{ -public: - enum SessionStyle - { - sssStream, - sssDatagram, // not supported now - sssRaw // not supported now - }; - - enum eStatus - { - OK, - EMPTY_ANSWER, - CLOSED_SOCKET, - CANNOT_PARSE_ERROR, - - // The destination is already in use - // - // -> SESSION CREATE ... - // <- SESSION STATUS RESULT=DUPLICATED_DEST - DUPLICATED_DEST, - - // The nickname is already associated with a session - // - // -> SESSION CREATE ... - // <- SESSION STATUS RESULT=DUPLICATED_ID - DUPLICATED_ID, - - // A generic I2P error (e.g. I2CP disconnection, etc.) - // - // -> HELLO VERSION ... - // <- HELLO REPLY RESULT=I2P_ERROR MESSAGE={$message} - // - // -> SESSION CREATE ... - // <- SESSION STATUS RESULT=I2P_ERROR MESSAGE={$message} - // - // -> STREAM CONNECT ... - // <- STREAM STATUS RESULT=I2P_ERROR MESSAGE={$message} - // - // -> STREAM ACCEPT ... - // <- STREAM STATUS RESULT=I2P_ERROR MESSAGE={$message} - // - // -> STREAM FORWARD ... - // <- STREAM STATUS RESULT=I2P_ERROR MESSAGE={$message} - // - // -> NAMING LOOKUP ... - // <- NAMING REPLY RESULT=INVALID_KEY NAME={$name} MESSAGE={$message} - I2P_ERROR, - - // Stream session ID doesn't exist - // - // -> STREAM CONNECT ... - // <- STREAM STATUS RESULT=INVALID_ID MESSAGE={$message} - // - // -> STREAM ACCEPT ... - // <- STREAM STATUS RESULT=INVALID_ID MESSAGE={$message} - // - // -> STREAM FORWARD ... - // <- STREAM STATUS RESULT=INVALID_ID MESSAGE={$message} - INVALID_ID, - - // The destination is not a valid private destination key - // - // -> SESSION CREATE ... - // <- SESSION STATUS RESULT=INVALID_KEY MESSAGE={$message} - // - // -> STREAM CONNECT ... - // <- STREAM STATUS RESULT=INVALID_KEY MESSAGE={$message} - // - // -> NAMING LOOKUP ... - // <- NAMING REPLY RESULT=INVALID_KEY NAME={$name} MESSAGE={$message} - INVALID_KEY, - - // The peer exists, but cannot be reached - // - // -> STREAM CONNECT ... - // <- STREAM STATUS RESULT=CANT_REACH_PEER MESSAGE={$message} - CANT_REACH_PEER, - - // Timeout while waiting for an event (e.g. peer answer) - // - // -> STREAM CONNECT ... - // <- STREAM STATUS RESULT=TIMEOUT MESSAGE={$message} - TIMEOUT, - - // The SAM bridge cannot find a suitable version - // - // -> HELLO VERSION ... - // <- HELLO REPLY RESULT=NOVERSION MESSAGE={$message} - NOVERSION, - - // The naming system can't resolve the given name - // - // -> NAMING LOOKUP ... - // <- NAMING REPLY RESULT=INVALID_KEY NAME={$name} MESSAGE={$message} - KEY_NOT_FOUND, - - // The peer cannot be found on the network - // - // ?? - PEER_NOT_FOUND, - - // ?? - // - // -> STREAM ACCEPT - // <- STREAM STATUS RESULT=ALREADY_ACCEPTING - ALREADY_ACCEPTING, - - // ?? - FAILED, - // ?? - CLOSED - }; - - template - struct Answer - { - const Message::eStatus status; - T value; - - Answer(Message::eStatus status, const T& value) - : status(status), value(value) {} - explicit Answer(Message::eStatus status) - : status(status), value() {} - }; - - static std::string hello(const std::string& minVer, const std::string& maxVer); - static std::string sessionCreate(SessionStyle style, const std::string& sessionID, const std::string& nickname, const std::string& destination = SAM_GENERATE_MY_DESTINATION, const std::string& options = ""); - static std::string streamAccept(const std::string& sessionID, bool silent = false); - static std::string streamConnect(const std::string& sessionID, const std::string& destination, bool silent = false); - static std::string streamForward(const std::string& sessionID, const std::string& host, uint16_t port, bool silent = false); - - static std::string namingLookup(const std::string& name); - static std::string destGenerate(); - - static eStatus checkAnswer(const std::string& answer); - static std::string getValue(const std::string& answer, const std::string& key); -private: - static std::string createSAMRequest(const char* format, ...); -}; - -class Socket -{ -public: - Socket(const std::string& SAMHost, uint16_t SAMPort, const std::string &minVer, const std::string& maxVer); - Socket(const sockaddr_in& addr, const std::string& minVer, const std::string& maxVer); - // explicit because we don't want to create any socket implicity - explicit Socket(const Socket& rhs); // creates a new socket with the same parameters - ~Socket(); - - void write(const std::string& msg); - std::string read(); - SOCKET release(); - void close(); - - bool isOk() const; - - const std::string& getVersion() const; - const std::string& getHost() const; - uint16_t getPort() const; - const std::string& getMinVer() const; - const std::string& getMaxVer() const; - - const sockaddr_in& getAddress() const; - -private: - SOCKET socket_; - sockaddr_in servAddr_; - std::string SAMHost_; - uint16_t SAMPort_; - const std::string minVer_; - const std::string maxVer_; - std::string version_; - -#ifdef WIN32 - static int instances_; - static void initWSA(); - static void freeWSA(); -#endif - - void handshake(); - void init(); - - Socket& operator=(const Socket&); -}; - -struct FullDestination -{ - std::string pub; - std::string priv; - bool isGenerated; - - FullDestination() {} - FullDestination(const std::string& pub, const std::string& priv, bool isGenerated) - :pub(pub), priv(priv), isGenerated(isGenerated) {} -}; - -template -struct RequestResult -{ - bool isOk; - T value; - - RequestResult() - : isOk(false) {} - - explicit RequestResult(const T& value) - : isOk(true), value(value) {} -}; - -template -struct RequestResult > -{ - // a class-helper for resolving a problem with conversion from temporary RequestResult to non-const RequestResult& - struct RequestResultRef - { - bool isOk; - T* value; - - RequestResultRef(bool isOk, T* value) - : isOk(isOk), value(value) {} - }; - - bool isOk; - std::shared_ptr value; - - RequestResult() - : isOk(false) {} - - explicit RequestResult(std::shared_ptr& value) - : isOk(true), value(value) {} - - - // some C++ magic - RequestResult(RequestResultRef ref) - : isOk(ref.isOk), value(ref.value) {} - - RequestResult& operator=(RequestResultRef ref) - { - if (value.get() != ref.value) - { - isOk = ref.isOk; - value.reset(ref.value); - } - return *this; - } - - operator RequestResultRef() - { - return RequestResultRef(this->isOk, this->value.release()); - } -}; - -template<> -struct RequestResult -{ - bool isOk; - - RequestResult() - : isOk(false) {} - - explicit RequestResult(bool isOk) - : isOk(isOk) {} -}; - -class StreamSession -{ -public: - StreamSession( - const std::string& nickname, - const std::string& SAMHost = SAM_DEFAULT_ADDRESS, - uint16_t SAMPort = SAM_DEFAULT_PORT, - const std::string& destination = SAM_GENERATE_MY_DESTINATION, - const std::string& i2pOptions = SAM_DEFAULT_I2P_OPTIONS, - const std::string& minVer = SAM_DEFAULT_MIN_VER, - const std::string& maxVer = SAM_DEFAULT_MAX_VER); - explicit StreamSession(StreamSession& rhs); - ~StreamSession(); - - static std::string generateSessionID(); - - RequestResult > accept(bool silent); - RequestResult > connect(const std::string& destination, bool silent); - RequestResult forward(const std::string& host, uint16_t port, bool silent); - RequestResult namingLookup(const std::string& name) const; - RequestResult destGenerate() const; - - void stopForwarding(const std::string& host, uint16_t port); - void stopForwardingAll(); - - const FullDestination& getMyDestination() const; - - const sockaddr_in& getSAMAddress() const; - const std::string& getSAMHost() const; - uint16_t getSAMPort() const; - const std::string& getNickname() const; - const std::string& getSessionID() const; - const std::string& getSAMMinVer() const; - const std::string& getSAMMaxVer() const; - const std::string& getSAMVersion() const; - const std::string& getOptions() const; - - bool isSick() const; - bool isReady () const { return socket_.isOk() && !isSick (); }; - - static std::ostream& getLogStream (); - static void SetLogFile (const std::string& filename); - static void CloseLogFile (); - -private: - StreamSession(const StreamSession& rhs); - StreamSession& operator=(const StreamSession& rhs); - - struct ForwardedStream - { - Socket* socket; - std::string host; - uint16_t port; - bool silent; - - ForwardedStream(Socket* socket, const std::string& host, uint16_t port, bool silent) - : socket(socket), host(host), port(port), silent(silent) {} - }; - - typedef std::list ForwardedStreamsContainer; - - Socket socket_; - const std::string nickname_; - const std::string sessionID_; - FullDestination myDestination_; - const std::string i2pOptions_; - ForwardedStreamsContainer forwardedStreams_; - mutable bool isSick_; - static std::shared_ptr logStream; - - void fallSick() const; - FullDestination createStreamSession(const std::string &destination); - - static Message::Answer rawRequest(Socket& socket, const std::string& requestStr); - static Message::Answer request(Socket& socket, const std::string& requestStr, const std::string& keyOnSuccess); - static Message::eStatus request(Socket& socket, const std::string& requestStr); - // commands - static Message::Answer createStreamSession(Socket& socket, const std::string& sessionID, const std::string& nickname, const std::string& destination, const std::string& options); - static Message::Answer namingLookup(Socket& socket, const std::string& name); - static Message::Answer destGenerate(Socket& socket); - - static Message::eStatus accept(Socket& socket, const std::string& sessionID, bool silent); - static Message::eStatus connect(Socket& socket, const std::string& sessionID, const std::string& destination, bool silent); - static Message::eStatus forward(Socket& socket, const std::string& sessionID, const std::string& host, uint16_t port, bool silent); -}; - -} // namespace SAM - -#endif // I2PSAM_H \ No newline at end of file diff --git a/src/init.cpp b/src/init.cpp index 27bdaefb..0337487d 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -37,10 +37,6 @@ #include #endif -#ifdef USE_NATIVE_I2P -#include "i2p.h" -#endif - using namespace std; using namespace boost; @@ -112,11 +108,19 @@ void Shutdown(void* parg) { fShutdown = true; -#ifdef USE_NATIVE_I2P - I2PSession::Instance().Stop(); //Shutdown I2P Session if enabled -#endif Finalise(); - // Finalise is main.cpp + /* + SecureMsgShutdown(); + + mempool.AddTransactionsUpdated(1); +// CTxDB().Close(); + bitdb.Flush(false); + StopNode(); + bitdb.Flush(true); + boost::filesystem::remove(GetPidFile()); + UnregisterWallet(pwalletMain); + delete pwalletMain; + */ NewThread(ExitTimeout, NULL); MilliSleep(50); printf("Denarius exited\n\n"); @@ -265,15 +269,6 @@ bool static InitWarning(const std::string &str) return true; } -#ifdef USE_NATIVE_I2P -bool static BindNativeI2P(/*bool fError = true*/) -{ - if (IsLimited(NET_NATIVE_I2P)) - return false; - return BindListenNativeI2P(); -} -#endif - bool static Bind(const CService &addr, bool fError = true) { @@ -312,7 +307,7 @@ std::string HelpMessage() " -connect= " + _("Connect only to the specified node(s)") + "\n" + " -seednode= " + _("Connect to a node to retrieve peer addresses, and disconnect") + "\n" + " -externalip= " + _("Specify your own public address") + "\n" + - " -onlynet= " + _("Only connect to nodes in network (IPv4, IPv6, I2P, Native I2P or Tor)") + "\n" + + " -onlynet= " + _("Only connect to nodes in network (IPv4, IPv6 or Tor)") + "\n" + " -discover " + _("Discover own IP address (default: 1 when listening and no -externalip)") + "\n" + " -listen " + _("Accept connections from outside (default: 1 if no -proxy or -connect)") + "\n" + " -bind= " + _("Bind to given address. Use [host]:port notation for IPv6") + "\n" + @@ -386,7 +381,8 @@ std::string HelpMessage() "\n" + _("Fortunastake options:") + "\n" + " -fortunastake= " + _("Enable the client to act as a fortunastake (0-1, default: 0)") + "\n" + - " -fsconf= " + _("Specify fortunastake configuration file (default: fortunastake.conf)") + "\n" + + " -mnconf= " + _("Specify fortunastake configuration file (default: fortunastake.conf)") + "\n" + + " -mnconflock= " + _("Lock fortunastakes from fortunastake configuration file (default: 1)") + " -fsconflock= " + _("Lock fortunastakes from fortunastake configuration file (default: 1)") + " -fortunastakeprivkey= " + _("Set the fortunastake private key") + "\n" + " -fortunastakeaddr= " + _("Set external address:port to get to this fortunastake (example: address:port)") + "\n" + @@ -470,28 +466,6 @@ bool AppInit2() // ********************************************************* Step 2: parameter interactions -#ifdef USE_NATIVE_I2P - if(fNativeI2P) - { - uiInterface.InitMessage(_("Creating Denarius I2P SAM session...")); - printf("Creating Denarius I2P SAM Session...\n"); - if (!I2PSession::Instance().Start() && IsI2POnly()) - return InitError("Can not start a connection to Denarius I2P SAM\n"); - - if (GetBoolArg(I2P_SAM_GENERATE_DESTINATION_PARAM, false)) - { - const SAM::FullDestination generatedDest = I2PSession::Instance().destGenerate(); - uiInterface.ThreadSafeShowGeneratedI2PAddress( - "Generated I2P address", - generatedDest.pub, - generatedDest.priv, - I2PSession::GenerateB32AddressFromDestination(generatedDest.pub), - GetConfigFile().string()); - return false; - } - } -#endif - nNodeLifespan = GetArg("-addrlifespan", 7); fUseFastIndex = GetBoolArg("-fastindex", true); nMinStakeInterval = GetArg("-minstakeinterval", 60); // 2 blocks, don't make pos chains! @@ -539,8 +513,6 @@ bool AppInit2() fTestNet = GetBoolArg("-testnet"); fNativeTor = GetBoolArg("-nativetor"); - fNativeI2P = GetBoolArg("-nativei2p"); - fFSLock = GetBoolArg("-fsconflock"); //if (fTestNet) @@ -688,7 +660,7 @@ bool AppInit2() if (GetBoolArg("-shrinkdebugfile", !fDebug)) ShrinkDebugFile(); - printf("\n"); + printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); printf("Denarius version %s (%s)\n", FormatFullVersion().c_str(), CLIENT_DATE.c_str()); printf("Using OpenSSL version %s\n", SSLeay_version(SSLEAY_VERSION)); if (!fLogTimestamps) @@ -697,17 +669,25 @@ bool AppInit2() printf("Used data directory %s\n", strDataDir.c_str()); std::ostringstream strErrors; + if (mapArgs.count("-fortunastakepaymentskey")) // fortunastake payments priv key + { + if (!fortunastakePayments.SetPrivKey(GetArg("-fortunastakepaymentskey", ""))) + return InitError(_("Unable to sign fortunastake payment winner, wrong key?")); + if (!sporkManager.SetPrivKey(GetArg("-fortunastakepaymentskey", ""))) + return InitError(_("Unable to sign spork message, wrong key?")); + } + //ignore fortunastakes below protocol version CFortunaStake::minProtoVersion = GetArg("-fortunastakeminprotocol", MIN_MN_PROTO_VERSION); if (fDaemon) - fprintf(stdout, "Denarius (D) server starting\n"); + fprintf(stdout, "Denarius server starting\n"); int64_t nStart; // Anonymous Ring Signatures ~ D e n a r i u s - v3.0.0.0 if (initialiseRingSigs() != 0) - return InitError("initializeRingSigs() failed."); + return InitError("initialiseRingSigs() failed."); // ********************************************************* Step 5: verify database integrity @@ -777,17 +757,6 @@ bool AppInit2() BOOST_FOREACH(std::string snet, mapMultiArgs["-onlynet"]) { enum Network net = ParseNetwork(snet); -#ifdef USE_NATIVE_I2P - if (net == NET_NATIVE_I2P) - { - // Disable upnp and listen on I2P only. -#ifdef USE_UPNP - SoftSetBoolArg("-upnp", false); -#endif - SoftSetBoolArg("-listen",true); - SoftSetBoolArg("-discover",false); - } -#endif if (net == NET_UNROUTABLE) return InitError(strprintf(_("Unknown network specified in -onlynet: '%s'"), snet.c_str())); nets.insert(net); @@ -835,7 +804,7 @@ bool AppInit2() }; }; -#ifdef USE_NATIVETOR + // Native Tor Onion and -tor flag integration if(fNativeTor) { @@ -853,23 +822,9 @@ bool AppInit2() SetReachable(NET_TOR); }; }; -#endif -#ifdef USE_NATIVE_I2P - // -i2p can override both tor and proxy - if(fNativeI2P) { - if (!(mapArgs.count("-i2p") && mapArgs["-i2p"] == "0") || IsI2POnly()) - { - // Disable on i2p per default -#ifdef USE_UPNP - SoftSetBoolArg("-upnp", false); -#endif - SoftSetBoolArg("-listen",true); - SetReachable(NET_NATIVE_I2P); - } - } -#endif + // see Step 2: parameter interactions for more information about these - if(!fNativeTor) // Available if nativetor are disabled + if(!fNativeTor) // Available if nativetor is disabled { fNoListen = !GetBoolArg("-listen", true); fDiscover = GetBoolArg("-discover", true); @@ -902,14 +857,8 @@ bool AppInit2() fBound |= Bind(CService(in6addr_any, GetListenPort()), false); if (!IsLimited(NET_IPV4)) fBound |= Bind(CService(inaddr_any, GetListenPort()), !fBound); -#ifdef USE_NATIVE_I2P - if(fNativeI2P) { - if (!IsLimited(NET_NATIVE_I2P)) - fBound |= BindNativeI2P(); - } -#endif }; - if (!fBound && !fNativeI2P) + if (!fBound) return InitError(_("Failed to listen on any port. Use -listen=0 if you want this.")); }; }; @@ -1226,7 +1175,7 @@ bool AppInit2() } if (pwalletMain) { - if(GetBoolArg("-fsconflock", true)) { + if(GetBoolArg("-fsconflock", true) & GetBoolArg("-mnconflock", true)) { LOCK(pwalletMain->cs_wallet); printf("Locking Fortunastakes:\n"); uint256 mnTxHash; @@ -1297,26 +1246,19 @@ bool AppInit2() printf("setKeyPool.size() = %" PRIszu"\n", pwalletMain->setKeyPool.size()); printf("mapWallet.size() = %" PRIszu"\n", pwalletMain->mapWallet.size()); printf("mapAddressBook.size() = %" PRIszu"\n", pwalletMain->mapAddressBook.size()); -#ifdef USE_NATIVETOR + if(fNativeTor) - printf("Native Tor Onion Relay Node Enabled\n"); - else - printf("Native Tor Onion Relay Disabled\n"); -#endif -#ifdef USE_NATIVE_I2P - if(fNativeI2P) - printf("Native I2P Node Enabled\n"); + printf("Native Tor Onion Relay Node Enabled"); else - printf("Native I2P Disabled\n"); -#endif + printf("Native Tor Onion Relay Disabled, Using Regular Peers..."); if (fDebug) - printf("Debugging is Enabled.\n"); + printf("Debugging is Enabled."); else - printf("Debugging is not enabled.\n"); + printf("Debugging is not enabled."); if (!NewThread(StartNode, NULL)) - InitError(_("Error: could not start node\n")); + InitError(_("Error: could not start node")); if (fServer) NewThread(ThreadRPCServer, NULL); diff --git a/src/main.cpp b/src/main.cpp index 0bb30b3b..4bc6fc63 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -67,7 +67,7 @@ bool fAddrIndex = false; CMedianFilter cPeerBlockCounts(5, 0); // Amount of blocks that other nodes claim to have std::map mapAnonOutputStats; - +//map mapAnonOutputStats; // display only, not 100% accurate, height could become inaccurate due to undos map mapOrphanBlocks; multimap mapOrphanBlocksByPrev; set > setStakeSeenOrphan; @@ -208,6 +208,13 @@ void static UpdatedTransaction(const uint256& hashTx) BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) pwallet->UpdatedTransaction(hashTx); } +/* +// dump all wallets +void static PrintWallets(const CBlock& block) +{ + BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered) + pwallet->PrintWallet(block); +} */ // notify wallets about an incoming inventory (for request counts) void static Inventory(const uint256& hash) @@ -243,12 +250,18 @@ bool Finalise() CTxDB().Close(); + return true; } bool AbortNode(const std::string &strMessage, const std::string &userMessage) { strMiscWarning = strMessage; printf("*** %s\n", strMessage.c_str()); + /* + uiInterface.ThreadSafeMessageBox( + userMessage.empty() ? _("Error: A fatal internal error occured, see debug.log for details") : userMessage, + "", CClientUIInterface::MSG_ERROR); + */ StartShutdown(); return false; } @@ -325,6 +338,12 @@ unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans) return nEvicted; } + + + + + + ////////////////////////////////////////////////////////////////////////////// // // CTransaction and CTxIndex @@ -358,6 +377,54 @@ bool CTransaction::ReadFromDisk(COutPoint prevout) return ReadFromDisk(txdb, prevout, txindex); } +// bool CTransaction::IsStandard() const +// { +// if (nVersion > CTransaction::CURRENT_VERSION) +// return false; + +// BOOST_FOREACH(const CTxIn& txin, vin) +// { +// // Biggest 'standard' txin is a 3-signature 3-of-3 CHECKMULTISIG +// // pay-to-script-hash, which is 3 ~80-byte signatures, 3 +// // ~65-byte public keys, plus a few script ops. +// if (txin.scriptSig.size() > 500) +// return false; +// if (!txin.scriptSig.IsPushOnly()) +// return false; +// if (fEnforceCanonical && !txin.scriptSig.HasCanonicalPushes()) { +// return false; +// } +// } + +// unsigned int nDataOut = 0; +// unsigned int nTxnOut = 0; + +// txnouttype whichType; +// BOOST_FOREACH(const CTxOut& txout, vout) { +// if (!::IsStandard(txout.scriptPubKey, whichType)) +// return false; +// if (whichType == TX_NULL_DATA) +// { +// nDataOut++; +// } else +// { +// if (txout.nValue == 0) +// return false; +// nTxnOut++; +// } +// if (fEnforceCanonical && !txout.scriptPubKey.HasCanonicalPushes()) { +// return false; +// } +// } + +// // only one OP_RETURN txout per txn out is permitted +// if (nDataOut > nTxnOut) { +// return false; +// } + +// return true; +// } + bool IsStandardTx(const CTransaction& tx, string& reason) { if (tx.nVersion > CTransaction::CURRENT_VERSION && tx.nVersion != ANON_TXN_VERSION) { @@ -665,6 +732,12 @@ int CMerkleTx::SetMerkleBranch(const CBlock* pblock) return pindexBest->nHeight - pindex->nHeight + 1; } + + + + + + bool CTransaction::CheckTransaction() const { // Basic checks that don't depend on any context @@ -1299,6 +1372,7 @@ bool CMerkleTx::AcceptToMemoryPool() bool CWalletTx::AcceptWalletTransaction(CTxDB& txdb) { + { // Add previous supporting transactions first BOOST_FOREACH(CMerkleTx& tx, vtxPrev) @@ -1665,6 +1739,10 @@ void CBlock::UpdateTime(const CBlockIndex* pindexPrev) nTime = max(GetBlockTime(), GetAdjustedTime()); } + + + + // Requires cs_main. void Misbehaving(NodeId pnode, int howmuch) { @@ -1691,6 +1769,10 @@ void Misbehaving(NodeId pnode, int howmuch) } } + + + + bool CTransaction::DisconnectInputs(CTxDB& txdb) { // Relinquish previous transactions' spent pointers @@ -1726,6 +1808,7 @@ bool CTransaction::DisconnectInputs(CTxDB& txdb) return true; } + bool CTransaction::FetchInputs(CTxDB& txdb, const map& mapTestPool, bool fBlock, bool fMiner, MapPrevTx& inputsRet, bool& fInvalid) { @@ -2315,6 +2398,17 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex, bool fJustCheck) unsigned int flags = SCRIPT_VERIFY_NOCACHE; + /* // Currently don't need + if(V3(nTime)) + { + flags |= SCRIPT_VERIFY_NULLDUMMY | + SCRIPT_VERIFY_STRICTENC | + SCRIPT_VERIFY_ALLOW_EMPTY_SIG | + SCRIPT_VERIFY_FIX_HASHTYPE | + SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY; + } + */ + //// issue here: it doesn't know the version unsigned int nTxPos; if (fJustCheck) @@ -4051,6 +4145,13 @@ string GetWarnings(string strFor) return "error"; } + + + + + + + ////////////////////////////////////////////////////////////////////////////// // // Messages @@ -4133,6 +4234,14 @@ void static ProcessGetData(CNode* pfrom) { // Send stream from relay memory bool pushed = false; + /*{ + LOCK(cs_mapRelay); + map::iterator mi = mapRelay.find(inv); + if (mi != mapRelay.end()) { + pfrom->PushMessage(inv.GetCommand(), (*mi).second); + pushed = true; + } + }*/ if (!pushed && inv.type == MSG_TX) { if(mapFortunaBroadcastTxes.count(inv.hash)){ CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); @@ -4205,7 +4314,7 @@ void static ProcessGetData(CNode* pfrom) // The message start string is designed to be unlikely to occur in normal data. // The characters are rarely used upper ASCII, not valid as UTF-8, and produce // a large 4-byte int at any alignment. -unsigned char pchMessageStart[4] = { 0xfa, 0xf2, 0xef, 0xb4 }; //Magic Number +unsigned char pchMessageStart[4] = { 0xfa, 0xf2, 0xef, 0xb4 }; bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, int64_t nTimeReceived) { @@ -4245,10 +4354,19 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, printf("Partner %s using obsolete version %i; DISCONNECTING\n", pfrom->addr.ToString().c_str(), pfrom->nVersion); pfrom->fDisconnect = true; if (pfrom->fForTunaMaster) - printf("Masternode hosting node version is obsolete. This masternode should be removed from the list\n"); + printf("Masternode hosting node version was obsolete. This masternode should be removed from the list\n"); return false; } + /* + if (pfrom->nVersion < PROTO_VERSION) + { + // disconnect from peers older than this proto version + printf("partner %s using obsolete version %i; disconnecting\n", pfrom->addr.ToString().c_str(), pfrom->nVersion); + pfrom->fDisconnect = true; + return false; + }*/ + if (pfrom->nVersion == 10300) pfrom->nVersion = 300; if (!vRecv.empty()) @@ -5231,6 +5349,8 @@ bool SendMessages(CNode* pto, bool fSendTrickle) SecureMsgSendData(pto, fSendTrickle); } + + return true; } @@ -5240,4 +5360,4 @@ int64_t GetFortunastakePayment(int nHeight, int64_t blockValue) int64_t ret = static_cast(blockValue * 1/3); //33% return ret; -} \ No newline at end of file +} diff --git a/src/makefile.arm b/src/makefile.arm index 6f887f40..e1925b78 100644 --- a/src/makefile.arm +++ b/src/makefile.arm @@ -8,7 +8,6 @@ USE_LEVELDB:=1 USE_UPNP:=1 USE_NATIVETOR:=- -USE_NATIVE_I2P:=1 LINK:=$(CXX) ARCH:=$(system lscpu | head -n 1 | awk '{print $2}') @@ -49,13 +48,6 @@ ifneq (${USE_NATIVETOR}, -) DEFS += $(addprefix -I,$(CURDIR)/tor) -DUSE_NATIVETOR=$(USE_NATIVETOR) endif -ifndef USE_NATIVE_I2P - override USE_NATIVE_I2P = - -endif -ifneq (${USE_NATIVE_I2P}, -) - DEFS += -DUSE_NATIVE_I2P=$(USE_NATIVE_I2P) -endif - ifndef USE_UPNP override USE_UPNP = - endif @@ -335,11 +327,6 @@ OBJS= \ obj/ringsig.o -ifeq (${USE_NATIVE_I2P}, 1) - OBJS += obj/i2p.o - OBJS += obj/i2psam.o -endif - all: denariusd # diff --git a/src/makefile.unix b/src/makefile.unix index 9759a22d..e07d48df 100644 --- a/src/makefile.unix +++ b/src/makefile.unix @@ -6,7 +6,6 @@ USE_LEVELDB:=1 USE_UPNP:=1 USE_NATIVETOR:=1 -USE_NATIVE_I2P:=1 LINK:=$(CXX) ARCH:=$(system lscpu | head -n 1 | awk '{print $2}') @@ -46,13 +45,6 @@ ifneq (${USE_NATIVETOR}, -) DEFS += $(addprefix -I,$(CURDIR)/tor) -DUSE_NATIVETOR=$(USE_NATIVETOR) endif -ifndef USE_NATIVE_I2P - override USE_NATIVE_I2P = - -endif -ifneq (${USE_NATIVE_I2P}, -) - DEFS += -DUSE_NATIVE_I2P=$(USE_NATIVE_I2P) -endif - ifndef USE_UPNP override USE_UPNP = - endif @@ -379,10 +371,6 @@ OBJS= \ obj/ringsig.o endif -ifeq (${USE_NATIVE_I2P}, 1) - OBJS += obj/i2p.o - OBJS += obj/i2psam.o -endif all: denariusd diff --git a/src/net.cpp b/src/net.cpp index c4a4a9ef..e7ba6040 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1,4 +1,3 @@ -// Copyright (c) 2019 Denarius developers // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2012 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying @@ -17,10 +16,6 @@ #include #endif -#ifdef USE_NATIVE_I2P -#include "i2p.h" -#endif - #ifdef USE_UPNP #include #include @@ -39,7 +34,7 @@ extern "C" { } #endif -static const int MAX_OUTBOUND_CONNECTIONS = 27; //Bumping up to 27 from 16 +static const int MAX_OUTBOUND_CONNECTIONS = 16; void ThreadMessageHandler2(void* parg); void ThreadSocketHandler2(void* parg); @@ -51,18 +46,20 @@ void ThreadMapPort2(void* parg); void ThreadDNSAddressSeed2(void* parg); bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound = NULL, const char *strDest = NULL, bool fOneShot = false); + +struct LocalServiceInfo { + int nScore; + int nPort; +}; + // // Global state variables // bool fDiscover = true; bool fUseUPnP = false; -#ifdef USE_NATIVE_I2P -uint64_t nLocalServices = NODE_I2P | NODE_NETWORK; -#else uint64_t nLocalServices = NODE_NETWORK; -#endif -CCriticalSection cs_mapLocalHost; -map mapLocalHost; +static CCriticalSection cs_mapLocalHost; +static map mapLocalHost; static bool vfReachable[NET_MAX] = {}; static bool vfLimited[NET_MAX] = {}; static CNode* pnodeLocalHost = NULL; @@ -73,11 +70,6 @@ boost::array vnThreadsRunning; static std::vector vhListenSocket; CAddrMan addrman; -#ifdef USE_NATIVE_I2P -static std::vector vhI2PListenSocket; -int nI2PNodeCount = 0; -#endif - vector vNodes; CCriticalSection cs_vNodes; map mapRelay; @@ -332,8 +324,8 @@ bool IsReachable(const CNetAddr& addr) bool GetMyExternalIP2(const CService& addrConnect, const char* pszGet, const char* pszKeyword, CNetAddr& ipRet) { SOCKET hSocket; - bool bProxyConnectionFailed = false; - int ntimeout = 1000; + bool bProxyConnectionFailed = false; + int ntimeout = 1000; if (!ConnectSocket(addrConnect, hSocket, ntimeout, &bProxyConnectionFailed)) return error("GetMyExternalIP() : connection to %s failed", addrConnect.ToString().c_str()); @@ -441,11 +433,6 @@ void ThreadGetMyExternalIP(void* parg) { // Make this thread recognisable as the external IP detection thread RenameThread("denarius-ext-ip"); -#ifdef USE_NATIVE_I2P - - if (IsI2POnly() && fNativeI2P) - return; -#endif CNetAddr addrLocalHost; if (GetMyExternalIP(addrLocalHost)) @@ -558,12 +545,6 @@ CNode* ConnectNode(CAddress addrConnect, const char *pszDest, bool forTunaMaster { LOCK(cs_vNodes); vNodes.push_back(pnode); -#ifdef USE_NATIVE_I2P - if (fNativeI2P) { - if (addrConnect.IsNativeI2P()) - ++nI2PNodeCount; - } -#endif } if(forTunaMaster) @@ -732,15 +713,7 @@ bool CNode::ReceiveMsgBytes(const char *pch, unsigned int nBytes) // get current incomplete message, or create a new one if (vRecvMsg.empty() || vRecvMsg.back().complete()) -#ifdef USE_NATIVE_I2P - if (fNativeI2P) { - vRecvMsg.push_back(CNetMessage(nRecvStreamType, nRecvVersion)); - } else { vRecvMsg.push_back(CNetMessage(SER_NETWORK, nRecvVersion)); - } -#else - vRecvMsg.push_back(CNetMessage(SER_NETWORK, nRecvVersion)); -#endif CNetMessage& msg = vRecvMsg.back(); @@ -764,52 +737,6 @@ bool CNode::ReceiveMsgBytes(const char *pch, unsigned int nBytes) return true; } -#ifdef USE_NATIVE_I2P -void AddIncomingConnection(SOCKET hSocket, const CAddress& addr) -{ - int nInbound = 0; - - { - LOCK(cs_vNodes); - BOOST_FOREACH(CNode* pnode, vNodes) - if (pnode->fInbound) - nInbound++; - } - - if (hSocket == INVALID_SOCKET) - { - int nErr = WSAGetLastError(); - if (nErr != WSAEWOULDBLOCK) - printf("I2P socket error accept failed: %d\n", nErr); - } - else if (nInbound >= GetArg("-maxconnections", 125) - MAX_OUTBOUND_CONNECTIONS) - { - { - LOCK(cs_setservAddNodeAddresses); - if (!setservAddNodeAddresses.count(addr)) - closesocket(hSocket); - } - } - else if (CNode::IsBanned(addr)) - { - printf("I2P connection from %s dropped (banned)\n", addr.ToString().c_str()); - closesocket(hSocket); - } - else - { - printf("I2P accepted connection %s\n", addr.ToString().c_str()); - CNode* pnode = new CNode(hSocket, addr, "", true); - pnode->AddRef(); - { - LOCK(cs_vNodes); - vNodes.push_back(pnode); - ++nI2PNodeCount; - } - } -} - -#endif - int CNetMessage::readHeader(const char *pch, unsigned int nBytes) { // copy data to temporary parsing buffer @@ -933,9 +860,6 @@ void ThreadSocketHandler2(void* parg) printf("ThreadSocketHandler started\n"); list vNodesDisconnected; unsigned int nPrevNodeCount = 0; -#ifdef USE_NATIVE_I2P - int nPrevI2PNodeCount = 0; -#endif while (true) { @@ -965,12 +889,6 @@ void ThreadSocketHandler2(void* parg) if (pnode->fNetworkNode || pnode->fInbound) pnode->Release(); vNodesDisconnected.push_back(pnode); -#ifdef USE_NATIVE_I2P - if (fNativeI2P) { - if (pnode->addr.IsNativeI2P()) - --nI2PNodeCount; - } -#endif } } @@ -1012,15 +930,6 @@ void ThreadSocketHandler2(void* parg) nPrevNodeCount = vNodes.size(); uiInterface.NotifyNumConnectionsChanged(vNodes.size()); } -#ifdef USE_NATIVE_I2P -if (fNativeI2P) { - if (nPrevI2PNodeCount != nI2PNodeCount) - { - nPrevI2PNodeCount = nI2PNodeCount; - uiInterface.NotifyNumI2PConnectionsChanged(nI2PNodeCount); - } -} -#endif // @@ -1039,19 +948,6 @@ if (fNativeI2P) { SOCKET hSocketMax = 0; bool have_fds = false; -#ifdef USE_NATIVE_I2P - if (fNativeI2P) { - BOOST_FOREACH(SOCKET hI2PListenSocket, vhI2PListenSocket) { - if (hI2PListenSocket != INVALID_SOCKET) - { - FD_SET(hI2PListenSocket, &fdsetRecv); - hSocketMax = max(hSocketMax, hI2PListenSocket); - have_fds = true; - } - } - } -#endif - BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket) { FD_SET(hListenSocket, &fdsetRecv); hSocketMax = max(hSocketMax, hListenSocket); @@ -1150,74 +1046,6 @@ if (fNativeI2P) { } } -#ifdef USE_NATIVE_I2P - // - // Accept new I2P connections - // -if (fNativeI2P) { - bool haveInvalids = false; - for (std::vector::iterator it = vhI2PListenSocket.begin(); it != vhI2PListenSocket.end(); ++it) - { - SOCKET& hI2PListenSocket = *it; - if (hI2PListenSocket == INVALID_SOCKET) - { - if (haveInvalids) - it = vhI2PListenSocket.erase(it) - 1; - else - BindListenNativeI2P(hI2PListenSocket); - haveInvalids = true; - } - else if (FD_ISSET(hI2PListenSocket, &fdsetRecv)) - { - const size_t bufSize = NATIVE_I2P_DESTINATION_SIZE + 1; - char pchBuf[bufSize]; - memset(pchBuf, 0, bufSize); - int nBytes = recv(hI2PListenSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT); - if (nBytes > 0) - { - if (nBytes == NATIVE_I2P_DESTINATION_SIZE + 1) // we're waiting for dest-hash + '\n' symbol - { - std::string incomingAddr(pchBuf, pchBuf + NATIVE_I2P_DESTINATION_SIZE); - CAddress addr; - if (addr.SetSpecial(incomingAddr) && addr.IsNativeI2P()) - { - AddIncomingConnection(hI2PListenSocket, addr); - } - else - { - printf("Invalid incoming destination hash received (%s)\n", incomingAddr.c_str()); - closesocket(hI2PListenSocket); - } - } - else - { - printf("Invalid incoming destination hash size received (%d)\n", nBytes); - closesocket(hI2PListenSocket); - } - } - else if (nBytes == 0) - { - // socket closed gracefully - printf("I2P listen socket closed\n"); - closesocket(hI2PListenSocket); - } - else if (nBytes < 0) - { - // error - const int nErr = WSAGetLastError(); - if (nErr == WSAEWOULDBLOCK || nErr == WSAEMSGSIZE || nErr == WSAEINTR || nErr == WSAEINPROGRESS) - continue; - - printf("I2P listen socket recv error %d\n", nErr); - closesocket(hI2PListenSocket); - } - hI2PListenSocket = INVALID_SOCKET; // we've saved this socket in a CNode or closed it, so we can safety reset it anyway - BindListenNativeI2P(hI2PListenSocket); - } - } -} -#endif - // // Service each socket @@ -1542,13 +1370,6 @@ void ThreadOnionSeed(void* parg) // The first name is used as information source for addrman. // The second name should resolve to a list of seed addresses. -#ifdef USE_NATIVE_I2P -static const char *strI2PDNSSeed[][2] = { - {"d4gii55rnvv22qm2ojre2n67bzms5utr4k3ckafwjdoym2cqmv2q.b32.i2p", "d4gii55rnvv22qm2ojre2n67bzms5utr4k3ckafwjdoym2cqmv2q.b32.i2p"}, // need some valid I2P DNS seeds - {"dd37luxnbh3hkihxfl2e7nwosebh5sbfvpvjqwn7c3g5kqftb5qq.b32.i2p", "dd37luxnbh3hkihxfl2e7nwosebh5sbfvpvjqwn7c3g5kqftb5qq.b32.i2p"} -}; -#endif - static const char *strDNSSeed[][2] = { {"dnsseed.hashbag.cc", "dnsseed.hashbag.cc"}, {"seed.denarius.host", "seed.denarius.host"}, @@ -1589,31 +1410,7 @@ void ThreadDNSAddressSeed2(void* parg) if (!fTestNet) { printf("Loading addresses from DNS seeds (could take a while)\n"); -#ifdef USE_NATIVE_I2P - if (fNativeI2P) { - for (unsigned int seed_idx = 0; seed_idx < ARRAYLEN(strI2PDNSSeed); seed_idx++) { - if (HaveNameProxy()) { - AddOneShot(strI2PDNSSeed[seed_idx][1]); - } else { - vector vaddr; - vector vAdd; - if (LookupHost(strI2PDNSSeed[seed_idx][1], vaddr)) { - BOOST_FOREACH(CNetAddr& ip, vaddr) { - int nOneDay = 24*3600; - CAddress addr = CAddress(CService(ip, GetDefaultPort())); - addr.nTime = GetTime() - 3*nOneDay - GetRand(4*nOneDay); // use a random age between 3 and 7 days old - vAdd.push_back(addr); - found++; - } - } - addrman.Add(vAdd, CNetAddr(strI2PDNSSeed[seed_idx][0], true)); - } - } - // Prefer I2P, if 4 is found, drop the clearnet dnsseed - if (found>4) - return; - } -#endif + for (unsigned int seed_idx = 0; seed_idx < ARRAYLEN(strDNSSeed); seed_idx++) { if (HaveNameProxy()) { AddOneShot(strDNSSeed[seed_idx][1]); @@ -1641,17 +1438,18 @@ void ThreadDNSAddressSeed2(void* parg) }; + + + + + + + unsigned int pnSeed[] = { 0x42ac0c50, }; -#ifdef USE_NATIVE_I2P -const std::string pstrI2PSeed[] = { - "Dw-NRnXaxoGZdyupTXX78~CmF8csc~RhJr8XR2vMbNpazKhGjWNfRjhCmwqXkkW9vwkNjovW2AAbof7PfVnMCff0sHSxMTiBNsH8cuHJS2ckBSJI3h4G4ffJLc5gflangrG1raHKrMXCw8Cn56pisx4RKokEKUYdeEPiMdyJUO5yjZW2oyk4NpaUaQCqFmcglIvNOCYzVe~LK124wjJQAJc5iME1Sg9sOHaGMPL5N2qkAm5osOg2S7cZNRdIkoNOq-ztxghrv5bDL0ybeC0sfIQzvxDiKugCrSHEHCvwkA~xOu9nhNlUvoPDyCRRi~ImeomdNoqke28di~h2JF7wBGE~3ACxxOMaa0I~c9LV3O7pRU2Xj9HDn76eMGL7YCcCU4dRByu97oqfB3E~qqmmFp8W1tgvnEAMtXFTFZPYc33ZaCaIJQD7UXcQRSRV7vjw39jhx49XFsmYV3K6~D8bN8U4sRJnKQpzOJGpOSEJWh88bII0XuA55bJsfrR4VEQ5AAAA", // need valid - "dL51K8bxVvqX2Z4epXReUYlWTNUAK-1XdlbBd7e796s2A3icCQRhJvGlaa6PX~tgPvos-2IJp9hFQrVa0lyKyYmpQN9X7GOErtsL-JbMQpglQsEd94jDRAsiBuvgyPZij~NNdBxKRMDvNm9s7eovzhEFTAimTSB-sgeZ4Afxx2IrNXDFM6KS8AUm8YsaMldzX9zKQDeuV0slp4ZfIAVQhZZy9zTZSmUNPnXQR7XPh5w7FkXzmKMTKSyG~layJ3AorQWqzZXmykzf4z3CE4zkzQcwc0~ZIcAg9tYvM2AdQIdgeN6ISMim6L8q6ku6abuONkyw-NJTi3NopeGHZva21Tc3uHetsKoW434N24HBVUtIjJVjGsbZ7xBfz2xM5kyhPl6SlD-RJarCw47Rovmfc9Piq6q3S~Zw-rvRl-xDMJzwraIYNjAROouDwjI9Bqnguq9DH5uFBxf4uN69X7T~yWTAjdvelZKp6BGe~HGo7bNQjBmymhlH4erCKZEXOaxDAAAA" -}; -#endif void DumpAddresses() @@ -1813,17 +1611,6 @@ void ThreadOpenConnections2(void* parg) addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek; vAdd.push_back(addr); } -#ifdef USE_NATIVE_I2P - if (fNativeI2P) { - for (size_t i = 0; i < ARRAYLEN(pstrI2PSeed); i++) - { - const int64_t nOneWeek = 7*24*60*60; - CAddress addr(CService((const std::string&)pstrI2PSeed[i])); - addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek; - vAdd.push_back(addr); - } - } -#endif addrman.Add(vAdd, CNetAddr("127.0.0.1")); } @@ -1873,18 +1660,8 @@ void ThreadOpenConnections2(void* parg) continue; // do not allow non-default ports, unless after 50 invalid addresses selected already -#ifdef USE_NATIVE_I2P - if (fNativeI2P) { - if (!addr.IsNativeI2P() && addr.GetPort() != GetDefaultPort() && nTries < 50) - continue; - } else { - if (addr.GetPort() != GetDefaultPort() && nTries < 50) - continue; - } -#else if (addr.GetPort() != GetDefaultPort() && nTries < 50) continue; -#endif addrConnect = addr; break; @@ -2183,49 +1960,7 @@ void ThreadMessageHandler2(void* parg) -#ifdef USE_NATIVE_I2P -bool BindListenNativeI2P() -{ - SOCKET hNewI2PListenSocket = INVALID_SOCKET; - if (!BindListenNativeI2P(hNewI2PListenSocket)) - return false; - vhI2PListenSocket.push_back(hNewI2PListenSocket); - return true; -} - -bool BindListenNativeI2P(SOCKET& hSocket) -{ - hSocket = I2PSession::Instance().accept(false); - if (!SetSocketOptions(hSocket) || hSocket == INVALID_SOCKET) - return false; - CService addrBind(I2PSession::Instance().getMyDestination().pub, 0); - if (addrBind.IsRoutable() && fDiscover) - printf("I2P: AddLocal() = %s\n", addrBind.ToString().c_str()); - AddLocal(addrBind, LOCAL_BIND); - return true; -} - -bool IsI2POnly() -{ -// bool i2pOnly = false; -// if (mapArgs.count("-onlynet")) -// { -// const std::vector& onlyNets = mapMultiArgs["-onlynet"]; -// i2pOnly = (onlyNets.size() == 1 && onlyNets[0] == NATIVE_I2P_NET_STRING); -// } -// return i2pOnly; - bool i2pOnly = NET_MAX > 0; // if NET_MAX == 0 we set i2pOnly to false and exit - for (int n = 0; n < NET_MAX; n++) - { - Network net = (Network)n; - if (net == NET_UNROUTABLE) - continue; - i2pOnly &= ((net == NET_NATIVE_I2P) != IsLimited(net)); // isI2P xor IsLimited - } - return i2pOnly; -} -#endif bool BindListenPort(const CService &addrBind, string& strError) @@ -2539,7 +2274,6 @@ bool StopNode() { printf("StopNode()\n"); fShutdown = true; - //MapPort(false); mempool.AddTransactionsUpdated(1); int64_t nStart = GetTime(); if (semOutbound) @@ -2591,14 +2325,7 @@ class CNetCleanup if (hListenSocket != INVALID_SOCKET) if (closesocket(hListenSocket) == SOCKET_ERROR) printf("closesocket(hListenSocket) failed with error %d\n", WSAGetLastError()); -#ifdef USE_NATIVE_I2P - if (fNativeI2P) { - BOOST_FOREACH(SOCKET& hI2PListenSocket, vhI2PListenSocket) - if (hI2PListenSocket != INVALID_SOCKET) - if (closesocket(hI2PListenSocket) == SOCKET_ERROR) - printf("closesocket(hI2PListenSocket) failed with error %d\n", WSAGetLastError()); - } -#endif + #ifdef WIN32 // Shutdown Windows Sockets WSACleanup(); @@ -2692,6 +2419,17 @@ void RelayForTunaElectionEntry(const CTxIn vin, const CService addr, const std:: } } +/* +void RelayForTunaElectionEntry(const CTxIn vin, const CService addr, const std::vector vchSig, const int64 nNow, const CPubKey pubkey, const CPubKey pubkey2, const int count, const int current, const int64 lastUpdated) +{ + LOCK(cs_vNodes); + BOOST_FOREACH(CNode* pnode, vNodes) + { + pnode->PushMessage("dsee", vin, addr, vchSig, nNow, pubkey, pubkey2, count, current, lastUpdated); + } +} +*/ + void SendForTunaElectionEntry(const CTxIn vin, const CService addr, const std::vector vchSig, const int64_t nNow, const CPubKey pubkey, const CPubKey pubkey2, const int count, const int current, const int64_t lastUpdated, const int protocolVersion) { LOCK(cs_vNodes); diff --git a/src/net.h b/src/net.h index a1d53ee8..572a1902 100644 --- a/src/net.h +++ b/src/net.h @@ -31,8 +31,8 @@ static const int PING_INTERVAL = 2 * 60; /** Time after which to disconnect, after waiting for a ping response (or inactivity). */ static const int TIMEOUT_INTERVAL = 20 * 60; -inline unsigned int ReceiveFloodSize() { return 1000*GetArg("-maxreceivebuffer", 10*1000); } // 10MB Buffer Size from 5MB 5*1000 -inline unsigned int SendBufferSize() { return 1000*GetArg("-maxsendbuffer", 10*1000); } // Previously 1MB 1*1000 +inline unsigned int ReceiveFloodSize() { return 1000*GetArg("-maxreceivebuffer", 5*1000); } +inline unsigned int SendBufferSize() { return 1000*GetArg("-maxsendbuffer", 1*1000); } void AddOneShot(std::string strDest); bool RecvLine(SOCKET hSocket, std::string& strLine); @@ -61,14 +61,6 @@ CNodeSignals& GetNodeSignals(); typedef int NodeId; -#ifdef USE_NATIVE_I2P -bool BindListenNativeI2P(); -bool BindListenNativeI2P(SOCKET& hSocket); -bool IsI2POnly(); - -extern int nI2PNodeCount; -#endif - enum { LOCAL_NONE, // unknown @@ -165,13 +157,6 @@ extern std::map mapAlreadyAskedFor; extern NodeId nLastNodeId; extern CCriticalSection cs_nLastNodeId; -struct LocalServiceInfo { - int nScore; - int nPort; -}; - -extern CCriticalSection cs_mapLocalHost; -extern std::map mapLocalHost; class CNodeStateStats { @@ -340,8 +325,8 @@ class CNode std::vector getBlocksHash; uint256 hashLastGetBlocksEnd; int nStartingHeight; - bool fStartSync; - int nMisbehavior; + bool fStartSync; + int nMisbehavior; // flood relay std::vector vAddrToSend; @@ -369,15 +354,7 @@ class CNode bool fPingQueued; CNode(SOCKET hSocketIn, CAddress addrIn, std::string addrNameIn = "", bool fInboundIn=false) : ssSend(SER_NETWORK, INIT_PROTO_VERSION), setAddrKnown(5000) -#ifdef USE_NATIVE_I2P - , nSendStreamType(SER_NETWORK | (((addrIn.nServices & NODE_I2P) || addrIn.IsNativeI2P()) ? 0 : SER_IPADDRONLY)) - , nRecvStreamType(SER_NETWORK | (((addrIn.nServices & NODE_I2P) || addrIn.IsNativeI2P()) ? 0 : SER_IPADDRONLY)) -#endif { - // Native I2P Socket CNode structure -#ifdef USE_NATIVE_I2P - ssSend.SetType(nSendStreamType); -#endif nServices = 0; hSocket = hSocketIn; nRecvVersion = INIT_PROTO_VERSION; @@ -405,7 +382,7 @@ class CNode pindexLastGetBlocksBegin = 0; hashLastGetBlocksEnd = 0; nStartingHeight = -1; - fStartSync = false; + fStartSync = false; fGetAddr = false; nMisbehavior = 0; hashCheckpointKnown = 0; @@ -441,39 +418,6 @@ class CNode static CCriticalSection cs_totalBytesSent; static uint64_t nTotalBytesRecv; static uint64_t nTotalBytesSent; -#ifdef USE_NATIVE_I2P -private: - int nSendStreamType; - int nRecvStreamType; -public: - void SetSendStreamType(int nType) - { - nSendStreamType = nType; - ssSend.SetType(nSendStreamType); - } - - void SetRecvStreamType(int nType) - { - nRecvStreamType = nType; - for (std::deque::iterator it = vRecvMsg.begin(), end = vRecvMsg.end(); it != end; ++it) - { - it->hdrbuf.SetType(nRecvStreamType); - it->vRecv.SetType(nRecvStreamType); - } - } - - int GetSendStreamType() const - { - return nSendStreamType; - } - - int GetRecvStreamType() const - { - return nRecvStreamType; - } - -#endif - public: NodeId GetId() const { return id; @@ -528,21 +472,8 @@ class CNode // Known checking here is only to save space from duplicates. // SendMessages will filter it again for knowns that were added // after addresses were pushed. -#ifdef USE_NATIVE_I2P - if(fNativeI2P) { - if (addr.IsValid() && !setAddrKnown.count(addr)) { - // if receiver doesn't support i2p-address we don't send it - if ((this->nServices & NODE_I2P) || !addr.IsNativeI2P()) - vAddrToSend.push_back(addr); - } - } else { - if (addr.IsValid() && !setAddrKnown.count(addr)) - vAddrToSend.push_back(addr); - } -#else if (addr.IsValid() && !setAddrKnown.count(addr)) vAddrToSend.push_back(addr); -#endif } diff --git a/src/netbase.cpp b/src/netbase.cpp index fde994f3..b8b1300b 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -11,10 +11,6 @@ #include #endif -#ifdef USE_NATIVE_I2P -#include "i2p.h" -#endif - #include "strlcpy.h" #include // for to_lower() @@ -35,9 +31,6 @@ enum Network ParseNetwork(std::string net) { if (net == "ipv6") return NET_IPV6; if (net == "tor") return NET_TOR; if (net == "i2p") return NET_I2P; -#ifdef USE_NATIVE_I2P - if (net == NATIVE_I2P_NET_STRING) return NET_NATIVE_I2P; -#endif return NET_UNROUTABLE; } @@ -48,9 +41,6 @@ std::string GetNetworkName(enum Network net) { case NET_IPV6: return "ipv6"; case NET_TOR: return "onion"; case NET_I2P: return "i2p"; -#ifdef USE_NATIVE_I2P - case NET_NATIVE_I2P: return NATIVE_I2P_NET_STRING; -#endif default: return ""; } } @@ -359,9 +349,8 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe if (connect(hSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR) { - int nErr = WSAGetLastError(); // WSAEINVAL is here because some legacy version of winsock uses it - if (nErr == WSAEINPROGRESS || nErr == WSAEWOULDBLOCK || nErr == WSAEINVAL) + if (WSAGetLastError() == WSAEINPROGRESS || WSAGetLastError() == WSAEWOULDBLOCK || WSAGetLastError() == WSAEINVAL) { struct timeval timeout; timeout.tv_sec = nTimeout / 1000; @@ -373,13 +362,13 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe int nRet = select(hSocket + 1, NULL, &fdset, NULL, &timeout); if (nRet == 0) { - printf("net connection to %s timeout\n", addrConnect.ToString().c_str()); + if (fDebugNet) printf("connection timeout\n"); closesocket(hSocket); return false; } if (nRet == SOCKET_ERROR) { - printf("select() for %s failed: %i\n", addrConnect.ToString().c_str(), WSAGetLastError()); + if (fDebugNet) printf("select() for connection failed: %i\n",WSAGetLastError()); closesocket(hSocket); return false; } @@ -390,13 +379,13 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, &nRet, &nRetSize) == SOCKET_ERROR) #endif { - printf("getsockopt() for %s failed: %i\n", addrConnect.ToString().c_str(), WSAGetLastError()); + printf("getsockopt() for connection failed: %i\n",WSAGetLastError()); closesocket(hSocket); return false; } if (nRet != 0) { - printf("connect() to %s failed after select(): %s\n", addrConnect.ToString().c_str(), strerror(nRet)); + printf("connect() failed after select(): %s\n",strerror(nRet)); closesocket(hSocket); return false; } @@ -407,7 +396,7 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe else #endif { - printf("connect() to %s failed: %i\n", addrConnect.ToString().c_str(), WSAGetLastError()); + printf("connect() failed: %i\n",WSAGetLastError()); closesocket(hSocket); return false; } @@ -484,53 +473,12 @@ bool IsProxy(const CNetAddr &addr) { return false; } -#ifdef USE_NATIVE_I2P -bool SetSocketOptions(SOCKET& hSocket) -{ - if (hSocket == INVALID_SOCKET) - return false; -#ifdef SO_NOSIGPIPE - int set = 1; - setsockopt(hSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&set, sizeof(int)); -#endif - -#ifdef WIN32 - u_long fNonblock = 1; - if (ioctlsocket(hSocket, FIONBIO, &fNonblock) == SOCKET_ERROR) -#else - int fFlags = fcntl(hSocket, F_GETFL, 0); - if (fcntl(hSocket, F_SETFL, fFlags | O_NONBLOCK) == -1) -#endif - { - closesocket(hSocket); - hSocket = INVALID_SOCKET; - return false; - } - return true; -} -#endif - bool ConnectSocket(const CService &addrDest, SOCKET& hSocketRet, int nTimeout, bool *outProxyConnectionFailed) { proxyType proxy; -#ifdef USE_NATIVE_I2P -if (fNativeI2P) { - if (addrDest.IsNativeI2P()) - { - SOCKET streamSocket = I2PSession::Instance().connect(addrDest.GetI2PDestination(), false/*, streamSocket*/); - if (SetSocketOptions(streamSocket)) - { - hSocketRet = streamSocket; - return true; - } - return false; - } -} -#endif - - if (outProxyConnectionFailed) - *outProxyConnectionFailed = false; + if (outProxyConnectionFailed) + *outProxyConnectionFailed = false; // no proxy needed if (!GetProxy(addrDest.GetNetwork(), proxy)) return ConnectSocketDirectly(addrDest, hSocketRet, nTimeout); @@ -605,21 +553,11 @@ bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest void CNetAddr::Init() { memset(ip, 0, 16); -#ifdef USE_NATIVE_I2P -if (fNativeI2P) { - memset(i2pDest, 0, NATIVE_I2P_DESTINATION_SIZE); -} -#endif } void CNetAddr::SetIP(const CNetAddr& ipIn) { memcpy(ip, ipIn.ip, sizeof(ip)); -#ifdef USE_NATIVE_I2P -if (fNativeI2P) { - memcpy(i2pDest, ipIn.i2pDest, NATIVE_I2P_DESTINATION_SIZE); -} -#endif } static const unsigned char pchOnionCat[] = {0xFD,0x87,0xD8,0x7E,0xEB,0x43}; @@ -627,22 +565,6 @@ static const unsigned char pchGarliCat[] = {0xFD,0x60,0xDB,0x4D,0xDD,0xB5}; bool CNetAddr::SetSpecial(const std::string &strName) { -#ifdef USE_NATIVE_I2P -if (fNativeI2P) { - const bool isBase32Addr = (strName.size() == NATIVE_I2P_B32ADDR_SIZE) && (strName.substr(strName.size() - 8, 8) == ".b32.i2p"); - const std::string addr = isBase32Addr ? I2PSession::Instance().namingLookup(strName) : strName; - - if (addr.size() == NATIVE_I2P_DESTINATION_SIZE) { - auto trailer = addr.substr(addr.size() - 5, 5); - if ((trailer == "AAA==") || (trailer == "AAQ==")) - { - // last 5 symbols of b64-destination must be AAA== (ElGamal) or AAQ== (ECIES) - memcpy(i2pDest, addr.c_str(), NATIVE_I2P_DESTINATION_SIZE); - return true; - } - } -} -#endif if (strName.size()>6 && strName.substr(strName.size() - 6, 6) == ".onion") { std::vector vchAddr = DecodeBase32(strName.substr(0, strName.size() - 6).c_str()); if (vchAddr.size() != 16-sizeof(pchOnionCat)) @@ -673,21 +595,11 @@ CNetAddr::CNetAddr(const struct in_addr& ipv4Addr) { memcpy(ip, pchIPv4, 12); memcpy(ip+12, &ipv4Addr, 4); -#ifdef USE_NATIVE_I2P -if (fNativeI2P) { - memset(i2pDest, 0, NATIVE_I2P_DESTINATION_SIZE); -} -#endif } CNetAddr::CNetAddr(const struct in6_addr& ipv6Addr) { memcpy(ip, &ipv6Addr, 16); -#ifdef USE_NATIVE_I2P -if (fNativeI2P) { - memset(i2pDest, 0, NATIVE_I2P_DESTINATION_SIZE); -} -#endif } CNetAddr::CNetAddr(const char *pszIp, bool fAllowLookup) @@ -718,16 +630,8 @@ bool CNetAddr::IsIPv4() const bool CNetAddr::IsIPv6() const { -#ifdef USE_NATIVE_I2P -if (fNativeI2P) { - return (!IsIPv4() && !IsTor() && !IsNativeI2P()); -} else { return (!IsIPv4() && !IsTor() && !IsI2P()); } -#else -return (!IsIPv4() && !IsTor() && !IsI2P()); -#endif -} bool CNetAddr::IsRFC1918() const { @@ -790,18 +694,6 @@ bool CNetAddr::IsTor() const return (memcmp(ip, pchOnionCat, sizeof(pchOnionCat)) == 0); } -#ifdef USE_NATIVE_I2P -bool CNetAddr::IsNativeI2P() const -{ - return i2pDest[0]; // nonzero -} - -std::string CNetAddr::GetI2PDestination() const -{ - return std::string(i2pDest, i2pDest + NATIVE_I2P_DESTINATION_SIZE); -} -#endif - bool CNetAddr::IsI2P() const { return (memcmp(ip, pchGarliCat, sizeof(pchGarliCat)) == 0); @@ -809,13 +701,6 @@ bool CNetAddr::IsI2P() const bool CNetAddr::IsLocal() const { - -#ifdef USE_NATIVE_I2P - if (fNativeI2P) { - if (IsNativeI2P()) - return false; - } -#endif // IPv4 loopback if (IsIPv4() && (GetByte(3) == 127 || GetByte(3) == 0)) return true; @@ -836,12 +721,6 @@ bool CNetAddr::IsMulticast() const bool CNetAddr::IsValid() const { -#ifdef USE_NATIVE_I2P - if (fNativeI2P) { - if (IsNativeI2P()) - return true; - } -#endif // Cleanup 3-byte shifted addresses caused by garbage in size field // of addr messages from versions before 0.2.9 checksum. // Two consecutive addr messages look like this: @@ -892,13 +771,6 @@ enum Network CNetAddr::GetNetwork() const if (IsTor()) return NET_TOR; -#ifdef USE_NATIVE_I2P - if (fNativeI2P) { - if (IsNativeI2P()) - return NET_NATIVE_I2P; - } -#endif - if (IsI2P()) return NET_I2P; @@ -907,12 +779,6 @@ enum Network CNetAddr::GetNetwork() const std::string CNetAddr::ToStringIP() const { -#ifdef USE_NATIVE_I2P - if (fNativeI2P) { - if (IsNativeI2P()) - return GetI2PDestination(); - } -#endif if (IsTor()) return EncodeBase32(&ip[6], 10) + ".onion"; if (IsI2P()) @@ -942,41 +808,17 @@ std::string CNetAddr::ToString() const bool operator==(const CNetAddr& a, const CNetAddr& b) { -#ifdef USE_NATIVE_I2P - if (fNativeI2P) { - return (memcmp(a.ip, b.ip, 16) == 0 && memcmp(a.i2pDest, b.i2pDest, NATIVE_I2P_DESTINATION_SIZE) == 0); - } else { - return (memcmp(a.ip, b.ip, 16) == 0); - } -#else -return (memcmp(a.ip, b.ip, 16) == 0); -#endif + return (memcmp(a.ip, b.ip, 16) == 0); } bool operator!=(const CNetAddr& a, const CNetAddr& b) { -#ifdef USE_NATIVE_I2P - if (fNativeI2P) { - return (memcmp(a.ip, b.ip, 16) != 0 || memcmp(a.i2pDest, b.i2pDest, NATIVE_I2P_DESTINATION_SIZE) != 0); - } else { - return (memcmp(a.ip, b.ip, 16) != 0); - } -#else -return (memcmp(a.ip, b.ip, 16) != 0); -#endif + return (memcmp(a.ip, b.ip, 16) != 0); } bool operator<(const CNetAddr& a, const CNetAddr& b) { -#ifdef USE_NATIVE_I2P - if (fNativeI2P) { - return (memcmp(a.ip, b.ip, 16) < 0 || (memcmp(a.ip, b.ip, 16) == 0 && memcmp(a.i2pDest, b.i2pDest, NATIVE_I2P_DESTINATION_SIZE) < 0)); - } else { - return (memcmp(a.ip, b.ip, 16) < 0); - } -#else -return (memcmp(a.ip, b.ip, 16) < 0); -#endif + return (memcmp(a.ip, b.ip, 16) < 0); } bool CNetAddr::GetInAddr(struct in_addr* pipv4Addr) const @@ -989,12 +831,6 @@ bool CNetAddr::GetInAddr(struct in_addr* pipv4Addr) const bool CNetAddr::GetIn6Addr(struct in6_addr* pipv6Addr) const { -#ifdef USE_NATIVE_I2P - if (fNativeI2P) { - if (IsNativeI2P()) - return false; - } -#endif memcpy(pipv6Addr, ip, 16); return true; } @@ -1008,18 +844,6 @@ std::vector CNetAddr::GetGroup() const int nStartByte = 0; int nBits = 16; -#ifdef USE_NATIVE_I2P - if (fNativeI2P) { - if (IsNativeI2P()) - { - vchRet.resize(NATIVE_I2P_DESTINATION_SIZE + 1); - vchRet[0] = NET_NATIVE_I2P; - memcpy(&vchRet[1], i2pDest, NATIVE_I2P_DESTINATION_SIZE); - return vchRet; - } - } -#endif - // all local addresses belong to the same group if (IsLocal()) { @@ -1086,22 +910,6 @@ std::vector CNetAddr::GetGroup() const return vchRet; } -#ifdef USE_NATIVE_I2P -uint64_t CNetAddr::GetHash() const -{ - if(fNativeI2P) { - uint256 hash = IsNativeI2P() ? Hash(i2pDest, i2pDest + NATIVE_I2P_DESTINATION_SIZE) : Hash(&ip[0], &ip[16]); - uint64_t nRet; - memcpy(&nRet, &hash, sizeof(nRet)); - return nRet; - } else { - uint256 hash = Hash(&ip[0], &ip[16]); - uint64_t nRet; - memcpy(&nRet, &hash, sizeof(nRet)); - return nRet; - } -} -#else uint64_t CNetAddr::GetHash() const { uint256 hash = Hash(&ip[0], &ip[16]); @@ -1109,7 +917,6 @@ uint64_t CNetAddr::GetHash() const memcpy(&nRet, &hash, sizeof(nRet)); return nRet; } -#endif void CNetAddr::print() const { @@ -1173,13 +980,6 @@ int CNetAddr::GetReachabilityFrom(const CNetAddr *paddrPartner) const default: return REACH_DEFAULT; case NET_I2P: return REACH_PRIVATE; } -#ifdef USE_NATIVE_I2P - case NET_NATIVE_I2P: - switch(ourNet) { - default: return REACH_UNREACHABLE; - case NET_NATIVE_I2P: return REACH_PRIVATE; - } -#endif case NET_TEREDO: switch(ourNet) { default: return REACH_DEFAULT; @@ -1196,10 +996,7 @@ int CNetAddr::GetReachabilityFrom(const CNetAddr *paddrPartner) const case NET_IPV6: return REACH_IPV6_WEAK; case NET_IPV4: return REACH_IPV4; case NET_I2P: return REACH_PRIVATE; // assume connections from unroutable addresses are - case NET_TOR: return REACH_PRIVATE; // either from Tor, or don't care about our address -#ifdef USE_NATIVE_I2P - case NET_NATIVE_I2P: return REACH_UNREACHABLE; -#endif + case NET_TOR: return REACH_PRIVATE; // either from Tor/I2P, or don't care about our address } } } @@ -1334,14 +1131,6 @@ bool CService::GetSockAddr(struct sockaddr* paddr, socklen_t *addrlen) const std::vector CService::GetKey() const { std::vector vKey; -#ifdef USE_NATIVE_I2P - if (IsNativeI2P() && fNativeI2P) - { - vKey.resize(NATIVE_I2P_DESTINATION_SIZE); - memcpy(&vKey[0], i2pDest, NATIVE_I2P_DESTINATION_SIZE); - return vKey; - } -#endif vKey.resize(18); memcpy(&vKey[0], ip, 16); vKey[16] = port / 0x100; diff --git a/src/netbase.h b/src/netbase.h index 26da4846..1e37422d 100644 --- a/src/netbase.h +++ b/src/netbase.h @@ -18,12 +18,6 @@ extern bool fNameLookup; #undef SetPort #endif -#ifdef USE_NATIVE_I2P -#define NATIVE_I2P_DESTINATION_SIZE 516 -#define NATIVE_I2P_B32ADDR_SIZE 60 -#define NATIVE_I2P_NET_STRING "native_i2p" -#endif - enum Network { NET_UNROUTABLE, @@ -31,9 +25,7 @@ enum Network NET_IPV6, NET_TOR, NET_I2P, -#ifdef USE_NATIVE_I2P - NET_NATIVE_I2P, -#endif + NET_MAX, }; @@ -42,9 +34,6 @@ class CNetAddr { protected: unsigned char ip[16]; // in network byte order -#ifdef USE_NATIVE_I2P - unsigned char i2pDest[NATIVE_I2P_DESTINATION_SIZE]; // I2P Destination -#endif public: CNetAddr(); @@ -85,11 +74,6 @@ class CNetAddr CNetAddr(const struct in6_addr& pipv6Addr); bool GetIn6Addr(struct in6_addr* pipv6Addr) const; -#ifdef USE_NATIVE_I2P - bool IsNativeI2P() const; - std::string GetI2PDestination() const; -#endif - friend bool operator==(const CNetAddr& a, const CNetAddr& b); friend bool operator!=(const CNetAddr& a, const CNetAddr& b); friend bool operator<(const CNetAddr& a, const CNetAddr& b); @@ -97,12 +81,6 @@ class CNetAddr IMPLEMENT_SERIALIZE ( READWRITE(FLATDATA(ip)); -#ifdef USE_NATIVE_I2P - if (!(nType & SER_IPADDRONLY)) - { - READWRITE(FLATDATA(i2pDest)); - } -#endif ) }; @@ -142,12 +120,6 @@ class CService : public CNetAddr ( CService* pthis = const_cast(this); READWRITE(FLATDATA(ip)); -#ifdef USE_NATIVE_I2P - if (!(nType & SER_IPADDRONLY)) - { - READWRITE(FLATDATA(i2pDest)); - } -#endif unsigned short portN = htons(port); READWRITE(portN); if (fRead) @@ -174,8 +146,4 @@ bool LookupNumeric(const char *pszName, CService& addr, int portDefault = 0); bool ConnectSocket(const CService &addr, SOCKET& hSocketRet, int nTimeout, bool *outProxyConnectionFailed = 0); bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest, int portDefault, int nTimeout, bool *outProxyConnectionFailed = 0); -#ifdef USE_NATIVE_I2P -bool SetSocketOptions(SOCKET& hSocket); -#endif - #endif diff --git a/src/protocol.h b/src/protocol.h index 4f410f52..7344b0c5 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -69,9 +69,6 @@ class CMessageHeader enum { NODE_NETWORK = (1 << 0), -#ifdef USE_NATIVE_I2P - NODE_I2P = (1 << 7), -#endif }; /** A CService with information about it as peer */ diff --git a/src/qt/bitcoin.qrc b/src/qt/bitcoin.qrc index c7d653f2..a4b564fd 100644 --- a/src/qt/bitcoin.qrc +++ b/src/qt/bitcoin.qrc @@ -16,7 +16,6 @@ res/icons/mark.png res/icons/btc.png res/icons/mn.png - res/icons/fs.png res/icons/multi.png res/icons/connect0_16.png res/icons/connect1_16.png @@ -64,11 +63,6 @@ res/icons/refresh.png res/icons/data.png res/icons/trade.png - res/icons/i2plogo_0_16.png - res/icons/i2plogo_1_16.png - res/icons/i2plogo_2_16.png - res/icons/i2plogo_3_16.png - res/icons/i2plogo_4_16.png res/images/about.png diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index b15f6cee..aac4bec6 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -38,10 +38,6 @@ #include "termsofuse.h" #include "proofofimage.h" -#ifdef USE_NATIVE_I2P -#include "showi2paddresses.h" -#endif - #ifdef Q_OS_MAC #include "macdockiconhandler.h" #endif @@ -183,12 +179,12 @@ BitcoinGUI::BitcoinGUI(QWidget *parent): // Create tabs overviewPage = new OverviewPage(); - statisticsPage = new StatisticsPage(this); - blockBrowser = new BlockBrowser(this); + statisticsPage = new StatisticsPage(this); + blockBrowser = new BlockBrowser(this); marketBrowser = new MarketBrowser(this); - multisigPage = new MultisigDialog(this); + multisigPage = new MultisigDialog(this); proofOfImagePage = new ProofOfImage(this); - //chatWindow = new ChatWindow(this); + //chatWindow = new ChatWindow(this); transactionsPage = new QWidget(this); @@ -197,7 +193,7 @@ BitcoinGUI::BitcoinGUI(QWidget *parent): vbox->addWidget(transactionView); transactionsPage->setLayout(vbox); - mintingPage = new QWidget(this); + mintingPage = new QWidget(this); QVBoxLayout *vboxMinting = new QVBoxLayout(); mintingView = new MintingView(this); vboxMinting->addWidget(mintingView); @@ -217,17 +213,17 @@ BitcoinGUI::BitcoinGUI(QWidget *parent): centralWidget = new QStackedWidget(this); centralWidget->addWidget(overviewPage); centralWidget->addWidget(transactionsPage); - centralWidget->addWidget(mintingPage); + centralWidget->addWidget(mintingPage); centralWidget->addWidget(addressBookPage); centralWidget->addWidget(receiveCoinsPage); centralWidget->addWidget(sendCoinsPage); centralWidget->addWidget(messagePage); - centralWidget->addWidget(statisticsPage); - centralWidget->addWidget(blockBrowser); + centralWidget->addWidget(statisticsPage); + centralWidget->addWidget(blockBrowser); centralWidget->addWidget(fortunastakeManagerPage); - centralWidget->addWidget(marketBrowser); + centralWidget->addWidget(marketBrowser); centralWidget->addWidget(proofOfImagePage); - //centralWidget->addWidget(chatWindow); + //centralWidget->addWidget(chatWindow); setCentralWidget(centralWidget); // Create status bar @@ -242,35 +238,15 @@ BitcoinGUI::BitcoinGUI(QWidget *parent): frameBlocksLayout->setSpacing(3); labelEncryptionIcon = new ActiveLabel(); -#ifdef USE_NATIVE_I2P - labelI2PConnections = new QLabel(); - labelI2POnly = new QLabel(); - labelI2PGenerated = new QLabel(); - if (fNativeI2P) - frameBlocksLayout->addStretch(); - frameBlocksLayout->addWidget(labelI2POnly); - frameBlocksLayout->addStretch(); - frameBlocksLayout->addWidget(labelI2PConnections); - frameBlocksLayout->addStretch(); - frameBlocksLayout->addWidget(labelI2PGenerated); -#endif - fFSLock = GetBoolArg("-fsconflock"); - fNativeTor = GetBoolArg("-nativetor"); - fNativeI2P = GetBoolArg("-nativei2p"); labelStakingIcon = new QLabel(); labelConnectionsIcon = new QLabel(); labelBlocksIcon = new QLabel(); labelConnectTypeIcon = new QLabel(); - labelFSLockIcon = new QLabel(); frameBlocksLayout->addStretch(); frameBlocksLayout->addWidget(labelEncryptionIcon); frameBlocksLayout->addStretch(); - if (fNativeTor) - frameBlocksLayout->addWidget(labelConnectTypeIcon); - frameBlocksLayout->addStretch(); - if (fFSLock) - frameBlocksLayout->addWidget(labelFSLockIcon); - frameBlocksLayout->addStretch(); + frameBlocksLayout->addWidget(labelConnectTypeIcon); + frameBlocksLayout->addStretch(); frameBlocksLayout->addWidget(labelStakingIcon); frameBlocksLayout->addStretch(); frameBlocksLayout->addWidget(labelConnectionsIcon); @@ -278,13 +254,6 @@ BitcoinGUI::BitcoinGUI(QWidget *parent): frameBlocksLayout->addWidget(labelBlocksIcon); frameBlocksLayout->addStretch(); - netLabel = new QLabel(); - netLabel->setObjectName("netLabel"); - netLabel->setStyleSheet("#netLabel { color: #4a4a4a; }"); - - frameBlocksLayout->addWidget(netLabel); - frameBlocksLayout->addStretch(); - if (GetBoolArg("-staking", true)) { QTimer *timerStakingIcon = new QTimer(labelStakingIcon); @@ -353,20 +322,20 @@ void BitcoinGUI::createActions() overviewAction->setStatusTip(tr("Wallet Overview")); tabGroup->addAction(overviewAction); - statisticsAction = new QAction(QIcon(":/icons/statistics"), tr("&Statistics"), this); + statisticsAction = new QAction(QIcon(":/icons/statistics"), tr("&Statistics"), this); statisticsAction->setToolTip(tr("View statistics")); statisticsAction->setCheckable(true); statisticsAction->setStatusTip(tr("Denarius Statistics")); tabGroup->addAction(statisticsAction); - blockAction = new QAction(QIcon(":/icons/block"), tr("&Block Explorer"), this); + blockAction = new QAction(QIcon(":/icons/block"), tr("&Block Explorer"), this); blockAction->setToolTip(tr("Explore the Denarius Blockchain")); blockAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_6)); blockAction->setStatusTip(tr("Block Explorer")); blockAction->setCheckable(true); tabGroup->addAction(blockAction); - marketAction = new QAction(QIcon(":/icons/mark"), tr("&Market"), this); + marketAction = new QAction(QIcon(":/icons/mark"), tr("&Market"), this); marketAction->setToolTip(tr("Market Data")); marketAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_7)); marketAction->setStatusTip(tr("Denarius Market Data")); @@ -413,7 +382,7 @@ void BitcoinGUI::createActions() messageAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_8)); tabGroup->addAction(messageAction); - mintingAction = new QAction(QIcon(":/icons/stake"), tr("&Staking"), this); + mintingAction = new QAction(QIcon(":/icons/stake"), tr("&Staking"), this); mintingAction->setToolTip(tr("Show your staking capacity")); mintingAction->setCheckable(true); mintingAction->setStatusTip(tr("Staking Estimations")); @@ -432,21 +401,21 @@ void BitcoinGUI::createActions() proofOfImageAction->setStatusTip(tr("PoD: Timestamp files")); tabGroup->addAction(proofOfImageAction); - multisigAction = new QAction(QIcon(":/icons/multi"), tr("Multisig"), this); + multisigAction = new QAction(QIcon(":/icons/multi"), tr("Multisig"), this); tabGroup->addAction(multisigAction); multisigAction->setStatusTip(tr("Multisig Interface")); connect(overviewAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized())); connect(overviewAction, SIGNAL(triggered()), this, SLOT(gotoOverviewPage())); - connect(blockAction, SIGNAL(triggered()), this, SLOT(gotoBlockBrowser())); - connect(statisticsAction, SIGNAL(triggered()), this, SLOT(gotoStatisticsPage())); - connect(marketAction, SIGNAL(triggered()), this, SLOT(gotoMarketBrowser())); - //connect(chatAction, SIGNAL(triggered()), this, SLOT(gotoChatPage())); + connect(blockAction, SIGNAL(triggered()), this, SLOT(gotoBlockBrowser())); + connect(statisticsAction, SIGNAL(triggered()), this, SLOT(gotoStatisticsPage())); + connect(marketAction, SIGNAL(triggered()), this, SLOT(gotoMarketBrowser())); + //connect(chatAction, SIGNAL(triggered()), this, SLOT(gotoChatPage())); connect(sendCoinsAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized())); connect(sendCoinsAction, SIGNAL(triggered()), this, SLOT(gotoSendCoinsPage())); connect(receiveCoinsAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized())); connect(receiveCoinsAction, SIGNAL(triggered()), this, SLOT(gotoReceiveCoinsPage())); - connect(mintingAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized())); + connect(mintingAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized())); connect(mintingAction, SIGNAL(triggered()), this, SLOT(gotoMintingPage())); connect(fortunastakeManagerAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized())); connect(fortunastakeManagerAction, SIGNAL(triggered()), this, SLOT(gotoFortunastakeManagerPage())); @@ -456,7 +425,7 @@ void BitcoinGUI::createActions() connect(addressBookAction, SIGNAL(triggered()), this, SLOT(gotoAddressBookPage())); connect(messageAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized())); connect(messageAction, SIGNAL(triggered()), this, SLOT(gotoMessagePage())); - connect(multisigAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized())); + connect(multisigAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized())); connect(multisigAction, SIGNAL(triggered()), this, SLOT(gotoMultisigPage())); connect(proofOfImageAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized())); connect(proofOfImageAction, SIGNAL(triggered()), this, SLOT(gotoProofOfImagePage())); @@ -500,7 +469,7 @@ void BitcoinGUI::createActions() openRPCConsoleAction->setToolTip(tr("Open debugging and diagnostic console")); openRPCConsoleAction->setStatusTip(tr("Show Debug Console")); - openInfoAction = new QAction(QApplication::style()->standardIcon(QStyle::SP_MessageBoxInformation), tr("&Information"), this); + openInfoAction = new QAction(QApplication::style()->standardIcon(QStyle::SP_MessageBoxInformation), tr("&Information"), this); openInfoAction->setStatusTip(tr("Show diagnostic information")); openGraphAction = new QAction(QIcon(":/icons/connect_4"), tr("&Network Monitor"), this); openGraphAction->setStatusTip(tr("Show Network Monitor")); @@ -642,40 +611,6 @@ void BitcoinGUI::checkTOU() void BitcoinGUI::setClientModel(ClientModel *clientModel) { -#ifdef USE_NATIVE_I2P -if (fNativeI2P) { - setNumI2PConnections(clientModel->getNumI2PConnections()); - connect(clientModel, SIGNAL(numI2PConnectionsChanged(int)), this, SLOT(setNumI2PConnections(int))); - if(clientModel->isI2POnly()) - { - netLabel->setText("I2P"); - netLabel->setToolTip(tr("Wallet is using I2P Denarius network only")); - } -} -#endif -if(!fNativeTor && !fNativeI2P) { - netLabel->setText("CLEARNET"); - netLabel->setToolTip(tr("Native Tor or I2P are not running.")); -} -if (fFSLock == true) { - labelFSLockIcon->setPixmap(QIcon(":/icons/fs").pixmap(STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE)); - labelFSLockIcon->setToolTip(tr("FS are locked with fsconflock=1")); -} -#ifdef USE_NATIVE_I2P -if (fNativeI2P) { - if (clientModel->isI2PAddressGenerated()) { - const QString puba = clientModel->getPublicI2PKey(); - const QString base32addy = clientModel->getB32Address(puba); - labelI2PGenerated->setText(tr(" DYNAMIC")); - labelI2PGenerated->setToolTip(tr("Wallet is running with a dynamic I2P address: ") + QString(base32addy)); - } else { - const QString pubs = clientModel->getPublicI2PKey(); - const QString b32addy = clientModel->getB32Address(pubs); - labelI2PGenerated->setText(tr(" STATIC")); - labelI2PGenerated->setToolTip(tr("Wallet is running with a static I2P address: ") + QString(b32addy)); - } -} -#endif this->clientModel = clientModel; if(clientModel) { @@ -729,19 +664,19 @@ void BitcoinGUI::setWalletModel(WalletModel *walletModel) // Put transaction list in tabs transactionView->setModel(walletModel); - mintingView->setModel(walletModel); + mintingView->setModel(walletModel); overviewPage->setModel(walletModel); addressBookPage->setModel(walletModel->getAddressTableModel()); receiveCoinsPage->setModel(walletModel->getAddressTableModel()); sendCoinsPage->setModel(walletModel); signVerifyMessageDialog->setModel(walletModel); - statisticsPage->setModel(clientModel); - blockBrowser->setModel(clientModel); - marketBrowser->setModel(clientModel); + statisticsPage->setModel(clientModel); + blockBrowser->setModel(clientModel); + marketBrowser->setModel(clientModel); fortunastakeManagerPage->setWalletModel(walletModel); - multisigPage->setModel(walletModel); - //chatWindow->setModel(clientModel); + multisigPage->setModel(walletModel); + //chatWindow->setModel(clientModel); setEncryptionStatus(walletModel->getEncryptionStatus()); connect(walletModel, SIGNAL(encryptionStatusChanged(int)), this, SLOT(setEncryptionStatus(int))); @@ -796,8 +731,8 @@ void BitcoinGUI::createTrayIcon() trayIconMenu->addSeparator(); trayIconMenu->addAction(sendCoinsAction); trayIconMenu->addAction(receiveCoinsAction); - trayIconMenu->addSeparator(); - trayIconMenu->addAction(multisigAction); + trayIconMenu->addSeparator(); + trayIconMenu->addAction(multisigAction); trayIconMenu->addSeparator(); trayIconMenu->addAction(signMessageAction); trayIconMenu->addAction(verifyMessageAction); @@ -829,11 +764,6 @@ void BitcoinGUI::optionsClicked() return; OptionsDialog dlg; dlg.setModel(clientModel->getOptionsModel()); -#ifdef USE_NATIVE_I2P - if (fNativeI2P) { - dlg.setClientModel(clientModel); - } -#endif dlg.exec(); } @@ -844,31 +774,6 @@ void BitcoinGUI::aboutClicked() dlg.exec(); } -#ifdef USE_NATIVE_I2P -void BitcoinGUI::showGeneratedI2PAddr(const QString& caption, const QString& pub, const QString& priv, const QString& b32, const QString& configFileName) -{ - ShowI2PAddresses i2pDialog(caption, pub, priv, b32, configFileName, this); - i2pDialog.exec(); -} - -void BitcoinGUI::setNumI2PConnections(int count) -{ - if(fNativeI2P) { - QString i2pIcon; - switch(count) - { - case 0: i2pIcon = ":/icons/i2pconnect_0"; break; - case 1: /*case 2: case 3:*/ i2pIcon = ":/icons/i2pconnect_1"; break; - case 2:/*case 4: case 5: case 6:*/ i2pIcon = ":/icons/i2pconnect_2"; break; - case 3:/*case 7: case 8: case 9:*/ i2pIcon = ":/icons/i2pconnect_3"; break; - default: i2pIcon = ":/icons/i2pconnect_4"; break; - } - labelI2PConnections->setPixmap(QIcon(i2pIcon).pixmap(50, 13)); - labelI2PConnections->setToolTip(tr("%n active connection(s) to the I2P Denarius network", "", count)); - } -} -#endif - void BitcoinGUI::setNumConnections(int count) { QString icon; @@ -881,7 +786,7 @@ void BitcoinGUI::setNumConnections(int count) default: icon = ":/icons/connect_4"; break; } labelConnectionsIcon->setPixmap(QIcon(icon).pixmap(STATUSBAR_ICONSIZE,STATUSBAR_ICONSIZE)); - labelConnectionsIcon->setToolTip(tr("%n active connection(s) to the Denarius network", "", count)); + labelConnectionsIcon->setToolTip(tr("%n active connection(s) to Denarius network", "", count)); if(fNativeTor) { @@ -898,6 +803,9 @@ void BitcoinGUI::setNumConnections(int count) QString onionauto; onionauto = tr("Connected via the Tor Network - ") + QString::fromStdString(automatic_onion); labelConnectTypeIcon->setToolTip(onionauto); + } else { + labelConnectTypeIcon->setPixmap(QIcon(":/icons/toroff").pixmap(STATUSBAR_ICONSIZE, STATUSBAR_ICONSIZE)); + labelConnectTypeIcon->setToolTip(tr("Not Connected via the Tor Network, Start Denarius with the flag nativetor=1")); } } @@ -906,13 +814,7 @@ void BitcoinGUI::setNumBlocks(int count, int nTotalBlocks) // don't bother showing anything if we have no connection to the network if (!clientModel || clientModel->getNumConnections() == 0) { - if (!fNativeI2P && !fNativeTor) { - progressBarLabel->setText(tr("Connecting to the Denarius network...")); - } else if (fNativeI2P) { - progressBarLabel->setText(tr("Connecting to the Denarius I2P network...")); - } else if (fNativeTor) { - progressBarLabel->setText(tr("Connecting to the Denarius Tor network...")); - } + progressBarLabel->setText(tr("Connecting to the Denarius network...")); progressBarLabel->setVisible(true); progressBar->setVisible(false); return; diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index ec2b3352..655a017c 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -112,19 +112,11 @@ class BitcoinGUI : public QMainWindow QLabel *labelConnectionsIcon; QLabel *labelBlocksIcon; QLabel *labelConnectTypeIcon; - QLabel *labelFSLockIcon; QLabel *progressBarLabel; QLabel *mainIcon; QToolBar *mainToolbar; QToolBar *secondaryToolbar; QProgressBar *progressBar; - QLabel* netLabel; - -#ifdef USE_NATIVE_I2P - QLabel* labelI2PConnections; - QLabel* labelI2POnly; - QLabel* labelI2PGenerated; -#endif QMenuBar *appMenuBar; QAction *overviewAction; @@ -191,9 +183,6 @@ class BitcoinGUI : public QMainWindow public slots: /** Set number of connections shown in the UI */ void setNumConnections(int count); -#ifdef USE_NATIVE_I2P - void setNumI2PConnections(int count); -#endif /** Set number of blocks shown in the UI */ void setNumBlocks(int count, int nTotalBlocks); /** Set the encryption status as shown in the UI. @@ -218,11 +207,7 @@ public slots: void mainToolbarOrientation(Qt::Orientation orientation); void secondaryToolbarOrientation(Qt::Orientation orientation); - void gotoMultisigPage(); - -#ifdef USE_NATIVE_I2P - void showGeneratedI2PAddr(const QString& caption, const QString& pub, const QString& priv, const QString& b32, const QString& configFileName); -#endif + void gotoMultisigPage(); private slots: /** Switch to overview (home) page */ diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index c2c49977..07b6efaf 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -12,10 +12,6 @@ #include #include -#ifdef USE_NATIVE_I2P -#include "i2p.h" -#endif - static const int64_t nClientStartupTime = GetTime(); ClientModel::ClientModel(OptionsModel *optionsModel, QObject *parent) : @@ -144,16 +140,6 @@ bool ClientModel::isNativeTor() const return fNativeTor; } -bool ClientModel::isNativeI2P() const -{ - return fNativeI2P; -} - -bool ClientModel::isFSLock() const -{ - return fFSLock; -} - bool ClientModel::inInitialBlockDownload() const { return IsInitialBlockDownload(); @@ -179,56 +165,6 @@ PeerTableModel *ClientModel::getPeerTableModel() return peerTableModel; } -#ifdef USE_NATIVE_I2P -QString ClientModel::formatI2PNativeFullVersion() const -{ - return QString::fromStdString(FormatI2PNativeFullVersion()); -} - -void ClientModel::updateNumI2PConnections(int numI2PConnections) -{ - emit numI2PConnectionsChanged(numI2PConnections); -} - -int ClientModel::getNumI2PConnections() const -{ - return nI2PNodeCount; -} - -QString ClientModel::getPublicI2PKey() const -{ - return QString::fromStdString(I2PSession::Instance().getMyDestination().pub); -} - -QString ClientModel::getPrivateI2PKey() const -{ - return QString::fromStdString(I2PSession::Instance().getMyDestination().priv); -} - -bool ClientModel::isI2PAddressGenerated() const -{ - return I2PSession::Instance().getMyDestination().isGenerated; -} - -bool ClientModel::isI2POnly() const -{ - return IsI2POnly(); -} - -QString ClientModel::getB32Address(const QString& destination) const -{ - return QString::fromStdString(I2PSession::GenerateB32AddressFromDestination(destination.toStdString())); -} - -void ClientModel::generateI2PDestination(QString& pub, QString& priv) const -{ - const SAM::FullDestination generatedDest = I2PSession::Instance().destGenerate(); - pub = QString::fromStdString(generatedDest.pub); - priv = QString::fromStdString(generatedDest.priv); -} - -#endif - QString ClientModel::formatFullVersion() const { return QString::fromStdString(FormatFullVersion()); @@ -249,14 +185,6 @@ QString ClientModel::formatClientStartupTime() const return QDateTime::fromTime_t(nClientStartupTime).toString(); } -#ifdef USE_NATIVE_I2P -static void NotifyNumI2PConnectionsChanged(ClientModel *clientmodel, int newNumI2PConnections) -{ - QMetaObject::invokeMethod(clientmodel, "updateNumI2PConnections", Qt::QueuedConnection, - Q_ARG(int, newNumI2PConnections)); -} -#endif - // Handlers for core signals static void NotifyBlocksChanged(ClientModel *clientmodel, int nHeight, int newNumBlocksOfPeers) { @@ -287,9 +215,6 @@ void ClientModel::subscribeToCoreSignals() uiInterface.NotifyBlocksChanged.connect(boost::bind(NotifyBlocksChanged, this, _1, _2)); uiInterface.NotifyNumConnectionsChanged.connect(boost::bind(NotifyNumConnectionsChanged, this, _1)); uiInterface.NotifyAlertChanged.connect(boost::bind(NotifyAlertChanged, this, _1, _2)); -#ifdef USE_NATIVE_I2P - uiInterface.NotifyNumI2PConnectionsChanged.connect(boost::bind(NotifyNumI2PConnectionsChanged, this, _1)); -#endif } void ClientModel::unsubscribeFromCoreSignals() @@ -298,7 +223,4 @@ void ClientModel::unsubscribeFromCoreSignals() uiInterface.NotifyBlocksChanged.disconnect(boost::bind(NotifyBlocksChanged, this, _1, _2)); uiInterface.NotifyNumConnectionsChanged.disconnect(boost::bind(NotifyNumConnectionsChanged, this, _1)); uiInterface.NotifyAlertChanged.disconnect(boost::bind(NotifyAlertChanged, this, _1, _2)); -#ifdef USE_NATIVE_I2P - uiInterface.NotifyNumI2PConnectionsChanged.disconnect(boost::bind(NotifyNumI2PConnectionsChanged, this, _1)); -#endif } diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h index b72b101c..7d6e72b7 100644 --- a/src/qt/clientmodel.h +++ b/src/qt/clientmodel.h @@ -37,15 +37,9 @@ class ClientModel : public QObject //! Return true if client connected to testnet bool isTestNet() const; - //! Return true if client connected to Native Tor + //! Return true if client connected to Tor bool isNativeTor() const; - //! Return true if client connected to Native I2P - bool isNativeI2P() const; - - //! Return true if client connected to Native I2P - bool isFSLock() const; - //! Return true if core is doing initial block download bool inInitialBlockDownload() const; //! Return conservative estimate of total number of blocks, or 0 if unknown @@ -57,17 +51,6 @@ class ClientModel : public QObject QString formatBuildDate() const; QString clientName() const; QString formatClientStartupTime() const; -#ifdef USE_NATIVE_I2P - QString formatI2PNativeFullVersion() const; - int getNumI2PConnections() const; - - QString getPublicI2PKey() const; - QString getPrivateI2PKey() const; - bool isI2PAddressGenerated() const; - bool isI2POnly() const; - QString getB32Address(const QString& destination) const; - void generateI2PDestination(QString& pub, QString& priv) const; -#endif private: OptionsModel *optionsModel; @@ -84,9 +67,6 @@ class ClientModel : public QObject void unsubscribeFromCoreSignals(); signals: void numConnectionsChanged(int count); -#ifdef USE_NATIVE_I2P - void numI2PConnectionsChanged(int count); -#endif void numBlocksChanged(int count, int countOfPeers); void bytesChanged(quint64 totalBytesIn, quint64 totalBytesOut); @@ -98,9 +78,6 @@ public slots: void updateNumConnections(int numConnections); void updateNumBlocks(int newNumBlocks, int newNumBlocksOfPeers); void updateAlert(const QString &hash, int status); -#ifdef USE_NATIVE_I2P - void updateNumI2PConnections(int numI2PConnections); -#endif }; #endif // CLIENTMODEL_H diff --git a/src/qt/forms/i2poptionswidget.ui b/src/qt/forms/i2poptionswidget.ui deleted file mode 100644 index f45256e3..00000000 --- a/src/qt/forms/i2poptionswidget.ui +++ /dev/null @@ -1,703 +0,0 @@ - - - I2POptionsWidget - - - - 0 - 0 - 449 - 389 - - - - Form - - - - - - - - Use I2P only (-onlynet=native_i2p) - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - http://www.i2p2.i2p/i2cp.html#options - - - <html><head/><body><p><a href="http://www.i2p2.i2p/i2cp.html#options"><span style=" text-decoration: underline; color:#ffffff;">Help</span></a></p></body></html> - - - Qt::RichText - - - true - - - Qt::TextBrowserInteraction - - - - - - - - - - - SAM host - - - - - - - - 0 - 0 - - - - 127.0.0.1 - - - - - - - SAM port - - - - - - - 1 - - - 65535 - - - 7656 - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - Tunnel name - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - Denarius-client - - - - - - - Qt::Horizontal - - - QSizePolicy::MinimumExpanding - - - - 166 - 20 - - - - - - - - - - - - View Current -I2P Address - - - - - - - Generate -I2P Address - - - - - - - - - - - - - I2CP options of inbound tunnels - - - - - - - - inbound.quantity - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - 1 - - - 16 - - - 2 - - - - - - - - - - - inbound.length - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - 0 - - - 7 - - - 2 - - - - - - - - - - - inbound.lengthVariance - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - -7 - - - 7 - - - - - - - - - - - inbound.backupQuantity - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - - - - inbound.allowZeroHop - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - true - - - - - - - - - - - inbound.IPRestriction - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - 4 - - - 2 - - - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - I2CP options of outbound tunnels - - - - - - - - outbound.quantity - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - 1 - - - 2 - - - - - - - - - - - outbound.length - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - 7 - - - 2 - - - - - - - - - - - outbound.lengthVariance - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - -7 - - - 7 - - - - - - - - - - - outbound.backupQuantity - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - - - - outbound.allowZeroHop - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - true - - - - - - - - - - - outbound.IPRestriction - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - 4 - - - 2 - - - - - - - - - - - outbound.priority - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - -25 - - - 25 - - - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - checkBoxUseI2POnly - lineEditSAMHost - spinBoxSAMPort - lineEditTunnelName - spinBoxInboundQuantity - spinBoxInboundLength - spinBoxInboundLengthVariance - spinBoxInboundBackupQuality - checkBoxInboundAllowZeroHop - spinBoxInboundIPRestriction - spinBoxOutboundQuantity - spinBoxOutboundLength - spinBoxOutboundLengthVariance - spinBoxOutboundBackupQuantity - checkBoxAllowZeroHop - spinBoxOutboundIPRestriction - spinBoxOutboundPriority - - - - diff --git a/src/qt/forms/rpcconsole.ui b/src/qt/forms/rpcconsole.ui index 35bc199d..28b83124 100644 --- a/src/qt/forms/rpcconsole.ui +++ b/src/qt/forms/rpcconsole.ui @@ -17,20 +17,13 @@ - 0 + 3 &Information - - - - Native I2P On/Off - - - @@ -44,6 +37,20 @@ + + + + Client name + + + + + + + Client version + + + @@ -60,20 +67,6 @@ - - - - Client version - - - - - - - Client name - - - @@ -84,22 +77,6 @@ - - - - IBeamCursor - - - N/A - - - Qt::PlainText - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse - - - @@ -139,8 +116,8 @@ - - + + IBeamCursor @@ -169,6 +146,22 @@ + + + + IBeamCursor + + + N/A + + + Qt::PlainText + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + @@ -182,26 +175,6 @@ - - - - false - - - - - - - - - - false - - - - - - @@ -218,10 +191,10 @@ - - + + - Current number of blocks + Testnet On/Off @@ -232,21 +205,34 @@ - - + + + + false + - Testnet On/Off + - - + + + + false + - Estimated total blocks + - + + + + Current number of blocks + + + + @@ -259,14 +245,7 @@ - - - - Last block time - - - - + IBeamCursor @@ -282,7 +261,21 @@ - + + + + Estimated total blocks + + + + + + + Last block time + + + + IBeamCursor @@ -298,20 +291,23 @@ - - - - - 75 - true - + + + + IBeamCursor - Command-line options + N/A + + + Qt::PlainText + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse - + Qt::Vertical @@ -324,23 +320,20 @@ - - - - IBeamCursor + + + + + 75 + true + - N/A - - - Qt::PlainText - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + Command-line options - + Open the Denarius debug log file from the current data directory. This can take a few seconds for large log files. @@ -353,20 +346,20 @@ - - - - Qt::Vertical + + + + + 75 + true + - - - 20 - 40 - + + Debug log file - + - + Show the Denarius-Qt help message to get a list with possible Denarius command-line options. @@ -379,28 +372,18 @@ - - - - - 75 - true - - - - Debug log file - - - - - - - false + + + + Qt::Vertical - - + + + 20 + 40 + - + diff --git a/src/qt/forms/showi2paddresses.ui b/src/qt/forms/showi2paddresses.ui deleted file mode 100644 index f20bef93..00000000 --- a/src/qt/forms/showi2paddresses.ui +++ /dev/null @@ -1,136 +0,0 @@ - - - ShowI2PAddresses - - - - 0 - 0 - 640 - 450 - - - - - 640 - 450 - - - - Dialog - - - - - - If you want to use a permanent Denarius I2P node address you have to set a 'mydestination' option in the configuration file: - - - true - - - - - - - Ready to save parameter (If you want to use this address save this text in the configuration file and keep it secret): - - - true - - - - - - - - 0 - 3 - - - - true - - - - - - - Address (you can publish it): - - - - - - - - 0 - 2 - - - - true - - - - - - - Short I2P base32-address: - - - - - - - false - - - false - - - true - - - - - - - - - Copy "mydestination" parameter -to the clipboard - - - - - - - Copy public address -to the clipboard - - - - - - - Copy b32-address -to the clipboard - - - - - - - - - privText - pubText - b32Line - privButton - pubButton - b32Button - - - - diff --git a/src/qt/i2poptionswidget.cpp b/src/qt/i2poptionswidget.cpp deleted file mode 100644 index 2ef18dde..00000000 --- a/src/qt/i2poptionswidget.cpp +++ /dev/null @@ -1,100 +0,0 @@ -#include "i2poptionswidget.h" -#include "ui_i2poptionswidget.h" - -#include "optionsmodel.h" -#include "monitoreddatamapper.h" -#include "showi2paddresses.h" -//#include "i2p.h" -#include "util.h" -#include "clientmodel.h" - - -I2POptionsWidget::I2POptionsWidget(QWidget *parent) : - QWidget(parent), - ui(new Ui::I2POptionsWidget), - clientModel(0) -{ - ui->setupUi(this); - - QObject::connect(ui->pushButtonCurrentI2PAddress, SIGNAL(clicked()), this, SLOT(ShowCurrentI2PAddress())); - QObject::connect(ui->pushButtonGenerateI2PAddress, SIGNAL(clicked()), this, SLOT(GenerateNewI2PAddress())); - - QObject::connect(ui->checkBoxAllowZeroHop , SIGNAL(stateChanged(int)) , this, SIGNAL(settingsChanged())); - QObject::connect(ui->checkBoxInboundAllowZeroHop , SIGNAL(stateChanged(int)) , this, SIGNAL(settingsChanged())); - QObject::connect(ui->checkBoxUseI2POnly , SIGNAL(stateChanged(int)) , this, SIGNAL(settingsChanged())); - QObject::connect(ui->lineEditSAMHost , SIGNAL(textChanged(QString)), this, SIGNAL(settingsChanged())); - QObject::connect(ui->lineEditTunnelName , SIGNAL(textChanged(QString)), this, SIGNAL(settingsChanged())); - QObject::connect(ui->spinBoxInboundBackupQuality , SIGNAL(valueChanged(int)) , this, SIGNAL(settingsChanged())); - QObject::connect(ui->spinBoxInboundIPRestriction , SIGNAL(valueChanged(int)) , this, SIGNAL(settingsChanged())); - QObject::connect(ui->spinBoxInboundLength , SIGNAL(valueChanged(int)) , this, SIGNAL(settingsChanged())); - QObject::connect(ui->spinBoxInboundLengthVariance , SIGNAL(valueChanged(int)) , this, SIGNAL(settingsChanged())); - QObject::connect(ui->spinBoxInboundQuantity , SIGNAL(valueChanged(int)) , this, SIGNAL(settingsChanged())); - QObject::connect(ui->spinBoxOutboundBackupQuantity, SIGNAL(valueChanged(int)) , this, SIGNAL(settingsChanged())); - QObject::connect(ui->spinBoxOutboundIPRestriction , SIGNAL(valueChanged(int)) , this, SIGNAL(settingsChanged())); - QObject::connect(ui->spinBoxOutboundLength , SIGNAL(valueChanged(int)) , this, SIGNAL(settingsChanged())); - QObject::connect(ui->spinBoxOutboundLengthVariance, SIGNAL(valueChanged(int)) , this, SIGNAL(settingsChanged())); - QObject::connect(ui->spinBoxOutboundPriority , SIGNAL(valueChanged(int)) , this, SIGNAL(settingsChanged())); - QObject::connect(ui->spinBoxOutboundQuantity , SIGNAL(valueChanged(int)) , this, SIGNAL(settingsChanged())); - QObject::connect(ui->spinBoxSAMPort , SIGNAL(valueChanged(int)) , this, SIGNAL(settingsChanged())); -} - -I2POptionsWidget::~I2POptionsWidget() -{ - delete ui; -} - -void I2POptionsWidget::setMapper(MonitoredDataMapper& mapper) -{ - mapper.addMapping(ui->checkBoxUseI2POnly , OptionsModel::I2PUseI2POnly); - mapper.addMapping(ui->lineEditSAMHost , OptionsModel::I2PSAMHost); - mapper.addMapping(ui->spinBoxSAMPort , OptionsModel::I2PSAMPort); - mapper.addMapping(ui->lineEditTunnelName , OptionsModel::I2PSessionName); - mapper.addMapping(ui->spinBoxInboundQuantity , OptionsModel::I2PInboundQuantity); - mapper.addMapping(ui->spinBoxInboundLength , OptionsModel::I2PInboundLength); - mapper.addMapping(ui->spinBoxInboundLengthVariance , OptionsModel::I2PInboundLengthVariance); - mapper.addMapping(ui->spinBoxInboundBackupQuality , OptionsModel::I2PInboundBackupQuantity); - mapper.addMapping(ui->checkBoxInboundAllowZeroHop , OptionsModel::I2PInboundAllowZeroHop); - mapper.addMapping(ui->spinBoxInboundIPRestriction , OptionsModel::I2PInboundIPRestriction); - mapper.addMapping(ui->spinBoxOutboundQuantity , OptionsModel::I2POutboundQuantity); - mapper.addMapping(ui->spinBoxOutboundLength , OptionsModel::I2POutboundLength); - mapper.addMapping(ui->spinBoxOutboundLengthVariance, OptionsModel::I2POutboundLengthVariance); - mapper.addMapping(ui->spinBoxOutboundBackupQuantity, OptionsModel::I2POutboundBackupQuantity); - mapper.addMapping(ui->checkBoxAllowZeroHop , OptionsModel::I2POutboundAllowZeroHop); - mapper.addMapping(ui->spinBoxOutboundIPRestriction , OptionsModel::I2POutboundIPRestriction); - mapper.addMapping(ui->spinBoxOutboundPriority , OptionsModel::I2POutboundIPRestriction); -} - -void I2POptionsWidget::setModel(ClientModel* model) -{ - clientModel = model; -} - -void I2POptionsWidget::ShowCurrentI2PAddress() -{ - if (clientModel) - { - const QString pub = clientModel->getPublicI2PKey(); - const QString priv = clientModel->getPrivateI2PKey(); - const QString b32 = clientModel->getB32Address(pub); - const QString configFile = QString::fromStdString(GetConfigFile().string()); - - ShowI2PAddresses i2pCurrDialog("Your current I2P address", pub, priv, b32, configFile, this); - i2pCurrDialog.exec(); - } -} - -void I2POptionsWidget::GenerateNewI2PAddress() -{ - if (clientModel) - { - QString pub, priv; - clientModel->generateI2PDestination(pub, priv); - const QString b32 = clientModel->getB32Address(pub); - const QString configFile = QString::fromStdString(GetConfigFile().string()); - - ShowI2PAddresses i2pCurrDialog("Generated I2P address", pub, priv, b32, configFile, this); - i2pCurrDialog.exec(); - } -} - - diff --git a/src/qt/i2poptionswidget.h b/src/qt/i2poptionswidget.h deleted file mode 100644 index 7e262a5d..00000000 --- a/src/qt/i2poptionswidget.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef I2POPTIONSWIDGET_H -#define I2POPTIONSWIDGET_H - -#include - -class MonitoredDataMapper; - -namespace Ui { -class I2POptionsWidget; -} - -class ClientModel; - -class I2POptionsWidget : public QWidget -{ - Q_OBJECT - -public: - explicit I2POptionsWidget(QWidget *parent = 0); - ~I2POptionsWidget(); - - void setMapper(MonitoredDataMapper& mapper); - void setModel(ClientModel* model); - -private: - Ui::I2POptionsWidget *ui; - ClientModel* clientModel; - -private slots: - void ShowCurrentI2PAddress(); - void GenerateNewI2PAddress(); - -signals: - void settingsChanged(); -}; - -#endif // I2POPTIONSWIDGET_H diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp index 2de17b99..7184925c 100644 --- a/src/qt/optionsdialog.cpp +++ b/src/qt/optionsdialog.cpp @@ -13,10 +13,6 @@ #include #include -#ifdef USE_NATIVE_I2P -#include "clientmodel.h" -#endif - OptionsDialog::OptionsDialog(QWidget *parent) : QDialog(parent), ui(new Ui::OptionsDialog), @@ -25,10 +21,6 @@ OptionsDialog::OptionsDialog(QWidget *parent) : fRestartWarningDisplayed_Proxy(false), fRestartWarningDisplayed_Lang(false), fProxyIpValid(true) -#ifdef USE_NATIVE_I2P - , fRestartWarningDisplayed_I2P(false) - , tabI2P(new I2POptionsWidget()) -#endif { ui->setupUi(this); @@ -128,29 +120,10 @@ void OptionsDialog::setModel(OptionsModel *model) /* warn only when language selection changes by user action (placed here so init via mapper doesn't trigger this) */ connect(ui->lang, SIGNAL(valueChanged()), this, SLOT(showRestartWarning_Lang())); -#ifdef USE_NATIVE_I2P - QObject::connect(tabI2P, SIGNAL(settingsChanged()), this, SLOT(showRestartWarning_I2P())); -#endif - /* disable apply button after settings are loaded as there is nothing to save */ disableApplyButton(); } -#ifdef USE_NATIVE_I2P -void OptionsDialog::setClientModel(ClientModel* clientModel) -{ - if (clientModel) - { - if (clientModel->isNativeI2P()) { - ui->tabWidget->addTab(tabI2P, QString("I2P")); - tabI2P->setModel(clientModel); - } else { - ui->tabWidget->removeTab(tabI2P); - } - } -} -#endif - void OptionsDialog::setMapper() { /* Main */ @@ -178,10 +151,6 @@ void OptionsDialog::setMapper() mapper->addMapping(ui->unit, OptionsModel::DisplayUnit); mapper->addMapping(ui->displayAddresses, OptionsModel::DisplayAddresses); mapper->addMapping(ui->coinControlFeatures, OptionsModel::CoinControlFeatures); - -#ifdef USE_NATIVE_I2P - tabI2P->setMapper(*mapper); -#endif } void OptionsDialog::enableApplyButton() @@ -247,17 +216,6 @@ void OptionsDialog::showRestartWarning_Lang() } } -#ifdef USE_NATIVE_I2P -void OptionsDialog::showRestartWarning_I2P() -{ - if(!fRestartWarningDisplayed_I2P) - { - QMessageBox::warning(this, tr("Warning"), tr("This setting will take effect after restarting Denarius."), QMessageBox::Ok); - fRestartWarningDisplayed_I2P = true; - } -} -#endif - void OptionsDialog::updateDisplayUnit() { if(model) diff --git a/src/qt/optionsdialog.h b/src/qt/optionsdialog.h index 79721c4e..18469f50 100644 --- a/src/qt/optionsdialog.h +++ b/src/qt/optionsdialog.h @@ -2,9 +2,6 @@ #define OPTIONSDIALOG_H #include -#ifdef USE_NATIVE_I2P -#include "i2poptionswidget.h" -#endif namespace Ui { class OptionsDialog; @@ -12,9 +9,6 @@ class OptionsDialog; class OptionsModel; class MonitoredDataMapper; class QValidatedLineEdit; -#ifdef USE_NATIVE_I2P -class ClientModel; -#endif /** Preferences dialog. */ class OptionsDialog : public QDialog @@ -24,9 +18,6 @@ class OptionsDialog : public QDialog public: explicit OptionsDialog(QWidget *parent = 0); ~OptionsDialog(); -#ifdef USE_NATIVE_I2P - void setClientModel(ClientModel* clientModel); -#endif void setModel(OptionsModel *model); void setMapper(); @@ -48,9 +39,6 @@ private slots: void on_okButton_clicked(); void on_cancelButton_clicked(); void on_applyButton_clicked(); -#ifdef USE_NATIVE_I2P - void showRestartWarning_I2P(); -#endif void showRestartWarning_Proxy(); void showRestartWarning_Lang(); @@ -67,10 +55,6 @@ private slots: bool fRestartWarningDisplayed_Proxy; bool fRestartWarningDisplayed_Lang; bool fProxyIpValid; -#ifdef USE_NATIVE_I2P - bool fRestartWarningDisplayed_I2P; - I2POptionsWidget* tabI2P; -#endif }; #endif // OPTIONSDIALOG_H diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index 9f85fc46..8bcd1451 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -7,31 +7,6 @@ #include "guiutil.h" #include "ringsig.h" -#ifdef USE_NATIVE_I2P -#include "i2p.h" -#include - -#define I2P_OPTIONS_SECTION_NAME "I2P" - -class ScopeGroupHelper -{ -public: - ScopeGroupHelper(QSettings& settings, const QString& groupName) - : settings_(settings) - { - settings_.beginGroup(groupName); - } - ~ScopeGroupHelper() - { - settings_.endGroup(); - } - -private: - QSettings& settings_; -}; - -#endif - OptionsModel::OptionsModel(QObject *parent) : QAbstractListModel(parent) { @@ -60,52 +35,6 @@ bool static ApplyProxySettings() return true; } -#ifdef USE_NATIVE_I2P -std::string& FormatI2POptionsString( - std::string& options, - const std::string& name, - const std::pair& value) -{ - if (value.first) - { - if (!options.empty()) - options += " "; - options += name + "=" + value.second; - } - return options; -} - -std::string& FormatI2POptionsString( - std::string& options, - const std::string& name, - const std::pair& value) -{ - if (value.first) - { - if (!options.empty()) - options += " "; - options += name + "=" + (value.second ? "true" : "false"); - } - return options; -} - -std::string& FormatI2POptionsString( - std::string& options, - const std::string& name, - const std::pair& value) -{ - if (value.first) - { - if (!options.empty()) - options += " "; - std::ostringstream oss; - oss << value.second; - options += name + "=" + oss.str(); - } - return options; -} -#endif - void OptionsModel::Init() { QSettings settings; @@ -132,61 +61,6 @@ void OptionsModel::Init() SoftSetBoolArg("-detachdb", settings.value("detachDB").toBool()); if (!language.isEmpty()) SoftSetArg("-lang", language.toStdString()); - -#ifdef USE_NATIVE_I2P - ScopeGroupHelper s(settings, I2P_OPTIONS_SECTION_NAME); - - if (settings.value("useI2POnly", false).toBool()) - { - mapArgs["-onlynet"] = NATIVE_I2P_NET_STRING; - std::vector& onlyNets = mapMultiArgs["-onlynet"]; - if (std::find(onlyNets.begin(), onlyNets.end(), NATIVE_I2P_NET_STRING) == onlyNets.end()) - onlyNets.push_back(NATIVE_I2P_NET_STRING); - } - - if (settings.contains("samhost")) - SoftSetArg(I2P_SAM_HOST_PARAM, settings.value("samhost").toString().toStdString()); - - if (settings.contains("samport")) - SoftSetArg(I2P_SAM_PORT_PARAM, settings.value("samport").toString().toStdString()); - - if (settings.contains("sessionName")) - SoftSetArg(I2P_SESSION_NAME_PARAM, settings.value("sessionName").toString().toStdString()); - - i2pInboundQuantity = settings.value(SAM_NAME_INBOUND_QUANTITY , SAM_DEFAULT_INBOUND_QUANTITY ).toInt(); - i2pInboundLength = settings.value(SAM_NAME_INBOUND_LENGTH , SAM_DEFAULT_INBOUND_LENGTH ).toInt(); - i2pInboundLengthVariance = settings.value(SAM_NAME_INBOUND_LENGTHVARIANCE , SAM_DEFAULT_INBOUND_LENGTHVARIANCE ).toInt(); - i2pInboundBackupQuantity = settings.value(SAM_NAME_INBOUND_BACKUPQUANTITY , SAM_DEFAULT_INBOUND_BACKUPQUANTITY ).toInt(); - i2pInboundAllowZeroHop = settings.value(SAM_NAME_INBOUND_ALLOWZEROHOP , SAM_DEFAULT_INBOUND_ALLOWZEROHOP ).toBool(); - i2pInboundIPRestriction = settings.value(SAM_NAME_INBOUND_IPRESTRICTION , SAM_DEFAULT_INBOUND_IPRESTRICTION ).toInt(); - i2pOutboundQuantity = settings.value(SAM_NAME_OUTBOUND_QUANTITY , SAM_DEFAULT_OUTBOUND_QUANTITY ).toInt(); - i2pOutboundLength = settings.value(SAM_NAME_OUTBOUND_LENGTH , SAM_DEFAULT_OUTBOUND_LENGTH ).toInt(); - i2pOutboundLengthVariance = settings.value(SAM_NAME_OUTBOUND_LENGTHVARIANCE, SAM_DEFAULT_OUTBOUND_LENGTHVARIANCE).toInt(); - i2pOutboundBackupQuantity = settings.value(SAM_NAME_OUTBOUND_BACKUPQUANTITY, SAM_DEFAULT_OUTBOUND_BACKUPQUANTITY).toInt(); - i2pOutboundAllowZeroHop = settings.value(SAM_NAME_OUTBOUND_ALLOWZEROHOP , SAM_DEFAULT_OUTBOUND_ALLOWZEROHOP ).toBool(); - i2pOutboundIPRestriction = settings.value(SAM_NAME_OUTBOUND_IPRESTRICTION , SAM_DEFAULT_OUTBOUND_IPRESTRICTION ).toInt(); - i2pOutboundPriority = settings.value(SAM_NAME_OUTBOUND_PRIORITY , SAM_DEFAULT_OUTBOUND_PRIORITY ).toInt(); - - std::string i2pOptionsTemp; - FormatI2POptionsString(i2pOptionsTemp, SAM_NAME_INBOUND_QUANTITY , std::make_pair(settings.contains(SAM_NAME_INBOUND_QUANTITY ), i2pInboundQuantity)); - FormatI2POptionsString(i2pOptionsTemp, SAM_NAME_INBOUND_LENGTH , std::make_pair(settings.contains(SAM_NAME_INBOUND_LENGTH ), i2pInboundLength)); - FormatI2POptionsString(i2pOptionsTemp, SAM_NAME_INBOUND_LENGTHVARIANCE , std::make_pair(settings.contains(SAM_NAME_INBOUND_LENGTHVARIANCE ), i2pInboundLengthVariance)); - FormatI2POptionsString(i2pOptionsTemp, SAM_NAME_INBOUND_BACKUPQUANTITY , std::make_pair(settings.contains(SAM_NAME_INBOUND_BACKUPQUANTITY ), i2pInboundBackupQuantity)); - FormatI2POptionsString(i2pOptionsTemp, SAM_NAME_INBOUND_ALLOWZEROHOP , std::make_pair(settings.contains(SAM_NAME_INBOUND_ALLOWZEROHOP ), i2pInboundAllowZeroHop)); - FormatI2POptionsString(i2pOptionsTemp, SAM_NAME_INBOUND_IPRESTRICTION , std::make_pair(settings.contains(SAM_NAME_INBOUND_IPRESTRICTION ), i2pInboundIPRestriction)); - FormatI2POptionsString(i2pOptionsTemp, SAM_NAME_OUTBOUND_QUANTITY , std::make_pair(settings.contains(SAM_NAME_OUTBOUND_QUANTITY ), i2pOutboundQuantity)); - FormatI2POptionsString(i2pOptionsTemp, SAM_NAME_OUTBOUND_LENGTH , std::make_pair(settings.contains(SAM_NAME_OUTBOUND_LENGTH ), i2pOutboundLength)); - FormatI2POptionsString(i2pOptionsTemp, SAM_NAME_OUTBOUND_LENGTHVARIANCE, std::make_pair(settings.contains(SAM_NAME_OUTBOUND_LENGTHVARIANCE), i2pOutboundLengthVariance)); - FormatI2POptionsString(i2pOptionsTemp, SAM_NAME_OUTBOUND_BACKUPQUANTITY, std::make_pair(settings.contains(SAM_NAME_OUTBOUND_BACKUPQUANTITY), i2pOutboundBackupQuantity)); - FormatI2POptionsString(i2pOptionsTemp, SAM_NAME_OUTBOUND_ALLOWZEROHOP , std::make_pair(settings.contains(SAM_NAME_OUTBOUND_ALLOWZEROHOP ), i2pOutboundAllowZeroHop)); - FormatI2POptionsString(i2pOptionsTemp, SAM_NAME_OUTBOUND_IPRESTRICTION , std::make_pair(settings.contains(SAM_NAME_OUTBOUND_IPRESTRICTION ), i2pOutboundIPRestriction)); - FormatI2POptionsString(i2pOptionsTemp, SAM_NAME_OUTBOUND_PRIORITY , std::make_pair(settings.contains(SAM_NAME_OUTBOUND_PRIORITY ), i2pOutboundPriority)); - - if (!i2pOptionsTemp.empty()) - SoftSetArg(I2P_SAM_I2P_OPTIONS_PARAM, i2pOptionsTemp); - - i2pOptions = QString::fromStdString(i2pOptionsTemp); -#endif } int OptionsModel::rowCount(const QModelIndex & parent) const @@ -241,61 +115,6 @@ QVariant OptionsModel::data(const QModelIndex & index, int role) const return settings.value("language", ""); case CoinControlFeatures: return QVariant(fCoinControlFeatures); -#ifdef USE_NATIVE_I2P - case I2PUseI2POnly: - { - ScopeGroupHelper s(settings, I2P_OPTIONS_SECTION_NAME); - bool useI2POnly = false; - if (mapArgs.count("-onlynet")) - { - const std::vector& onlyNets = mapMultiArgs["-onlynet"]; - if (std::find(onlyNets.begin(), onlyNets.end(), NATIVE_I2P_NET_STRING) != onlyNets.end()) - useI2POnly = true; - } - return settings.value("useI2POnly", useI2POnly); - } - case I2PSAMHost: - { - ScopeGroupHelper s(settings, I2P_OPTIONS_SECTION_NAME); - return settings.value("samhost", QString::fromStdString(GetArg(I2P_SAM_HOST_PARAM, I2P_SAM_HOST_DEFAULT))); - } - case I2PSAMPort: - { - ScopeGroupHelper s(settings, I2P_OPTIONS_SECTION_NAME); - return settings.value("samport", QString::number((qint64)GetArg(I2P_SAM_PORT_PARAM, I2P_SAM_PORT_DEFAULT))); - } - case I2PSessionName: - { - ScopeGroupHelper s(settings, I2P_OPTIONS_SECTION_NAME); - return settings.value("sessionName", QString::fromStdString(GetArg(I2P_SESSION_NAME_PARAM, I2P_SESSION_NAME_DEFAULT))); - } - case I2PInboundQuantity: - return QVariant(i2pInboundQuantity); - case I2PInboundLength: - return QVariant(i2pInboundLength); - case I2PInboundLengthVariance: - return QVariant(i2pInboundLengthVariance); - case I2PInboundBackupQuantity: - return QVariant(i2pInboundBackupQuantity); - case I2PInboundAllowZeroHop: - return QVariant(i2pInboundAllowZeroHop); - case I2PInboundIPRestriction: - return QVariant(i2pInboundIPRestriction); - case I2POutboundQuantity: - return QVariant(i2pOutboundQuantity); - case I2POutboundLength: - return QVariant(i2pOutboundLength); - case I2POutboundLengthVariance: - return QVariant(i2pOutboundLengthVariance); - case I2POutboundBackupQuantity: - return QVariant(i2pOutboundBackupQuantity); - case I2POutboundAllowZeroHop: - return QVariant(i2pOutboundAllowZeroHop); - case I2POutboundIPRestriction: - return QVariant(i2pOutboundIPRestriction); - case I2POutboundPriority: - return QVariant(i2pOutboundPriority); -#endif default: return QVariant(); } @@ -396,124 +215,6 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in emit coinControlFeaturesChanged(fCoinControlFeatures); } break; -#ifdef USE_NATIVE_I2P - case I2PUseI2POnly: - { - ScopeGroupHelper s(settings, I2P_OPTIONS_SECTION_NAME); - settings.setValue("useI2POnly", value.toBool()); - break; - } - case I2PSAMHost: - { - ScopeGroupHelper s(settings, I2P_OPTIONS_SECTION_NAME); - settings.setValue("samhost", value.toString()); - break; - } - case I2PSAMPort: - { - ScopeGroupHelper s(settings, I2P_OPTIONS_SECTION_NAME); - settings.setValue("samport", value.toString()); - break; - } - case I2PSessionName: - { - ScopeGroupHelper s(settings, I2P_OPTIONS_SECTION_NAME); - settings.setValue("sessionName", value.toString()); - break; - } - case I2PInboundQuantity: - { - ScopeGroupHelper s(settings, I2P_OPTIONS_SECTION_NAME); - i2pInboundQuantity = value.toInt(); - settings.setValue(SAM_NAME_INBOUND_QUANTITY, i2pInboundQuantity); - break; - } - case I2PInboundLength: - { - ScopeGroupHelper s(settings, I2P_OPTIONS_SECTION_NAME); - i2pInboundLength = value.toInt(); - settings.setValue(SAM_NAME_INBOUND_LENGTH, i2pInboundLength); - break; - } - case I2PInboundLengthVariance: - { - ScopeGroupHelper s(settings, I2P_OPTIONS_SECTION_NAME); - i2pInboundLengthVariance = value.toInt(); - settings.setValue(SAM_NAME_INBOUND_LENGTHVARIANCE, i2pInboundLengthVariance); - break; - } - case I2PInboundBackupQuantity: - { - ScopeGroupHelper s(settings, I2P_OPTIONS_SECTION_NAME); - i2pInboundBackupQuantity = value.toInt(); - settings.setValue(SAM_NAME_INBOUND_BACKUPQUANTITY, i2pInboundBackupQuantity); - break; - } - case I2PInboundAllowZeroHop: - { - ScopeGroupHelper s(settings, I2P_OPTIONS_SECTION_NAME); - i2pInboundAllowZeroHop = value.toBool(); - settings.setValue(SAM_NAME_INBOUND_ALLOWZEROHOP, i2pInboundAllowZeroHop); - break; - } - case I2PInboundIPRestriction: - { - ScopeGroupHelper s(settings, I2P_OPTIONS_SECTION_NAME); - i2pInboundIPRestriction = value.toInt(); - settings.setValue(SAM_NAME_INBOUND_IPRESTRICTION, i2pInboundIPRestriction); - break; - } - case I2POutboundQuantity: - { - ScopeGroupHelper s(settings, I2P_OPTIONS_SECTION_NAME); - i2pOutboundQuantity = value.toInt(); - settings.setValue(SAM_NAME_OUTBOUND_QUANTITY, i2pOutboundQuantity); - break; - } - case I2POutboundLength: - { - ScopeGroupHelper s(settings, I2P_OPTIONS_SECTION_NAME); - i2pOutboundLength = value.toInt(); - settings.setValue(SAM_NAME_OUTBOUND_LENGTH, i2pOutboundLength); - break; - } - case I2POutboundLengthVariance: - { - ScopeGroupHelper s(settings, I2P_OPTIONS_SECTION_NAME); - i2pOutboundLengthVariance = value.toInt(); - settings.setValue(SAM_NAME_OUTBOUND_LENGTHVARIANCE, i2pOutboundLengthVariance); - break; - } - case I2POutboundBackupQuantity: - { - ScopeGroupHelper s(settings, I2P_OPTIONS_SECTION_NAME); - i2pOutboundBackupQuantity = value.toInt(); - settings.setValue(SAM_NAME_OUTBOUND_BACKUPQUANTITY, i2pOutboundBackupQuantity); - break; - } - case I2POutboundAllowZeroHop: - { - ScopeGroupHelper s(settings, I2P_OPTIONS_SECTION_NAME); - i2pOutboundAllowZeroHop = value.toBool(); - settings.setValue(SAM_NAME_OUTBOUND_ALLOWZEROHOP, i2pOutboundAllowZeroHop); - break; - } - case I2POutboundIPRestriction: - { - ScopeGroupHelper s(settings, I2P_OPTIONS_SECTION_NAME); - i2pOutboundIPRestriction = value.toInt(); - settings.setValue(SAM_NAME_OUTBOUND_IPRESTRICTION, i2pOutboundIPRestriction); - break; - } - case I2POutboundPriority: - { - ScopeGroupHelper s(settings, I2P_OPTIONS_SECTION_NAME); - i2pOutboundPriority = value.toInt(); - settings.setValue(SAM_NAME_OUTBOUND_PRIORITY, i2pOutboundPriority); - break; - } - -#endif default: break; } diff --git a/src/qt/optionsmodel.h b/src/qt/optionsmodel.h index dfec983e..be499519 100644 --- a/src/qt/optionsmodel.h +++ b/src/qt/optionsmodel.h @@ -32,27 +32,6 @@ class OptionsModel : public QAbstractListModel DetachDatabases, // bool Language, // QString CoinControlFeatures, // bool -#ifdef USE_NATIVE_I2P - I2PUseI2POnly, // bool - I2PSAMHost, // QString - I2PSAMPort, // int - I2PSessionName, // QString - - I2PInboundQuantity, // int - I2PInboundLength, // int - I2PInboundLengthVariance, // int - I2PInboundBackupQuantity, // int - I2PInboundAllowZeroHop, // bool - I2PInboundIPRestriction, // int - - I2POutboundQuantity, // int - I2POutboundLength, // int - I2POutboundLengthVariance, // int - I2POutboundBackupQuantity, // int - I2POutboundAllowZeroHop, // bool - I2POutboundIPRestriction, // int - I2POutboundPriority, // int -#endif OptionIDRowCount, }; @@ -79,22 +58,6 @@ class OptionsModel : public QAbstractListModel bool fMinimizeOnClose; bool fCoinControlFeatures; QString language; -#ifdef USE_NATIVE_I2P - int i2pInboundQuantity; - int i2pInboundLength; - int i2pInboundLengthVariance; - int i2pInboundBackupQuantity; - bool i2pInboundAllowZeroHop; - int i2pInboundIPRestriction; - int i2pOutboundQuantity; - int i2pOutboundLength; - int i2pOutboundLengthVariance; - int i2pOutboundBackupQuantity; - bool i2pOutboundAllowZeroHop; - int i2pOutboundIPRestriction; - int i2pOutboundPriority; - QString i2pOptions; -#endif signals: void displayUnitChanged(int unit); diff --git a/src/qt/res/icons/fs.png b/src/qt/res/icons/fs.png deleted file mode 100644 index 0813b667487b4e6427fb87a5e657ffa7de3541c0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33382 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 diff --git a/src/qt/res/icons/i2plogo_1_16.png b/src/qt/res/icons/i2plogo_1_16.png deleted file mode 100644 index 8b660972eb28f98f02bfb2cd8cb3bb556ae06744..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3242 zcmb_f2~-o;8pcu-@hP^Vh*1dH0W0uotdQ&3c#WM&|eWU@&DE+`6$f*a3P z0YwE{>VmdNMFsRxmLphD>r!Qj7;ys%6spjoz6kJFT?}?_P$>)({U%8R5v2x#~DkGzDlMMGLqs;87MnqJLSUFEAyx#TG*1tzn-(SwNHH}+)k-BY6|8lq4cdjtwxOF&qYgsUvF@~a z28Yy$fFPhXD%QD*&Helat669HUv3QnGDc{&TyfFECA%fYzE9^Qim=Y=}n2^ za0uUL$QSwLPK!~i%#LcBhd{--IBQkC>IIhSEePjIKrGbkLb$2x$W|ILCx2@z@IKlC6FK@gz}8(?yTAizP`Y(R+d7yyHZG8t?JkH->0!`2ol z#pIeqByU?autG_T5QyU_6G8wSBugM-vblf|60!k^je`)61#(3Y&!GH4F~PoK6DTZ1SF?CQsFd{On3wN5xAP5Yl4Rwp(laCMbJTzYugONu6LM3m!s|Z}JL6q3M zXfk&nB1HP1@mC>nf6X2PaTH~tAX!Zg7hq##H4zb+JRISPxI8Y#0lC8A=>N!`MM@iH zfWyN5o9u^@BZ@&}(HOba(rJG`o)1&!8=~)v=beT4e~pK3*ks>GjsD*%92|RVLng~P z*hTL0hUUoeLVk=KP?(HNm6AMuqU&|_N0%Vbg zBX^hp7ROI5Idx4aNwQzI+sC`rnqzz4JT0^8=0v;1jaA$7wtZY=Hnu9o)Fx!xEl+-> zwcWS(`ix^8i#`I5TyR!9cD#CW_2;^h_*V*DTiL;b2YRzg8m%8Us_NrkG^*;-Z?H?P z{3hy0wX-&#=mJY-7*GA4^;2rpl)l^dC+&B>TIrJNW!34(;BxQ=eS^P$;59#|SL+~q zLU1E*$@YZ}v4W24*Q@epWNC`;Umdp!@YtbZHU0dr;KFVbNzL;_(~FT$zCf9ES9&i| z=GGJ&A4?NQJwH_$-nD6pjo&w)T2}(atgNUV^k-=bN%f4c!)D2R7p6A*bneOu?sN4J z@}(^G>+U%D+P-jny~1&2&aaxHBlK!_MJ@Ve3LP{8d{mo9dVzna^e`z0-8`Lfcy?wfLh z*8-caDPYoz1F2Eg6}n~GnU`0zPVo8e`w+J!QwbKY_4536%jD<%k}Wdycczv#wiW;@ za;KH{HC47^yJiQgq|+il@cvqrQ`Sb2og{>6yL;@<~2? ze)QIZZWV{p!*U7_M_;ch3wgOJN}O==G#k1bo|$mrG;@8+z#*|h?arG~T4W zc5ut-U?uC!OoDeZXI@38*FKc|Ft&+dp2(i`a089sDVth8K51N_sq8lg-?sKkJ0F=w z7c4_AbW_gnu@9jq1!2HDjpou(YG zcpc~3|LsIj_j&rIyOmu>vlRpW`6Z(lSxwm5iT7HqEZok%>#+I?{>k32XFsTmRCFCl$90IQ*(13A2dl?8+lzL~)UfD`$chTv#^1_pcV_lu3?)`4oy1D#k(=EpZt0J`d z4|UCH8;;h_8MR<0-fs8wuKzy4_&O-wjxKy~K6oHk6YB8}-Np7|o&SZ{t?R!z z@L83=y>{t1y;)1^o$$U#Ek#zP=aMzf2{UnQAGRRk)u+bQWyh@QOB`>sXL#5Iyg)Yt zGc0tOMXp{mA=j7G;D{&{7VOuu($j!u?t9Vg~Lo26}>T|O%|^vn9( q@&?;#-WC_NaozV($(C)+uZ`EWmnOKGo1ZoOO$fXL`33V=CH)(@S_#tt diff --git a/src/qt/res/icons/i2plogo_2_16.png b/src/qt/res/icons/i2plogo_2_16.png deleted file mode 100644 index 62696edb9ef41619bef0e8f6263da4741f3da09b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3411 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 diff --git a/src/qt/res/icons/i2plogo_4_16.png b/src/qt/res/icons/i2plogo_4_16.png deleted file mode 100644 index c14c55451f08bbc998632f59614c7b3bc148fef6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3598 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 k0jbUj4<>&getNumConnections()); ui->isTestNet->setChecked(model->isTestNet()); ui->isNativeTor->setChecked(model->isNativeTor()); - ui->isNativeI2P->setChecked(model->isNativeI2P()); setNumBlocks(model->getNumBlocks(), model->getNumBlocksOfPeers()); } diff --git a/src/qt/showi2paddresses.cpp b/src/qt/showi2paddresses.cpp deleted file mode 100644 index 7ccefa3e..00000000 --- a/src/qt/showi2paddresses.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#include "showi2paddresses.h" -#include "ui_showi2paddresses.h" - -ShowI2PAddresses::ShowI2PAddresses(const QString& caption, const QString& pub, const QString& priv, const QString& b32, const QString& configFileName, QWidget *parent) : - QDialog(parent), - ui(new Ui::ShowI2PAddresses) -{ - ui->setupUi(this); - this->setWindowTitle(caption); - ui->pubText->setPlainText(pub); - ui->privText->setText("mydestination=" + priv); - ui->b32Line->setText(b32); - ui->label->setText(ui->label->text() + "\n" + configFileName); - - QObject::connect(ui->privButton, SIGNAL(clicked()), - ui->privText, SLOT(selectAll())); - QObject::connect(ui->privButton, SIGNAL(clicked()), - ui->privText, SLOT(copy())); - - QObject::connect(ui->pubButton, SIGNAL(clicked()), - ui->pubText, SLOT(selectAll())); - QObject::connect(ui->pubButton, SIGNAL(clicked()), - ui->pubText, SLOT(copy())); - - QObject::connect(ui->b32Button, SIGNAL(clicked()), - ui->b32Line, SLOT(selectAll())); - QObject::connect(ui->b32Button, SIGNAL(clicked()), - ui->b32Line, SLOT(copy())); -} - -ShowI2PAddresses::~ShowI2PAddresses() -{ - delete ui; -} diff --git a/src/qt/showi2paddresses.h b/src/qt/showi2paddresses.h deleted file mode 100644 index bcd21a10..00000000 --- a/src/qt/showi2paddresses.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef SHOWI2PADDRESSES_H -#define SHOWI2PADDRESSES_H - -#include - -namespace Ui { -class ShowI2PAddresses; -} - -class ShowI2PAddresses : public QDialog -{ - Q_OBJECT - -public: - explicit ShowI2PAddresses(const QString& caption, const QString& pub, const QString& priv, const QString& b32, const QString& configFileName, QWidget *parent = 0); - ~ShowI2PAddresses(); - -private: - Ui::ShowI2PAddresses *ui; -}; - -#endif // SHOWI2PADDRESSES_H diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index b304546f..e317a679 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -676,6 +676,29 @@ void WalletModel::getOutputs(const std::vector& vOutpoints, std::vect vOutputs.push_back(out); } } +/* +// AvailableCoins + LockedCoins grouped by wallet address (put change in one group with wallet address) +void WalletModel::listCoins(std::map >& mapCoins) const +{ + std::vector vCoins; + wallet->AvailableCoins(vCoins); + + BOOST_FOREACH(const COutput& out, vCoins) + { + COutput cout = out; + while (wallet->IsChange(cout.tx->vout[cout.i]) && cout.tx->vin.size() > 0 && wallet->IsMine(cout.tx->vin[0], ISMINE_SPENDABLE)) + { + if (!wallet->mapWallet.count(cout.tx->vin[0].prevout.hash)) break; + //cout = COutput(&wallet->mapWallet[cout.tx->vin[0].prevout.hash], cout.tx->vin[0].prevout.n, 0); + cout = COutput(&wallet->mapWallet[cout.tx->vin[0].prevout.hash], cout.tx->vin[0].prevout.n, 0, true); + } + + CTxDestination address; + if(!ExtractDestination(cout.tx->vout[cout.i].scriptPubKey, address)) continue; + mapCoins[CBitcoinAddress(address).ToString().c_str()].push_back(out); + } +} +*/ // AvailableCoins + LockedCoins grouped by wallet address (put change in one group with wallet address) void WalletModel::listCoins(std::map >& mapCoins) const diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp index 47f052a4..b3aad66a 100644 --- a/src/rpcnet.cpp +++ b/src/rpcnet.cpp @@ -23,163 +23,6 @@ Value getconnectioncount(const Array& params, bool fHelp) return (int)vNodes.size(); } -Value ping(const Array& params, bool fHelp) -{ - if (fHelp || params.size() != 0) - throw runtime_error( - "ping\n" - "Requests that a ping be sent to all other nodes, to measure ping time.\n" - "Results provided in getpeerinfo, pingtime and pingwait fields are decimal seconds.\n" - "Ping command is handled in queue with all other commands, so it measures processing backlog, not just network ping."); - - // Request that each node send a ping during next message processing pass - LOCK(cs_vNodes); - BOOST_FOREACH(CNode* pNode, vNodes) { - pNode->fPingQueued = true; - } - - return Value::null; -} - -/* -#ifdef USE_NATIVE_I2P -Value destination(const Array& params, bool fHelp) -{ - if (fHelp || params.size() > 2) - throw runtime_error( - "destination [\"match|good|attempt|connect\"] [\"b32.i2p|base64|ip:port\"]\n" - "\n Returns I2P destination details stored in your b32.i2p address manager lookup system.\n" - "\nArguments:\n" - " If no arguments are provided, the command returns all the b32.i2p addresses. NOTE: Results will not include base64\n" - " 1st argument = \"match\" then a 2nd argument is also required.\n" - " 2nd argument = Any string. If a match is found in any of the address, source or base64 fields, that result will be returned.\n" - " 1st argument = \"good\" destinations that has been tried, connected and found to be good will be returned.\n" - " 1st argument = \"attempt\" destinations that have been attempted, will be returned.\n" - " 1st argument = \"connect\" destinations that have been connected to in the past, will be returned.\n" - "\nResults are returned as a json array of object(s).\n" - " The 1st result pair is the total size of the address hash map.\n" - " The 2nd result pair is the number of objects which follow, as matching this query. It can be zero, if no match was found.\n" - "\nResult:\n" - "[\n" - " {\n" - " \"tablesize\": nnn, (numeric) The total number of destinations in the i2p address book\n" - " \"matchsize\": nnn, (numeric) The number of results returned, which matched your query\n" - " }\n" - " {\n" - " \"address\":\"b32.i2p\", (string) Base32 hash of a i2p destination, a possible peer\n" - " \"good\": true|false, (boolean) Has this address been tried & found to be good\n" - " \"attempt\": nnn, (numeric) The number of times it has been attempted\n" - " \"lasttry\": ttt, (numeric) The time of a last attempted connection (memory only)\n" - " \"connect\": ttt, (numeric) The time of a last successful connection\n" - " \"source\":\"b32.i2p|ip:port\", (string) The source of information about this address\n" - " \"base64\":\"destination\", (string) The full Base64 Public Key of this peers b32.i2p address\n" - " }\n" - " ,...\n" - "]\n" - "\nNOTE: The results obtained are only a snapshot, while you are connected to the network.\n" - " Peers are updating addresses & destinations all the time.\n" - "\nExamples: destination good|attempt|connect|match returns all I2P destinations currently known about on the system.\n" - "\nExamples: destination good returns the I2P destinations marked as 'good', happens if they have been tried and a successful version handshake made.\n" - "\nExample: destination attempt returns I2P destinations marked as having made an attempt to connect\n" - "\nExample: destination connect returns I2P destinations which are marked as having been connected to.\n" - "\nExamples: destination match returns I2P destination entries which came from the 'source' IP address 215.49.103.xxx\n" - "\nExamples: destination match returns all I2P b32.i2p destinations which match the patter, these could be found in the 'source' or the 'address' fields.\n" - ); - //! We must not have node or main processing as Addrman needs to - //! be considered static for the time required to process this. - LOCK2(cs_main, cs_vNodes); - - bool fSelectedMatch = false; - bool fMatchStr = false; - bool fMatchTried = false; - bool fMatchAttempt = false; - bool fMatchConnect = false; - bool fUnknownCmd = false; - string sMatchStr; - - if( params.size() > 0 ) { // Lookup the address and return the one object if found - string sCmdStr = params[0].get_str(); - if( sCmdStr == "match" ) { - if( params.size() > 1 ) { - sMatchStr = params[1].get_str(); - fMatchStr = true; - } else - fUnknownCmd = true; - } else if( sCmdStr == "good" ) - fMatchTried = true; - else if( sCmdStr == "attempt" ) - fMatchAttempt = true; - else if( sCmdStr == "connect") - fMatchConnect = true; - else - fUnknownCmd = true; - fSelectedMatch = true; - } - - Array ret; - // Load the vector with all the objects we have and return with - // the total number of addresses we have on file - vector vecStats; - int nTableSize = addrman.CopyDestinationStats(vecStats); - if( !fUnknownCmd ) { // If set, throw runtime error - for( int i = 0; i < 2; i++ ) { // Loop through the data twice - bool fMatchFound = false; // Assume no match - int nMatchSize = 0; // the match counter - BOOST_FOREACH(const CDestinationStats& stats, vecStats) { - if( fSelectedMatch ) { - if( fMatchStr ) { - if( stats.sAddress.find(sMatchStr) != string::npos || - stats.sSource.find(sMatchStr) != string::npos || - stats.sBase64.find(sMatchStr) != string::npos ) - fMatchFound = true; - } else if( fMatchTried ) { - if( stats.fInTried ) fMatchFound = true; - } - else if( fMatchAttempt ) { - if( stats.nAttempts > 0 ) fMatchFound = true; - } - else if( fMatchConnect ) { - if( stats.nSuccessTime > 0 ) fMatchFound = true; - } - } else // Match everything - fMatchFound = true; - - if( i == 1 && fMatchFound ) { - Object obj; - obj.push_back(Pair("address", stats.sAddress)); - obj.push_back(Pair("good", stats.fInTried)); - obj.push_back(Pair("attempt", stats.nAttempts)); - obj.push_back(Pair("lasttry", stats.nLastTry)); - obj.push_back(Pair("connect", stats.nSuccessTime)); - obj.push_back(Pair("source", stats.sSource)); - //! Do to an RPC buffer limit of 65535 with stream output, we can not send these and ever get a result - //! This should be considered a short term fix ToDo: Allocate bigger iostream buffer for the output - if( fSelectedMatch ) - obj.push_back(Pair("base64", stats.sBase64)); - ret.push_back(obj); - } - if( fMatchFound ) { - nMatchSize++; - fMatchFound = false; - } - } - // The 1st time we get a count of the matches, so we can list that first in the results, - // then we finally build the output objects, on the 2nd pass...and don't put this in there twice - if( i == 0 ) { - Object objSizes; - objSizes.push_back(Pair("tablesize", nTableSize)); - objSizes.push_back(Pair("matchsize", nMatchSize)); - ret.push_back(objSizes); // This is the 1st object put on the Array - } - } - } else - throw runtime_error( "Unknown subcommand or argument missing" ); - - return ret; -} -#endif -*/ - static void CopyNodeStats(std::vector& vstats) { vstats.clear(); @@ -193,91 +36,6 @@ static void CopyNodeStats(std::vector& vstats) } } -static Array GetNetworksInfo() -{ - Array networks; - for(int n=0; n(n); - if(network == NET_UNROUTABLE) - continue; - proxyType proxy; - Object obj; - GetProxy(network, proxy); - obj.push_back(Pair("name", GetNetworkName(network))); - obj.push_back(Pair("limited", IsLimited(network))); - //obj.push_back(Pair("reachable", IsReachable(network))); - //obj.push_back(Pair("proxy", proxy.IsValid() ? proxy.ToStringIPPort() : string())); - networks.push_back(obj); - } - return networks; -} - -static const string SingleAlertSubVersionsString( const std::set& setVersions ) -{ - std::string strSetSubVer; - BOOST_FOREACH(std::string str, setVersions) { - if(strSetSubVer.size()) // Must be more than one - strSetSubVer += " or "; - strSetSubVer += str; - } - return strSetSubVer; -} - -Value getnetworkinfo(const Array& params, bool fHelp) -{ - if (fHelp || params.size() != 0) - throw runtime_error( - "getnetworkinfo\n" - " Returns an object containing various state info regarding P2P networking.\n" - "\nResult:\n" - "{\n" - " \"version\": xxxxx, (numeric) the server version\n" - " \"subver\": \"/s:n.n.n.n/\", (string) this clients subversion string\n" - " \"protocolversion\": xxxxx, (numeric) the protocol version\n" - " \"localservices\": \"xxxx\", (hex string) Our local service bits as a 16 char string.\n" - " \"timeoffset\": xxxxx, (numeric) the time offset\n" - " \"connections\": xxxxx, (numeric) the number of connections\n" - " \"networkconnections\": [ (array) the state of each possible network connection type\n" - " \"name\": \"xxx\", (string) network name\n" - " \"limited\" : true|false, (boolean) if service is limited\n" - " ]\n" - " \"localaddresses\": [ (array) list of local addresses\n" - " \"address\": \"xxxx\", (string) network address\n" - " \"port\": xxx, (numeric) network port\n" - " \"score\": xxx (numeric) relative score\n" - " ]\n" - "}\n" - ); - - LOCK(cs_main); - - Object obj; - obj.push_back(Pair("version", (int)CLIENT_VERSION)); - obj.push_back(Pair("subversion", FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector()))); - obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION)); - obj.push_back(Pair("localservices", strprintf("%016", PRIx64, nLocalServices))); - obj.push_back(Pair("timeoffset", GetTimeOffset())); - obj.push_back(Pair("connections", (int)vNodes.size())); - //obj.push_back(Pair("relayfee", ValueFromAmount(minRelayTxFee.GetFeePerK()))); - obj.push_back(Pair("networkconnections",GetNetworksInfo())); - Array localAddresses; - { - LOCK(cs_mapLocalHost); - BOOST_FOREACH(const PAIRTYPE(CNetAddr, LocalServiceInfo) &item, mapLocalHost) - { - Object rec; - rec.push_back(Pair("address", item.first.ToString())); - rec.push_back(Pair("port", item.second.nPort)); - rec.push_back(Pair("score", item.second.nScore)); - localAddresses.push_back(rec); - } - } - obj.push_back(Pair("localaddresses", localAddresses)); - - return obj; -} - Value getpeerinfo(const Array& params, bool fHelp) { if (fHelp || params.size() != 0) @@ -294,15 +52,10 @@ Value getpeerinfo(const Array& params, bool fHelp) Object obj; obj.push_back(Pair("addr", stats.addrName)); - if (!(stats.addrLocal.empty())) - obj.push_back(Pair("addrlocal", stats.addrLocal)); - obj.push_back(Pair("services", strprintf("%016" PRIx64, stats.nServices))); + obj.push_back(Pair("services", strprintf("%08" PRIx64, stats.nServices))); obj.push_back(Pair("lastsend", (int64_t)stats.nLastSend)); obj.push_back(Pair("lastrecv", (int64_t)stats.nLastRecv)); obj.push_back(Pair("conntime", (int64_t)stats.nTimeConnected)); - obj.push_back(Pair("pingtime", stats.dPingTime)); //return nodes ping time - if (stats.dPingWait > 0.0) - obj.push_back(Pair("pingwait", stats.dPingWait)); obj.push_back(Pair("version", stats.nVersion)); obj.push_back(Pair("subver", stats.strSubVer)); obj.push_back(Pair("inbound", stats.fInbound)); @@ -383,113 +136,6 @@ Value setdebug(const Array& params, bool fHelp) return Value::null; } -Value getaddednodeinfo(const Array& params, bool fHelp) -{ - if (fHelp || params.size() < 1 || params.size() > 2) - throw runtime_error( - "getaddednodeinfo [node]\n" - "Returns information about the given added node, or all added nodes\n" - "(note that onetry addnodes are not listed here)\n" - "If dns is false, only a list of added nodes will be provided,\n" - "otherwise connected information will also be available."); - - bool fDns = params[0].get_bool(); - - list laddedNodes(0); - if (params.size() == 1) - { - LOCK(cs_vAddedNodes); - BOOST_FOREACH(string& strAddNode, vAddedNodes) - laddedNodes.push_back(strAddNode); - } - else - { - string strNode = params[1].get_str(); - LOCK(cs_vAddedNodes); - BOOST_FOREACH(string& strAddNode, vAddedNodes) - if (strAddNode == strNode) - { - laddedNodes.push_back(strAddNode); - break; - } - if (laddedNodes.size() == 0) - throw JSONRPCError(RPC_CLIENT_NODE_NOT_ADDED, "Error: Node has not been added."); - } - - if (!fDns) - { - Object ret; - BOOST_FOREACH(string& strAddNode, laddedNodes) - ret.push_back(Pair("addednode", strAddNode)); - return ret; - } - - Array ret; - - list > > laddedAddreses(0); - BOOST_FOREACH(string& strAddNode, laddedNodes) - { - vector vservNode(0); - if(Lookup(strAddNode.c_str(), vservNode, GetDefaultPort(), fNameLookup, 0)) - laddedAddreses.push_back(make_pair(strAddNode, vservNode)); - else - { - Object obj; - obj.push_back(Pair("addednode", strAddNode)); - obj.push_back(Pair("connected", false)); - Array addresses; - obj.push_back(Pair("addresses", addresses)); - } - } - - LOCK(cs_vNodes); - for (list > >::iterator it = laddedAddreses.begin(); it != laddedAddreses.end(); it++) - { - Object obj; - obj.push_back(Pair("addednode", it->first)); - - Array addresses; - bool fConnected = false; - BOOST_FOREACH(CService& addrNode, it->second) - { - bool fFound = false; - Object node; - node.push_back(Pair("address", addrNode.ToString())); - BOOST_FOREACH(CNode* pnode, vNodes) - if (pnode->addr == addrNode) - { - fFound = true; - fConnected = true; - node.push_back(Pair("connected", pnode->fInbound ? "inbound" : "outbound")); - break; - } - if (!fFound) - node.push_back(Pair("connected", "false")); - addresses.push_back(node); - } - obj.push_back(Pair("connected", fConnected)); - obj.push_back(Pair("addresses", addresses)); - ret.push_back(obj); - } - - return ret; -} - -Value getnettotals(const Array& params, bool fHelp) -{ - if (fHelp || params.size() > 0) - throw runtime_error( - "getnettotals\n" - "Returns information about network traffic, including bytes in, bytes out,\n" - "and current time."); - - Object obj; - obj.push_back(Pair("totalbytesrecv", CNode::GetTotalBytesRecv())); - obj.push_back(Pair("totalbytessent", CNode::GetTotalBytesSent())); - obj.push_back(Pair("timemillis", GetTimeMillis())); - return obj; -} - // ppcoin: send alert. // There is a known deadlock situation with ThreadMessageHandler // ThreadMessageHandler: holds cs_vSend and acquiring cs_main in SendMessages() diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index 40612f8b..1edf7655 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -14,10 +14,6 @@ #include "ringsig.h" #include "txdb.h" -#ifdef USE_NATIVE_I2P -#include "i2p.h" -#endif - #include #include #include @@ -113,7 +109,6 @@ Value getinfo(const Array& params, bool fHelp) obj.push_back(Pair("moneysupply", ValueFromAmount(pindexBest->nMoneySupply))); obj.push_back(Pair("connections", (int)vNodes.size())); obj.push_back(Pair("proxy", (proxy.first.IsValid() ? proxy.first.ToStringIPPort() : string()))); -#ifdef USE_NATIVETOR if(fNativeTor) { string automatic_onion; @@ -127,18 +122,7 @@ Value getinfo(const Array& params, bool fHelp) file >> automatic_onion; obj.push_back(Pair("tor", (automatic_onion))); } -#endif -#ifdef USE_NATIVE_I2P - if (fNativeI2P) - { - if (IsI2POnly()) { - obj.push_back(Pair("onlynet", ("native_i2p"))); - } - std::string i2p_address = I2PSession::GenerateB32AddressFromDestination(addrSeenByPeer.GetI2PDestination()); // Not the best way yet - obj.push_back(Pair("i2p", (i2p_address.c_str()))); - } -#endif - if(!fNativeTor && !fNativeI2P) + if(!fNativeTor) obj.push_back(Pair("ip", addrSeenByPeer.ToStringIP())); diff.push_back(Pair("proof-of-work", GetDifficulty())); @@ -146,14 +130,8 @@ Value getinfo(const Array& params, bool fHelp) obj.push_back(Pair("difficulty", diff)); obj.push_back(Pair("testnet", fTestNet)); - obj.push_back(Pair("fortunastake", fFortunaStake)); - obj.push_back(Pair("fslock", fFSLock)); -#ifdef USE_NATIVETOR + obj.push_back(Pair("fortunastake", fFortunaStake)); obj.push_back(Pair("nativetor", fNativeTor)); -#endif -#ifdef USE_NATIVE_I2P - obj.push_back(Pair("nativei2p", fNativeI2P)); -#endif obj.push_back(Pair("keypoololdest", (int64_t)pwalletMain->GetOldestKeyPoolTime())); obj.push_back(Pair("keypoolsize", (int)pwalletMain->GetKeyPoolSize())); obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee))); diff --git a/src/serialize.h b/src/serialize.h index 0d4b093a..a11afd5b 100644 --- a/src/serialize.h +++ b/src/serialize.h @@ -46,7 +46,7 @@ inline T* NCONST_PTR(const T* val) return const_cast(val); } -/** +/** * Get begin pointer of vector (non-const version). * @note These functions avoid the undefined case of indexing into an empty * vector, as well as that of indexing after the end of the vector. @@ -92,9 +92,6 @@ enum // modifiers SER_SKIPSIG = (1 << 16), SER_BLOCKHEADERONLY = (1 << 17), -#ifdef USE_NATIVE_I2P - SER_IPADDRONLY = (1 << 18), -#endif }; #define IMPLEMENT_SERIALIZE(statements) \ @@ -139,11 +136,11 @@ enum #define READWRITES(obj) (::SerReadWrite(s, (obj), nType, nVersion, ser_action)) -/** +/** * Implement three methods for serializable objects. These are actually wrappers over * "SerializationOp" template, which implements the body of each class' serialization * code. Adding "ADD_SERIALIZE_METHODS" in the body of the class causes these wrappers to be - * added as members. + * added as members. */ #define ADD_SERIALIZE_METHODS \ size_t GetSerializeSize(int nType, int nVersion) const { \ diff --git a/src/ui_interface.h b/src/ui_interface.h index 5e5ac1eb..e6e61980 100644 --- a/src/ui_interface.h +++ b/src/ui_interface.h @@ -96,11 +96,6 @@ class CClientUIInterface * @note called with lock cs_mapAlerts held. */ boost::signals2::signal NotifyAlertChanged; -#ifdef USE_NATIVE_I2P - boost::signals2::signal ThreadSafeShowGeneratedI2PAddress; - - boost::signals2::signal NotifyNumI2PConnectionsChanged; -#endif }; extern CClientUIInterface uiInterface; diff --git a/src/util.cpp b/src/util.cpp index b87de936..4eda8889 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -92,8 +92,6 @@ bool fCommandLine = false; string strMiscWarning; bool fTestNet = false; bool fNativeTor = false; -bool fNativeI2P = false; -bool fFSLock = false; bool fNoListen = false; bool fLogTimestamps = false; CMedianFilter vTimeOffsets(200,0); @@ -1322,7 +1320,7 @@ boost::filesystem::path GetConfigFile() boost::filesystem::path GetFortunastakeConfigFile() { - boost::filesystem::path pathConfigFile(GetArg("-fsconf", "fortunastake.conf")); + boost::filesystem::path pathConfigFile(GetArg("-mnconf", "fortunastake.conf")); if (!pathConfigFile.is_complete()) pathConfigFile = GetDataDir(false) / pathConfigFile; return pathConfigFile; } @@ -1544,13 +1542,6 @@ string FormatFullVersion() return CLIENT_BUILD; } -#ifdef USE_NATIVE_I2P -std::string FormatI2PNativeFullVersion() -{ - return; //return I2P_NATIVE_BUILD; -} -#endif - // Format the subversion field according to BIP 14 spec (https://en.bitcoin.it/wiki/BIP_0014) std::string FormatSubVersion(const std::string& name, int nClientVersion, const std::vector& comments) { diff --git a/src/util.h b/src/util.h index b33e200e..19698ea9 100644 --- a/src/util.h +++ b/src/util.h @@ -220,8 +220,6 @@ extern bool fCommandLine; extern std::string strMiscWarning; extern bool fTestNet; extern bool fNativeTor; -extern bool fNativeI2P; -extern bool fFSLock; extern bool fNoListen; extern bool fLogTimestamps; extern bool fReopenDebugLog; @@ -304,9 +302,7 @@ std::string FormatSubVersion(const std::string& name, int nClientVersion, const void AddTimeData(const CNetAddr& ip, int64_t nTime); void runCommand(std::string strCommand); -#ifdef USE_NATIVE_I2P -std::string FormatI2PNativeFullVersion(); -#endif + diff --git a/src/version.cpp b/src/version.cpp index 9ceb5585..3f2c0c09 100644 --- a/src/version.cpp +++ b/src/version.cpp @@ -33,7 +33,7 @@ const std::string CLIENT_NAME("Denarii"); # include "build.h" #endif -// git will put "#define GIT_ARCHIVE 1" on the next line inside archives. +// git will put "#define GIT_ARCHIVE 1" on the next line inside archives. #define GIT_ARCHIVE 0 #ifdef GIT_ARCHIVE # define GIT_COMMIT_ID "" diff --git a/src/wallet.cpp b/src/wallet.cpp index 295d419f..a7909f5a 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -1122,6 +1122,78 @@ void CWalletTx::GetAmounts(list& listReceived, if (fIsMine) listReceived.push_back(output); }; + + /* + // Sent/received. + BOOST_FOREACH(const CTxOut& txout, vout) + { + // Skip special stake out + if (txout.scriptPubKey.empty()) + continue; + + opcodetype firstOpCode; + CScript::const_iterator pc = txout.scriptPubKey.begin(); + if (txout.scriptPubKey.GetOp(pc, firstOpCode) + && firstOpCode == OP_RETURN) + continue; + + + bool fIsMine; + // Only need to handle txouts if AT LEAST one of these is true: + // 1) they debit from us (sent) + // 2) the output is to us (received) + if (nDebit > 0) + { + // Don't report 'change' txouts + if (pwallet->IsChange(txout)) + continue; + fIsMine = pwallet->IsMine(txout); + } + else if (!(fIsMine = pwallet->IsMine(txout))) + continue; + + + + // Sent/received. + for (unsigned int i = 0; i < vout.size(); ++i) + { + const CTxOut& txout = vout[i]; + if (nVersion == ANON_TXN_VERSION + && txout.IsAnonOutput()) + continue; + isminetype fIsMine = pwallet->IsMine(txout); + // Only need to handle txouts if AT LEAST one of these is true: + // 1) they debit from us (sent) + // 2) the output is to us (received) + if (nDebit > 0) + { + // Don't report 'change' txouts + if (pwallet->IsChange(txout)) + continue; + } + else if (!(fIsMine & filter)) + continue; + + // In either case, we need to get the destination address + CTxDestination address; + if (!ExtractDestination(txout.scriptPubKey, address)) + { + printf("CWalletTx::GetAmounts: Unknown transaction type found, txid %s\n", + this->GetHash().ToString().c_str()); + address = CNoDestination(); + } + + COutputEntry output = {address, txout.nValue, (int)i}; + + // If we are debited by the transaction, add the output as a "sent" entry + if (nDebit > 0) + listSent.push_back(output); + + // If we are receiving the output, add it as a "received" entry + if (fIsMine & filter) + listReceived.push_back(output); + } + */ } void CWalletTx::GetAccountAmounts(const string& strAccount, int64_t& nReceived, @@ -3335,6 +3407,9 @@ bool CWallet::FindStealthTransactions(const CTransaction& tx, mapValue_t& mapNar return true; }; + + + // NovaCoin: get current stake weight bool CWallet::GetStakeWeight(const CKeyStore& keystore, uint64_t& nMinWeight, uint64_t& nMaxWeight, uint64_t& nWeight) { @@ -6941,6 +7016,46 @@ bool CWallet::ExpandLockedAnonOutput(CWalletDB *pwdb, CKeyID &ckeyId, CLockedAno return error("%s: StealthSecretSpend() failed.", __func__); }; + /* + // - check ext account stealth keys + ExtKeyAccountMap::const_iterator mi; + if (!fFound) + for (mi = mapExtAccounts.begin(); mi != mapExtAccounts.end(); ++mi) + { + fFound = true; + + CExtKeyAccount *ea = mi->second; + + CKeyID sxId = lao.pkScan.GetID(); + + AccStealthKeyMap::const_iterator miSk = ea->mapStealthKeys.find(sxId); + if (miSk == ea->mapStealthKeys.end()) + continue; + + const CEKAStealthKey &aks = miSk->second; + if (ea->IsLocked(aks)) + return error("%s: Stealth is locked.", __func__); + + ec_point pkExtracted; + ec_secret sShared; + + pkEphem.resize(lao.pkEphem.size()); + memcpy(&pkEphem[0], lao.pkEphem.begin(), lao.pkEphem.size()); + memcpy(&sScan.e[0], aks.skScan.begin(), EC_SECRET_SIZE); + + // - need sShared to extract key + if (StealthSecret(sScan, pkEphem, aks.pkSpend, sShared, pkExtracted) != 0) + return error("%s: StealthSecret() failed.", __func__); + + CKey kChild; + + if (0 != ea->ExpandStealthChildKey(&aks, sShared, kChild)) + return error("%s: ExpandStealthChildKey() failed %s.", __func__, aks.ToStealthAddress().c_str()); + + memcpy(&sSpendR.e[0], kChild.begin(), EC_SECRET_SIZE); + }; + */ + if (!fFound) return error("%s: No stealth key found.", __func__); From f73b1f497f77a2a3eae44922d9b7f42719b3ba9d Mon Sep 17 00:00:00 2001 From: carsenk Date: Fri, 16 Aug 2019 16:14:49 -0600 Subject: [PATCH 22/26] Fix segfault upon launch --- src/util.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util.cpp b/src/util.cpp index 4eda8889..d0a19de8 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -1334,7 +1334,7 @@ void ReadConfigFile(map& mapSettingsRet, FILE* configFile = fopen(GetConfigFile().string().c_str(), "a"); if (configFile != NULL) { WriteConfigFile(configFile); - fclose(configFile); + //fclose(configFile); printf("WriteConfigFile() Denarius.conf Setup Successfully!"); ReadConfigFile(mapSettingsRet, mapMultiSettingsRet); } else { From 509f4badb358f423e7dec5aada94c6eace14737c Mon Sep 17 00:00:00 2001 From: carsenk Date: Sun, 18 Aug 2019 14:36:28 -0600 Subject: [PATCH 23/26] Added ping, addnode ban, getnetworkinfo, and other rpc commands --- src/bitcoinrpc.cpp | 4 + src/bitcoinrpc.h | 8 ++ src/net.cpp | 51 +++++++--- src/net.h | 15 +++ src/rpcnet.cpp | 233 ++++++++++++++++++++++++++++++++++++++++++++- 5 files changed, 295 insertions(+), 16 deletions(-) diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp index fbbf2367..ef9ebbaa 100644 --- a/src/bitcoinrpc.cpp +++ b/src/bitcoinrpc.cpp @@ -265,6 +265,10 @@ static const CRPCCommand vRPCCommands[] = { "getblockcount", &getblockcount, true, false }, { "getconnectioncount", &getconnectioncount, true, false }, { "getpeerinfo", &getpeerinfo, true, false }, + { "getaddednodeinfo", &getaddednodeinfo, true, true }, + { "ping", &ping, true, true }, + { "getnettotals", &getnettotals, true, false }, + { "getnetworkinfo", &getnetworkinfo, true, false }, { "gethashespersec", &gethashespersec, true, false }, { "addnode", &addnode, true, true }, { "dumpbootstrap", &dumpbootstrap, false, false }, diff --git a/src/bitcoinrpc.h b/src/bitcoinrpc.h index 7a2f4a5d..cd708902 100644 --- a/src/bitcoinrpc.h +++ b/src/bitcoinrpc.h @@ -50,10 +50,13 @@ enum RPCErrorCode RPC_INVALID_PARAMETER = -8, // Invalid, missing or duplicate parameter RPC_DATABASE_ERROR = -20, // Database error RPC_DESERIALIZATION_ERROR = -22, // Error parsing or validating structure in raw format + RPC_SERVER_NOT_STARTED = -18, // RPC server was not started (StartRPCThreads() not called) // P2P client errors RPC_CLIENT_NOT_CONNECTED = -9, // Bitcoin is not connected RPC_CLIENT_IN_INITIAL_DOWNLOAD = -10, // Still downloading initial blocks + RPC_CLIENT_NODE_ALREADY_ADDED = -23, // Node is already added + RPC_CLIENT_NODE_NOT_ADDED = -24, // Node has not been added before // Wallet errors RPC_WALLET_ERROR = -4, // Unspecified problem with wallet (key not found etc.) @@ -152,6 +155,11 @@ extern std::vector ParseHexO(const json_spirit::Object& o, std::s extern json_spirit::Value getconnectioncount(const json_spirit::Array& params, bool fHelp); // in rpcnet.cpp extern json_spirit::Value getpeerinfo(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value addnode(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value ping(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value getaddednodeinfo(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value getnettotals(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value getnetworkinfo(const json_spirit::Array& params, bool fHelp); + extern json_spirit::Value dumpwallet(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value importwallet(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value dumpprivkey(const json_spirit::Array& params, bool fHelp); // in rpcdump.cpp diff --git a/src/net.cpp b/src/net.cpp index e7ba6040..614ea0da 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -47,19 +47,14 @@ void ThreadDNSAddressSeed2(void* parg); bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound = NULL, const char *strDest = NULL, bool fOneShot = false); -struct LocalServiceInfo { - int nScore; - int nPort; -}; - // // Global state variables // bool fDiscover = true; bool fUseUPnP = false; uint64_t nLocalServices = NODE_NETWORK; -static CCriticalSection cs_mapLocalHost; -static map mapLocalHost; +CCriticalSection cs_mapLocalHost; +map mapLocalHost; static bool vfReachable[NET_MAX] = {}; static bool vfLimited[NET_MAX] = {}; static CNode* pnodeLocalHost = NULL; @@ -471,7 +466,7 @@ CNode* FindNode(const CNetAddr& ip) return NULL; } -CNode* FindNode(std::string addrName) +CNode* FindNode(const std::string& addrName) { LOCK(cs_vNodes); BOOST_FOREACH(CNode* pnode, vNodes) @@ -565,7 +560,7 @@ void CNode::CloseSocketDisconnect() fDisconnect = true; if (hSocket != INVALID_SOCKET) { - printf("disconnecting node %s\n", addrName.c_str()); + printf("Net() Disconnecting node %s\n", addrName.c_str()); closesocket(hSocket); hSocket = INVALID_SOCKET; @@ -621,6 +616,35 @@ bool CNode::IsBanned(CNetAddr ip) return fResult; } +bool CNode::Ban(const CNetAddr &addr) { + int64_t banTime = GetTime()+GetArg("-bantime", 60*60*24); // Default 24-hour ban + { + LOCK(cs_setBanned); + if (setBanned[addr] < banTime) + setBanned[addr] = banTime; + } + return true; +} + +//Whitelisted peers/nodes +//std::vector CNode::vWhitelistedRange; +//CCriticalSection CNode::cs_vWhitelistedRange; +/* +bool CNode::IsWhitelistedRange(const CNetAddr &addr) { + LOCK(cs_vWhitelistedRange); + BOOST_FOREACH(const CSubNet& subnet, vWhitelistedRange) { + if (subnet.Match(addr)) + return true; + } + return false; +} + +void CNode::AddWhitelistedRange(const CSubNet &subnet) { + LOCK(cs_vWhitelistedRange); + vWhitelistedRange.push_back(subnet); +} + */ + bool CNode::Misbehaving(int howmuch) { if (addr.IsLocal()) @@ -663,6 +687,7 @@ void CNode::copyStats(CNodeStats &stats) X(fInbound); X(nStartingHeight); X(nMisbehavior); + //X(fWhitelisted); // It is common for nodes with good ping times to suddenly become lagged, // due to a new block arriving or other large transfer. @@ -1785,12 +1810,12 @@ bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOu // if (fShutdown) return false; - if (!strDest) + if (!strDest) { if (IsLocal(addrConnect) || - FindNode((CNetAddr)addrConnect) || CNode::IsBanned(addrConnect) || - FindNode(addrConnect.ToStringIPPort().c_str())) + FindNode((CNetAddr) addrConnect) || CNode::IsBanned(addrConnect) || + FindNode(addrConnect.ToStringIPPort())) return false; - if (strDest && FindNode(strDest)) + } else if (FindNode(strDest)) return false; vnThreadsRunning[THREAD_OPENCONNECTIONS]--; diff --git a/src/net.h b/src/net.h index 572a1902..71b7f827 100644 --- a/src/net.h +++ b/src/net.h @@ -39,6 +39,7 @@ bool RecvLine(SOCKET hSocket, std::string& strLine); bool GetMyExternalIP(CNetAddr& ipRet); void AddressCurrentlyConnected(const CService& addr); CNode* FindNode(const CNetAddr& ip); +CNode* FindNode(const std::string& addrName); CNode* FindNode(const CService& ip); //CNode* ConnectNode(CAddress addrConnect, const char *strDest = NULL); CNode* ConnectNode(CAddress addrConnect, const char *strDest = NULL, bool forTunaMaster=false); @@ -157,6 +158,13 @@ extern std::map mapAlreadyAskedFor; extern NodeId nLastNodeId; extern CCriticalSection cs_nLastNodeId; +struct LocalServiceInfo { + int nScore; + int nPort; +}; + +extern CCriticalSection cs_mapLocalHost; +extern std::map mapLocalHost; class CNodeStateStats { @@ -291,6 +299,7 @@ class CNode CService addrLocal; int nVersion; std::string strSubVer; + //bool fWhitelisted; // This peer can bypass DoS banning. bool fOneShot; bool fClient; bool fInbound; @@ -314,6 +323,11 @@ class CNode static std::map setBanned; static CCriticalSection cs_setBanned; + // Whitelisted ranges. Any node connecting from these is automatically + // whitelisted (as well as those connecting to whitelisted binds). + //static std::vector vWhitelistedRange; + //static CCriticalSection cs_vWhitelistedRange; + std::vector vecRequestsFulfilled; //keep track of what client has asked for public: @@ -789,6 +803,7 @@ template& vstats) } } +Value ping(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 0) + throw runtime_error( + "ping\n" + "Requests that a ping be sent to all other nodes, to measure ping time.\n" + "Results provided in getpeerinfo, pingtime and pingwait fields are decimal seconds.\n" + "Ping command is handled in queue with all other commands, so it measures processing backlog, not just network ping."); + + // Request that each node send a ping during next message processing pass + LOCK(cs_vNodes); + BOOST_FOREACH(CNode* pNode, vNodes) { + pNode->fPingQueued = true; + } + + return Value::null; +} + Value getpeerinfo(const Array& params, bool fHelp) { if (fHelp || params.size() != 0) @@ -52,10 +70,15 @@ Value getpeerinfo(const Array& params, bool fHelp) Object obj; obj.push_back(Pair("addr", stats.addrName)); + if (!(stats.addrLocal.empty())) + obj.push_back(Pair("addrlocal", stats.addrLocal)); obj.push_back(Pair("services", strprintf("%08" PRIx64, stats.nServices))); obj.push_back(Pair("lastsend", (int64_t)stats.nLastSend)); obj.push_back(Pair("lastrecv", (int64_t)stats.nLastRecv)); obj.push_back(Pair("conntime", (int64_t)stats.nTimeConnected)); + obj.push_back(Pair("pingtime", stats.dPingTime)); //return nodes ping time + if (stats.dPingWait > 0.0) + obj.push_back(Pair("pingwait", stats.dPingWait)); obj.push_back(Pair("version", stats.nVersion)); obj.push_back(Pair("subver", stats.strSubVer)); obj.push_back(Pair("inbound", stats.fInbound)); @@ -74,10 +97,10 @@ Value addnode(const Array& params, bool fHelp) if (params.size() == 2) strCommand = params[1].get_str(); if (fHelp || params.size() != 2 || - (strCommand != "onetry" && strCommand != "add" && strCommand != "remove")) + (strCommand != "onetry" && strCommand != "add" && strCommand != "remove" && strCommand != "ban")) throw runtime_error( - "addnode \n" - "Attempts add or remove from the addnode list or try a connection to once."); + "addnode \n" + "Attempts add or remove from the addnode list or try a connection to once, 'ban' to ban connected node\n"); string strNode = params[0].get_str(); @@ -87,6 +110,17 @@ Value addnode(const Array& params, bool fHelp) ConnectNode(addr, strNode.c_str()); return Value::null; } + else if(strCommand == "ban") + { + CNode* pnode = FindNode(strNode); + if(pnode) { + CNode::Ban(pnode->addr); + pnode->CloseSocketDisconnect(); + } else { + throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Error: Node is not connected."); + } + return Value::null; + } LOCK(cs_vAddedNodes); vector::iterator it = vAddedNodes.begin(); @@ -107,9 +141,202 @@ Value addnode(const Array& params, bool fHelp) vAddedNodes.erase(it); } + return Value::null; } +static Array GetNetworksInfo() +{ + Array networks; + for(int n=0; n(n); + if(network == NET_UNROUTABLE) + continue; + proxyType proxy; + Object obj; + GetProxy(network, proxy); + obj.push_back(Pair("name", GetNetworkName(network))); + obj.push_back(Pair("limited", IsLimited(network))); + //obj.push_back(Pair("reachable", IsReachable(network))); + //obj.push_back(Pair("proxy", proxy.IsValid() ? proxy.ToStringIPPort() : string())); + networks.push_back(obj); + } + return networks; +} + +static const string SingleAlertSubVersionsString( const std::set& setVersions ) +{ + std::string strSetSubVer; + BOOST_FOREACH(std::string str, setVersions) { + if(strSetSubVer.size()) // Must be more than one + strSetSubVer += " or "; + strSetSubVer += str; + } + return strSetSubVer; +} + +Value getnetworkinfo(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 0) + throw runtime_error( + "getnetworkinfo\n" + " Returns an object containing various state info regarding P2P networking.\n" + "\nResult:\n" + "{\n" + " \"version\": xxxxx, (numeric) the server version\n" + " \"subver\": \"/s:n.n.n.n/\", (string) this clients subversion string\n" + " \"protocolversion\": xxxxx, (numeric) the protocol version\n" + " \"localservices\": \"xxxx\", (hex string) Our local service bits as a 16 char string.\n" + " \"timeoffset\": xxxxx, (numeric) the time offset\n" + " \"connections\": xxxxx, (numeric) the number of connections\n" + " \"networkconnections\": [ (array) the state of each possible network connection type\n" + " \"name\": \"xxx\", (string) network name\n" + " \"limited\" : true|false, (boolean) if service is limited\n" + " ]\n" + " \"localaddresses\": [ (array) list of local addresses\n" + " \"address\": \"xxxx\", (string) network address\n" + " \"port\": xxx, (numeric) network port\n" + " \"score\": xxx (numeric) relative score\n" + " ]\n" + "}\n" + ); + + LOCK(cs_main); + + Object obj; + obj.push_back(Pair("version", (int)CLIENT_VERSION)); + obj.push_back(Pair("subversion", FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector()))); + obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION)); + obj.push_back(Pair("localservices", strprintf("%016", PRIx64, nLocalServices))); + obj.push_back(Pair("timeoffset", GetTimeOffset())); + obj.push_back(Pair("connections", (int)vNodes.size())); + //obj.push_back(Pair("relayfee", ValueFromAmount(minRelayTxFee.GetFeePerK()))); + obj.push_back(Pair("networkconnections",GetNetworksInfo())); + Array localAddresses; + { + LOCK(cs_mapLocalHost); + BOOST_FOREACH(const PAIRTYPE(CNetAddr, LocalServiceInfo) &item, mapLocalHost) + { + Object rec; + rec.push_back(Pair("address", item.first.ToString())); + rec.push_back(Pair("port", item.second.nPort)); + rec.push_back(Pair("score", item.second.nScore)); + localAddresses.push_back(rec); + } + } + obj.push_back(Pair("localaddresses", localAddresses)); + + return obj; +} + +Value getaddednodeinfo(const Array& params, bool fHelp) +{ + if (fHelp || params.size() < 1 || params.size() > 2) + throw runtime_error( + "getaddednodeinfo [node]\n" + "Returns information about the given added node, or all added nodes\n" + "(note that onetry addnodes are not listed here)\n" + "If dns is false, only a list of added nodes will be provided,\n" + "otherwise connected information will also be available."); + + bool fDns = params[0].get_bool(); + + list laddedNodes(0); + if (params.size() == 1) + { + LOCK(cs_vAddedNodes); + BOOST_FOREACH(string& strAddNode, vAddedNodes) + laddedNodes.push_back(strAddNode); + } + else + { + string strNode = params[1].get_str(); + LOCK(cs_vAddedNodes); + BOOST_FOREACH(string& strAddNode, vAddedNodes) + if (strAddNode == strNode) + { + laddedNodes.push_back(strAddNode); + break; + } + if (laddedNodes.size() == 0) + throw JSONRPCError(RPC_CLIENT_NODE_NOT_ADDED, "Error: Node has not been added."); + } + + if (!fDns) + { + Object ret; + BOOST_FOREACH(string& strAddNode, laddedNodes) + ret.push_back(Pair("addednode", strAddNode)); + return ret; + } + + Array ret; + + list > > laddedAddreses(0); + BOOST_FOREACH(string& strAddNode, laddedNodes) + { + vector vservNode(0); + if(Lookup(strAddNode.c_str(), vservNode, GetDefaultPort(), fNameLookup, 0)) + laddedAddreses.push_back(make_pair(strAddNode, vservNode)); + else + { + Object obj; + obj.push_back(Pair("addednode", strAddNode)); + obj.push_back(Pair("connected", false)); + Array addresses; + obj.push_back(Pair("addresses", addresses)); + } + } + + LOCK(cs_vNodes); + for (list > >::iterator it = laddedAddreses.begin(); it != laddedAddreses.end(); it++) + { + Object obj; + obj.push_back(Pair("addednode", it->first)); + + Array addresses; + bool fConnected = false; + BOOST_FOREACH(CService& addrNode, it->second) + { + bool fFound = false; + Object node; + node.push_back(Pair("address", addrNode.ToString())); + BOOST_FOREACH(CNode* pnode, vNodes) + if (pnode->addr == addrNode) + { + fFound = true; + fConnected = true; + node.push_back(Pair("connected", pnode->fInbound ? "inbound" : "outbound")); + break; + } + if (!fFound) + node.push_back(Pair("connected", "false")); + addresses.push_back(node); + } + obj.push_back(Pair("connected", fConnected)); + obj.push_back(Pair("addresses", addresses)); + ret.push_back(obj); + } + + return ret; +} + +Value getnettotals(const Array& params, bool fHelp) +{ + if (fHelp || params.size() > 0) + throw runtime_error( + "getnettotals\n" + "Returns information about network traffic, including bytes in, bytes out,\n" + "and current time."); + + Object obj; + obj.push_back(Pair("totalbytesrecv", CNode::GetTotalBytesRecv())); + obj.push_back(Pair("totalbytessent", CNode::GetTotalBytesSent())); + obj.push_back(Pair("timemillis", GetTimeMillis())); + return obj; +} + Value setdebug(const Array& params, bool fHelp) { string strType; From c5209c9976675b24f1ac7743666833d056c39c67 Mon Sep 17 00:00:00 2001 From: carsenk Date: Sun, 18 Aug 2019 18:08:45 -0600 Subject: [PATCH 24/26] Added disconnectnode rpc command --- src/bitcoinrpc.cpp | 1 + src/bitcoinrpc.h | 2 ++ src/rpcnet.cpp | 21 +++++++++++++++++++++ src/util.cpp | 12 ++++++------ 4 files changed, 30 insertions(+), 6 deletions(-) diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp index ef9ebbaa..bc28f7b9 100644 --- a/src/bitcoinrpc.cpp +++ b/src/bitcoinrpc.cpp @@ -268,6 +268,7 @@ static const CRPCCommand vRPCCommands[] = { "getaddednodeinfo", &getaddednodeinfo, true, true }, { "ping", &ping, true, true }, { "getnettotals", &getnettotals, true, false }, + { "disconnectnode", &disconnectnode, true, false }, { "getnetworkinfo", &getnetworkinfo, true, false }, { "gethashespersec", &gethashespersec, true, false }, { "addnode", &addnode, true, true }, diff --git a/src/bitcoinrpc.h b/src/bitcoinrpc.h index cd708902..1a9a8d61 100644 --- a/src/bitcoinrpc.h +++ b/src/bitcoinrpc.h @@ -57,6 +57,7 @@ enum RPCErrorCode RPC_CLIENT_IN_INITIAL_DOWNLOAD = -10, // Still downloading initial blocks RPC_CLIENT_NODE_ALREADY_ADDED = -23, // Node is already added RPC_CLIENT_NODE_NOT_ADDED = -24, // Node has not been added before + RPC_CLIENT_NODE_NOT_CONNECTED = -29, // Node to disconnect not found in connected nodes // Wallet errors RPC_WALLET_ERROR = -4, // Unspecified problem with wallet (key not found etc.) @@ -159,6 +160,7 @@ extern json_spirit::Value ping(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value getaddednodeinfo(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value getnettotals(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value getnetworkinfo(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value disconnectnode(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value dumpwallet(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value importwallet(const json_spirit::Array& params, bool fHelp); diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp index d5a684fd..1db61338 100644 --- a/src/rpcnet.cpp +++ b/src/rpcnet.cpp @@ -145,6 +145,27 @@ Value addnode(const Array& params, bool fHelp) return Value::null; } +Value disconnectnode(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 1) + throw runtime_error( + "disconnectnode \"node\" \n" + "\nImmediately disconnects from the specified node.\n" + "\nArguments:\n" + "1. \"node\" (string, required) The node (see getpeerinfo for nodes)\n" + ); + + string theNode = params[0].get_str(); + + CNode* pNode = FindNode(theNode); + if (pNode == NULL) + throw JSONRPCError(RPC_CLIENT_NODE_NOT_CONNECTED, "Node not found in connected nodes"); + + pNode->fDisconnect = true; + + return Value::null; +} + static Array GetNetworksInfo() { Array networks; diff --git a/src/util.cpp b/src/util.cpp index d0a19de8..763b250c 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -1178,12 +1178,12 @@ void WriteConfigFile(FILE* configFile) fputs ("daemon=1\n", configFile); fputs ("listen=1\n", configFile); fputs ("server=1\n", configFile); - fputs ("addnode=104.248.148.86:33369\n", configFile); - fputs ("addnode=124.183.249.162:33369\n", configFile); - fputs ("addnode=128.199.150.171:33369\n", configFile); - fputs ("addnode=148.122.187.2:33369\n", configFile); - fputs ("addnode=149.28.51.135:33369\n", configFile); - fputs ("addnode=168.62.175.85:33369\n", configFile); + fputs ("addnode=108.61.103.90\n", configFile); + fputs ("addnode=144.136.70.136\n", configFile); + fputs ("addnode=24.117.192.101\n", configFile); + fputs ("addnode=24.205.81.255\n", configFile); + fputs ("addnode=45.77.235.152\n", configFile); + fputs ("addnode=81.204.3.6\n", configFile); fputs ("addnode=173.255.132.121:33369\n", configFile); fputs ("addnode=185.153.46.15:333691\n", configFile); fputs ("addnode=217.122.154.194:33369\n", configFile); From 8612f1efbcce0f5ac2d721643bcb4aa8812398b7 Mon Sep 17 00:00:00 2001 From: The_Next_Guy Date: Tue, 20 Aug 2019 18:41:31 -0700 Subject: [PATCH 25/26] Added [rescan=true] arg to importprivkey --- src/rpcdump.cpp | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/rpcdump.cpp b/src/rpcdump.cpp index 08a7280f..bdd663f0 100644 --- a/src/rpcdump.cpp +++ b/src/rpcdump.cpp @@ -107,15 +107,18 @@ class CTxDump Value importprivkey(const Array& params, bool fHelp) { - if (fHelp || params.size() < 1 || params.size() > 2) + if (fHelp || params.size() < 1 || params.size() > 3) throw runtime_error( - "importprivkey [label]\n" + "importprivkey [label] [rescan=true]\n" "Adds a private key (as returned by dumpprivkey) to your wallet."); + bool fRescan = true; string strSecret = params[0].get_str(); string strLabel = ""; if (params.size() > 1) strLabel = params[1].get_str(); + if (params.size() > 2) + fRescan = params[2].get_bool(); CBitcoinSecret vchSecret; bool fGood = vchSecret.SetString(strSecret); @@ -141,11 +144,12 @@ Value importprivkey(const Array& params, bool fHelp) if (!pwalletMain->AddKey(key)) throw JSONRPCError(RPC_WALLET_ERROR, "Error adding key to wallet"); - // whenever a key is imported, we need to scan the whole chain - pwalletMain->nTimeFirstKey = 1; // 0 would be considered 'no value' - - pwalletMain->ScanForWalletTransactions(pindexGenesisBlock, true); - pwalletMain->ReacceptWalletTransactions(); + // if rescan is true, we need to scan the whole chain + if(fRescan){ + pwalletMain->nTimeFirstKey = 1; // 0 would be considered 'no value' + pwalletMain->ScanForWalletTransactions(pindexGenesisBlock, true); + pwalletMain->ReacceptWalletTransactions(); + } } return Value::null; @@ -372,4 +376,4 @@ Value dumpwallet(const Array& params, bool fHelp) file << "# End of dump\n"; file.close(); return Value::null; -} +} \ No newline at end of file From e52995767bb526b5acc2c0172a586967f298c030 Mon Sep 17 00:00:00 2001 From: carsenk Date: Sun, 25 Aug 2019 17:10:55 -0600 Subject: [PATCH 26/26] Mandatory Update Protocol 33900 --- src/fortuna.cpp | 4 +-- src/fortuna.h | 2 +- src/fortunastake.cpp | 2 +- src/main.cpp | 4 +-- src/net.cpp | 11 ++++++ src/net.h | 2 +- src/util.cpp | 81 ++------------------------------------------ src/version.h | 8 ++--- 8 files changed, 24 insertions(+), 90 deletions(-) diff --git a/src/fortuna.cpp b/src/fortuna.cpp index 5c12ec46..8b278141 100644 --- a/src/fortuna.cpp +++ b/src/fortuna.cpp @@ -40,12 +40,12 @@ CActiveFortunastake activeFortunastake; int RequestedFortunaStakeList = 0; //MIN_MN_PROTO_VERSION -int MIN_MN_PROTO_VERSION = 31005; // Since block 1.5m it is 31005 +int MIN_MN_PROTO_VERSION = 33900; // D v3.3.9.2 - Proto - 33900 /* *** BEGIN FORTUNA MAGIC ********** Copyright 2014, Darkcoin Developers eduffield - evan@darkcoin.io - Copyright 2018, Denarius Developers + Copyright 2018-2019, Denarius Developers carsenk - admin@denarius.io enkayz - enkayz@denarius.io */ diff --git a/src/fortuna.h b/src/fortuna.h index 90c24fd4..52b46374 100644 --- a/src/fortuna.h +++ b/src/fortuna.h @@ -224,7 +224,7 @@ class CFortunaSession class CForTunaPool { public: - static const int PROTOCOL_VERSION = 31005; //31005, D v3.3 + static const int PROTOCOL_VERSION = 33900; //33900, D v3.3.9.2 // clients entries std::vector myEntries; diff --git a/src/fortunastake.cpp b/src/fortunastake.cpp index 7eb07205..f9c53a35 100644 --- a/src/fortunastake.cpp +++ b/src/fortunastake.cpp @@ -131,7 +131,7 @@ void ProcessMessageFortunastake(CNode* pfrom, std::string& strCommand, CDataStre if((fTestNet && addr.GetPort() != 19999) || (!fTestNet && addr.GetPort() != 9999)) return; //search existing fortunastake list, this is where we update existing fortunastakes with new dsee broadcasts - LOCK(cs_fortunastakes); + LOCK(cs_fortunastakes); BOOST_FOREACH(CFortunaStake& mn, vecFortunastakes) { if(mn.vin.prevout == vin.prevout) { // count == -1 when it's a new entry diff --git a/src/main.cpp b/src/main.cpp index 4bc6fc63..d4ef26f5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2646,7 +2646,7 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex, bool fJustCheck) } else { if (fDebug) printf("CheckBlock-POS(): This fortunastake payment is too aggressive and will be accepted after block %d\n", MN_ENFORCEMENT_ACTIVE_HEIGHT); } - //break; No more breaking out of the checks + //break; } else { if (fDebug) printf("CheckBlock-POS() : Payment meets rate requirement: payee has earnt %s against average %s\n",FormatMoney(mn.payValue).c_str(),FormatMoney(nAverageFSIncome).c_str()); } @@ -3680,7 +3680,7 @@ bool ProcessBlock(CNode* pfrom, CBlock* pblock) //After block 1.5m, The Minimum FortunaStake Protocol Version is 31005 if(nBestHeight >= 1500000) { - MIN_MN_PROTO_VERSION = 31005; + MIN_MN_PROTO_VERSION = 33900; } // ppcoin: if responsible for sync-checkpoint send it diff --git a/src/net.cpp b/src/net.cpp index 614ea0da..56ce4f72 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1132,6 +1132,17 @@ void ThreadSocketHandler2(void* parg) pnode->CloseSocketDisconnect(); } } + else if (nBytes > 100000) // 100,000 Bytes + { + // error + int nErr = WSAGetLastError(); + if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS) + { + if (!pnode->fDisconnect) + printf("Closing socket, output too large %d\n", nErr); + pnode->CloseSocketDisconnect(); + } + } } } } diff --git a/src/net.h b/src/net.h index 71b7f827..fd4bb029 100644 --- a/src/net.h +++ b/src/net.h @@ -31,7 +31,7 @@ static const int PING_INTERVAL = 2 * 60; /** Time after which to disconnect, after waiting for a ping response (or inactivity). */ static const int TIMEOUT_INTERVAL = 20 * 60; -inline unsigned int ReceiveFloodSize() { return 1000*GetArg("-maxreceivebuffer", 5*1000); } +inline unsigned int ReceiveFloodSize() { return 1000*GetArg("-maxreceivebuffer", 1*1000); } inline unsigned int SendBufferSize() { return 1000*GetArg("-maxsendbuffer", 1*1000); } void AddOneShot(std::string strDest); diff --git a/src/util.cpp b/src/util.cpp index 763b250c..f10c25ca 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -1178,8 +1178,8 @@ void WriteConfigFile(FILE* configFile) fputs ("daemon=1\n", configFile); fputs ("listen=1\n", configFile); fputs ("server=1\n", configFile); - fputs ("addnode=108.61.103.90\n", configFile); - fputs ("addnode=144.136.70.136\n", configFile); + fputs ("addnode=149.28.51.135\n", configFile); //mining.cafe + fputs ("addnode=144.136.70.136\n", configFile); // Peers need updating after mandatory fputs ("addnode=24.117.192.101\n", configFile); fputs ("addnode=24.205.81.255\n", configFile); fputs ("addnode=45.77.235.152\n", configFile); @@ -1195,83 +1195,6 @@ void WriteConfigFile(FILE* configFile) fputs ("addnode=70.161.133.63:33369\n", configFile); fputs ("addnode=82.51.2.218:33369\n", configFile); fputs ("addnode=94.64.12.74:33369\n", configFile); - fputs ("addnode=100.38.242.115\n", configFile); - fputs ("addnode=104.156.255.101\n", configFile); - fputs ("addnode=104.238.162.100\n", configFile); - fputs ("addnode=104.248.41.59\n", configFile); - fputs ("addnode=109.134.82.155\n", configFile); - fputs ("addnode=123.211.68.126\n", configFile); - fputs ("addnode=124.191.151.106\n", configFile); - fputs ("addnode=137.59.252.143\n", configFile); - fputs ("addnode=139.162.38.211\n", configFile); - fputs ("addnode=139.99.195.240\n", configFile); - fputs ("addnode=144.136.70.136\n", configFile); - fputs ("addnode=155.138.133.72\n", configFile); - fputs ("addnode=159.69.149.169\n", configFile); - fputs ("addnode=163.172.216.135\n", configFile); - fputs ("addnode=167.86.103.39\n", configFile); - fputs ("addnode=173.212.200.54\n", configFile); - fputs ("addnode=173.212.203.31\n", configFile); - fputs ("addnode=173.212.233.87\n", configFile); - fputs ("addnode=173.244.200.118\n", configFile); - fputs ("addnode=179.108.185.4\n", configFile); - fputs ("addnode=184.82.239.220\n", configFile); - fputs ("addnode=185.153.46.151\n", configFile); - fputs ("addnode=192.64.24.117\n", configFile); - fputs ("addnode=198.144.158.68\n", configFile); - fputs ("addnode=207.148.116.109\n", configFile); - fputs ("addnode=207.148.86.124\n", configFile); - fputs ("addnode=209.250.240.123\n", configFile); - fputs ("addnode=212.237.18.237\n", configFile); - fputs ("addnode=217.104.40.146\n", configFile); - fputs ("addnode=24.159.177.122\n", configFile); - fputs ("addnode=24.20.163.158\n", configFile); - fputs ("addnode=24.243.68.87\n", configFile); - fputs ("addnode=37.97.136.239\n", configFile); - fputs ("addnode=45.32.111.0\n", configFile); - fputs ("addnode=45.32.238.209\n", configFile); - fputs ("addnode=46.164.32.192\n", configFile); - fputs ("addnode=46.45.35.61\n", configFile); - fputs ("addnode=46.45.38.100\n", configFile); - fputs ("addnode=5.79.133.86\n", configFile); - fputs ("addnode=54.39.50.173\n", configFile); - fputs ("addnode=58.84.91.117\n", configFile); - fputs ("addnode=61.73.245.43\n", configFile); - fputs ("addnode=67.167.13.102\n", configFile); - fputs ("addnode=71.104.62.144\n", configFile); - fputs ("addnode=71.76.176.17\n", configFile); - fputs ("addnode=72.76.16.71\n", configFile); - fputs ("addnode=73.111.172.144\n", configFile); - fputs ("addnode=73.163.144.109\n", configFile); - fputs ("addnode=75.67.45.138\n", configFile); - fputs ("addnode=75.84.146.213\n", configFile); - fputs ("addnode=75.9.150.108\n", configFile); - fputs ("addnode=76.10.217.138\n", configFile); - fputs ("addnode=76.113.60.252\n", configFile); - fputs ("addnode=76.115.234.254\n", configFile); - fputs ("addnode=78.45.117.19\n", configFile); - fputs ("addnode=78.46.46.38\n", configFile); - fputs ("addnode=79.216.91.125\n", configFile); - fputs ("addnode=8.40.180.108\n", configFile); - fputs ("addnode=80.211.103.62\n", configFile); - fputs ("addnode=80.211.141.205\n", configFile); - fputs ("addnode=80.211.7.186\n", configFile); - fputs ("addnode=82.1.110.30\n", configFile); - fputs ("addnode=84.205.5.160\n", configFile); - fputs ("addnode=84.236.48.53\n", configFile); - fputs ("addnode=85.156.168.35\n", configFile); - fputs ("addnode=85.214.152.190\n", configFile); - fputs ("addnode=85.214.204.133\n", configFile); - fputs ("addnode=88.198.38.83\n", configFile); - fputs ("addnode=92.42.12.212\n", configFile); - fputs ("addnode=93.82.23.12\n", configFile); - fputs ("addnode=95.90.222.253\n", configFile); - fputs ("addnode=96.38.188.5\n", configFile); - fputs ("addnode=96.43.143.42\n", configFile); - fputs ("addnode=98.116.221.45\n", configFile); - fputs ("addnode=98.116.47.234\n", configFile); - fputs ("addnode=98.163.65.122\n", configFile); - fputs ("addnode=98.202.247.195\n", configFile); fclose(configFile); ReadConfigFile(mapArgs, mapMultiArgs); } diff --git a/src/version.h b/src/version.h index 0eb274c0..4de8509d 100644 --- a/src/version.h +++ b/src/version.h @@ -30,20 +30,20 @@ static const int DATABASE_VERSION = 21212; // network protocol versioning // -static const int PROTOCOL_VERSION = 33500; //Protocol is now 33500 as of D v3.3.5 +static const int PROTOCOL_VERSION = 33900; //Protocol is now 33900 as of D v3.3.9.2 // intial proto version, to be increased after version/verack negotiation -static const int INIT_PROTO_VERSION = 21212; +static const int INIT_PROTO_VERSION = 33900; // Bumped up from 21212 to 33900 v3.3.9.2 // disconnect from peers older than this proto version -static const int MIN_PEER_PROTO_VERSION = 31005; +static const int MIN_PEER_PROTO_VERSION = 33900; // Don't forget to change proto in FORTUNA.h as well!! On Block 1.5m this will be 31005 extern int MIN_MN_PROTO_VERSION; // nTime field added to CAddress, starting with this version; // if possible, avoid requesting addresses nodes older than this -static const int CADDR_TIME_VERSION = 33500; // start sharing node timeinfo with this proto version 33500 +static const int CADDR_TIME_VERSION = 33900; // start sharing node timeinfo with this proto version 33500 // only request blocks from nodes outside this range of versions static const int NOBLKS_VERSION_START = 70002;