mirror of
https://github.com/jwinterm/aeon.git
synced 2026-10-22 05:58:33 +02:00
version-1.4
This commit is contained in:
+190
-5
@@ -38,10 +38,14 @@ void do_prepare_file_names(const std::string& file_path, std::string& keys_file,
|
||||
keys_file += ".keys";
|
||||
}
|
||||
}
|
||||
|
||||
} //namespace
|
||||
|
||||
namespace tools
|
||||
{
|
||||
// for now, limit to 30 attempts. TODO: discuss a good number to limit to.
|
||||
const size_t MAX_SPLIT_ATTEMPTS = 30;
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::init(const std::string& daemon_address, uint64_t upper_transaction_size_limit)
|
||||
{
|
||||
@@ -435,7 +439,7 @@ void wallet2::load_keys(const std::string& keys_file_name, const std::string& pa
|
||||
THROW_WALLET_EXCEPTION_IF(!r, error::invalid_password);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::generate(const std::string& wallet_, const std::string& password)
|
||||
crypto::secret_key wallet2::generate(const std::string& wallet_, const std::string& password, const crypto::secret_key& recovery_param, bool recover, bool two_random)
|
||||
{
|
||||
clear();
|
||||
prepare_file_names(wallet_);
|
||||
@@ -444,7 +448,8 @@ void wallet2::generate(const std::string& wallet_, const std::string& password)
|
||||
THROW_WALLET_EXCEPTION_IF(boost::filesystem::exists(m_wallet_file, ignored_ec), error::file_exists, m_wallet_file);
|
||||
THROW_WALLET_EXCEPTION_IF(boost::filesystem::exists(m_keys_file, ignored_ec), error::file_exists, m_keys_file);
|
||||
|
||||
m_account.generate();
|
||||
crypto::secret_key retval = m_account.generate(recovery_param, recover, two_random);
|
||||
|
||||
m_account_public_address = m_account.get_keys().m_account_address;
|
||||
|
||||
bool r = store_keys(m_keys_file, password);
|
||||
@@ -454,6 +459,7 @@ void wallet2::generate(const std::string& wallet_, const std::string& password)
|
||||
if(!r) LOG_PRINT_RED_L0("String with address text not saved");
|
||||
|
||||
store();
|
||||
return retval;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::wallet_exists(const std::string& file_path, bool& keys_file_exists, bool& wallet_file_exists)
|
||||
@@ -627,10 +633,17 @@ namespace
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
// Select random input sources for transaction.
|
||||
// returns:
|
||||
// direct return: amount of money found
|
||||
// modified reference: selected_transfers, a list of iterators/indices of input sources
|
||||
uint64_t wallet2::select_transfers(uint64_t needed_money, bool add_dust, uint64_t dust, std::list<transfer_container::iterator>& selected_transfers)
|
||||
{
|
||||
std::vector<size_t> unused_transfers_indices;
|
||||
std::vector<size_t> unused_dust_indices;
|
||||
|
||||
// aggregate sources available for transfers
|
||||
// if dust needed, take dust from only one source (so require source has at least dust amount)
|
||||
for (size_t i = 0; i < m_transfers.size(); ++i)
|
||||
{
|
||||
const transfer_details& td = m_transfers[i];
|
||||
@@ -675,16 +688,188 @@ void wallet2::add_unconfirmed_tx(const cryptonote::transaction& tx, uint64_t cha
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::transfer(const std::vector<cryptonote::tx_destination_entry>& dsts, size_t fake_outputs_count,
|
||||
uint64_t unlock_time, uint64_t fee, const std::vector<uint8_t>& extra, cryptonote::transaction& tx)
|
||||
uint64_t unlock_time, uint64_t fee, const std::vector<uint8_t>& extra, cryptonote::transaction& tx, pending_tx& ptx)
|
||||
{
|
||||
transfer(dsts, fake_outputs_count, unlock_time, fee, extra, detail::digit_split_strategy, tx_dust_policy(fee), tx);
|
||||
transfer(dsts, fake_outputs_count, unlock_time, fee, extra, detail::digit_split_strategy, tx_dust_policy(fee), tx, ptx);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::transfer(const std::vector<cryptonote::tx_destination_entry>& dsts, size_t fake_outputs_count,
|
||||
uint64_t unlock_time, uint64_t fee, const std::vector<uint8_t>& extra)
|
||||
{
|
||||
cryptonote::transaction tx;
|
||||
transfer(dsts, fake_outputs_count, unlock_time, fee, extra, tx);
|
||||
pending_tx ptx;
|
||||
transfer(dsts, fake_outputs_count, unlock_time, fee, extra, tx, ptx);
|
||||
}
|
||||
|
||||
namespace {
|
||||
// split_amounts(vector<cryptonote::tx_destination_entry> dsts, size_t num_splits)
|
||||
//
|
||||
// split amount for each dst in dsts into num_splits parts
|
||||
// and make num_splits new vector<crypt...> instances to hold these new amounts
|
||||
std::vector<std::vector<cryptonote::tx_destination_entry>> split_amounts(
|
||||
std::vector<cryptonote::tx_destination_entry> dsts, size_t num_splits)
|
||||
{
|
||||
std::vector<std::vector<cryptonote::tx_destination_entry>> retVal;
|
||||
|
||||
if (num_splits <= 1)
|
||||
{
|
||||
retVal.push_back(dsts);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
// for each split required
|
||||
for (size_t i=0; i < num_splits; i++)
|
||||
{
|
||||
std::vector<cryptonote::tx_destination_entry> new_dsts;
|
||||
|
||||
// for each destination
|
||||
for (size_t j=0; j < dsts.size(); j++)
|
||||
{
|
||||
cryptonote::tx_destination_entry de;
|
||||
uint64_t amount;
|
||||
|
||||
amount = dsts[j].amount;
|
||||
amount = amount / num_splits;
|
||||
|
||||
// if last split, add remainder
|
||||
if (i + 1 == num_splits)
|
||||
{
|
||||
amount += dsts[j].amount % num_splits;
|
||||
}
|
||||
|
||||
de.addr = dsts[j].addr;
|
||||
de.amount = amount;
|
||||
|
||||
new_dsts.push_back(de);
|
||||
}
|
||||
|
||||
retVal.push_back(new_dsts);
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
} // anonymous namespace
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
// take a pending tx and actually send it to the daemon
|
||||
void wallet2::commit_tx(pending_tx& ptx)
|
||||
{
|
||||
using namespace cryptonote;
|
||||
COMMAND_RPC_SEND_RAW_TX::request req;
|
||||
req.tx_as_hex = epee::string_tools::buff_to_hex_nodelimer(tx_to_blob(ptx.tx));
|
||||
COMMAND_RPC_SEND_RAW_TX::response daemon_send_resp;
|
||||
bool r = epee::net_utils::invoke_http_json_remote_command2(m_daemon_address + "/sendrawtransaction", req, daemon_send_resp, m_http_client, 200000);
|
||||
THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "sendrawtransaction");
|
||||
THROW_WALLET_EXCEPTION_IF(daemon_send_resp.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "sendrawtransaction");
|
||||
THROW_WALLET_EXCEPTION_IF(daemon_send_resp.status != CORE_RPC_STATUS_OK, error::tx_rejected, ptx.tx, daemon_send_resp.status);
|
||||
|
||||
add_unconfirmed_tx(ptx.tx, ptx.change_dts.amount);
|
||||
|
||||
LOG_PRINT_L2("transaction " << get_transaction_hash(ptx.tx) << " generated ok and sent to daemon, key_images: [" << ptx.key_images << "]");
|
||||
|
||||
BOOST_FOREACH(transfer_container::iterator it, ptx.selected_transfers)
|
||||
it->m_spent = true;
|
||||
|
||||
LOG_PRINT_L0("Transaction successfully sent. <" << get_transaction_hash(ptx.tx) << ">" << ENDL
|
||||
<< "Commission: " << print_money(ptx.fee+ptx.dust) << " (dust: " << print_money(ptx.dust) << ")" << ENDL
|
||||
<< "Balance: " << print_money(balance()) << ENDL
|
||||
<< "Unlocked: " << print_money(unlocked_balance()) << ENDL
|
||||
<< "Please, wait for confirmation for your balance to be unlocked.");
|
||||
}
|
||||
|
||||
void wallet2::commit_tx(std::vector<pending_tx>& ptx_vector)
|
||||
{
|
||||
for (auto & ptx : ptx_vector)
|
||||
{
|
||||
commit_tx(ptx);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
// separated the call(s) to wallet2::transfer into their own function
|
||||
//
|
||||
// this function will make multiple calls to wallet2::transfer if multiple
|
||||
// transactions will be required
|
||||
std::vector<wallet2::pending_tx> wallet2::create_transactions(std::vector<cryptonote::tx_destination_entry> dsts, const size_t fake_outs_count, const uint64_t unlock_time, const uint64_t fee, const std::vector<uint8_t> extra)
|
||||
{
|
||||
|
||||
// failsafe split attempt counter
|
||||
size_t attempt_count = 0;
|
||||
|
||||
for(attempt_count = 1; ;attempt_count++)
|
||||
{
|
||||
auto split_values = split_amounts(dsts, attempt_count);
|
||||
|
||||
// Throw if split_amounts comes back with a vector of size different than it should
|
||||
if (split_values.size() != attempt_count)
|
||||
{
|
||||
throw std::runtime_error("Splitting transactions returned a number of potential tx not equal to what was requested");
|
||||
}
|
||||
|
||||
std::vector<pending_tx> ptx_vector;
|
||||
try
|
||||
{
|
||||
// for each new destination vector (i.e. for each new tx)
|
||||
for (auto & dst_vector : split_values)
|
||||
{
|
||||
cryptonote::transaction tx;
|
||||
pending_tx ptx;
|
||||
transfer(dst_vector, fake_outs_count, unlock_time, fee, extra, tx, ptx);
|
||||
ptx_vector.push_back(ptx);
|
||||
|
||||
// mark transfers to be used as "spent"
|
||||
BOOST_FOREACH(transfer_container::iterator it, ptx.selected_transfers)
|
||||
it->m_spent = true;
|
||||
}
|
||||
|
||||
// if we made it this far, we've selected our transactions. committing them will mark them spent,
|
||||
// so this is a failsafe in case they don't go through
|
||||
// unmark pending tx transfers as spent
|
||||
for (auto & ptx : ptx_vector)
|
||||
{
|
||||
// mark transfers to be used as not spent
|
||||
BOOST_FOREACH(transfer_container::iterator it2, ptx.selected_transfers)
|
||||
it2->m_spent = false;
|
||||
|
||||
}
|
||||
|
||||
// if we made it this far, we're OK to actually send the transactions
|
||||
return ptx_vector;
|
||||
|
||||
}
|
||||
// only catch this here, other exceptions need to pass through to the calling function
|
||||
catch (const tools::error::tx_too_big& e)
|
||||
{
|
||||
|
||||
// unmark pending tx transfers as spent
|
||||
for (auto & ptx : ptx_vector)
|
||||
{
|
||||
// mark transfers to be used as not spent
|
||||
BOOST_FOREACH(transfer_container::iterator it2, ptx.selected_transfers)
|
||||
it2->m_spent = false;
|
||||
|
||||
}
|
||||
|
||||
if (attempt_count >= MAX_SPLIT_ATTEMPTS)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// in case of some other exception, make sure any tx in queue are marked unspent again
|
||||
|
||||
// unmark pending tx transfers as spent
|
||||
for (auto & ptx : ptx_vector)
|
||||
{
|
||||
// mark transfers to be used as not spent
|
||||
BOOST_FOREACH(transfer_container::iterator it2, ptx.selected_transfers)
|
||||
it2->m_spent = false;
|
||||
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+34
-24
@@ -23,6 +23,7 @@
|
||||
|
||||
#include "wallet_errors.h"
|
||||
|
||||
#include <iostream>
|
||||
#define DEFAULT_TX_SPENDABLE_AGE 10
|
||||
#define WALLET_RCP_CONNECTION_TIMEOUT 200000
|
||||
|
||||
@@ -86,6 +87,15 @@ namespace tools
|
||||
typedef std::vector<transfer_details> transfer_container;
|
||||
typedef std::unordered_multimap<crypto::hash, payment_details> payment_container;
|
||||
|
||||
struct pending_tx
|
||||
{
|
||||
cryptonote::transaction tx;
|
||||
uint64_t dust, fee;
|
||||
cryptonote::tx_destination_entry change_dts;
|
||||
std::list<transfer_container::iterator> selected_transfers;
|
||||
std::string key_images;
|
||||
};
|
||||
|
||||
struct keys_file_data
|
||||
{
|
||||
crypto::chacha8_iv iv;
|
||||
@@ -97,7 +107,7 @@ namespace tools
|
||||
END_SERIALIZE()
|
||||
};
|
||||
|
||||
void generate(const std::string& wallet, const std::string& password);
|
||||
crypto::secret_key generate(const std::string& wallet, const std::string& password, const crypto::secret_key& recovery_param = crypto::secret_key(), bool recover = false, bool two_random = false);
|
||||
void load(const std::string& wallet, const std::string& password);
|
||||
void store();
|
||||
cryptonote::account_base& get_account(){return m_account;}
|
||||
@@ -125,9 +135,12 @@ namespace tools
|
||||
template<typename T>
|
||||
void transfer(const std::vector<cryptonote::tx_destination_entry>& dsts, size_t fake_outputs_count, uint64_t unlock_time, uint64_t fee, const std::vector<uint8_t>& extra, T destination_split_strategy, const tx_dust_policy& dust_policy);
|
||||
template<typename T>
|
||||
void transfer(const std::vector<cryptonote::tx_destination_entry>& dsts, size_t fake_outputs_count, uint64_t unlock_time, uint64_t fee, const std::vector<uint8_t>& extra, T destination_split_strategy, const tx_dust_policy& dust_policy, cryptonote::transaction &tx);
|
||||
void transfer(const std::vector<cryptonote::tx_destination_entry>& dsts, size_t fake_outputs_count, uint64_t unlock_time, uint64_t fee, const std::vector<uint8_t>& extra, T destination_split_strategy, const tx_dust_policy& dust_policy, cryptonote::transaction& tx, pending_tx& ptx);
|
||||
void transfer(const std::vector<cryptonote::tx_destination_entry>& dsts, size_t fake_outputs_count, uint64_t unlock_time, uint64_t fee, const std::vector<uint8_t>& extra);
|
||||
void transfer(const std::vector<cryptonote::tx_destination_entry>& dsts, size_t fake_outputs_count, uint64_t unlock_time, uint64_t fee, const std::vector<uint8_t>& extra, cryptonote::transaction& tx);
|
||||
void transfer(const std::vector<cryptonote::tx_destination_entry>& dsts, size_t fake_outputs_count, uint64_t unlock_time, uint64_t fee, const std::vector<uint8_t>& extra, cryptonote::transaction& tx, pending_tx& ptx);
|
||||
void commit_tx(pending_tx& ptx_vector);
|
||||
void commit_tx(std::vector<pending_tx>& ptx_vector);
|
||||
std::vector<pending_tx> create_transactions(std::vector<cryptonote::tx_destination_entry> dsts, const size_t fake_outs_count, const uint64_t unlock_time, const uint64_t fee, const std::vector<uint8_t> extra);
|
||||
bool check_connection();
|
||||
void get_transfers(wallet2::transfer_container& incoming_transfers) const;
|
||||
void get_payments(const crypto::hash& payment_id, std::list<wallet2::payment_details>& payments) const;
|
||||
@@ -227,6 +240,7 @@ namespace boost
|
||||
|
||||
namespace tools
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
@@ -294,18 +308,23 @@ namespace tools
|
||||
void wallet2::transfer(const std::vector<cryptonote::tx_destination_entry>& dsts, size_t fake_outputs_count,
|
||||
uint64_t unlock_time, uint64_t fee, const std::vector<uint8_t>& extra, T destination_split_strategy, const tx_dust_policy& dust_policy)
|
||||
{
|
||||
pending_tx ptx;
|
||||
cryptonote::transaction tx;
|
||||
transfer(dsts, fake_outputs_count, unlock_time, fee, extra, destination_split_strategy, dust_policy, tx);
|
||||
transfer(dsts, fake_outputs_count, unlock_time, fee, extra, destination_split_strategy, dust_policy, tx, ptx);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void wallet2::transfer(const std::vector<cryptonote::tx_destination_entry>& dsts, size_t fake_outputs_count,
|
||||
uint64_t unlock_time, uint64_t fee, const std::vector<uint8_t>& extra, T destination_split_strategy, const tx_dust_policy& dust_policy, cryptonote::transaction &tx)
|
||||
uint64_t unlock_time, uint64_t fee, const std::vector<uint8_t>& extra, T destination_split_strategy, const tx_dust_policy& dust_policy, cryptonote::transaction& tx, pending_tx &ptx)
|
||||
{
|
||||
using namespace cryptonote;
|
||||
// throw if attempting a transaction with no destinations
|
||||
THROW_WALLET_EXCEPTION_IF(dsts.empty(), error::zero_destination);
|
||||
|
||||
uint64_t needed_money = fee;
|
||||
|
||||
// calculate total amount being sent to all destinations
|
||||
// throw if total amount overflows uint64_t
|
||||
BOOST_FOREACH(auto& dt, dsts)
|
||||
{
|
||||
THROW_WALLET_EXCEPTION_IF(0 == dt.amount, error::zero_destination);
|
||||
@@ -313,6 +332,8 @@ namespace tools
|
||||
THROW_WALLET_EXCEPTION_IF(needed_money < dt.amount, error::tx_sum_overflow, dsts, fee);
|
||||
}
|
||||
|
||||
// randomly select inputs for transaction
|
||||
// throw if requested send amount is greater than amount available to send
|
||||
std::list<transfer_container::iterator> selected_transfers;
|
||||
uint64_t found_money = select_transfers(needed_money, 0 == fake_outputs_count, dust_policy.dust_threshold, selected_transfers);
|
||||
THROW_WALLET_EXCEPTION_IF(found_money < needed_money, error::not_enough_money, found_money, needed_money - fee, fee);
|
||||
@@ -425,25 +446,14 @@ namespace tools
|
||||
});
|
||||
THROW_WALLET_EXCEPTION_IF(!all_are_txin_to_key, error::unexpected_txin_type, tx);
|
||||
|
||||
COMMAND_RPC_SEND_RAW_TX::request req;
|
||||
req.tx_as_hex = epee::string_tools::buff_to_hex_nodelimer(tx_to_blob(tx));
|
||||
COMMAND_RPC_SEND_RAW_TX::response daemon_send_resp;
|
||||
r = epee::net_utils::invoke_http_json_remote_command2(m_daemon_address + "/sendrawtransaction", req, daemon_send_resp, m_http_client, 200000);
|
||||
THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "sendrawtransaction");
|
||||
THROW_WALLET_EXCEPTION_IF(daemon_send_resp.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "sendrawtransaction");
|
||||
THROW_WALLET_EXCEPTION_IF(daemon_send_resp.status != CORE_RPC_STATUS_OK, error::tx_rejected, tx, daemon_send_resp.status);
|
||||
ptx.key_images = key_images;
|
||||
ptx.fee = fee;
|
||||
ptx.dust = dust;
|
||||
ptx.tx = tx;
|
||||
ptx.change_dts = change_dts;
|
||||
ptx.selected_transfers = selected_transfers;
|
||||
|
||||
add_unconfirmed_tx(tx, change_dts.amount);
|
||||
|
||||
LOG_PRINT_L2("transaction " << get_transaction_hash(tx) << " generated ok and sent to daemon, key_images: [" << key_images << "]");
|
||||
|
||||
BOOST_FOREACH(transfer_container::iterator it, selected_transfers)
|
||||
it->m_spent = true;
|
||||
|
||||
LOG_PRINT_L0("Transaction successfully sent. <" << get_transaction_hash(tx) << ">" << ENDL
|
||||
<< "Commission: " << print_money(fee+dust) << " (dust: " << print_money(dust) << ")" << ENDL
|
||||
<< "Balance: " << print_money(balance()) << ENDL
|
||||
<< "Unlocked: " << print_money(unlocked_balance()) << ENDL
|
||||
<< "Please, wait for confirmation for your balance to be unlocked.");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -188,6 +188,17 @@ namespace tools
|
||||
|
||||
std::string to_string() const { return wallet_logic_error::to_string(); }
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
struct invalid_pregenerated_random : public wallet_logic_error
|
||||
{
|
||||
explicit invalid_pregenerated_random (std::string&& loc)
|
||||
: wallet_logic_error(std::move(loc), "invalid pregenerated random for wallet creation/recovery")
|
||||
{
|
||||
}
|
||||
|
||||
std::string to_string() const { return wallet_logic_error::to_string(); }
|
||||
};
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
struct refresh_error : public wallet_logic_error
|
||||
{
|
||||
|
||||
@@ -10,6 +10,7 @@ using namespace epee;
|
||||
#include "common/command_line.h"
|
||||
#include "cryptonote_core/cryptonote_format_utils.h"
|
||||
#include "cryptonote_core/account.h"
|
||||
#include "wallet_rpc_server_commands_defs.h"
|
||||
#include "misc_language.h"
|
||||
#include "string_tools.h"
|
||||
#include "crypto/hash.h"
|
||||
@@ -85,12 +86,11 @@ namespace tools
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_transfer(const wallet_rpc::COMMAND_RPC_TRANSFER::request& req, wallet_rpc::COMMAND_RPC_TRANSFER::response& res, epee::json_rpc::error& er, connection_context& cntx)
|
||||
{
|
||||
|
||||
std::vector<cryptonote::tx_destination_entry> dsts;
|
||||
for (auto it = req.destinations.begin(); it != req.destinations.end(); it++)
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::validate_transfer(const std::list<wallet_rpc::transfer_destination> destinations, const std::string payment_id, std::vector<cryptonote::tx_destination_entry>& dsts, std::vector<uint8_t> extra, epee::json_rpc::error& er)
|
||||
{
|
||||
for (auto it = destinations.begin(); it != destinations.end(); it++)
|
||||
{
|
||||
cryptonote::tx_destination_entry de;
|
||||
if(!get_account_address_from_str(de.addr, it->address))
|
||||
@@ -103,11 +103,11 @@ namespace tools
|
||||
dsts.push_back(de);
|
||||
}
|
||||
|
||||
std::vector<uint8_t> extra;
|
||||
if (!req.payment_id.empty()) {
|
||||
if (!payment_id.empty())
|
||||
{
|
||||
|
||||
/* Just to clarify */
|
||||
const std::string& payment_id_str = req.payment_id;
|
||||
const std::string& payment_id_str = payment_id;
|
||||
|
||||
crypto::hash payment_id;
|
||||
/* Parse payment ID */
|
||||
@@ -128,12 +128,85 @@ namespace tools
|
||||
}
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_transfer(const wallet_rpc::COMMAND_RPC_TRANSFER::request& req, wallet_rpc::COMMAND_RPC_TRANSFER::response& res, epee::json_rpc::error& er, connection_context& cntx)
|
||||
{
|
||||
|
||||
std::vector<cryptonote::tx_destination_entry> dsts;
|
||||
std::vector<uint8_t> extra;
|
||||
|
||||
// validate the transfer requested and populate dsts & extra
|
||||
if (!validate_transfer(req.destinations, req.payment_id, dsts, extra, er))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
cryptonote::transaction tx;
|
||||
m_wallet.transfer(dsts, req.mixin, req.unlock_time, req.fee, extra, tx);
|
||||
res.tx_hash = boost::lexical_cast<std::string>(cryptonote::get_transaction_hash(tx));
|
||||
std::vector<wallet2::pending_tx> ptx_vector = m_wallet.create_transactions(dsts, req.mixin, req.unlock_time, req.fee, extra);
|
||||
|
||||
// reject proposed transactions if there are more than one. see on_transfer_split below.
|
||||
if (ptx_vector.size() != 1)
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_GENERIC_TRANSFER_ERROR;
|
||||
er.message = "Transaction would be too large. try /transfer_split.";
|
||||
return false;
|
||||
}
|
||||
|
||||
m_wallet.commit_tx(ptx_vector);
|
||||
|
||||
// populate response with tx hash
|
||||
res.tx_hash = boost::lexical_cast<std::string>(cryptonote::get_transaction_hash(ptx_vector.back().tx));
|
||||
return true;
|
||||
}
|
||||
catch (const tools::error::daemon_busy& e)
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_DAEMON_IS_BUSY;
|
||||
er.message = e.what();
|
||||
return false;
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_GENERIC_TRANSFER_ERROR;
|
||||
er.message = e.what();
|
||||
return false;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
|
||||
er.message = "WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_transfer_split(const wallet_rpc::COMMAND_RPC_TRANSFER_SPLIT::request& req, wallet_rpc::COMMAND_RPC_TRANSFER_SPLIT::response& res, epee::json_rpc::error& er, connection_context& cntx)
|
||||
{
|
||||
|
||||
std::vector<cryptonote::tx_destination_entry> dsts;
|
||||
std::vector<uint8_t> extra;
|
||||
|
||||
// validate the transfer requested and populate dsts & extra; RPC_TRANSFER::request and RPC_TRANSFER_SPLIT::request are identical types.
|
||||
if (!validate_transfer(req.destinations, req.payment_id, dsts, extra, er))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
std::vector<wallet2::pending_tx> ptx_vector = m_wallet.create_transactions(dsts, req.mixin, req.unlock_time, req.fee, extra);
|
||||
|
||||
m_wallet.commit_tx(ptx_vector);
|
||||
|
||||
// populate response with tx hashes
|
||||
for (auto & ptx : ptx_vector)
|
||||
{
|
||||
res.tx_hash_list.push_back(boost::lexical_cast<std::string>(cryptonote::get_transaction_hash(ptx.tx)));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (const tools::error::daemon_busy& e)
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#include <boost/program_options/options_description.hpp>
|
||||
#include <boost/program_options/variables_map.hpp>
|
||||
#include "net/http_server_impl_base.h"
|
||||
#include "wallet_rpc_server_commans_defs.h"
|
||||
#include "wallet_rpc_server_commands_defs.h"
|
||||
#include "wallet2.h"
|
||||
#include "common/command_line.h"
|
||||
namespace tools
|
||||
@@ -38,6 +38,7 @@ namespace tools
|
||||
MAP_JON_RPC_WE("getbalance", on_getbalance, wallet_rpc::COMMAND_RPC_GET_BALANCE)
|
||||
MAP_JON_RPC_WE("getaddress", on_getaddress, wallet_rpc::COMMAND_RPC_GET_ADDRESS)
|
||||
MAP_JON_RPC_WE("transfer", on_transfer, wallet_rpc::COMMAND_RPC_TRANSFER)
|
||||
MAP_JON_RPC_WE("transfer_split", on_transfer_split, wallet_rpc::COMMAND_RPC_TRANSFER_SPLIT)
|
||||
MAP_JON_RPC_WE("store", on_store, wallet_rpc::COMMAND_RPC_STORE)
|
||||
MAP_JON_RPC_WE("get_payments", on_get_payments, wallet_rpc::COMMAND_RPC_GET_PAYMENTS)
|
||||
MAP_JON_RPC_WE("incoming_transfers", on_incoming_transfers, wallet_rpc::COMMAND_RPC_INCOMING_TRANSFERS)
|
||||
@@ -47,7 +48,9 @@ namespace tools
|
||||
//json_rpc
|
||||
bool on_getbalance(const wallet_rpc::COMMAND_RPC_GET_BALANCE::request& req, wallet_rpc::COMMAND_RPC_GET_BALANCE::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||
bool on_getaddress(const wallet_rpc::COMMAND_RPC_GET_ADDRESS::request& req, wallet_rpc::COMMAND_RPC_GET_ADDRESS::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||
bool validate_transfer(const std::list<wallet_rpc::transfer_destination> destinations, const std::string payment_id, std::vector<cryptonote::tx_destination_entry>& dsts, std::vector<uint8_t> extra, epee::json_rpc::error& er);
|
||||
bool on_transfer(const wallet_rpc::COMMAND_RPC_TRANSFER::request& req, wallet_rpc::COMMAND_RPC_TRANSFER::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||
bool on_transfer_split(const wallet_rpc::COMMAND_RPC_TRANSFER_SPLIT::request& req, wallet_rpc::COMMAND_RPC_TRANSFER_SPLIT::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||
bool on_store(const wallet_rpc::COMMAND_RPC_STORE::request& req, wallet_rpc::COMMAND_RPC_STORE::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||
bool on_get_payments(const wallet_rpc::COMMAND_RPC_GET_PAYMENTS::request& req, wallet_rpc::COMMAND_RPC_GET_PAYMENTS::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||
bool on_incoming_transfers(const wallet_rpc::COMMAND_RPC_INCOMING_TRANSFERS::request& req, wallet_rpc::COMMAND_RPC_INCOMING_TRANSFERS::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||
|
||||
@@ -1,182 +0,0 @@
|
||||
// Copyright (c) 2012-2013 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 "cryptonote_protocol/cryptonote_protocol_defs.h"
|
||||
#include "cryptonote_core/cryptonote_basic.h"
|
||||
#include "crypto/hash.h"
|
||||
#include "wallet_rpc_server_error_codes.h"
|
||||
namespace tools
|
||||
{
|
||||
namespace wallet_rpc
|
||||
{
|
||||
#define WALLET_RPC_STATUS_OK "OK"
|
||||
#define WALLET_RPC_STATUS_BUSY "BUSY"
|
||||
|
||||
struct COMMAND_RPC_GET_BALANCE
|
||||
{
|
||||
struct request
|
||||
{
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
struct response
|
||||
{
|
||||
uint64_t balance;
|
||||
uint64_t unlocked_balance;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(balance)
|
||||
KV_SERIALIZE(unlocked_balance)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
};
|
||||
|
||||
struct COMMAND_RPC_GET_ADDRESS
|
||||
{
|
||||
struct request
|
||||
{
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
struct response
|
||||
{
|
||||
std::string address;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(address)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
};
|
||||
|
||||
struct trnsfer_destination
|
||||
{
|
||||
uint64_t amount;
|
||||
std::string address;
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(amount)
|
||||
KV_SERIALIZE(address)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
struct COMMAND_RPC_TRANSFER
|
||||
{
|
||||
struct request
|
||||
{
|
||||
std::list<trnsfer_destination> destinations;
|
||||
uint64_t fee;
|
||||
uint64_t mixin;
|
||||
uint64_t unlock_time;
|
||||
std::string payment_id;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(destinations)
|
||||
KV_SERIALIZE(fee)
|
||||
KV_SERIALIZE(mixin)
|
||||
KV_SERIALIZE(unlock_time)
|
||||
KV_SERIALIZE(payment_id)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
struct response
|
||||
{
|
||||
std::string tx_hash;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(tx_hash)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
};
|
||||
|
||||
struct COMMAND_RPC_STORE
|
||||
{
|
||||
struct request
|
||||
{
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
struct response
|
||||
{
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
};
|
||||
|
||||
struct payment_details
|
||||
{
|
||||
std::string tx_hash;
|
||||
uint64_t amount;
|
||||
uint64_t block_height;
|
||||
uint64_t unlock_time;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(tx_hash)
|
||||
KV_SERIALIZE(amount)
|
||||
KV_SERIALIZE(block_height)
|
||||
KV_SERIALIZE(unlock_time)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
struct COMMAND_RPC_GET_PAYMENTS
|
||||
{
|
||||
struct request
|
||||
{
|
||||
std::string payment_id;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(payment_id)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
struct response
|
||||
{
|
||||
std::list<payment_details> payments;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(payments)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
};
|
||||
|
||||
struct transfer_details
|
||||
{
|
||||
uint64_t amount;
|
||||
bool spent;
|
||||
uint64_t global_index;
|
||||
std::string tx_hash;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(amount)
|
||||
KV_SERIALIZE(spent)
|
||||
KV_SERIALIZE(global_index)
|
||||
KV_SERIALIZE(tx_hash)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
struct COMMAND_RPC_INCOMING_TRANSFERS
|
||||
{
|
||||
struct request
|
||||
{
|
||||
std::string transfer_type;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(transfer_type)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
struct response
|
||||
{
|
||||
std::list<transfer_details> transfers;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(transfers)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user