import wallet refactoring

use_xmregcore
moneroexamples 5 years ago
parent fb20cb2179
commit 9de3a4a116

@ -58,7 +58,7 @@
"max_number_of_blocks_to_import" : 132000,
"mysql_ping_every_seconds" : 200,
"_comment": "if the threadpool_size (no of threads) below is 0, its size is automaticly set based on your cpu. If its not 0, the value specified is used instead",
"blockchain_treadpool_size" : 0,
"blockchain_treadpool_size" : 1,
"ssl" :
{
"enable" : false,

@ -3,7 +3,7 @@ var config = {
mainnetExplorerUrl: "https://xmrchain.com/",
testnetExplorerUrl: "https://testnet.xmrchain.com/",
stagenetExplorerUrl: "http://139.162.60.17:8082/",
nettype: 0, /* 0 - MAINNET, 1 - TESTNET, 2 - STAGENET */
nettype: 2, /* 0 - MAINNET, 1 - TESTNET, 2 - STAGENET */
coinUnitPlaces: 12,
txMinConfirms: 10, // corresponds to CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE in Monero
txCoinbaseMinConfirms: 60, // corresponds to CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW in Monero

@ -70,53 +70,25 @@ OpenMoneroRequests::login(const shared_ptr<Session> session, const Bytes & body)
}
// a placeholder for exciting or new account data
XmrAccount acc;
uint64_t acc_id {0};
// marks if this is new account creation or not
bool new_account_created {false};
auto acc = select_account(xmr_address, view_key);
// first check if new account
// select this account if its existing one
if (!xmr_accounts->select(xmr_address, acc))
if (!acc)
{
// account does not exist, so create new one
// for this address
uint64_t current_blockchain_height = get_current_blockchain_height();
// initialize current blockchain timestamp with current time
// in a moment we will try to get last block timestamp
// to replace this value. But if it fails, we just use current
// timestamp
uint64_t current_blockchain_timestamp = std::time(nullptr);
// get last block so we have its timestamp when
// createing the account
block last_blk;
if (current_bc_status->get_block(current_blockchain_height, last_blk))
{
current_blockchain_timestamp = last_blk.timestamp;
}
DateTime blk_timestamp_mysql_format
= XmrTransaction::timestamp_to_DateTime(
current_blockchain_timestamp);
// create new account
XmrAccount new_account(
mysqlpp::null,
xmr_address,
make_hash(view_key),
current_blockchain_height, /* for scanned_block_height */
blk_timestamp_mysql_format,
current_blockchain_height);
acc = create_account(xmr_address, view_key);
// insert the new account into the mysql
if ((acc_id = xmr_accounts->insert(new_account)) == 0)
if (!acc)
{
// if creating account failed
j_response = json {{"status", "error"},
@ -132,13 +104,13 @@ OpenMoneroRequests::login(const shared_ptr<Session> session, const Bytes & body)
// their first install
new_account_created = true;
} // if (!xmr_accounts->select(xmr_address, acc))
} // if (!acc)
// so by now new account has been created or it already exists
// so we just login into it.
if (login_and_start_search_thread(xmr_address, view_key, acc, j_response))
if (login_and_start_search_thread(xmr_address, view_key, *acc, j_response))
{
// if successfuly logged in and created search thread
j_response["status"] = "success";
@ -210,25 +182,13 @@ OpenMoneroRequests::get_address_txs(
// for this to continue, search thread must have already been
// created and still exisits.
// if (current_bc_status->search_thread_exist(xmr_address))
// {
if (login_and_start_search_thread(xmr_address, view_key, acc, j_response))
{
// populate acc and check view_key
// if (!login_and_start_search_thread(xmr_address, view_key, acc, j_response))
// {
// // some error with loggin in or search thread start
// session_close(session, j_response.dump());
// return;
// }
// before fetching txs, check if provided view key
// is correct. this is simply to ensure that
// we cant fetch an account's txs using only address.
// knowlage of the viewkey is also needed.
uint64_t total_received {0};
uint64_t total_received_unlocked {0};
@ -1011,7 +971,7 @@ OpenMoneroRequests::import_wallet_request(
}
catch (json::exception const& e)
{
OMERROR << "json exception: " << e.what();
OMWARN << "json exception: " << e.what();
session_close(session, j_response, UNPROCESSABLE_ENTITY,
e.what());
return;
@ -1026,12 +986,13 @@ OpenMoneroRequests::import_wallet_request(
j_response["error"] = "Some error occured";
// get account from mysql db if exists
auto xmr_account = select_account(xmr_address);
auto xmr_account = select_account(xmr_address, view_key);
if (!xmr_account)
{
// if creation failed, just close the session
session_close(session, j_response, UNPROCESSABLE_ENTITY,
"The account does not exists!");
"The account login or creation failed!");
return;
}
@ -1274,7 +1235,8 @@ OpenMoneroRequests::import_recent_wallet_request(
}
catch (json::exception const& e)
{
OMERROR << "json exception: " << e.what();
OMERROR << xmr_address.substr(0,6)
<< ": json exception: " << e.what();
session_close(session, j_response, UNPROCESSABLE_ENTITY,
e.what());
return;
@ -1294,12 +1256,23 @@ OpenMoneroRequests::import_recent_wallet_request(
+ j_request["no_blocks_to_import"].get<string>()
+ " into number";
cerr << msg << '\n';
OMERROR << xmr_address.substr(0,6) + ": " + msg;
j_response["Error"] = msg;
session_close(session, j_response);
return;
}
// get account from mysql db if exists
auto xmr_account = select_account(xmr_address, view_key);
if (!xmr_account)
{
// if creation failed, just close the session
session_close(session, j_response, UNPROCESSABLE_ENTITY,
"The account login or creation failed!");
return;
}
// make sure that we dont import more that the maximum alowed no of blocks
no_blocks_to_import = std::min(no_blocks_to_import,
@ -1310,52 +1283,45 @@ OpenMoneroRequests::import_recent_wallet_request(
= std::min(no_blocks_to_import,
current_bc_status->get_current_blockchain_height());
XmrAccount acc;
XmrAccount& acc = *xmr_account;
if (xmr_accounts->select(xmr_address, acc))
{
XmrAccount updated_acc = acc;
XmrAccount updated_acc = acc;
// make sure scanned_block_height is larger than
// no_blocks_to_import so we dont
// end up with overflowing uint64_t.
// make sure scanned_block_height is larger than
// no_blocks_to_import so we dont
// end up with overflowing uint64_t.
if (updated_acc.scanned_block_height >= no_blocks_to_import)
{
// repetead calls to import_recent_wallet_request will be
// moving the scanning backward.
// not sure yet if any protection is needed to
// make sure that a user does not
// go back too much back by importing his/hers
// wallet multiple times in a row.
updated_acc.scanned_block_height
= updated_acc.scanned_block_height - no_blocks_to_import;
if (updated_acc.scanned_block_height >= no_blocks_to_import)
if (xmr_accounts->update(acc, updated_acc))
{
// repetead calls to import_recent_wallet_request will be
// moving the scanning backward.
// not sure yet if any protection is needed to
// make sure that a user does not
// go back too much back by importing his/hers
// wallet multiple times in a row.
updated_acc.scanned_block_height
= updated_acc.scanned_block_height - no_blocks_to_import;
if (xmr_accounts->update(acc, updated_acc))
// change search blk number in the search thread
if (!current_bc_status
->set_new_searched_blk_no(xmr_address,
updated_acc.scanned_block_height))
{
// change search blk number in the search thread
if (!current_bc_status
->set_new_searched_blk_no(xmr_address,
updated_acc.scanned_block_height))
{
cerr << "Updating searched_blk_no failed!" << endl;
j_response["Error"] = "Updating searched_blk_no failed!";
}
else
{
// if success, makre that request was successful;
request_fulfilled = true;
}
OMERROR << xmr_address.substr(0,6)
<< ": updating searched_blk_no failed!" << endl;
j_response["Error"] = "Updating searched_blk_no failed!";
}
else
{
// if success, makre that request was successful;
request_fulfilled = true;
}
}
} // if (updated_acc.scanned_block_height > no_blocks_to_import)
}
else
{
cerr << "Updating account with new scanned_block_height failed!\n";
j_response["status"]
= "Updating account with new scanned_block_height failed!";
}
} // if (updated_acc.scanned_block_height > no_blocks_to_import)
if (request_fulfilled)
{
@ -1367,7 +1333,8 @@ OpenMoneroRequests::import_recent_wallet_request(
string response_body = j_response.dump();
auto response_headers = make_headers({{ "Content-Length",
std::to_string(response_body.size())}});
std::to_string(
response_body.size())}});
session->close( OK, response_body, response_headers);
}
@ -1401,7 +1368,7 @@ OpenMoneroRequests::get_tx(
}
catch (json::exception const& e)
{
cerr << "json exception: " << e.what() << '\n';
OMWARN << "json exception: " << e.what();
session_close(session, j_response);
return;
}
@ -1457,277 +1424,275 @@ OpenMoneroRequests::get_tx(
tx_found = true;
}
if (tx_found)
if (!tx_found)
{
crypto::hash tx_hash = get_transaction_hash(tx);
// if creation failed, just close the session
session_close(session, j_response, UNPROCESSABLE_ENTITY,
" Cant get tx details for" + tx_hash_str);
return;
}
// return tx hash. can be used to check if we acctually
// delivered the tx that was requested
j_response["tx_hash"] = pod_to_hex(tx_hash);
// return tx hash. can be used to check if we acctually
// delivered the tx that was requested
j_response["tx_hash"] = pod_to_hex(tx_hash);
j_response["pub_key"] = pod_to_hex(
xmreg::get_tx_pub_key_from_received_outs(tx));
j_response["pub_key"] = pod_to_hex(
xmreg::get_tx_pub_key_from_received_outs(tx));
bool coinbase = is_coinbase(tx);
bool coinbase = is_coinbase(tx);
j_response["coinbase"] = coinbase;
j_response["coinbase"] = coinbase;
// key images of inputs
vector<txin_to_key> input_key_imgs;
// key images of inputs
vector<txin_to_key> input_key_imgs;
// public keys and xmr amount of outputs
vector<pair<txout_to_key, uint64_t>> output_pub_keys;
// public keys and xmr amount of outputs
vector<pair<txout_to_key, uint64_t>> output_pub_keys;
uint64_t xmr_inputs;
uint64_t xmr_outputs;
uint64_t num_nonrct_inputs;
uint64_t fee {0};
uint64_t mixin_no;
uint64_t size;
uint64_t xmr_inputs;
uint64_t xmr_outputs;
uint64_t num_nonrct_inputs;
uint64_t fee {0};
uint64_t mixin_no;
uint64_t size;
// sum xmr in inputs and ouputs in the given tx
array<uint64_t, 4> const& sum_data = xmreg::summary_of_in_out_rct(
tx, output_pub_keys, input_key_imgs);
// sum xmr in inputs and ouputs in the given tx
array<uint64_t, 4> const& sum_data = xmreg::summary_of_in_out_rct(
tx, output_pub_keys, input_key_imgs);
xmr_outputs = sum_data[0];
xmr_inputs = sum_data[1];
mixin_no = sum_data[2];
num_nonrct_inputs = sum_data[3];
xmr_outputs = sum_data[0];
xmr_inputs = sum_data[1];
mixin_no = sum_data[2];
num_nonrct_inputs = sum_data[3];
j_response["xmr_outputs"] = xmr_outputs;
j_response["xmr_inputs"] = xmr_inputs;
j_response["mixin_no"] = mixin_no;
j_response["num_of_outputs"] = output_pub_keys.size();
j_response["num_of_inputs"] = input_key_imgs.size();
j_response["xmr_outputs"] = xmr_outputs;
j_response["xmr_inputs"] = xmr_inputs;
j_response["mixin_no"] = mixin_no;
j_response["num_of_outputs"] = output_pub_keys.size();
j_response["num_of_inputs"] = input_key_imgs.size();
if (!coinbase && tx.vin.size() > 0)
if (!coinbase && tx.vin.size() > 0)
{
// check if not miner tx
// i.e., for blocks without any user transactions
if (tx.vin.at(0).type() != typeid(txin_gen))
{
// check if not miner tx
// i.e., for blocks without any user transactions
if (tx.vin.at(0).type() != typeid(txin_gen))
{
// get tx fee
fee = get_tx_fee(tx);
}
// get tx fee
fee = get_tx_fee(tx);
}
}
j_response["fee"] = fee;
j_response["fee"] = fee;
// get tx size in bytes
size = get_object_blobsize(tx);
// get tx size in bytes
size = get_object_blobsize(tx);
j_response["size"] = size;
j_response["size"] = size;
// to be field later on using data from OutputInputIdentification
j_response["total_sent"] = "0";
j_response["total_received"] = "0";
// to be field later on using data from OutputInputIdentification
j_response["total_sent"] = "0";
j_response["total_received"] = "0";
int64_t tx_height {-1};
int64_t tx_height {-1};
int64_t no_confirmations {-1};
int64_t no_confirmations {-1};
if (current_bc_status->get_tx_block_height(tx_hash, tx_height))
{
// get the current blockchain height. Just to check
uint64_t bc_height = get_current_blockchain_height();
if (current_bc_status->get_tx_block_height(tx_hash, tx_height))
{
// get the current blockchain height. Just to check
uint64_t bc_height = get_current_blockchain_height();
no_confirmations = bc_height - tx_height;
}
no_confirmations = bc_height - tx_height;
}
// Class that is responsible for identification of our outputs
// and inputs in a given tx.
// Class that is responsible for identification of our outputs
// and inputs in a given tx.
j_response["payment_id"] = string {};
j_response["timestamp"] = default_timestamp;
j_response["payment_id"] = string {};
j_response["timestamp"] = default_timestamp;
address_parse_info address_info;
secret_key viewkey;
address_parse_info address_info;
secret_key viewkey;
MicroCoreAdapter mcore_addapter {current_bc_status.get()};
MicroCoreAdapter mcore_addapter {current_bc_status.get()};
// to get info about recived xmr in this tx, we calculate it from
// scrach, i.e., search for outputs. We could get this info
// directly from the database, but doing it again here, is a good way
// to double check tx data in the frontend, and also maybe try doing
// it differently than before. Its not great, since we reinvent
// the wheel
// but its worth double checking
// the mysql data, and also allows for new
// implementation in the frontend.
if (current_bc_status->get_xmr_address_viewkey(
xmr_address, address_info, viewkey))
{
auto identifier = make_identifier(tx,
make_unique<Output>(&address_info, &viewkey));
// to get info about recived xmr in this tx, we calculate it from
// scrach, i.e., search for outputs. We could get this info
// directly from the database, but doing it again here, is a good way
// to double check tx data in the frontend, and also maybe try doing
// it differently than before. Its not great, since we reinvent
// the wheel
// but its worth double checking
// the mysql data, and also allows for new
// implementation in the frontend.
if (current_bc_status->get_xmr_address_viewkey(
xmr_address, address_info, viewkey))
{
auto identifier = make_identifier(tx,
make_unique<Output>(&address_info, &viewkey));
identifier.identify();
auto const& outputs_identified
= identifier.get<Output>()->get();
identifier.identify();
auto const& outputs_identified
= identifier.get<Output>()->get();
auto total_received = calc_total_xmr(outputs_identified);
auto total_received = calc_total_xmr(outputs_identified);
j_response["total_received"] = std::to_string(total_received);
j_response["total_received"] = std::to_string(total_received);
json j_spent_outputs = json::array();
json j_spent_outputs = json::array();
// to get spendings, we need to have our key_images. but
// the backend does not have spendkey, so it cant determine
// which key images are really ours or not. this is the task
// for the frontend. however, backend can only provide guesses and
// nessessery data to the frontend to filter out incorrect
// guesses.
//
// for input identification, we will use our mysql. its just much
// faster to use it here, than before. but first we need to
// get account id of the user asking for tx details.
// to get spendings, we need to have our key_images. but
// the backend does not have spendkey, so it cant determine
// which key images are really ours or not. this is the task
// for the frontend. however, backend can only provide guesses and
// nessessery data to the frontend to filter out incorrect
// guesses.
//
// for input identification, we will use our mysql. its just much
// faster to use it here, than before. but first we need to
// get account id of the user asking for tx details.
// a placeholder for exciting or new account data
XmrAccount acc;
// a placeholder for exciting or new account data
XmrAccount acc;
// select this account if its existing one
if (xmr_accounts->select(xmr_address, acc))
// select this account if its existing one
if (xmr_accounts->select(xmr_address, acc))
{
// if user exist, get tx data from database
// this will work only for tx in the blockchain,
// not those in the mempool.
if (!tx_in_mempool)
{
// if user exist, get tx data from database
// this will work only for tx in the blockchain,
// not those in the mempool.
// if not in mempool, but in blockchain, just
// get data aout key images from the mysql
XmrTransaction xmr_tx;
if (!tx_in_mempool)
if (xmr_accounts->tx_exists(
acc.id.data, tx_hash_str, xmr_tx))
{
// if not in mempool, but in blockchain, just
// get data aout key images from the mysql
j_response["payment_id"] = xmr_tx.payment_id;
j_response["timestamp"]
= static_cast<uint64_t>(xmr_tx.timestamp*1e3);
XmrTransaction xmr_tx;
vector<XmrInput> inputs;
if (xmr_accounts->tx_exists(
acc.id.data, tx_hash_str, xmr_tx))
if (xmr_accounts->select_for_tx(
xmr_tx.id.data, inputs))
{
j_response["payment_id"] = xmr_tx.payment_id;
j_response["timestamp"]
= static_cast<uint64_t>(xmr_tx.timestamp*1e3);
json j_spent_outputs = json::array();
vector<XmrInput> inputs;
uint64_t total_spent {0};
if (xmr_accounts->select_for_tx(
xmr_tx.id.data, inputs))
for (XmrInput input: inputs)
{
json j_spent_outputs = json::array();
uint64_t total_spent {0};
XmrOutput out;
for (XmrInput input: inputs)
if (xmr_accounts
->select_by_primary_id(
input.output_id, out))
{
XmrOutput out;
total_spent += input.amount;
if (xmr_accounts
->select_by_primary_id(
input.output_id, out))
{
total_spent += input.amount;
j_spent_outputs.push_back({
{"amount" , std::to_string(input.amount)},
{"key_image" , input.key_image},
{"tx_pub_key" , out.tx_pub_key},
{"out_index" , out.out_index},
{"mixin" , out.mixin}});
}
j_spent_outputs.push_back({
{"amount" , std::to_string(input.amount)},
{"key_image" , input.key_image},
{"tx_pub_key" , out.tx_pub_key},
{"out_index" , out.out_index},
{"mixin" , out.mixin}});
}
} // for (XmrInput input: inputs)
} // for (XmrInput input: inputs)
j_response["total_sent"] = std::to_string(total_spent);
j_response["total_sent"] = std::to_string(total_spent);
j_response["spent_outputs"] = j_spent_outputs;
} // if (xmr_accounts->select_inputs_
j_response["spent_outputs"] = j_spent_outputs;
} // if (xmr_accounts->tx_exists(acc.id
} // if (xmr_accounts->select_inputs_
} // if (!tx_in_mempool)
else
{
// if tx in mempool, mysql will not have this tx, so
// we cant pull info about key images from mysql for this tx.
} // if (xmr_accounts->tx_exists(acc.id
// we have to redo this info from basically from scrach.
} // if (!tx_in_mempool)
else
unordered_map<public_key, uint64_t> known_outputs_keys;
if (current_bc_status->get_known_outputs_keys(
xmr_address, known_outputs_keys))
{
// if tx in mempool, mysql will not have this tx, so
// we cant pull info about key images from mysql for this tx.
// we got known_outputs_keys from the search thread.
// so now we can use OutputInputIdentification to
// get info about inputs.
// Class that is resposnible for idenficitaction
// of our outputs
// and inputs in a given tx.
auto identifier = make_identifier(tx,
make_unique<Input>(&address_info, &viewkey,
&known_outputs_keys,
&mcore_addapter));
identifier.identify();
auto const& inputs_identfied
= identifier.get<Input>()->get();
// we have to redo this info from basically from scrach.
json j_spent_outputs = json::array();
unordered_map<public_key, uint64_t> known_outputs_keys;
uint64_t total_spent {0};
if (current_bc_status->get_known_outputs_keys(
xmr_address, known_outputs_keys))
for (auto& in_info: inputs_identfied)
{
// we got known_outputs_keys from the search thread.
// so now we can use OutputInputIdentification to
// get info about inputs.
// Class that is resposnible for idenficitaction
// of our outputs
// and inputs in a given tx.
auto identifier = make_identifier(tx,
make_unique<Input>(&address_info, &viewkey,
&known_outputs_keys,
&mcore_addapter));
identifier.identify();
auto const& inputs_identfied
= identifier.get<Input>()->get();
json j_spent_outputs = json::array();
// need to get output info from mysql, as we need
// to know output's amount, its orginal
// tx public key and its index in that tx
XmrOutput out;
uint64_t total_spent {0};
string out_pub_key
= pod_to_hex(in_info.out_pub_key);
for (auto& in_info: inputs_identfied)
if (xmr_accounts->output_exists(out_pub_key, out))
{
total_spent += out.amount;
// need to get output info from mysql, as we need
// to know output's amount, its orginal
// tx public key and its index in that tx
XmrOutput out;
string out_pub_key
= pod_to_hex(in_info.out_pub_key);
if (xmr_accounts->output_exists(out_pub_key, out))
{
total_spent += out.amount;
j_spent_outputs.push_back({
{"amount" , std::to_string(in_info.amount)},
{"key_image" , pod_to_hex(in_info.key_img)},
{"tx_pub_key" , out.tx_pub_key},
{"out_index" , out.out_index},
{"mixin" , out.mixin}});
}
j_spent_outputs.push_back({
{"amount" , std::to_string(in_info.amount)},
{"key_image" , pod_to_hex(in_info.key_img)},
{"tx_pub_key" , out.tx_pub_key},
{"out_index" , out.out_index},
{"mixin" , out.mixin}});
}
} // for (auto& in_info: oi_identification
} // for (auto& in_info: oi_identification
j_response["total_sent"] = std::to_string(total_spent);
j_response["total_sent"] = std::to_string(total_spent);
j_response["spent_outputs"] = j_spent_outputs;
j_response["spent_outputs"] = j_spent_outputs;
} //if (current_bc_status->get_known_outputs_keys(
// xmr_address, known_outputs_keys))
} //if (current_bc_status->get_known_outputs_keys(
// xmr_address, known_outputs_keys))
} // else
} // else
} // if (xmr_accounts->select(xmr_address, acc))
} // if (xmr_accounts->select(xmr_address, acc))
} // if (current_bc_status->get_xmr_add
} // if (current_bc_status->get_xmr_add
j_response["tx_height"] = tx_height;
j_response["no_confirmations"] = no_confirmations;
j_response["status"] = "OK";
j_response["error"] = "";
}
else
{
cerr << "Cant get tx details for tx hash! : " << tx_hash_str << '\n';
j_response["status"] = "Cant get tx details for tx hash! : " + tx_hash_str;
}
j_response["tx_height"] = tx_height;
j_response["no_confirmations"] = no_confirmations;
j_response["status"] = "OK";
j_response["error"] = "";
string response_body = j_response.dump();
@ -1841,7 +1806,7 @@ OpenMoneroRequests::body_to_json(const Bytes & body)
uint64_t
OpenMoneroRequests::get_current_blockchain_height()
OpenMoneroRequests::get_current_blockchain_height() const
{
return current_bc_status->get_current_blockchain_height();
}
@ -1951,7 +1916,7 @@ OpenMoneroRequests::parse_request(
const Bytes& body,
vector<string>& values_map,
json& j_request,
json& j_response)
json& j_response) const
{
try
{
@ -1986,23 +1951,139 @@ OpenMoneroRequests::parse_request(
}
}
boost::optional<XmrAccount>
OpenMoneroRequests::create_account(
string const& xmr_address,
string const& view_key) const
{
boost::optional<XmrAccount> acc = XmrAccount{};
if (xmr_accounts->select(xmr_address, *acc))
{
// if acc already exist, just return
// existing one
return acc;
}
uint64_t current_blockchain_height = get_current_blockchain_height();
// initialize current blockchain timestamp with current time
// in a moment we will try to get last block timestamp
// to replace this value. But if it fails, we just use current
// timestamp
uint64_t current_blockchain_timestamp = std::time(nullptr);
// get last block so we have its timestamp when
// createing the account
block last_blk;
if (current_bc_status->get_block(current_blockchain_height, last_blk))
{
current_blockchain_timestamp = last_blk.timestamp;
}
DateTime blk_timestamp_mysql_format
= XmrTransaction::timestamp_to_DateTime(
current_blockchain_timestamp);
// create new account
acc = XmrAccount(
mysqlpp::null,
xmr_address,
make_hash(view_key),
current_blockchain_height, /* for scanned_block_height */
blk_timestamp_mysql_format,
current_blockchain_height);
uint64_t acc_id {0};
// insert the new account into the mysql
if ((acc_id = xmr_accounts->insert(*acc)) == 0)
{
// if creating account failed
OMERROR << xmr_address.substr(0,6) + ": account creation failed";
return {};
}
// add acc database id
acc->id = acc_id;
// add also the view_key into acc object. its needs to be done
// as we dont store viewkeys in the database
acc->viewkey = view_key;
return acc;
}
boost::optional<XmrAccount>
OpenMoneroRequests::select_account(
string const& xmr_address) const
string const& xmr_address,
string const& view_key,
bool create_if_notfound) const
{
boost::optional<XmrAccount> acc = XmrAccount{};
if (!xmr_accounts->select(xmr_address, *acc))
{
OMERROR << xmr_address.substr(0,6) +
": address does not exists!";
OMINFO << xmr_address.substr(0,6) +
": address does not exists";
return acc;
if (!create_if_notfound)
return {};
// for this address
if (!(acc = create_account(xmr_address, view_key)))
return {};
// once account has been created
// make and start a search thread for it
if (!make_search_thread(*acc))
return {};
}
// also need to check if view key matches
string viewkey_hash = make_hash(view_key);
if (viewkey_hash != acc->viewkey_hash)
{
OMWARN << xmr_address.substr(0,6) +
": viewkey does not match " +
"the one in database!";
return {};
}
return acc;
}
bool
OpenMoneroRequests::make_search_thread(
XmrAccount& acc) const
{
if (current_bc_status->search_thread_exist(acc.address))
{
return true;
}
std::unique_ptr<TxSearch> tx_search;
try
{
tx_search = std::make_unique<TxSearch>(
acc, current_bc_status);
}
catch (std::exception const& e)
{
OMERROR << acc.address.substr(0,6)
+ ": txSearch construction faild.";
return false;
}
return current_bc_status->start_tx_search_thread(
acc, std::move(tx_search));
}
boost::optional<XmrPayment>
OpenMoneroRequests::select_payment(
XmrAccount const& xmr_account) const

