2015-07-30 15:22:07 +00:00
|
|
|
// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers
|
|
|
|
//
|
|
|
|
// This file is part of Bytecoin.
|
|
|
|
//
|
|
|
|
// Bytecoin is free software: you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU Lesser General Public License as published by
|
|
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
|
|
// (at your option) any later version.
|
|
|
|
//
|
|
|
|
// Bytecoin is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
// GNU Lesser General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU Lesser General Public License
|
|
|
|
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
#include "PaymentGateService.h"
|
|
|
|
|
|
|
|
#include <future>
|
|
|
|
|
|
|
|
#include "Common/SignalHandler.h"
|
|
|
|
#include "InProcessNode/InProcessNode.h"
|
|
|
|
#include "Logging/LoggerRef.h"
|
|
|
|
#include "PaymentGate/PaymentServiceJsonRpcServer.h"
|
|
|
|
|
|
|
|
#include "CryptoNoteCore/CoreConfig.h"
|
|
|
|
#include "CryptoNoteCore/Core.h"
|
|
|
|
#include "CryptoNoteProtocol/CryptoNoteProtocolHandler.h"
|
|
|
|
#include "P2p/NetNode.h"
|
|
|
|
#include <System/Context.h>
|
|
|
|
|
|
|
|
#ifdef ERROR
|
|
|
|
#undef ERROR
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
#include <direct.h>
|
|
|
|
#else
|
|
|
|
#include <unistd.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
using namespace PaymentService;
|
|
|
|
|
|
|
|
void changeDirectory(const std::string& path) {
|
|
|
|
if (chdir(path.c_str())) {
|
|
|
|
throw std::runtime_error("Couldn't change directory to \'" + path + "\': " + strerror(errno));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void stopSignalHandler(PaymentGateService* pg) {
|
|
|
|
pg->stop();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool PaymentGateService::init(int argc, char** argv) {
|
|
|
|
if (!config.init(argc, argv)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
logger.setMaxLevel(static_cast<Logging::Level>(config.gateConfiguration.logLevel));
|
|
|
|
logger.addLogger(consoleLogger);
|
|
|
|
|
|
|
|
Logging::LoggerRef log(logger, "main");
|
|
|
|
|
|
|
|
if (config.gateConfiguration.testnet) {
|
|
|
|
log(Logging::INFO) << "Starting in testnet mode";
|
|
|
|
currencyBuilder.testnet(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!config.gateConfiguration.serverRoot.empty()) {
|
|
|
|
changeDirectory(config.gateConfiguration.serverRoot);
|
|
|
|
log(Logging::INFO) << "Current working directory now is " << config.gateConfiguration.serverRoot;
|
|
|
|
}
|
|
|
|
|
|
|
|
fileStream.open(config.gateConfiguration.logFile, std::ofstream::app);
|
|
|
|
|
|
|
|
if (!fileStream) {
|
|
|
|
throw std::runtime_error("Couldn't open log file");
|
|
|
|
}
|
|
|
|
|
|
|
|
fileLogger.attachToStream(fileStream);
|
|
|
|
logger.addLogger(fileLogger);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
WalletConfiguration PaymentGateService::getWalletConfig() const {
|
|
|
|
return WalletConfiguration{
|
|
|
|
config.gateConfiguration.walletFile,
|
|
|
|
config.gateConfiguration.walletPassword
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
const CryptoNote::Currency PaymentGateService::getCurrency() {
|
|
|
|
return currencyBuilder.currency();
|
|
|
|
}
|
|
|
|
|
|
|
|
void PaymentGateService::run() {
|
|
|
|
|
|
|
|
System::Dispatcher localDispatcher;
|
|
|
|
System::Event localStopEvent(localDispatcher);
|
|
|
|
|
|
|
|
this->dispatcher = &localDispatcher;
|
|
|
|
this->stopEvent = &localStopEvent;
|
|
|
|
|
|
|
|
Tools::SignalHandler::install(std::bind(&stopSignalHandler, this));
|
|
|
|
|
|
|
|
Logging::LoggerRef log(logger, "run");
|
|
|
|
|
|
|
|
if (config.startInprocess) {
|
|
|
|
runInProcess(log);
|
|
|
|
} else {
|
|
|
|
runRpcProxy(log);
|
|
|
|
}
|
|
|
|
|
|
|
|
this->dispatcher = nullptr;
|
|
|
|
this->stopEvent = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PaymentGateService::stop() {
|
|
|
|
Logging::LoggerRef log(logger, "stop");
|
|
|
|
|
|
|
|
log(Logging::INFO) << "Stop signal caught";
|
|
|
|
|
|
|
|
if (dispatcher != nullptr) {
|
|
|
|
dispatcher->remoteSpawn([&]() {
|
|
|
|
if (stopEvent != nullptr) {
|
|
|
|
stopEvent->set();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void PaymentGateService::runInProcess(Logging::LoggerRef& log) {
|
|
|
|
log(Logging::INFO) << "Starting Payment Gate with local node";
|
|
|
|
|
|
|
|
CryptoNote::Currency currency = currencyBuilder.currency();
|
|
|
|
CryptoNote::core core(currency, NULL, logger);
|
|
|
|
|
|
|
|
CryptoNote::CryptoNoteProtocolHandler protocol(currency, *dispatcher, core, NULL, logger);
|
|
|
|
CryptoNote::NodeServer p2pNode(*dispatcher, protocol, logger);
|
|
|
|
|
|
|
|
protocol.set_p2p_endpoint(&p2pNode);
|
|
|
|
core.set_cryptonote_protocol(&protocol);
|
|
|
|
|
|
|
|
log(Logging::INFO) << "initializing p2pNode";
|
|
|
|
if (!p2pNode.init(config.netNodeConfig)) {
|
|
|
|
throw std::runtime_error("Failed to init p2pNode");
|
|
|
|
}
|
|
|
|
|
|
|
|
log(Logging::INFO) << "initializing core";
|
|
|
|
CryptoNote::MinerConfig emptyMiner;
|
|
|
|
core.init(config.coreConfig, emptyMiner, true);
|
|
|
|
|
|
|
|
std::promise<std::error_code> initPromise;
|
|
|
|
auto initFuture = initPromise.get_future();
|
|
|
|
|
|
|
|
std::unique_ptr<CryptoNote::INode> node(new CryptoNote::InProcessNode(core, protocol));
|
|
|
|
|
|
|
|
node->init([&initPromise, &log](std::error_code ec) {
|
|
|
|
if (ec) {
|
2015-10-01 15:27:18 +00:00
|
|
|
log(Logging::WARNING, Logging::YELLOW) << "Failed to init node: " << ec.message();
|
2015-07-30 15:22:07 +00:00
|
|
|
} else {
|
|
|
|
log(Logging::INFO) << "node is inited successfully";
|
|
|
|
}
|
|
|
|
|
|
|
|
initPromise.set_value(ec);
|
|
|
|
});
|
|
|
|
|
|
|
|
auto ec = initFuture.get();
|
|
|
|
if (ec) {
|
|
|
|
throw std::system_error(ec);
|
|
|
|
}
|
|
|
|
|
|
|
|
log(Logging::INFO) << "Spawning p2p server";
|
|
|
|
|
|
|
|
System::Event p2pStarted(*dispatcher);
|
|
|
|
|
|
|
|
System::Context<> context(*dispatcher, [&]() {
|
|
|
|
p2pStarted.set();
|
|
|
|
p2pNode.run();
|
|
|
|
});
|
|
|
|
|
|
|
|
p2pStarted.wait();
|
|
|
|
|
|
|
|
runWalletService(currency, *node);
|
|
|
|
|
|
|
|
p2pNode.sendStopSignal();
|
|
|
|
context.get();
|
|
|
|
node->shutdown();
|
|
|
|
core.deinit();
|
|
|
|
p2pNode.deinit();
|
|
|
|
}
|
|
|
|
|
|
|
|
void PaymentGateService::runRpcProxy(Logging::LoggerRef& log) {
|
|
|
|
log(Logging::INFO) << "Starting Payment Gate with remote node";
|
|
|
|
CryptoNote::Currency currency = currencyBuilder.currency();
|
|
|
|
|
|
|
|
std::unique_ptr<CryptoNote::INode> node(
|
|
|
|
PaymentService::NodeFactory::createNode(
|
|
|
|
config.remoteNodeConfig.daemonHost,
|
|
|
|
config.remoteNodeConfig.daemonPort));
|
|
|
|
|
|
|
|
runWalletService(currency, *node);
|
|
|
|
}
|
|
|
|
|
|
|
|
void PaymentGateService::runWalletService(const CryptoNote::Currency& currency, CryptoNote::INode& node) {
|
|
|
|
PaymentService::WalletConfiguration walletConfiguration{
|
|
|
|
config.gateConfiguration.walletFile,
|
|
|
|
config.gateConfiguration.walletPassword
|
|
|
|
};
|
|
|
|
|
|
|
|
service = new PaymentService::WalletService(currency, *dispatcher, node, walletConfiguration, logger);
|
|
|
|
std::unique_ptr<PaymentService::WalletService> serviceGuard(service);
|
|
|
|
try {
|
|
|
|
service->init();
|
|
|
|
} catch (std::exception& e) {
|
2015-10-01 15:27:18 +00:00
|
|
|
Logging::LoggerRef(logger, "run")(Logging::ERROR, Logging::BRIGHT_RED) << "Failed to init walletService reason: " << e.what();
|
2015-07-30 15:22:07 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (config.gateConfiguration.printAddresses) {
|
|
|
|
// print addresses and exit
|
|
|
|
size_t addressCount = 0;
|
|
|
|
service->getAddressCount(addressCount);
|
|
|
|
for (size_t i = 0; i < addressCount; ++i) {
|
|
|
|
std::string address;
|
|
|
|
if (service->getAddress(i, address) == std::error_code()) {
|
|
|
|
std::cout << "Address: " << address << std::endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
PaymentService::PaymentServiceJsonRpcServer rpcServer(*dispatcher, *stopEvent, *service, logger);
|
|
|
|
rpcServer.start(config.gateConfiguration.bindAddress, config.gateConfiguration.bindPort);
|
|
|
|
|
|
|
|
try {
|
|
|
|
service->saveWallet();
|
|
|
|
} catch (std::exception& ex) {
|
2015-10-01 15:27:18 +00:00
|
|
|
Logging::LoggerRef(logger, "saveWallet")(Logging::WARNING, Logging::YELLOW) << "Couldn't save wallet: " << ex.what();
|
2015-07-30 15:22:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|