CryptoNoteWallet update
This commit is contained in:
parent
5a886fd7f4
commit
2ac125f28b
142
CMakeLists.txt
142
CMakeLists.txt
|
@ -14,8 +14,7 @@ include_directories(${CMAKE_BINARY_DIR}
|
||||||
src
|
src
|
||||||
cryptonote/external
|
cryptonote/external
|
||||||
cryptonote/include
|
cryptonote/include
|
||||||
cryptonote/src
|
cryptonote/src)
|
||||||
cryptonote/contrib/epee/include)
|
|
||||||
|
|
||||||
find_package(Qt5Gui REQUIRED)
|
find_package(Qt5Gui REQUIRED)
|
||||||
find_package(Qt5Widgets REQUIRED)
|
find_package(Qt5Widgets REQUIRED)
|
||||||
|
@ -44,9 +43,6 @@ add_definitions(-DGIT_REVISION=\"${GIT_REVISION}\")
|
||||||
set(CMAKE_AUTOMOC ON)
|
set(CMAKE_AUTOMOC ON)
|
||||||
|
|
||||||
set(CRYPTONOTE_SOURCES
|
set(CRYPTONOTE_SOURCES
|
||||||
cryptonote/contrib/epee/include/misc_log_ex.cpp
|
|
||||||
cryptonote/contrib/epee/include/misc_os_dependent.cpp
|
|
||||||
cryptonote/contrib/epee/include/string_tools.cpp
|
|
||||||
cryptonote/external/miniupnpc/connecthostport.c
|
cryptonote/external/miniupnpc/connecthostport.c
|
||||||
cryptonote/external/miniupnpc/igd_desc_parse.c
|
cryptonote/external/miniupnpc/igd_desc_parse.c
|
||||||
cryptonote/external/miniupnpc/minisoap.c
|
cryptonote/external/miniupnpc/minisoap.c
|
||||||
|
@ -57,9 +53,20 @@ set(CRYPTONOTE_SOURCES
|
||||||
cryptonote/external/miniupnpc/receivedata.c
|
cryptonote/external/miniupnpc/receivedata.c
|
||||||
cryptonote/external/miniupnpc/upnpcommands.c
|
cryptonote/external/miniupnpc/upnpcommands.c
|
||||||
cryptonote/external/miniupnpc/upnpreplyparse.c
|
cryptonote/external/miniupnpc/upnpreplyparse.c
|
||||||
cryptonote/src/common/base58.cpp
|
cryptonote/src/Common/Base58.cpp
|
||||||
cryptonote/src/common/command_line.cpp
|
cryptonote/src/Common/CommandLine.cpp
|
||||||
cryptonote/src/common/util.cpp
|
cryptonote/src/Common/Util.cpp
|
||||||
|
cryptonote/src/Common/StringTools.cpp
|
||||||
|
cryptonote/src/Common/JsonValue.cpp
|
||||||
|
cryptonote/src/Common/ConsoleTools.cpp
|
||||||
|
cryptonote/src/Common/MemoryInputStream.cpp
|
||||||
|
cryptonote/src/Common/PathTools.cpp
|
||||||
|
cryptonote/src/Common/StdInputStream.cpp
|
||||||
|
cryptonote/src/Common/StdOutputStream.cpp
|
||||||
|
cryptonote/src/Common/StreamTools.cpp
|
||||||
|
cryptonote/src/Common/StringOutputStream.cpp
|
||||||
|
cryptonote/src/Common/StringView.cpp
|
||||||
|
cryptonote/src/Common/VectorOutputStream.cpp
|
||||||
cryptonote/src/crypto/blake256.c
|
cryptonote/src/crypto/blake256.c
|
||||||
cryptonote/src/crypto/chacha8.c
|
cryptonote/src/crypto/chacha8.c
|
||||||
cryptonote/src/crypto/crypto-ops-data.c
|
cryptonote/src/crypto/crypto-ops-data.c
|
||||||
|
@ -79,44 +86,87 @@ set(CRYPTONOTE_SOURCES
|
||||||
cryptonote/src/crypto/slow-hash.c
|
cryptonote/src/crypto/slow-hash.c
|
||||||
cryptonote/src/crypto/slow-hash.cpp
|
cryptonote/src/crypto/slow-hash.cpp
|
||||||
cryptonote/src/crypto/tree-hash.c
|
cryptonote/src/crypto/tree-hash.c
|
||||||
cryptonote/src/cryptonote_core/BlockIndex.cpp
|
cryptonote/src/CryptoNoteCore/BlockchainIndices.cpp
|
||||||
cryptonote/src/cryptonote_core/CoreConfig.cpp
|
cryptonote/src/CryptoNoteCore/BlockchainMessages.cpp
|
||||||
cryptonote/src/cryptonote_core/Currency.cpp
|
cryptonote/src/CryptoNoteCore/BlockIndex.cpp
|
||||||
cryptonote/src/cryptonote_core/MinerConfig.cpp
|
cryptonote/src/CryptoNoteCore/CoreConfig.cpp
|
||||||
cryptonote/src/cryptonote_core/Transaction.cpp
|
cryptonote/src/CryptoNoteCore/CryptoNoteBasic.cpp
|
||||||
cryptonote/src/cryptonote_core/account.cpp
|
cryptonote/src/CryptoNoteCore/CryptoNoteTools.cpp
|
||||||
cryptonote/src/cryptonote_core/blockchain_storage.cpp
|
cryptonote/src/CryptoNoteCore/Currency.cpp
|
||||||
cryptonote/src/cryptonote_core/checkpoints.cpp
|
cryptonote/src/CryptoNoteCore/MinerConfig.cpp
|
||||||
cryptonote/src/cryptonote_core/cryptonote_basic_impl.cpp
|
cryptonote/src/CryptoNoteCore/Transaction.cpp
|
||||||
cryptonote/src/cryptonote_core/cryptonote_core.cpp
|
cryptonote/src/CryptoNoteCore/Account.cpp
|
||||||
cryptonote/src/cryptonote_core/cryptonote_format_utils.cpp
|
cryptonote/src/CryptoNoteCore/Blockchain.cpp
|
||||||
cryptonote/src/cryptonote_core/cryptonote_serialization.cpp
|
cryptonote/src/CryptoNoteCore/Checkpoints.cpp
|
||||||
cryptonote/src/cryptonote_core/difficulty.cpp
|
cryptonote/src/CryptoNoteCore/CryptoNoteBasicImpl.cpp
|
||||||
cryptonote/src/cryptonote_core/miner.cpp
|
cryptonote/src/CryptoNoteCore/Core.cpp
|
||||||
cryptonote/src/cryptonote_core/tx_pool.cpp
|
cryptonote/src/CryptoNoteCore/CryptoNoteFormatUtils.cpp
|
||||||
cryptonote/src/inprocess_node/InProcessNode.cpp
|
cryptonote/src/CryptoNoteCore/CryptoNoteSerialization.cpp
|
||||||
cryptonote/src/inprocess_node/InProcessNodeErrors.cpp
|
cryptonote/src/CryptoNoteCore/Difficulty.cpp
|
||||||
cryptonote/src/node_rpc_proxy/NodeErrors.cpp
|
cryptonote/src/CryptoNoteCore/IBlock.cpp
|
||||||
cryptonote/src/node_rpc_proxy/NodeRpcProxy.cpp
|
cryptonote/src/CryptoNoteCore/Miner.cpp
|
||||||
cryptonote/src/p2p/NetNodeConfig.cpp
|
cryptonote/src/CryptoNoteCore/TransactionExtra.cpp
|
||||||
cryptonote/src/serialization/BinaryInputStreamSerializer.cpp
|
cryptonote/src/CryptoNoteCore/TransactionPool.cpp
|
||||||
cryptonote/src/serialization/BinaryOutputStreamSerializer.cpp
|
cryptonote/src/CryptoNoteCore/TransactionPrefixImpl.cpp
|
||||||
cryptonote/src/transfers/BlockchainSynchronizer.cpp
|
cryptonote/src/CryptoNoteCore/TransactionUtils.cpp
|
||||||
cryptonote/src/transfers/SynchronizationState.cpp
|
cryptonote/src/InProcessNode/InProcessNode.cpp
|
||||||
cryptonote/src/transfers/TransfersConsumer.cpp
|
cryptonote/src/InProcessNode/InProcessNodeErrors.cpp
|
||||||
cryptonote/src/transfers/TransfersContainer.cpp
|
cryptonote/src/NodeRpcProxy/NodeErrors.cpp
|
||||||
cryptonote/src/transfers/TransfersSubscription.cpp
|
cryptonote/src/NodeRpcProxy/NodeRpcProxy.cpp
|
||||||
cryptonote/src/transfers/TransfersSynchronizer.cpp
|
cryptonote/src/P2p/NetNodeConfig.cpp
|
||||||
cryptonote/src/wallet/KeysStorage.cpp
|
cryptonote/src/Serialization/BinaryInputStreamSerializer.cpp
|
||||||
cryptonote/src/wallet/Wallet.cpp
|
cryptonote/src/Serialization/BinaryOutputStreamSerializer.cpp
|
||||||
cryptonote/src/wallet/WalletAsyncContextCounter.cpp
|
cryptonote/src/Serialization/JsonInputValueSerializer.cpp
|
||||||
cryptonote/src/wallet/WalletErrors.cpp
|
cryptonote/src/Serialization/JsonOutputStreamSerializer.cpp
|
||||||
cryptonote/src/wallet/WalletSerializer.cpp
|
cryptonote/src/Serialization/KVBinaryInputStreamSerializer.cpp
|
||||||
cryptonote/src/wallet/WalletSerialization.cpp
|
cryptonote/src/Serialization/KVBinaryOutputStreamSerializer.cpp
|
||||||
cryptonote/src/wallet/WalletTransactionSender.cpp
|
cryptonote/src/Serialization/SerializationOverloads.cpp
|
||||||
cryptonote/src/wallet/WalletUnconfirmedTransactions.cpp
|
cryptonote/src/Transfers/BlockchainSynchronizer.cpp
|
||||||
cryptonote/src/wallet/WalletUserTransactionsCache.cpp
|
cryptonote/src/Transfers/SynchronizationState.cpp
|
||||||
cryptonote/src/wallet/LegacyKeysImporter.cpp
|
cryptonote/src/Transfers/TransfersConsumer.cpp
|
||||||
|
cryptonote/src/Transfers/TransfersContainer.cpp
|
||||||
|
cryptonote/src/Transfers/TransfersSubscription.cpp
|
||||||
|
cryptonote/src/Transfers/TransfersSynchronizer.cpp
|
||||||
|
cryptonote/src/Wallet/LegacyKeysImporter.cpp
|
||||||
|
cryptonote/src/Wallet/WalletAsyncContextCounter.cpp
|
||||||
|
cryptonote/src/Wallet/WalletErrors.cpp
|
||||||
|
cryptonote/src/WalletLegacy/KeysStorage.cpp
|
||||||
|
cryptonote/src/WalletLegacy/WalletLegacy.cpp
|
||||||
|
cryptonote/src/WalletLegacy/WalletHelper.cpp
|
||||||
|
cryptonote/src/WalletLegacy/WalletLegacySerializer.cpp
|
||||||
|
cryptonote/src/WalletLegacy/WalletLegacySerialization.cpp
|
||||||
|
cryptonote/src/WalletLegacy/WalletTransactionSender.cpp
|
||||||
|
cryptonote/src/WalletLegacy/WalletUnconfirmedTransactions.cpp
|
||||||
|
cryptonote/src/WalletLegacy/WalletUserTransactionsCache.cpp
|
||||||
|
cryptonote/src/System/ContextGroup.cpp
|
||||||
|
cryptonote/src/System/Event.cpp
|
||||||
|
cryptonote/src/System/EventLock.cpp
|
||||||
|
cryptonote/src/System/InterruptedException.cpp
|
||||||
|
cryptonote/src/System/Ipv4Address.cpp
|
||||||
|
cryptonote/src/System/TcpStream.cpp
|
||||||
|
cryptonote/src/HTTP/HttpRequest.cpp
|
||||||
|
cryptonote/src/HTTP/HttpParser.cpp
|
||||||
|
cryptonote/src/HTTP/HttpParserErrorCodes.cpp
|
||||||
|
cryptonote/src/HTTP/HttpResponse.cpp
|
||||||
|
cryptonote/src/Rpc/HttpClient.cpp
|
||||||
|
cryptonote/src/Rpc/JsonRpc.cpp
|
||||||
|
cryptonote/src/P2p/NetNode.cpp
|
||||||
|
cryptonote/src/P2p/LevinProtocol.cpp
|
||||||
|
cryptonote/src/P2p/NetNodeConfig.cpp
|
||||||
|
cryptonote/src/P2p/PeerListManager.cpp
|
||||||
|
cryptonote/src/CryptoNoteProtocol/CryptoNoteProtocolHandler.cpp
|
||||||
|
cryptonote/src/Logging/ILogger.cpp
|
||||||
|
cryptonote/src/Logging/LoggerGroup.cpp
|
||||||
|
cryptonote/src/Logging/CommonLogger.cpp
|
||||||
|
cryptonote/src/Logging/LoggerManager.cpp
|
||||||
|
cryptonote/src/Logging/FileLogger.cpp
|
||||||
|
cryptonote/src/Logging/StreamLogger.cpp
|
||||||
|
cryptonote/src/Logging/ConsoleLogger.cpp
|
||||||
|
cryptonote/src/Logging/LoggerMessage.cpp
|
||||||
|
cryptonote/src/Logging/LoggerRef.cpp
|
||||||
|
cryptonote/src/BlockchainExplorer/BlockchainExplorer.cpp
|
||||||
|
cryptonote/src/BlockchainExplorer/BlockchainExplorerDataBuilder.cpp
|
||||||
|
cryptonote/src/BlockchainExplorer/BlockchainExplorerErrors.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
file(GLOB_RECURSE SOURCES src/*.cpp)
|
file(GLOB_RECURSE SOURCES src/*.cpp)
|
||||||
|
|
|
@ -2,54 +2,122 @@
|
||||||
// Distributed under the MIT/X11 software license, see the accompanying
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
#include <QCoreApplication>
|
#include <Common/Util.h>
|
||||||
|
#include <CryptoNoteConfig.h>
|
||||||
#include <common/util.h>
|
|
||||||
|
|
||||||
#include "CommandLineParser.h"
|
#include "CommandLineParser.h"
|
||||||
#include "CurrencyAdapter.h"
|
|
||||||
|
|
||||||
namespace WalletGui {
|
namespace WalletGui {
|
||||||
|
|
||||||
CommandLineParser::CommandLineParser() : QObject(), m_parser(), m_help_option(m_parser.addHelpOption()),
|
CommandLineParser::CommandLineParser(QObject* _parent) : QObject(_parent), m_parser(), m_helpOption(m_parser.addHelpOption()),
|
||||||
m_version_option(m_parser.addVersionOption()),
|
m_versionOption(m_parser.addVersionOption()),
|
||||||
m_data_dir_option("data-dir", tr("Specify data directory"), tr("directory"), QString::fromStdString(tools::get_default_data_dir())) {
|
m_testnetOption("testnet", tr("Used to deploy test nets. Checkpoints and hardcoded seeds are ignored, network id is changed. "
|
||||||
m_parser.setApplicationDescription(QString(tr("%1 wallet")).arg(CurrencyAdapter::instance().getCurrencyDisplayName()));
|
"Use it with –data-dir flag. The wallet must be launched with –testnet flag")),
|
||||||
|
m_p2pBindIpOption("p2p-bind-ip", tr("Interface for p2p network protocol"), tr("ip"), "0.0.0.0"),
|
||||||
|
m_p2pBindPortOption("p2p-bind-port", tr("Port for p2p network protocol"), tr("port"), QString::number(CryptoNote::P2P_DEFAULT_PORT)),
|
||||||
|
m_p2pExternalOption("p2p-external-port", tr("xternal port for p2p network protocol (if port forwarding used with NAT)"),
|
||||||
|
tr("port"), 0),
|
||||||
|
m_allowLocalIpOption("allow-local-ip", tr("Allow local ip add to peer list, mostly in debug purposes")),
|
||||||
|
m_addPeerOption("add-peer", tr("Manually add peer to local peerlist"), tr("peer")),
|
||||||
|
m_addPriorityNodeOption("add-priority-node", tr("Specify list of peers to connect to and attempt to keep the connection open"),
|
||||||
|
tr("node")),
|
||||||
|
m_addExclusiveNodeOption("add-exclusive-node", tr("Specify list of peers to connect to only. If this option is given the options "
|
||||||
|
"add-priority-node and seed-node are ignored"), tr("node")),
|
||||||
|
m_seedNodeOption("seed-node", tr("Connect to a node to retrieve peer addresses, and disconnect"), tr("node")),
|
||||||
|
m_hideMyPortOption("hide-my-port", tr("Do not announce yourself as peerlist candidate")),
|
||||||
|
m_dataDirOption("data-dir", tr("Specify data directory"), tr("directory"), QString::fromStdString(Tools::getDefaultDataDirectory())),
|
||||||
|
m_minimized("minimized", tr("Run application in minimized mode")) {
|
||||||
|
m_parser.setApplicationDescription(tr("Bytecoin wallet"));
|
||||||
m_parser.addHelpOption();
|
m_parser.addHelpOption();
|
||||||
m_parser.addVersionOption();
|
m_parser.addVersionOption();
|
||||||
m_parser.addOption(m_data_dir_option);
|
m_parser.addOption(m_testnetOption);
|
||||||
|
m_parser.addOption(m_p2pBindIpOption);
|
||||||
|
m_parser.addOption(m_p2pBindPortOption);
|
||||||
|
m_parser.addOption(m_p2pExternalOption);
|
||||||
|
m_parser.addOption(m_allowLocalIpOption);
|
||||||
|
m_parser.addOption(m_addPeerOption);
|
||||||
|
m_parser.addOption(m_addPriorityNodeOption);
|
||||||
|
m_parser.addOption(m_addExclusiveNodeOption);
|
||||||
|
m_parser.addOption(m_seedNodeOption);
|
||||||
|
m_parser.addOption(m_hideMyPortOption);
|
||||||
|
m_parser.addOption(m_dataDirOption);
|
||||||
|
m_parser.addOption(m_minimized);
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandLineParser::~CommandLineParser() {
|
CommandLineParser::~CommandLineParser() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CommandLineParser::process() {
|
bool CommandLineParser::process(const QStringList& _argv) {
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
return m_parser.parse(QCoreApplication::arguments());
|
return m_parser.parse(_argv);
|
||||||
#else
|
#else
|
||||||
m_parser.process(*QCoreApplication::instance());
|
m_parser.process(_argv);
|
||||||
return true;
|
return true;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CommandLineParser::hasHelpOption() const {
|
bool CommandLineParser::hasHelpOption() const {
|
||||||
return m_parser.isSet(m_help_option);
|
return m_parser.isSet(m_helpOption);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CommandLineParser::hasMinimizedOption() const {
|
||||||
|
return m_parser.isSet(m_minimized);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CommandLineParser::hasVersionOption() const {
|
bool CommandLineParser::hasVersionOption() const {
|
||||||
return m_parser.isSet(m_version_option);
|
return m_parser.isSet(m_versionOption);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString CommandLineParser::errorText() const {
|
bool CommandLineParser::hasTestnetOption() const {
|
||||||
|
return m_parser.isSet(m_testnetOption);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CommandLineParser::hasAllowLocalIpOption() const {
|
||||||
|
return m_parser.isSet(m_allowLocalIpOption);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CommandLineParser::hasHideMyPortOption() const {
|
||||||
|
return m_parser.isSet(m_hideMyPortOption);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString CommandLineParser::getErrorText() const {
|
||||||
return m_parser.errorText();
|
return m_parser.errorText();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString CommandLineParser::helpText() const {
|
QString CommandLineParser::getHelpText() const {
|
||||||
return m_parser.helpText();
|
return m_parser.helpText();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString CommandLineParser::getP2pBindIp() const {
|
||||||
|
return m_parser.value(m_p2pBindIpOption);
|
||||||
|
}
|
||||||
|
|
||||||
|
quint16 CommandLineParser::getP2pBindPort() const {
|
||||||
|
return m_parser.value(m_p2pBindPortOption).toUShort();
|
||||||
|
}
|
||||||
|
|
||||||
|
quint16 CommandLineParser::getP2pExternalPort() const {
|
||||||
|
return m_parser.value(m_p2pExternalOption).toUShort();
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList CommandLineParser::getPeers() const {
|
||||||
|
return m_parser.values(m_addPeerOption);
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList CommandLineParser::getPiorityNodes() const {
|
||||||
|
return m_parser.values(m_addPriorityNodeOption);
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList CommandLineParser::getExclusiveNodes() const {
|
||||||
|
return m_parser.values(m_addExclusiveNodeOption);
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList CommandLineParser::getSeedNodes() const {
|
||||||
|
return m_parser.values(m_seedNodeOption);
|
||||||
|
}
|
||||||
|
|
||||||
QString CommandLineParser::getDataDir() const {
|
QString CommandLineParser::getDataDir() const {
|
||||||
return m_parser.value(m_data_dir_option);
|
return m_parser.value(m_dataDirOption);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,24 +11,46 @@ namespace WalletGui {
|
||||||
|
|
||||||
class CommandLineParser : public QObject {
|
class CommandLineParser : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_DISABLE_COPY(CommandLineParser)
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CommandLineParser();
|
CommandLineParser(QObject* _parent);
|
||||||
~CommandLineParser();
|
~CommandLineParser();
|
||||||
|
|
||||||
bool process();
|
bool process(const QStringList& _argv);
|
||||||
|
|
||||||
bool hasHelpOption() const;
|
bool hasHelpOption() const;
|
||||||
bool hasVersionOption() const;
|
bool hasVersionOption() const;
|
||||||
QString errorText() const;
|
bool hasTestnetOption() const;
|
||||||
QString helpText() const;
|
bool hasMinimizedOption() const;
|
||||||
|
bool hasAllowLocalIpOption() const;
|
||||||
|
bool hasHideMyPortOption() const;
|
||||||
|
QString getErrorText() const;
|
||||||
|
QString getHelpText() const;
|
||||||
|
QString getP2pBindIp() const;
|
||||||
|
quint16 getP2pBindPort() const;
|
||||||
|
quint16 getP2pExternalPort() const;
|
||||||
|
QStringList getPeers() const;
|
||||||
|
QStringList getPiorityNodes() const;
|
||||||
|
QStringList getExclusiveNodes() const;
|
||||||
|
QStringList getSeedNodes() const;
|
||||||
QString getDataDir() const;
|
QString getDataDir() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QCommandLineParser m_parser;
|
QCommandLineParser m_parser;
|
||||||
QCommandLineOption m_help_option;
|
QCommandLineOption m_helpOption;
|
||||||
QCommandLineOption m_version_option;
|
QCommandLineOption m_versionOption;
|
||||||
QCommandLineOption m_data_dir_option;
|
QCommandLineOption m_testnetOption;
|
||||||
|
QCommandLineOption m_p2pBindIpOption;
|
||||||
|
QCommandLineOption m_p2pBindPortOption;
|
||||||
|
QCommandLineOption m_p2pExternalOption;
|
||||||
|
QCommandLineOption m_allowLocalIpOption;
|
||||||
|
QCommandLineOption m_addPeerOption;
|
||||||
|
QCommandLineOption m_addPriorityNodeOption;
|
||||||
|
QCommandLineOption m_addExclusiveNodeOption;
|
||||||
|
QCommandLineOption m_seedNodeOption;
|
||||||
|
QCommandLineOption m_hideMyPortOption;
|
||||||
|
QCommandLineOption m_dataDirOption;
|
||||||
|
QCommandLineOption m_minimized;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,34 +2,27 @@
|
||||||
// Distributed under the MIT/X11 software license, see the accompanying
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
#include "CryptoNote.h"
|
#include "CryptoNoteWrapper.h"
|
||||||
#include "cryptonote_core/cryptonote_basic_impl.h"
|
#include "CryptoNoteCore/CryptoNoteBasicImpl.h"
|
||||||
#include "cryptonote_core/cryptonote_format_utils.h"
|
#include "CryptoNoteCore/CryptoNoteFormatUtils.h"
|
||||||
#include "cryptonote_core/Currency.h"
|
#include "CryptoNoteCore/Currency.h"
|
||||||
#include "node_rpc_proxy/NodeRpcProxy.h"
|
#include "NodeRpcProxy/NodeRpcProxy.h"
|
||||||
#include "cryptonote_core/CoreConfig.h"
|
#include "CryptoNoteCore/CoreConfig.h"
|
||||||
#include "cryptonote_core/cryptonote_core.h"
|
#include "P2p/NetNodeConfig.h"
|
||||||
#include "cryptonote_protocol/cryptonote_protocol_handler.h"
|
#include "CryptoNoteCore/Core.h"
|
||||||
#include "inprocess_node/InProcessNode.h"
|
#include "CryptoNoteProtocol/CryptoNoteProtocolHandler.h"
|
||||||
#include "p2p/net_node.h"
|
#include "InProcessNode/InProcessNode.h"
|
||||||
#include "wallet/Wallet.h"
|
#include "P2p/NetNode.h"
|
||||||
|
#include "WalletLegacy/WalletLegacy.h"
|
||||||
|
#include "Logging/LoggerManager.h"
|
||||||
|
#include "System/Dispatcher.h"
|
||||||
|
|
||||||
namespace WalletGui {
|
namespace WalletGui {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
bool parsePaymentId(const std::string& payment_id_str, crypto::hash& payment_id) {
|
bool parsePaymentId(const std::string& payment_id_str, Crypto::Hash& payment_id) {
|
||||||
cryptonote::blobdata payment_id_data;
|
return CryptoNote::parsePaymentId(payment_id_str, payment_id);
|
||||||
if (!epee::string_tools::parse_hexstr_to_binbuff(payment_id_str, payment_id_data)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sizeof(crypto::hash) != payment_id_data.size()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
payment_id = *reinterpret_cast<const crypto::hash*>(payment_id_data.data());
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string convertPaymentId(const std::string& paymentIdString) {
|
std::string convertPaymentId(const std::string& paymentIdString) {
|
||||||
|
@ -37,7 +30,7 @@ std::string convertPaymentId(const std::string& paymentIdString) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
crypto::hash paymentId;
|
Crypto::Hash paymentId;
|
||||||
if (!parsePaymentId(paymentIdString, paymentId)) {
|
if (!parsePaymentId(paymentIdString, paymentId)) {
|
||||||
std::stringstream errorStr;
|
std::stringstream errorStr;
|
||||||
errorStr << "Payment id has invalid format: \"" + paymentIdString + "\", expected 64-character string";
|
errorStr << "Payment id has invalid format: \"" + paymentIdString + "\", expected 64-character string";
|
||||||
|
@ -45,9 +38,9 @@ std::string convertPaymentId(const std::string& paymentIdString) {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<uint8_t> extra;
|
std::vector<uint8_t> extra;
|
||||||
std::string extra_nonce;
|
CryptoNote::BinaryArray extraNonce;
|
||||||
cryptonote::set_payment_id_to_tx_extra_nonce(extra_nonce, paymentId);
|
CryptoNote::setPaymentIdToTransactionExtraNonce(extraNonce, paymentId);
|
||||||
if (!cryptonote::add_extra_nonce_to_tx_extra(extra, extra_nonce)) {
|
if (!CryptoNote::addExtraNonceToTransactionExtra(extra, extraNonce)) {
|
||||||
std::stringstream errorStr;
|
std::stringstream errorStr;
|
||||||
errorStr << "Something went wrong with payment_id. Please check its format: \"" + paymentIdString + "\", expected 64-character string";
|
errorStr << "Something went wrong with payment_id. Please check its format: \"" + paymentIdString + "\", expected 64-character string";
|
||||||
throw std::runtime_error(errorStr.str());
|
throw std::runtime_error(errorStr.str());
|
||||||
|
@ -57,19 +50,19 @@ std::string convertPaymentId(const std::string& paymentIdString) {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string extractPaymentId(const std::string& extra) {
|
std::string extractPaymentId(const std::string& extra) {
|
||||||
std::vector<cryptonote::tx_extra_field> extraFields;
|
std::vector<CryptoNote::TransactionExtraField> extraFields;
|
||||||
std::vector<uint8_t> extraVector;
|
std::vector<uint8_t> extraVector;
|
||||||
std::copy(extra.begin(), extra.end(), std::back_inserter(extraVector));
|
std::copy(extra.begin(), extra.end(), std::back_inserter(extraVector));
|
||||||
|
|
||||||
if (!cryptonote::parse_tx_extra(extraVector, extraFields)) {
|
if (!CryptoNote::parseTransactionExtra(extraVector, extraFields)) {
|
||||||
throw std::runtime_error("Can't parse extra");
|
throw std::runtime_error("Can't parse extra");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string result;
|
std::string result;
|
||||||
cryptonote::tx_extra_nonce extra_nonce;
|
CryptoNote::TransactionExtraNonce extraNonce;
|
||||||
if (cryptonote::find_tx_extra_field_by_type(extraFields, extra_nonce)) {
|
if (CryptoNote::findTransactionExtraFieldByType(extraFields, extraNonce)) {
|
||||||
crypto::hash paymentIdHash;
|
Crypto::Hash paymentIdHash;
|
||||||
if (cryptonote::get_payment_id_from_tx_extra_nonce(extra_nonce.nonce, paymentIdHash)) {
|
if (CryptoNote::getPaymentIdFromTransactionExtraNonce(extraNonce.nonce, paymentIdHash)) {
|
||||||
unsigned char* buff = reinterpret_cast<unsigned char *>(&paymentIdHash);
|
unsigned char* buff = reinterpret_cast<unsigned char *>(&paymentIdHash);
|
||||||
for (size_t i = 0; i < sizeof(paymentIdHash); ++i) {
|
for (size_t i = 0; i < sizeof(paymentIdHash); ++i) {
|
||||||
result.push_back("0123456789ABCDEF"[buff[i] >> 4]);
|
result.push_back("0123456789ABCDEF"[buff[i] >> 4]);
|
||||||
|
@ -89,7 +82,7 @@ Node::~Node() {
|
||||||
|
|
||||||
class RpcNode : CryptoNote::INodeObserver, public Node {
|
class RpcNode : CryptoNote::INodeObserver, public Node {
|
||||||
public:
|
public:
|
||||||
RpcNode(const cryptonote::Currency& currency, INodeCallback& callback, const std::string& nodeHost, unsigned short nodePort) :
|
RpcNode(const CryptoNote::Currency& currency, INodeCallback& callback, const std::string& nodeHost, unsigned short nodePort) :
|
||||||
m_callback(callback),
|
m_callback(callback),
|
||||||
m_currency(currency),
|
m_currency(currency),
|
||||||
m_node(nodeHost, nodePort) {
|
m_node(nodeHost, nodePort) {
|
||||||
|
@ -130,14 +123,14 @@ public:
|
||||||
return m_node.getPeerCount();
|
return m_node.getPeerCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
CryptoNote::IWallet* createWallet() override {
|
CryptoNote::IWalletLegacy* createWallet() override {
|
||||||
return new CryptoNote::Wallet(m_currency, m_node);
|
return new CryptoNote::WalletLegacy(m_currency, m_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
INodeCallback& m_callback;
|
INodeCallback& m_callback;
|
||||||
const cryptonote::Currency& m_currency;
|
const CryptoNote::Currency& m_currency;
|
||||||
cryptonote::NodeRpcProxy m_node;
|
CryptoNote::NodeRpcProxy m_node;
|
||||||
|
|
||||||
void peerCountUpdated(size_t count) {
|
void peerCountUpdated(size_t count) {
|
||||||
m_callback.peerCountUpdated(*this, count);
|
m_callback.peerCountUpdated(*this, count);
|
||||||
|
@ -154,23 +147,23 @@ private:
|
||||||
|
|
||||||
class InprocessNode : CryptoNote::INodeObserver, public Node {
|
class InprocessNode : CryptoNote::INodeObserver, public Node {
|
||||||
public:
|
public:
|
||||||
InprocessNode(const cryptonote::Currency& currency, INodeCallback& callback, const cryptonote::CoreConfig& coreConfig) :
|
InprocessNode(const CryptoNote::Currency& currency, Logging::LoggerManager& logManager, const CryptoNote::CoreConfig& coreConfig,
|
||||||
|
const CryptoNote::NetNodeConfig& netNodeConfig, INodeCallback& callback) :
|
||||||
|
m_currency(currency), m_dispatcher(),
|
||||||
m_callback(callback),
|
m_callback(callback),
|
||||||
m_currency(currency),
|
|
||||||
m_coreConfig(coreConfig),
|
m_coreConfig(coreConfig),
|
||||||
m_core(m_currency, nullptr),
|
m_netNodeConfig(netNodeConfig),
|
||||||
m_protocolHandler(m_core, nullptr),
|
m_protocolHandler(currency, m_dispatcher, m_core, nullptr, logManager),
|
||||||
m_nodeServer(m_protocolHandler),
|
m_core(currency, &m_protocolHandler, logManager),
|
||||||
|
m_nodeServer(m_dispatcher, m_protocolHandler, logManager),
|
||||||
m_node(m_core, m_protocolHandler) {
|
m_node(m_core, m_protocolHandler) {
|
||||||
|
|
||||||
m_core.set_cryptonote_protocol(&m_protocolHandler);
|
m_core.set_cryptonote_protocol(&m_protocolHandler);
|
||||||
m_protocolHandler.set_p2p_endpoint(&m_nodeServer);
|
m_protocolHandler.set_p2p_endpoint(&m_nodeServer);
|
||||||
cryptonote::checkpoints checkpoints;
|
CryptoNote::Checkpoints checkpoints(logManager);
|
||||||
for (const cryptonote::CheckpointData& checkpoint : cryptonote::CHECKPOINTS) {
|
for (const CryptoNote::CheckpointData& checkpoint : CryptoNote::CHECKPOINTS) {
|
||||||
checkpoints.add_checkpoint(checkpoint.height, checkpoint.blockId);
|
checkpoints.add_checkpoint(checkpoint.height, checkpoint.blockId);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_core.set_checkpoints(std::move(checkpoints));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~InprocessNode() override {
|
~InprocessNode() override {
|
||||||
|
@ -178,28 +171,33 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
void init(const std::function<void(std::error_code)>& callback) override {
|
void init(const std::function<void(std::error_code)>& callback) override {
|
||||||
if (!m_core.init(m_coreConfig, cryptonote::MinerConfig(), true)) {
|
try {
|
||||||
callback(make_error_code(cryptonote::error::NOT_INITIALIZED));
|
if (!m_core.init(m_coreConfig, CryptoNote::MinerConfig(), true)) {
|
||||||
|
callback(make_error_code(CryptoNote::error::NOT_INITIALIZED));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!m_nodeServer.init(nodetool::NetNodeConfig(), false)) {
|
|
||||||
m_core.deinit();
|
if (!m_nodeServer.init(m_netNodeConfig)) {
|
||||||
callback(make_error_code(cryptonote::error::NOT_INITIALIZED));
|
callback(make_error_code(CryptoNote::error::NOT_INITIALIZED));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
} catch (std::runtime_error& _err) {
|
||||||
|
callback(make_error_code(CryptoNote::error::NOT_INITIALIZED));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
m_node.init([this, callback](std::error_code ec) {
|
m_node.init([this, callback](std::error_code ec) {
|
||||||
m_node.addObserver(this);
|
m_node.addObserver(this);
|
||||||
callback(ec);
|
callback(ec);
|
||||||
});
|
});
|
||||||
m_nodeServer.run();
|
|
||||||
|
|
||||||
|
m_nodeServer.run();
|
||||||
m_nodeServer.deinit();
|
m_nodeServer.deinit();
|
||||||
m_core.deinit();
|
|
||||||
m_node.shutdown();
|
m_node.shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
void deinit() override {
|
void deinit() override {
|
||||||
m_nodeServer.send_stop_signal();
|
m_nodeServer.sendStopSignal();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string convertPaymentId(const std::string& paymentIdString) override {
|
std::string convertPaymentId(const std::string& paymentIdString) override {
|
||||||
|
@ -226,17 +224,19 @@ public:
|
||||||
return m_node.getPeerCount();
|
return m_node.getPeerCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
CryptoNote::IWallet* createWallet() override {
|
CryptoNote::IWalletLegacy* createWallet() override {
|
||||||
return new CryptoNote::Wallet(m_currency, m_node);
|
return new CryptoNote::WalletLegacy(m_currency, m_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
INodeCallback& m_callback;
|
INodeCallback& m_callback;
|
||||||
const cryptonote::Currency& m_currency;
|
const CryptoNote::Currency& m_currency;
|
||||||
cryptonote::CoreConfig m_coreConfig;
|
System::Dispatcher m_dispatcher;
|
||||||
cryptonote::core m_core;
|
CryptoNote::CoreConfig m_coreConfig;
|
||||||
cryptonote::t_cryptonote_protocol_handler<cryptonote::core> m_protocolHandler;
|
CryptoNote::NetNodeConfig m_netNodeConfig;
|
||||||
nodetool::node_server<cryptonote::t_cryptonote_protocol_handler<cryptonote::core>> m_nodeServer;
|
CryptoNote::core m_core;
|
||||||
|
CryptoNote::CryptoNoteProtocolHandler m_protocolHandler;
|
||||||
|
CryptoNote::NodeServer m_nodeServer;
|
||||||
CryptoNote::InProcessNode m_node;
|
CryptoNote::InProcessNode m_node;
|
||||||
std::future<bool> m_nodeServerFuture;
|
std::future<bool> m_nodeServerFuture;
|
||||||
|
|
||||||
|
@ -253,12 +253,13 @@ private:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Node* createRpcNode(const cryptonote::Currency& currency, INodeCallback& callback, const std::string& nodeHost, unsigned short nodePort) {
|
Node* createRpcNode(const CryptoNote::Currency& currency, INodeCallback& callback, const std::string& nodeHost, unsigned short nodePort) {
|
||||||
return new RpcNode(currency, callback, nodeHost, nodePort);
|
return new RpcNode(currency, callback, nodeHost, nodePort);
|
||||||
}
|
}
|
||||||
|
|
||||||
Node* createInprocessNode(const cryptonote::Currency& currency, INodeCallback& callback, const cryptonote::CoreConfig& coreConfig) {
|
Node* createInprocessNode(const CryptoNote::Currency& currency, Logging::LoggerManager& logManager,
|
||||||
return new InprocessNode(currency, callback, coreConfig);
|
const CryptoNote::CoreConfig& coreConfig, const CryptoNote::NetNodeConfig& netNodeConfig, INodeCallback& callback) {
|
||||||
|
return new InprocessNode(currency, logManager, coreConfig, netNodeConfig, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -9,21 +9,20 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <system_error>
|
#include <system_error>
|
||||||
|
|
||||||
#include <cryptonote_core/CoreConfig.h>
|
|
||||||
|
|
||||||
namespace cryptonote {
|
|
||||||
|
|
||||||
class Currency;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace CryptoNote {
|
namespace CryptoNote {
|
||||||
|
|
||||||
class INode;
|
class INode;
|
||||||
class IWallet;
|
class IWalletLegacy;
|
||||||
|
class Currency;
|
||||||
|
class CoreConfig;
|
||||||
|
class NetNodeConfig;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace Logging {
|
||||||
|
class LoggerManager;
|
||||||
|
}
|
||||||
|
|
||||||
namespace WalletGui {
|
namespace WalletGui {
|
||||||
|
|
||||||
class Node {
|
class Node {
|
||||||
|
@ -39,7 +38,7 @@ public:
|
||||||
virtual uint64_t getLastLocalBlockTimestamp() const = 0;
|
virtual uint64_t getLastLocalBlockTimestamp() const = 0;
|
||||||
virtual uint64_t getPeerCount() const = 0;
|
virtual uint64_t getPeerCount() const = 0;
|
||||||
|
|
||||||
virtual CryptoNote::IWallet* createWallet() = 0;
|
virtual CryptoNote::IWalletLegacy* createWallet() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class INodeCallback {
|
class INodeCallback {
|
||||||
|
@ -49,7 +48,8 @@ public:
|
||||||
virtual void lastKnownBlockHeightUpdated(Node& node, uint64_t height) = 0;
|
virtual void lastKnownBlockHeightUpdated(Node& node, uint64_t height) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
Node* createRpcNode(const cryptonote::Currency& currency, INodeCallback& callback, const std::string& nodeHost, unsigned short nodePort);
|
Node* createRpcNode(const CryptoNote::Currency& currency, INodeCallback& callback, const std::string& nodeHost, unsigned short nodePort);
|
||||||
Node* createInprocessNode(const cryptonote::Currency& currency, INodeCallback& callback, const cryptonote::CoreConfig& coreConfig);
|
Node* createInprocessNode(const CryptoNote::Currency& currency, Logging::LoggerManager& logManager,
|
||||||
|
const CryptoNote::CoreConfig& coreConfig, const CryptoNote::NetNodeConfig& netNodeConfig, INodeCallback& callback);
|
||||||
|
|
||||||
}
|
}
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#include "CurrencyAdapter.h"
|
#include "CurrencyAdapter.h"
|
||||||
#include "CryptoNoteWalletConfig.h"
|
#include "CryptoNoteWalletConfig.h"
|
||||||
|
#include "LoggerAdapter.h"
|
||||||
|
|
||||||
namespace WalletGui {
|
namespace WalletGui {
|
||||||
|
|
||||||
|
@ -12,13 +13,13 @@ CurrencyAdapter& CurrencyAdapter::instance() {
|
||||||
return inst;
|
return inst;
|
||||||
}
|
}
|
||||||
|
|
||||||
CurrencyAdapter::CurrencyAdapter() : m_currency(cryptonote::CurrencyBuilder().currency()) {
|
CurrencyAdapter::CurrencyAdapter() : m_currency(CryptoNote::CurrencyBuilder(LoggerAdapter::instance().getLoggerManager()).currency()) {
|
||||||
}
|
}
|
||||||
|
|
||||||
CurrencyAdapter::~CurrencyAdapter() {
|
CurrencyAdapter::~CurrencyAdapter() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const cryptonote::Currency& CurrencyAdapter::getCurrency() {
|
const CryptoNote::Currency& CurrencyAdapter::getCurrency() {
|
||||||
return m_currency;
|
return m_currency;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,7 +32,7 @@ QString CurrencyAdapter::getCurrencyDisplayName() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
QString CurrencyAdapter::getCurrencyName() const {
|
QString CurrencyAdapter::getCurrencyName() const {
|
||||||
return cryptonote::CRYPTONOTE_NAME;
|
return CryptoNote::CRYPTONOTE_NAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString CurrencyAdapter::getCurrencyTicker() const {
|
QString CurrencyAdapter::getCurrencyTicker() const {
|
||||||
|
@ -101,7 +102,7 @@ quint64 CurrencyAdapter::parseAmount(const QString& _amountString) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CurrencyAdapter::validateAddress(const QString& _address) const {
|
bool CurrencyAdapter::validateAddress(const QString& _address) const {
|
||||||
cryptonote::AccountPublicAddress internalAddress;
|
CryptoNote::AccountPublicAddress internalAddress;
|
||||||
return m_currency.parseAccountAddressString(_address.toStdString(), internalAddress);
|
return m_currency.parseAccountAddressString(_address.toStdString(), internalAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
#include "cryptonote_core/Currency.h"
|
#include "CryptoNoteCore/Currency.h"
|
||||||
|
|
||||||
namespace WalletGui {
|
namespace WalletGui {
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ class CurrencyAdapter {
|
||||||
public:
|
public:
|
||||||
static CurrencyAdapter& instance();
|
static CurrencyAdapter& instance();
|
||||||
|
|
||||||
const cryptonote::Currency& getCurrency();
|
const CryptoNote::Currency& getCurrency();
|
||||||
QString getCurrencyDisplayName() const;
|
QString getCurrencyDisplayName() const;
|
||||||
QString getCurrencyName() const;
|
QString getCurrencyName() const;
|
||||||
QString getCurrencyTicker() const;
|
QString getCurrencyTicker() const;
|
||||||
|
@ -26,7 +26,7 @@ public:
|
||||||
bool validateAddress(const QString& _address) const;
|
bool validateAddress(const QString& _address) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
cryptonote::Currency m_currency;
|
CryptoNote::Currency m_currency;
|
||||||
|
|
||||||
CurrencyAdapter();
|
CurrencyAdapter();
|
||||||
~CurrencyAdapter();
|
~CurrencyAdapter();
|
||||||
|
|
36
src/LoggerAdapter.cpp
Normal file
36
src/LoggerAdapter.cpp
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
// Copyright (c) 2011-2015 The Cryptonote developers
|
||||||
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
#include "LoggerAdapter.h"
|
||||||
|
#include "Settings.h"
|
||||||
|
|
||||||
|
namespace WalletGui {
|
||||||
|
|
||||||
|
LoggerAdapter& LoggerAdapter::instance() {
|
||||||
|
static LoggerAdapter inst;
|
||||||
|
return inst;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoggerAdapter::init() {
|
||||||
|
Common::JsonValue loggerConfiguration(Common::JsonValue::OBJECT);
|
||||||
|
loggerConfiguration.insert("globalLevel", static_cast<int64_t>(Logging::INFO));
|
||||||
|
Common::JsonValue& cfgLoggers = loggerConfiguration.insert("loggers", Common::JsonValue::ARRAY);
|
||||||
|
Common::JsonValue& fileLogger = cfgLoggers.pushBack(Common::JsonValue::OBJECT);
|
||||||
|
fileLogger.insert("type", "file");
|
||||||
|
fileLogger.insert("filename", Settings::instance().getDataDir().absoluteFilePath("bytecoinwallet.log").toStdString());
|
||||||
|
fileLogger.insert("level", static_cast<int64_t>(Logging::INFO));
|
||||||
|
m_logManager.configure(loggerConfiguration);
|
||||||
|
}
|
||||||
|
|
||||||
|
LoggerAdapter::LoggerAdapter() : m_logManager() {
|
||||||
|
}
|
||||||
|
|
||||||
|
LoggerAdapter::~LoggerAdapter() {
|
||||||
|
}
|
||||||
|
|
||||||
|
Logging::LoggerManager& LoggerAdapter::getLoggerManager() {
|
||||||
|
return m_logManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
25
src/LoggerAdapter.h
Normal file
25
src/LoggerAdapter.h
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
// Copyright (c) 2011-2015 The Cryptonote developers
|
||||||
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Logging/LoggerManager.h"
|
||||||
|
|
||||||
|
namespace WalletGui {
|
||||||
|
|
||||||
|
class LoggerAdapter {
|
||||||
|
|
||||||
|
public:
|
||||||
|
static LoggerAdapter& instance();
|
||||||
|
void init();
|
||||||
|
Logging::LoggerManager& getLoggerManager();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Logging::LoggerManager m_logManager;
|
||||||
|
|
||||||
|
LoggerAdapter();
|
||||||
|
~LoggerAdapter();
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -8,14 +8,30 @@
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
|
|
||||||
#include <wallet/WalletErrors.h>
|
#include <CryptoNoteCore/CoreConfig.h>
|
||||||
|
#include <P2p/NetNodeConfig.h>
|
||||||
|
#include <Wallet/WalletErrors.h>
|
||||||
|
|
||||||
#include "CurrencyAdapter.h"
|
#include "CurrencyAdapter.h"
|
||||||
|
#include "LoggerAdapter.h"
|
||||||
#include "NodeAdapter.h"
|
#include "NodeAdapter.h"
|
||||||
#include "Settings.h"
|
#include "Settings.h"
|
||||||
|
|
||||||
namespace WalletGui {
|
namespace WalletGui {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
std::vector<std::string> convertStringListToVector(const QStringList& list) {
|
||||||
|
std::vector<std::string> result;
|
||||||
|
Q_FOREACH (const QString& item, list) {
|
||||||
|
result.push_back(item.toStdString());
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
class InProcessNodeInitializer : public QObject {
|
class InProcessNodeInitializer : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_DISABLE_COPY(InProcessNodeInitializer)
|
Q_DISABLE_COPY(InProcessNodeInitializer)
|
||||||
|
@ -32,8 +48,9 @@ public:
|
||||||
~InProcessNodeInitializer() {
|
~InProcessNodeInitializer() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void start(Node** _node, const cryptonote::Currency* currency, INodeCallback* _callback, const cryptonote::CoreConfig& _coreConfig) {
|
void start(Node** _node, const CryptoNote::Currency* currency, INodeCallback* _callback, Logging::LoggerManager* _loggerManager,
|
||||||
(*_node) = createInprocessNode(*currency, *_callback, _coreConfig);
|
const CryptoNote::CoreConfig& _coreConfig, const CryptoNote::NetNodeConfig& _netNodeConfig) {
|
||||||
|
(*_node) = createInprocessNode(*currency, *_loggerManager, _coreConfig, _netNodeConfig, *_callback);
|
||||||
try {
|
try {
|
||||||
(*_node)->init([this](std::error_code _err) {
|
(*_node)->init([this](std::error_code _err) {
|
||||||
if (_err) {
|
if (_err) {
|
||||||
|
@ -46,7 +63,7 @@ public:
|
||||||
QCoreApplication::processEvents();
|
QCoreApplication::processEvents();
|
||||||
});
|
});
|
||||||
} catch (std::runtime_error& err) {
|
} catch (std::runtime_error& err) {
|
||||||
Q_EMIT nodeInitFailedSignal(cryptonote::error::INTERNAL_WALLET_ERROR);
|
Q_EMIT nodeInitFailedSignal(CryptoNote::error::INTERNAL_WALLET_ERROR);
|
||||||
QCoreApplication::processEvents();
|
QCoreApplication::processEvents();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -70,15 +87,12 @@ NodeAdapter& NodeAdapter::instance() {
|
||||||
NodeAdapter::NodeAdapter() : QObject(), m_node(nullptr), m_nodeInitializerThread(), m_nodeInitializer(new InProcessNodeInitializer) {
|
NodeAdapter::NodeAdapter() : QObject(), m_node(nullptr), m_nodeInitializerThread(), m_nodeInitializer(new InProcessNodeInitializer) {
|
||||||
m_nodeInitializer->moveToThread(&m_nodeInitializerThread);
|
m_nodeInitializer->moveToThread(&m_nodeInitializerThread);
|
||||||
|
|
||||||
qRegisterMetaType<cryptonote::CoreConfig>("cryptonote::CoreConfig");
|
qRegisterMetaType<CryptoNote::CoreConfig>("CryptoNote::CoreConfig");
|
||||||
|
qRegisterMetaType<CryptoNote::NetNodeConfig>("CryptoNote::NetNodeConfig");
|
||||||
|
|
||||||
connect(m_nodeInitializer, &InProcessNodeInitializer::nodeInitCompletedSignal, this, &NodeAdapter::nodeInitCompletedSignal, Qt::QueuedConnection);
|
connect(m_nodeInitializer, &InProcessNodeInitializer::nodeInitCompletedSignal, this, &NodeAdapter::nodeInitCompletedSignal, Qt::QueuedConnection);
|
||||||
connect(this, &NodeAdapter::initNodeSignal, m_nodeInitializer, &InProcessNodeInitializer::start, Qt::QueuedConnection);
|
connect(this, &NodeAdapter::initNodeSignal, m_nodeInitializer, &InProcessNodeInitializer::start, Qt::QueuedConnection);
|
||||||
connect(this, &NodeAdapter::deinitNodeSignal, m_nodeInitializer, &InProcessNodeInitializer::stop, Qt::QueuedConnection);
|
connect(this, &NodeAdapter::deinitNodeSignal, m_nodeInitializer, &InProcessNodeInitializer::stop, Qt::QueuedConnection);
|
||||||
|
|
||||||
QString logFileName = QCoreApplication::applicationName() + ".log";
|
|
||||||
epee::log_space::log_singletone::add_logger(LOGGER_FILE, logFileName.toLocal8Bit(),
|
|
||||||
Settings::instance().getDataDir().absolutePath().toLocal8Bit());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeAdapter::~NodeAdapter() {
|
NodeAdapter::~NodeAdapter() {
|
||||||
|
@ -103,14 +117,14 @@ QString NodeAdapter::extractPaymentId(const std::string& _extra) const {
|
||||||
return QString::fromStdString(m_node->extractPaymentId(_extra));
|
return QString::fromStdString(m_node->extractPaymentId(_extra));
|
||||||
}
|
}
|
||||||
|
|
||||||
CryptoNote::IWallet* NodeAdapter::createWallet() const {
|
CryptoNote::IWalletLegacy* NodeAdapter::createWallet() const {
|
||||||
Q_CHECK_PTR(m_node);
|
Q_CHECK_PTR(m_node);
|
||||||
return m_node->createWallet();
|
return m_node->createWallet();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NodeAdapter::init() {
|
bool NodeAdapter::init() {
|
||||||
Q_ASSERT(m_node == nullptr);
|
Q_ASSERT(m_node == nullptr);
|
||||||
QUrl localNodeUrl = QUrl::fromUserInput(QString("127.0.0.1:%1").arg(cryptonote::RPC_DEFAULT_PORT));
|
QUrl localNodeUrl = QUrl::fromUserInput(QString("127.0.0.1:%1").arg(CryptoNote::RPC_DEFAULT_PORT));
|
||||||
|
|
||||||
m_node = createRpcNode(CurrencyAdapter::instance().getCurrency(), *this, localNodeUrl.host().toStdString(), localNodeUrl.port());
|
m_node = createRpcNode(CurrencyAdapter::instance().getCurrency(), *this, localNodeUrl.host().toStdString(), localNodeUrl.port());
|
||||||
|
|
||||||
|
@ -170,8 +184,9 @@ void NodeAdapter::lastKnownBlockHeightUpdated(Node& _node, uint64_t _height) {
|
||||||
bool NodeAdapter::initInProcessNode() {
|
bool NodeAdapter::initInProcessNode() {
|
||||||
Q_ASSERT(m_node == nullptr);
|
Q_ASSERT(m_node == nullptr);
|
||||||
m_nodeInitializerThread.start();
|
m_nodeInitializerThread.start();
|
||||||
cryptonote::CoreConfig coreConfig = makeCoreConfig();
|
CryptoNote::CoreConfig coreConfig = makeCoreConfig();
|
||||||
Q_EMIT initNodeSignal(&m_node, &CurrencyAdapter::instance().getCurrency(), this, coreConfig);
|
CryptoNote::NetNodeConfig netNodeConfig = makeNetNodeConfig();
|
||||||
|
Q_EMIT initNodeSignal(&m_node, &CurrencyAdapter::instance().getCurrency(), this, &LoggerAdapter::instance().getLoggerManager(), coreConfig, netNodeConfig);
|
||||||
QEventLoop waitLoop;
|
QEventLoop waitLoop;
|
||||||
connect(m_nodeInitializer, &InProcessNodeInitializer::nodeInitCompletedSignal, &waitLoop, &QEventLoop::quit);
|
connect(m_nodeInitializer, &InProcessNodeInitializer::nodeInitCompletedSignal, &waitLoop, &QEventLoop::quit);
|
||||||
connect(m_nodeInitializer, &InProcessNodeInitializer::nodeInitFailedSignal, &waitLoop, &QEventLoop::exit);
|
connect(m_nodeInitializer, &InProcessNodeInitializer::nodeInitFailedSignal, &waitLoop, &QEventLoop::exit);
|
||||||
|
@ -200,8 +215,8 @@ void NodeAdapter::deinit() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cryptonote::CoreConfig NodeAdapter::makeCoreConfig() const {
|
CryptoNote::CoreConfig NodeAdapter::makeCoreConfig() const {
|
||||||
cryptonote::CoreConfig config;
|
CryptoNote::CoreConfig config;
|
||||||
boost::program_options::variables_map options;
|
boost::program_options::variables_map options;
|
||||||
boost::any dataDir = Settings::instance().getDataDir().absolutePath().toStdString();
|
boost::any dataDir = Settings::instance().getDataDir().absolutePath().toStdString();
|
||||||
options.insert(std::make_pair("data-dir", boost::program_options::variable_value(dataDir, false)));
|
options.insert(std::make_pair("data-dir", boost::program_options::variable_value(dataDir, false)));
|
||||||
|
@ -209,6 +224,47 @@ cryptonote::CoreConfig NodeAdapter::makeCoreConfig() const {
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CryptoNote::NetNodeConfig NodeAdapter::makeNetNodeConfig() const {
|
||||||
|
CryptoNote::NetNodeConfig config;
|
||||||
|
boost::program_options::variables_map options;
|
||||||
|
boost::any p2pBindIp = Settings::instance().getP2pBindIp().toStdString();
|
||||||
|
boost::any p2pBindPort = static_cast<uint16_t>(Settings::instance().getP2pBindPort());
|
||||||
|
boost::any p2pExternalPort = static_cast<uint16_t>(Settings::instance().getP2pExternalPort());
|
||||||
|
boost::any p2pAllowLocalIp = Settings::instance().hasAllowLocalIpOption();
|
||||||
|
boost::any dataDir = Settings::instance().getDataDir().absolutePath().toStdString();
|
||||||
|
boost::any hideMyPort = Settings::instance().hasHideMyPortOption();
|
||||||
|
options.insert(std::make_pair("p2p-bind-ip", boost::program_options::variable_value(p2pBindIp, false)));
|
||||||
|
options.insert(std::make_pair("p2p-bind-port", boost::program_options::variable_value(p2pBindPort, false)));
|
||||||
|
options.insert(std::make_pair("p2p-external-port", boost::program_options::variable_value(p2pExternalPort, false)));
|
||||||
|
options.insert(std::make_pair("allow-local-ip", boost::program_options::variable_value(p2pAllowLocalIp, false)));
|
||||||
|
std::vector<std::string> peerList = convertStringListToVector(Settings::instance().getPeers());
|
||||||
|
if (!peerList.empty()) {
|
||||||
|
options.insert(std::make_pair("add-peer", boost::program_options::variable_value(peerList, false)));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> priorityNodeList = convertStringListToVector(Settings::instance().getPriorityNodes());
|
||||||
|
if (!priorityNodeList.empty()) {
|
||||||
|
options.insert(std::make_pair("add-priority-node", boost::program_options::variable_value(priorityNodeList, false)));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> exclusiveNodeList = convertStringListToVector(Settings::instance().getExclusiveNodes());
|
||||||
|
if (!exclusiveNodeList.empty()) {
|
||||||
|
options.insert(std::make_pair("add-exclusive-node", boost::program_options::variable_value(exclusiveNodeList, false)));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> seedNodeList = convertStringListToVector(Settings::instance().getSeedNodes());
|
||||||
|
if (!seedNodeList.empty()) {
|
||||||
|
options.insert(std::make_pair("seed-node", boost::program_options::variable_value(seedNodeList, false)));
|
||||||
|
}
|
||||||
|
|
||||||
|
options.insert(std::make_pair("hide-my-port", boost::program_options::variable_value(hideMyPort, false)));
|
||||||
|
options.insert(std::make_pair("data-dir", boost::program_options::variable_value(dataDir, false)));
|
||||||
|
int size = options.size();
|
||||||
|
config.init(options);
|
||||||
|
config.setTestnet(Settings::instance().isTestnet());
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "NodeAdapter.moc"
|
#include "NodeAdapter.moc"
|
||||||
|
|
|
@ -8,16 +8,20 @@
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
|
|
||||||
#include <INode.h>
|
#include <INode.h>
|
||||||
#include <IWallet.h>
|
#include <IWalletLegacy.h>
|
||||||
|
|
||||||
#include "CryptoNote.h"
|
#include "CryptoNoteWrapper.h"
|
||||||
|
|
||||||
namespace cryptonote {
|
namespace CryptoNote {
|
||||||
|
|
||||||
class Currency;
|
class Currency;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace Logging {
|
||||||
|
class LoggerManager;
|
||||||
|
}
|
||||||
|
|
||||||
namespace WalletGui {
|
namespace WalletGui {
|
||||||
|
|
||||||
class InProcessNodeInitializer;
|
class InProcessNodeInitializer;
|
||||||
|
@ -32,7 +36,7 @@ public:
|
||||||
quintptr getPeerCount() const;
|
quintptr getPeerCount() const;
|
||||||
std::string convertPaymentId(const QString& _payment_id_string) const;
|
std::string convertPaymentId(const QString& _payment_id_string) const;
|
||||||
QString extractPaymentId(const std::string& _extra) const;
|
QString extractPaymentId(const std::string& _extra) const;
|
||||||
CryptoNote::IWallet* createWallet() const;
|
CryptoNote::IWalletLegacy* createWallet() const;
|
||||||
|
|
||||||
bool init();
|
bool init();
|
||||||
void deinit();
|
void deinit();
|
||||||
|
@ -52,14 +56,16 @@ private:
|
||||||
~NodeAdapter();
|
~NodeAdapter();
|
||||||
|
|
||||||
bool initInProcessNode();
|
bool initInProcessNode();
|
||||||
cryptonote::CoreConfig makeCoreConfig() const;
|
CryptoNote::CoreConfig makeCoreConfig() const;
|
||||||
|
CryptoNote::NetNodeConfig makeNetNodeConfig() const;
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void localBlockchainUpdatedSignal(quint64 _height);
|
void localBlockchainUpdatedSignal(quint64 _height);
|
||||||
void lastKnownBlockHeightUpdatedSignal(quint64 _height);
|
void lastKnownBlockHeightUpdatedSignal(quint64 _height);
|
||||||
void nodeInitCompletedSignal();
|
void nodeInitCompletedSignal();
|
||||||
void peerCountUpdatedSignal(quintptr _count);
|
void peerCountUpdatedSignal(quintptr _count);
|
||||||
void initNodeSignal(Node** _node, const cryptonote::Currency* currency, INodeCallback* _callback, const cryptonote::CoreConfig& _core_config);
|
void initNodeSignal(Node** _node, const CryptoNote::Currency* currency, INodeCallback* _callback, Logging::LoggerManager* _loggerManager,
|
||||||
|
const CryptoNote::CoreConfig& _coreConfig, const CryptoNote::NetNodeConfig& _netNodeConfig);
|
||||||
void deinitNodeSignal(Node** _node);
|
void deinitNodeSignal(Node** _node);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
#include <QTextCodec>
|
#include <QTextCodec>
|
||||||
|
|
||||||
#include <common/util.h>
|
#include <Common/Util.h>
|
||||||
|
|
||||||
#include "CommandLineParser.h"
|
#include "CommandLineParser.h"
|
||||||
#include "CurrencyAdapter.h"
|
#include "CurrencyAdapter.h"
|
||||||
|
@ -49,6 +49,56 @@ void Settings::load() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Settings::isTestnet() const {
|
||||||
|
Q_ASSERT(m_cmdLineParser != nullptr);
|
||||||
|
return m_cmdLineParser->hasTestnetOption();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Settings::hasAllowLocalIpOption() const {
|
||||||
|
Q_ASSERT(m_cmdLineParser != nullptr);
|
||||||
|
return m_cmdLineParser->hasAllowLocalIpOption();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Settings::hasHideMyPortOption() const {
|
||||||
|
Q_ASSERT(m_cmdLineParser != nullptr);
|
||||||
|
return m_cmdLineParser->hasHideMyPortOption();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Settings::getP2pBindIp() const {
|
||||||
|
Q_ASSERT(m_cmdLineParser != nullptr);
|
||||||
|
return m_cmdLineParser->getP2pBindIp();
|
||||||
|
}
|
||||||
|
|
||||||
|
quint16 Settings::getP2pBindPort() const {
|
||||||
|
Q_ASSERT(m_cmdLineParser != nullptr);
|
||||||
|
return m_cmdLineParser->getP2pBindPort();
|
||||||
|
}
|
||||||
|
|
||||||
|
quint16 Settings::getP2pExternalPort() const {
|
||||||
|
Q_ASSERT(m_cmdLineParser != nullptr);
|
||||||
|
return m_cmdLineParser->getP2pExternalPort();
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList Settings::getPeers() const {
|
||||||
|
Q_ASSERT(m_cmdLineParser != nullptr);
|
||||||
|
return m_cmdLineParser->getPeers();
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList Settings::getPriorityNodes() const {
|
||||||
|
Q_ASSERT(m_cmdLineParser != nullptr);
|
||||||
|
return m_cmdLineParser->getPiorityNodes();
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList Settings::getExclusiveNodes() const {
|
||||||
|
Q_ASSERT(m_cmdLineParser != nullptr);
|
||||||
|
return m_cmdLineParser->getExclusiveNodes();
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList Settings::getSeedNodes() const {
|
||||||
|
Q_ASSERT(m_cmdLineParser != nullptr);
|
||||||
|
return m_cmdLineParser->getSeedNodes();
|
||||||
|
}
|
||||||
|
|
||||||
QDir Settings::getDataDir() const {
|
QDir Settings::getDataDir() const {
|
||||||
Q_CHECK_PTR(m_cmdLineParser);
|
Q_CHECK_PTR(m_cmdLineParser);
|
||||||
return QDir(m_cmdLineParser->getDataDir());
|
return QDir(m_cmdLineParser->getDataDir());
|
||||||
|
|
|
@ -22,7 +22,19 @@ public:
|
||||||
void setCommandLineParser(CommandLineParser* _cmd_line_parser);
|
void setCommandLineParser(CommandLineParser* _cmd_line_parser);
|
||||||
void load();
|
void load();
|
||||||
|
|
||||||
|
bool hasAllowLocalIpOption() const;
|
||||||
|
bool hasHideMyPortOption() const;
|
||||||
|
bool isTestnet() const;
|
||||||
QDir getDataDir() const;
|
QDir getDataDir() const;
|
||||||
|
QString getP2pBindIp() const;
|
||||||
|
quint16 getLocalRpcPort() const;
|
||||||
|
quint16 getP2pBindPort() const;
|
||||||
|
quint16 getP2pExternalPort() const;
|
||||||
|
QStringList getExclusiveNodes() const;
|
||||||
|
QStringList getPeers() const;
|
||||||
|
QStringList getPriorityNodes() const;
|
||||||
|
QStringList getSeedNodes() const;
|
||||||
|
|
||||||
QString getWalletFile() const;
|
QString getWalletFile() const;
|
||||||
QString getAddressBookFile() const;
|
QString getAddressBookFile() const;
|
||||||
bool isEncrypted() const;
|
bool isEncrypted() const;
|
||||||
|
|
|
@ -7,9 +7,9 @@
|
||||||
#include <QLocale>
|
#include <QLocale>
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
|
|
||||||
#include <common/util.h>
|
#include <Common/Util.h>
|
||||||
#include <wallet/WalletErrors.h>
|
#include <Wallet/WalletErrors.h>
|
||||||
#include <wallet/LegacyKeysImporter.h>
|
#include <Wallet/LegacyKeysImporter.h>
|
||||||
|
|
||||||
#include "NodeAdapter.h"
|
#include "NodeAdapter.h"
|
||||||
#include "Settings.h"
|
#include "Settings.h"
|
||||||
|
@ -127,13 +127,13 @@ bool WalletAdapter::importLegacyWallet(const QString &_password) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
cryptonote::importLegacyKeys(Settings::instance().getWalletFile().toStdString(), _password.toStdString(), m_file);
|
CryptoNote::importLegacyKeys(Settings::instance().getWalletFile().toStdString(), _password.toStdString(), m_file);
|
||||||
closeFile();
|
closeFile();
|
||||||
Settings::instance().setWalletFile(fileName);
|
Settings::instance().setWalletFile(fileName);
|
||||||
return true;
|
return true;
|
||||||
} catch (std::system_error& _err) {
|
} catch (std::system_error& _err) {
|
||||||
closeFile();
|
closeFile();
|
||||||
if (_err.code().value() == cryptonote::error::WRONG_PASSWORD) {
|
if (_err.code().value() == CryptoNote::error::WRONG_PASSWORD) {
|
||||||
Settings::instance().setEncrypted(true);
|
Settings::instance().setEncrypted(true);
|
||||||
Q_EMIT openWalletWithPasswordSignal(!_password.isEmpty());
|
Q_EMIT openWalletWithPasswordSignal(!_password.isEmpty());
|
||||||
}
|
}
|
||||||
|
@ -208,7 +208,7 @@ quint64 WalletAdapter::getTransferCount() const {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WalletAdapter::getTransaction(CryptoNote::TransactionId& _id, CryptoNote::TransactionInfo& _transaction) {
|
bool WalletAdapter::getTransaction(CryptoNote::TransactionId& _id, CryptoNote::WalletLegacyTransaction& _transaction) {
|
||||||
Q_CHECK_PTR(m_wallet);
|
Q_CHECK_PTR(m_wallet);
|
||||||
try {
|
try {
|
||||||
return m_wallet->getTransaction(_id, _transaction);
|
return m_wallet->getTransaction(_id, _transaction);
|
||||||
|
@ -218,7 +218,7 @@ bool WalletAdapter::getTransaction(CryptoNote::TransactionId& _id, CryptoNote::T
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WalletAdapter::getTransfer(CryptoNote::TransferId& _id, CryptoNote::Transfer& _transfer) {
|
bool WalletAdapter::getTransfer(CryptoNote::TransferId& _id, CryptoNote::WalletLegacyTransfer& _transfer) {
|
||||||
Q_CHECK_PTR(m_wallet);
|
Q_CHECK_PTR(m_wallet);
|
||||||
try {
|
try {
|
||||||
return m_wallet->getTransfer(_id, _transfer);
|
return m_wallet->getTransfer(_id, _transfer);
|
||||||
|
@ -228,7 +228,7 @@ bool WalletAdapter::getTransfer(CryptoNote::TransferId& _id, CryptoNote::Transfe
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WalletAdapter::sendTransaction(const QVector<CryptoNote::Transfer>& _transfers, quint64 _fee, const QString& _paymentId, quint64 _mixin) {
|
void WalletAdapter::sendTransaction(const QVector<CryptoNote::WalletLegacyTransfer>& _transfers, quint64 _fee, const QString& _paymentId, quint64 _mixin) {
|
||||||
Q_CHECK_PTR(m_wallet);
|
Q_CHECK_PTR(m_wallet);
|
||||||
try {
|
try {
|
||||||
lock();
|
lock();
|
||||||
|
@ -242,7 +242,7 @@ void WalletAdapter::sendTransaction(const QVector<CryptoNote::Transfer>& _transf
|
||||||
bool WalletAdapter::changePassword(const QString& _oldPassword, const QString& _newPassword) {
|
bool WalletAdapter::changePassword(const QString& _oldPassword, const QString& _newPassword) {
|
||||||
Q_CHECK_PTR(m_wallet);
|
Q_CHECK_PTR(m_wallet);
|
||||||
try {
|
try {
|
||||||
if (m_wallet->changePassword(_oldPassword.toStdString(), _newPassword.toStdString()).value() == cryptonote::error::WRONG_PASSWORD) {
|
if (m_wallet->changePassword(_oldPassword.toStdString(), _newPassword.toStdString()).value() == CryptoNote::error::WRONG_PASSWORD) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} catch (std::system_error&) {
|
} catch (std::system_error&) {
|
||||||
|
@ -281,7 +281,7 @@ void WalletAdapter::onWalletInitCompleted(int _error, const QString& _errorText)
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case cryptonote::error::WRONG_PASSWORD:
|
case CryptoNote::error::WRONG_PASSWORD:
|
||||||
Q_EMIT openWalletWithPasswordSignal(Settings::instance().isEncrypted());
|
Q_EMIT openWalletWithPasswordSignal(Settings::instance().isEncrypted());
|
||||||
Settings::instance().setEncrypted(true);
|
Settings::instance().setEncrypted(true);
|
||||||
delete m_wallet;
|
delete m_wallet;
|
||||||
|
@ -311,7 +311,7 @@ void WalletAdapter::saveCompleted(std::error_code _error) {
|
||||||
Q_EMIT walletSaveCompletedSignal(_error.value(), QString::fromStdString(_error.message()));
|
Q_EMIT walletSaveCompletedSignal(_error.value(), QString::fromStdString(_error.message()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void WalletAdapter::synchronizationProgressUpdated(uint64_t _current, uint64_t _total) {
|
void WalletAdapter::synchronizationProgressUpdated(uint32_t _current, uint32_t _total) {
|
||||||
m_isSynchronized = false;
|
m_isSynchronized = false;
|
||||||
Q_EMIT walletStateChangedSignal(QString("%1 %2/%3").arg(tr("Synchronizing")).arg(_current).arg(_total));
|
Q_EMIT walletStateChangedSignal(QString("%1 %2/%3").arg(tr("Synchronizing")).arg(_current).arg(_total));
|
||||||
Q_EMIT walletSynchronizationProgressUpdatedSignal(_current, _total);
|
Q_EMIT walletSynchronizationProgressUpdatedSignal(_current, _total);
|
||||||
|
@ -352,7 +352,7 @@ void WalletAdapter::onWalletSendTransactionCompleted(CryptoNote::TransactionId _
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
CryptoNote::TransactionInfo transaction;
|
CryptoNote::WalletLegacyTransaction transaction;
|
||||||
if (!this->getTransaction(_transactionId, transaction)) {
|
if (!this->getTransaction(_transactionId, transaction)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,11 +11,11 @@
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
#include <IWallet.h>
|
#include <IWalletLegacy.h>
|
||||||
|
|
||||||
namespace WalletGui {
|
namespace WalletGui {
|
||||||
|
|
||||||
class WalletAdapter : public QObject, public CryptoNote::IWalletObserver {
|
class WalletAdapter : public QObject, public CryptoNote::IWalletLegacyObserver {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_DISABLE_COPY(WalletAdapter)
|
Q_DISABLE_COPY(WalletAdapter)
|
||||||
|
|
||||||
|
@ -32,16 +32,16 @@ public:
|
||||||
quint64 getPendingBalance() const;
|
quint64 getPendingBalance() const;
|
||||||
quint64 getTransactionCount() const;
|
quint64 getTransactionCount() const;
|
||||||
quint64 getTransferCount() const;
|
quint64 getTransferCount() const;
|
||||||
bool getTransaction(CryptoNote::TransactionId& _id, CryptoNote::TransactionInfo& _transaction);
|
bool getTransaction(CryptoNote::TransactionId& _id, CryptoNote::WalletLegacyTransaction& _transaction);
|
||||||
bool getTransfer(CryptoNote::TransferId& _id, CryptoNote::Transfer& _transfer);
|
bool getTransfer(CryptoNote::TransferId& _id, CryptoNote::WalletLegacyTransfer& _transfer);
|
||||||
bool isOpen() const;
|
bool isOpen() const;
|
||||||
void sendTransaction(const QVector<CryptoNote::Transfer>& _transfers, quint64 _fee, const QString& _payment_id, quint64 _mixin);
|
void sendTransaction(const QVector<CryptoNote::WalletLegacyTransfer>& _transfers, quint64 _fee, const QString& _payment_id, quint64 _mixin);
|
||||||
bool changePassword(const QString& _old_pass, const QString& _new_pass);
|
bool changePassword(const QString& _old_pass, const QString& _new_pass);
|
||||||
void setWalletFile(const QString& _path);
|
void setWalletFile(const QString& _path);
|
||||||
|
|
||||||
void initCompleted(std::error_code _result) Q_DECL_OVERRIDE;
|
void initCompleted(std::error_code _result) Q_DECL_OVERRIDE;
|
||||||
void saveCompleted(std::error_code _result) Q_DECL_OVERRIDE;
|
void saveCompleted(std::error_code _result) Q_DECL_OVERRIDE;
|
||||||
void synchronizationProgressUpdated(uint64_t _current, uint64_t _total) Q_DECL_OVERRIDE;
|
void synchronizationProgressUpdated(uint32_t _current, uint32_t _total) Q_DECL_OVERRIDE;
|
||||||
void synchronizationCompleted(std::error_code _error) Q_DECL_OVERRIDE;
|
void synchronizationCompleted(std::error_code _error) Q_DECL_OVERRIDE;
|
||||||
void actualBalanceUpdated(uint64_t _actual_balance) Q_DECL_OVERRIDE;
|
void actualBalanceUpdated(uint64_t _actual_balance) Q_DECL_OVERRIDE;
|
||||||
void pendingBalanceUpdated(uint64_t _pending_balance) Q_DECL_OVERRIDE;
|
void pendingBalanceUpdated(uint64_t _pending_balance) Q_DECL_OVERRIDE;
|
||||||
|
@ -51,7 +51,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::fstream m_file;
|
std::fstream m_file;
|
||||||
CryptoNote::IWallet* m_wallet;
|
CryptoNote::IWalletLegacy* m_wallet;
|
||||||
QMutex m_mutex;
|
QMutex m_mutex;
|
||||||
std::atomic<bool> m_isBackupInProgress;
|
std::atomic<bool> m_isBackupInProgress;
|
||||||
std::atomic<bool> m_isSynchronized;
|
std::atomic<bool> m_isSynchronized;
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
#include <QSystemTrayIcon>
|
#include <QSystemTrayIcon>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
#include <common/util.h>
|
#include <Common/Util.h>
|
||||||
|
|
||||||
#include "AboutDialog.h"
|
#include "AboutDialog.h"
|
||||||
#include "AnimatedLabel.h"
|
#include "AnimatedLabel.h"
|
||||||
|
|
|
@ -61,7 +61,7 @@ void SendFrame::clearAllClicked() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SendFrame::sendClicked() {
|
void SendFrame::sendClicked() {
|
||||||
QVector<CryptoNote::Transfer> walletTransfers;
|
QVector<CryptoNote::WalletLegacyTransfer> walletTransfers;
|
||||||
Q_FOREACH (TransferFrame * transfer, m_transfers) {
|
Q_FOREACH (TransferFrame * transfer, m_transfers) {
|
||||||
QString address = transfer->getAddress();
|
QString address = transfer->getAddress();
|
||||||
if (!CurrencyAdapter::instance().validateAddress(address)) {
|
if (!CurrencyAdapter::instance().validateAddress(address)) {
|
||||||
|
@ -71,7 +71,7 @@ void SendFrame::sendClicked() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
CryptoNote::Transfer walletTransfer;
|
CryptoNote::WalletLegacyTransfer walletTransfer;
|
||||||
walletTransfer.address = address.toStdString();
|
walletTransfer.address = address.toStdString();
|
||||||
uint64_t amount = CurrencyAdapter::instance().parseAmount(transfer->getAmountString());
|
uint64_t amount = CurrencyAdapter::instance().parseAmount(transfer->getAmountString());
|
||||||
walletTransfer.amount = amount;
|
walletTransfer.amount = amount;
|
||||||
|
|
|
@ -123,13 +123,13 @@ QVariant TransactionsModel::data(const QModelIndex& _index, int _role) const {
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
CryptoNote::TransactionInfo transaction;
|
CryptoNote::WalletLegacyTransaction transaction;
|
||||||
CryptoNote::Transfer transfer;
|
CryptoNote::WalletLegacyTransfer transfer;
|
||||||
CryptoNote::TransactionId transactionId = m_transfers.value(_index.row()).first;
|
CryptoNote::TransactionId transactionId = m_transfers.value(_index.row()).first;
|
||||||
CryptoNote::TransferId transferId = m_transfers.value(_index.row()).second;
|
CryptoNote::TransferId transferId = m_transfers.value(_index.row()).second;
|
||||||
|
|
||||||
if(!WalletAdapter::instance().getTransaction(transactionId, transaction) ||
|
if(!WalletAdapter::instance().getTransaction(transactionId, transaction) ||
|
||||||
(m_transfers.value(_index.row()).second != CryptoNote::INVALID_TRANSFER_ID &&
|
(m_transfers.value(_index.row()).second != CryptoNote::WALLET_LEGACY_INVALID_TRANSFER_ID &&
|
||||||
!WalletAdapter::instance().getTransfer(transferId, transfer))) {
|
!WalletAdapter::instance().getTransfer(transferId, transfer))) {
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
@ -259,7 +259,7 @@ QVariant TransactionsModel::getAlignmentRole(const QModelIndex& _index) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant TransactionsModel::getUserRole(const QModelIndex& _index, int _role, CryptoNote::TransactionId _transactionId,
|
QVariant TransactionsModel::getUserRole(const QModelIndex& _index, int _role, CryptoNote::TransactionId _transactionId,
|
||||||
CryptoNote::TransactionInfo& _transaction, CryptoNote::TransferId _transferId, CryptoNote::Transfer& _transfer) const {
|
CryptoNote::WalletLegacyTransaction& _transaction, CryptoNote::TransferId _transferId, CryptoNote::WalletLegacyTransfer& _transfer) const {
|
||||||
switch(_role) {
|
switch(_role) {
|
||||||
case ROLE_DATE:
|
case ROLE_DATE:
|
||||||
return (_transaction.timestamp > 0 ? QDateTime::fromTime_t(_transaction.timestamp) : QDateTime());
|
return (_transaction.timestamp > 0 ? QDateTime::fromTime_t(_transaction.timestamp) : QDateTime());
|
||||||
|
@ -278,13 +278,13 @@ QVariant TransactionsModel::getUserRole(const QModelIndex& _index, int _role, Cr
|
||||||
}
|
}
|
||||||
|
|
||||||
case ROLE_HASH:
|
case ROLE_HASH:
|
||||||
return QByteArray(reinterpret_cast<char*>(&_transaction.hash.front()), _transaction.hash.size());
|
return QByteArray(reinterpret_cast<char*>(&_transaction.hash), sizeof(_transaction.hash));
|
||||||
|
|
||||||
case ROLE_ADDRESS:
|
case ROLE_ADDRESS:
|
||||||
return QString::fromStdString(_transfer.address);
|
return QString::fromStdString(_transfer.address);
|
||||||
|
|
||||||
case ROLE_AMOUNT:
|
case ROLE_AMOUNT:
|
||||||
return static_cast<qint64>(_transferId == CryptoNote::INVALID_TRANSFER_ID ? _transaction.totalAmount : -_transfer.amount);
|
return static_cast<qint64>(_transferId == CryptoNote::WALLET_LEGACY_INVALID_TRANSFER_ID ? _transaction.totalAmount : -_transfer.amount);
|
||||||
|
|
||||||
case ROLE_PAYMENT_ID:
|
case ROLE_PAYMENT_ID:
|
||||||
return NodeAdapter::instance().extractPaymentId(_transaction.extra);
|
return NodeAdapter::instance().extractPaymentId(_transaction.extra);
|
||||||
|
@ -304,7 +304,7 @@ QVariant TransactionsModel::getUserRole(const QModelIndex& _index, int _role, Cr
|
||||||
return static_cast<quint64>(_transaction.fee);
|
return static_cast<quint64>(_transaction.fee);
|
||||||
|
|
||||||
case ROLE_NUMBER_OF_CONFIRMATIONS:
|
case ROLE_NUMBER_OF_CONFIRMATIONS:
|
||||||
return (_transaction.blockHeight == CryptoNote::UNCONFIRMED_TRANSACTION_HEIGHT ? 0 :
|
return (_transaction.blockHeight == CryptoNote::WALLET_LEGACY_UNCONFIRMED_TRANSACTION_HEIGHT ? 0 :
|
||||||
NodeAdapter::instance().getLastKnownBlockHeight() - _transaction.blockHeight + 1);
|
NodeAdapter::instance().getLastKnownBlockHeight() - _transaction.blockHeight + 1);
|
||||||
|
|
||||||
case ROLE_COLUMN:
|
case ROLE_COLUMN:
|
||||||
|
@ -335,7 +335,7 @@ void TransactionsModel::reloadWalletTransactions() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void TransactionsModel::appendTransaction(CryptoNote::TransactionId _transactionId, quint32& _insertedRowCount) {
|
void TransactionsModel::appendTransaction(CryptoNote::TransactionId _transactionId, quint32& _insertedRowCount) {
|
||||||
CryptoNote::TransactionInfo transaction;
|
CryptoNote::WalletLegacyTransaction transaction;
|
||||||
if (!WalletAdapter::instance().getTransaction(_transactionId, transaction)) {
|
if (!WalletAdapter::instance().getTransaction(_transactionId, transaction)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -348,7 +348,7 @@ void TransactionsModel::appendTransaction(CryptoNote::TransactionId _transaction
|
||||||
++_insertedRowCount;
|
++_insertedRowCount;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
m_transfers.append(TransactionTransferId(_transactionId, CryptoNote::INVALID_TRANSFER_ID));
|
m_transfers.append(TransactionTransferId(_transactionId, CryptoNote::WALLET_LEGACY_INVALID_TRANSFER_ID));
|
||||||
m_transactionRow[_transactionId] = qMakePair(m_transfers.size() - 1, 1);
|
m_transactionRow[_transactionId] = qMakePair(m_transfers.size() - 1, 1);
|
||||||
++_insertedRowCount;
|
++_insertedRowCount;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
#include <QAbstractItemModel>
|
#include <QAbstractItemModel>
|
||||||
#include <QSortFilterProxyModel>
|
#include <QSortFilterProxyModel>
|
||||||
|
|
||||||
#include <IWallet.h>
|
#include <IWalletLegacy.h>
|
||||||
|
|
||||||
namespace WalletGui {
|
namespace WalletGui {
|
||||||
|
|
||||||
|
@ -52,8 +52,8 @@ private:
|
||||||
QVariant getDisplayRole(const QModelIndex& _index) const;
|
QVariant getDisplayRole(const QModelIndex& _index) const;
|
||||||
QVariant getDecorationRole(const QModelIndex& _index) const;
|
QVariant getDecorationRole(const QModelIndex& _index) const;
|
||||||
QVariant getAlignmentRole(const QModelIndex& _index) const;
|
QVariant getAlignmentRole(const QModelIndex& _index) const;
|
||||||
QVariant getUserRole(const QModelIndex& _index, int _role, CryptoNote::TransactionId _transactionId, CryptoNote::TransactionInfo& _transaction,
|
QVariant getUserRole(const QModelIndex& _index, int _role, CryptoNote::TransactionId _transactionId, CryptoNote::WalletLegacyTransaction& _transaction,
|
||||||
CryptoNote::TransferId _transferId, CryptoNote::Transfer& _transfer) const;
|
CryptoNote::TransferId _transferId, CryptoNote::WalletLegacyTransfer& _transfer) const;
|
||||||
|
|
||||||
void reloadWalletTransactions();
|
void reloadWalletTransactions();
|
||||||
void appendTransaction(CryptoNote::TransactionId _id, quint32& _row_count);
|
void appendTransaction(CryptoNote::TransactionId _id, quint32& _row_count);
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
|
|
||||||
#include "CommandLineParser.h"
|
#include "CommandLineParser.h"
|
||||||
#include "CurrencyAdapter.h"
|
#include "CurrencyAdapter.h"
|
||||||
|
#include "LoggerAdapter.h"
|
||||||
#include "NodeAdapter.h"
|
#include "NodeAdapter.h"
|
||||||
#include "Settings.h"
|
#include "Settings.h"
|
||||||
#include "SignalHandler.h"
|
#include "SignalHandler.h"
|
||||||
|
@ -33,9 +34,9 @@ int main(int argc, char* argv[]) {
|
||||||
QApplication::setStyle(QStyleFactory::create("Fusion"));
|
QApplication::setStyle(QStyleFactory::create("Fusion"));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
CommandLineParser cmdLineParser;
|
CommandLineParser cmdLineParser(nullptr);
|
||||||
Settings::instance().setCommandLineParser(&cmdLineParser);
|
Settings::instance().setCommandLineParser(&cmdLineParser);
|
||||||
bool cmdLineParseResult = cmdLineParser.process();
|
bool cmdLineParseResult = cmdLineParser.process(app.arguments());
|
||||||
Settings::instance().load();
|
Settings::instance().load();
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
|
@ -48,6 +49,8 @@ int main(int argc, char* argv[]) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
LoggerAdapter::instance().init();
|
||||||
|
|
||||||
QString dataDirPath = Settings::instance().getDataDir().absolutePath();
|
QString dataDirPath = Settings::instance().getDataDir().absolutePath();
|
||||||
if (!QDir().exists(dataDirPath)) {
|
if (!QDir().exists(dataDirPath)) {
|
||||||
QDir().mkpath(dataDirPath);
|
QDir().mkpath(dataDirPath);
|
||||||
|
|
Loading…
Reference in a new issue