@ -131,7 +131,7 @@ public:
body_to_json(const Bytes & body);
inline uint64_t
get_current_blockchain_height();
get_current_blockchain_height() const;
private:
@ -147,10 +147,19 @@ private:
parse_request(const Bytes& body,
vector<string>& values_map,
json& j_request,
json& j_response);
json& j_response) const;
boost::optional<XmrAccount>
select_account(string const& xmr_address) const;
create_account(string const& xmr_address,
string const& view_key) const;
bool
make_search_thread(XmrAccount& acc) const;
boost::optional<XmrAccount>
select_account(string const& xmr_address,
string const& view_key,
bool create_if_notfound = true) const;
boost::optional<XmrPayment>
select_payment(XmrAccount const& xmr_account) const;

@ -19,7 +19,7 @@ namespace xmreg
TxSearch::TxSearch(XmrAccount& _acc,
TxSearch::TxSearch(XmrAccount const& _acc,
std::shared_ptr<CurrentBlockchainStatus> _current_bc_status)
: current_bc_status {_current_bc_status}
{

@ -97,7 +97,7 @@ public:
// make default constructor. useful in testing
TxSearch() = default;
TxSearch(XmrAccount& _acc,
TxSearch(XmrAccount const& _acc,
std::shared_ptr<CurrentBlockchainStatus> _current_bc_status);
virtual void

@ -255,6 +255,8 @@ MySqlAccounts::select(const string& address, XmrAccount& account)
vector<XmrAccount> res;
query.storein(res, address);
//while(query.more_results());
if (!res.empty())
{
account = std::move(res.at(0));

Loading…
Cancel
Save