diff --git a/include/IWallet.h b/include/IWallet.h index 5cfaff32..0711c4a0 100644 --- a/include/IWallet.h +++ b/include/IWallet.h @@ -209,6 +209,7 @@ class IWallet { virtual std::vector getTransfers(size_t index, uint32_t flags) const = 0; virtual std::string getReserveProof(const uint64_t &reserve, const std::string& address, const std::string &message) = 0; + virtual std::string getSpendableOutputs(const std::string& address) = 0; virtual size_t transfer(const TransactionParameters& sendingTransaction, Crypto::SecretKey &txSecretKey) = 0; diff --git a/src/PaymentGate/PaymentServiceJsonRpcMessages.cpp b/src/PaymentGate/PaymentServiceJsonRpcMessages.cpp index 27456127..f306ee35 100644 --- a/src/PaymentGate/PaymentServiceJsonRpcMessages.cpp +++ b/src/PaymentGate/PaymentServiceJsonRpcMessages.cpp @@ -320,6 +320,18 @@ void GetReserveProof::Response::serialize(DynexCN::ISerializer& serializer) { serializer(reserveProof, "reserveProof"); } +// offline-signature: +void ExportOutputs::Request::serialize(DynexCN::ISerializer& serializer) { + if (!serializer(address, "address")) { + throw RequestSerializationError(); + } +} + +void ExportOutputs::Response::serialize(DynexCN::ISerializer& serializer) { + serializer(message, "message"); +} +// -- + void WalletRpcOrder::serialize(DynexCN::ISerializer& serializer) { bool r = serializer(address, "address"); r &= serializer(amount, "amount"); diff --git a/src/PaymentGate/PaymentServiceJsonRpcMessages.h b/src/PaymentGate/PaymentServiceJsonRpcMessages.h index 6b0177ea..249abd46 100644 --- a/src/PaymentGate/PaymentServiceJsonRpcMessages.h +++ b/src/PaymentGate/PaymentServiceJsonRpcMessages.h @@ -399,6 +399,21 @@ struct GetReserveProof { }; }; +// offline-signature: +struct ExportOutputs { + struct Request { + std::string address; + + void serialize(DynexCN::ISerializer& serializer); + }; + + struct Response { + std::string message; + + void serialize(DynexCN::ISerializer& serializer); + }; +}; + struct WalletRpcOrder { std::string address; uint64_t amount; diff --git a/src/PaymentGate/PaymentServiceJsonRpcServer.cpp b/src/PaymentGate/PaymentServiceJsonRpcServer.cpp index 6bbc5c67..13d670bf 100644 --- a/src/PaymentGate/PaymentServiceJsonRpcServer.cpp +++ b/src/PaymentGate/PaymentServiceJsonRpcServer.cpp @@ -82,6 +82,7 @@ PaymentServiceJsonRpcServer::PaymentServiceJsonRpcServer(System::Dispatcher& sys handlers.emplace("estimateFusion", jsonHandler(std::bind(&PaymentServiceJsonRpcServer::handleEstimateFusion, this, std::placeholders::_1, std::placeholders::_2))); handlers.emplace("validateAddress", jsonHandler(std::bind(&PaymentServiceJsonRpcServer::handleValidateAddress, this, std::placeholders::_1, std::placeholders::_2))); handlers.emplace("getReserveProof", jsonHandler(std::bind(&PaymentServiceJsonRpcServer::handleGetReserveProof, this, std::placeholders::_1, std::placeholders::_2))); + handlers.emplace("exportOutputs", jsonHandler(std::bind(&PaymentServiceJsonRpcServer::handleexportOutputs, this, std::placeholders::_1, std::placeholders::_2))); } void PaymentServiceJsonRpcServer::processJsonRpcRequest(const Common::JsonValue& req, Common::JsonValue& resp) { @@ -229,6 +230,11 @@ std::error_code PaymentServiceJsonRpcServer::handleGetReserveProof(const GetRese return service.getReserveProof(response.reserveProof, request.address, request.message, request.amount); } +// offline-signature +std::error_code PaymentServiceJsonRpcServer::handleexportOutputs(const ExportOutputs::Request& request, ExportOutputs::Response& response) { + return service.getExportOutputs(response.message, request.address); +} + std::error_code PaymentServiceJsonRpcServer::handleSendTransaction(const SendTransaction::Request& request, SendTransaction::Response& response) { return service.sendTransaction(request, response.transactionHash, response.transactionSecretKey); } diff --git a/src/PaymentGate/PaymentServiceJsonRpcServer.h b/src/PaymentGate/PaymentServiceJsonRpcServer.h index d24fbb82..3f9b9293 100644 --- a/src/PaymentGate/PaymentServiceJsonRpcServer.h +++ b/src/PaymentGate/PaymentServiceJsonRpcServer.h @@ -117,9 +117,10 @@ class PaymentServiceJsonRpcServer : public DynexCN::JsonRpcServer { std::error_code handleGetAddresses(const GetAddresses::Request& request, GetAddresses::Response& response); std::error_code handleValidateAddress(const ValidateAddress::Request& request, ValidateAddress::Response& response); std::error_code handleGetReserveProof(const GetReserveProof::Request& request, GetReserveProof::Response& response); - std::error_code handleSendFusionTransaction(const SendFusionTransaction::Request& request, SendFusionTransaction::Response& response); std::error_code handleEstimateFusion(const EstimateFusion::Request& request, EstimateFusion::Response& response); + // offline signature: + std::error_code handleexportOutputs(const ExportOutputs::Request& request, ExportOutputs::Response& response); }; }//namespace PaymentService diff --git a/src/PaymentGate/WalletService.cpp b/src/PaymentGate/WalletService.cpp index cd7261be..cf471284 100644 --- a/src/PaymentGate/WalletService.cpp +++ b/src/PaymentGate/WalletService.cpp @@ -1183,6 +1183,21 @@ std::error_code WalletService::getReserveProof(std::string& reserveProof, const return std::error_code(); } +// offline-signature +std::error_code WalletService::getExportOutputs(std::string& message, const std::string& address) { + try { + System::EventLock lk(readyEvent); + message = wallet.getSpendableOutputs(address); + } catch (std::system_error& x) { + logger(Logging::WARNING, Logging::BRIGHT_YELLOW) << "Error while getting outputs: " << x.what(); + return x.code(); + } catch (std::exception& x) { + logger(Logging::WARNING, Logging::BRIGHT_YELLOW) << "Error while getting outputs: " << x.what(); + return make_error_code(DynexCN::error::INTERNAL_WALLET_ERROR); + } + return std::error_code(); +} + std::error_code WalletService::getAddresses(std::vector& addresses) { try { System::EventLock lk(readyEvent); diff --git a/src/PaymentGate/WalletService.h b/src/PaymentGate/WalletService.h index dc47f548..3677b759 100644 --- a/src/PaymentGate/WalletService.h +++ b/src/PaymentGate/WalletService.h @@ -126,6 +126,7 @@ class WalletService { std::error_code estimateFusion(uint64_t threshold, const std::vector& addresses, uint32_t& fusionReadyCount, uint32_t& totalOutputCount); std::error_code validateAddress(const std::string& address, bool& isvalid, std::string& _address, std::string& spendPublicKey, std::string& viewPublicKey); std::error_code getReserveProof(std::string& reserveProof, const std::string& address, const std::string& message, const uint64_t& amount = 0); + std::error_code getExportOutputs(std::string& message, const std::string& address); private: void refresh(); diff --git a/src/Wallet/WalletGreen.cpp b/src/Wallet/WalletGreen.cpp index 1eba058c..be764535 100644 --- a/src/Wallet/WalletGreen.cpp +++ b/src/Wallet/WalletGreen.cpp @@ -78,6 +78,9 @@ #include "WalletUtils.h" #include "DynexCNCore/TransactionExtra.h" +// offline signature: +#include + extern "C" { #include "crypto/keccak.h" @@ -2830,6 +2833,29 @@ bool WalletGreen::getTransactionProof(const Crypto::Hash& transactionHash, const return true; } +// offline-signature: +std::string WalletGreen::getSpendableOutputs(const std::string& address) { + throwIfNotInitialized(); + throwIfStopped(); + + WalletOuts outs = pickWallet(address); + + std::cout << "Exporting outputs: " << outs.outs.size() << std::endl; + + std::stringstream fout; + for (auto& t : outs.outs) { + fout.write(reinterpret_cast(&t.amount), sizeof(t.amount)); + fout.write(reinterpret_cast(&t.globalOutputIndex), sizeof(t.globalOutputIndex)); + fout.write(reinterpret_cast(&t.outputInTransaction), sizeof(t.outputInTransaction)); + fout.write(reinterpret_cast(&t.transactionHash), sizeof(t.transactionHash)); + fout.write(reinterpret_cast(&t.transactionPublicKey), sizeof(t.transactionPublicKey)); + fout.write(reinterpret_cast(&t.outputKey), sizeof(t.outputKey)); + fout.write(reinterpret_cast(&t.requiredSignatures), sizeof(t.requiredSignatures)); + } + + return Tools::Base64::encode(fout.str()); +} + std::string WalletGreen::getReserveProof(const uint64_t &reserve, const std::string& address, const std::string &message) { throwIfNotInitialized(); throwIfTrackingMode(); diff --git a/src/Wallet/WalletGreen.h b/src/Wallet/WalletGreen.h index e71bc964..ba2fbf90 100644 --- a/src/Wallet/WalletGreen.h +++ b/src/Wallet/WalletGreen.h @@ -119,6 +119,8 @@ class WalletGreen : public IWallet, virtual std::vector getTransfers(size_t index, uint32_t flags) const override; virtual std::string getReserveProof(const uint64_t &reserve, const std::string& address, const std::string &message) override; + // offline signature: + virtual std::string getSpendableOutputs(const std::string& address) override; virtual size_t transfer(const TransactionParameters& sendingTransaction, Crypto::SecretKey& txSecretKey) override;