select_txs_for_account_spendability_check method added

pull/2/head
moneroexamples 7 years ago
parent 87a7c3418b
commit 06252cabdb

@ -436,7 +436,7 @@ MysqlTransactions::insert(const XmrTransaction& tx_data)
}
uint64_t
MysqlTransactions::mark_spendable(const uint64_t tx_id_no)
MysqlTransactions::mark_spendable(const uint64_t& tx_id_no)
{
Query query = conn->query(XmrTransaction::MARK_AS_SPENDABLE_STMT);
query.parse();
@ -445,8 +445,27 @@ MysqlTransactions::mark_spendable(const uint64_t tx_id_no)
{
SimpleResult sr = query.execute(tx_id_no);
if (sr.rows() == 1)
return sr.rows();
return sr.rows();
}
catch (mysqlpp::Exception& e)
{
MYSQL_EXCEPTION_MSG(e);
return 0;
}
}
uint64_t
MysqlTransactions::delete_tx(const uint64_t& tx_id_no)
{
Query query = conn->query(XmrTransaction::DELETE_STMT);
query.parse();
try
{
SimpleResult sr = query.execute(tx_id_no);
return sr.rows();
}
catch (mysqlpp::Exception& e)
{
@ -811,6 +830,83 @@ MySqlAccounts::select_txs(const uint64_t& account_id, vector<XmrTransaction>& tx
}
bool
MySqlAccounts::select_txs_for_account_spendability_check(
const uint64_t& account_id,
vector<XmrTransaction>& txs)
{
vector<XmrTransaction> txs_tmp;
if (!select_txs(account_id, txs))
{
return false;
}
for (XmrTransaction& tx: txs_tmp)
{
// first we check if txs stored in db are already spendable
// it means if they are older than 10 blocks. If yes,
// we mark them as spendable, as we assumet that blocks
// older than 10 blocks are permanent, i.e, they wont get
// orphaned.
if (bool {tx.spendable} == false)
{
if (CurrentBlockchainStatus::is_tx_unlocked(tx.height))
{
// this tx was before marked as unspendable, but now
// it is spendable. Meaning, that its older than 10 blocks.
// so mark it as spendable, so that its permanet.
uint64_t no_row_updated = mark_tx_spendable(tx.id);
if (no_row_updated != 1)
{
throw runtime_error("no_row_updated != 1 "
"due to "
"xmr_accounts->mark_tx_spendable(tx.id)");
}
tx.spendable = true;
}
else
{
// tx was marked as non-spendable, i.e., younger than 10 blocks
// so we still are going to use this txs, but we need to double
// check if its still valid, i.e., it's block did not get orphaned.
// we do this by checking if txs still exists in the blockchain
// and if its in the same block as noted in the database.
if (!CurrentBlockchainStatus::tx_exist(tx.hash))
{
// tx does not exist in blockchain, but it was there before.
// probably was in orphaned block. So remove it from the
// mysql database.
uint64_t no_row_updated = delete_tx(tx.id);
if (no_row_updated != 1)
{
throw runtime_error("no_row_updated != 1 "
"due to "
"xmr_accounts->delete_tx(tx.id)");
}
continue;
}
} // else
} // if (bool {tx.spendable} == false)
txs.push_back(tx);
} //for (XmrTransaction& tx: txs_tmp)
return true;
}
bool
MySqlAccounts::select_txs_with_inputs_and_outputs(const uint64_t& account_id,
vector<XmrTransactionWithOutsAndIns>& txs)
@ -862,11 +958,17 @@ MySqlAccounts::tx_exists(const uint64_t& account_id, const string& tx_hash_str,
}
uint64_t
MySqlAccounts::mark_tx_spendable(uint64_t tx_id_no)
MySqlAccounts::mark_tx_spendable(const uint64_t& tx_id_no)
{
return mysql_tx->mark_spendable(tx_id_no);
}
uint64_t
MySqlAccounts::delete_tx(const uint64_t& tx_id_no)
{
return mysql_tx->delete_tx(tx_id_no);
}
uint64_t
MySqlAccounts::insert_payment(const XmrPayment& payment)
{

@ -123,7 +123,10 @@ public:
insert(const XmrTransaction& tx_data);
uint64_t
mark_spendable(const uint64_t tx_id_no);
mark_spendable(const uint64_t& tx_id_no);
uint64_t
delete_tx(const uint64_t& tx_id_no);
bool
@ -209,6 +212,10 @@ public:
bool
select_txs(const uint64_t& account_id, vector<XmrTransaction>& txs);
bool
select_txs_for_account_spendability_check(const uint64_t& account_id,
vector<XmrTransaction>& txs);
bool
select_txs_with_inputs_and_outputs(const uint64_t& account_id,
vector<XmrTransactionWithOutsAndIns>& txs);
@ -234,7 +241,10 @@ public:
tx_exists(const uint64_t& account_id, const string& tx_hash_str, XmrTransaction& tx);
uint64_t
mark_tx_spendable(uint64_t tx_id_no);
mark_tx_spendable(const uint64_t& tx_id_no);
uint64_t
delete_tx(const uint64_t& tx_id_no);
uint64_t
insert_payment(const XmrPayment& payment);

@ -160,97 +160,54 @@ YourMoneroRequests::get_address_txs(const shared_ptr< Session > session, const B
xmreg::XmrAccount acc;
// select this account if its existing one
if (xmr_accounts->select(xmr_address, acc))
{
j_response["total_received"] = acc.total_received;
j_response["start_height"] = acc.start_height;
if (xmr_accounts->select(xmr_address, acc)) {
uint64_t total_received{0};
j_response["total_received"] = total_received;
j_response["start_height"] = acc.start_height;
j_response["scanned_block_height"] = acc.scanned_block_height;
j_response["blockchain_height"] = CurrentBlockchainStatus::get_current_blockchain_height();
j_response["blockchain_height"] = CurrentBlockchainStatus::get_current_blockchain_height();
vector<XmrTransaction> txs;
// retrieve txs from mysql associated with the given address
if (xmr_accounts->select_txs(acc.id, txs))
{
if (!txs.empty())
{
// we found some txs.
json j_txs = json::array();
for (XmrTransaction tx: txs)
{
if (xmr_accounts->select_txs_for_account_spendability_check(acc.id, txs)) {
// first we check if txs stored in db are already spendable
// it means if they are older than 10 blocks. If yes,
// we mark them as spendable, as we assumet that blocks
// older than 10 blocks are permanent, i.e, they wont get
// orphaned.
json j_txs = json::array();
if (bool {tx.spendable} == false)
{
if (CurrentBlockchainStatus::is_tx_unlocked(tx.height))
{
for (XmrTransaction tx: txs)
{
json j_tx = tx.to_json();
// this tx was before marked as unspendable, but now
// it is spendable. Meaning, that its older than 10 blocks.
// so mark it as spendable, so that its permanet.
vector<XmrTransactionWithOutsAndIns> inputs;
uint64_t no_row_updated = xmr_accounts->mark_tx_spendable(tx.id);
if (xmr_accounts->select_inputs_for_tx(tx.id, inputs)) {
json j_spent_outputs = json::array();
if (no_row_updated != 1)
{
throw runtime_error("no_row_updated != 1");
}
uint64_t total_spent{0};
tx.spendable = true;
}
else
{
// tx was marked as non-spendable, i.e., youger than 10 blocks
// so we still are going to use this txs, but we need to double
// check if its still valid, i.e., it's block did not get orphaned.
// we do this by checking if txs still exists in the blockchain
// and if its in the same block as noted in the database.
}
for (XmrTransactionWithOutsAndIns input: inputs) {
total_spent += input.amount;
j_spent_outputs.push_back(input.spent_output());
}
// get inputs associated with a given
// transaction, if any.
json j_tx = tx.to_json();
j_tx["total_sent"] = total_spent;
vector<XmrTransactionWithOutsAndIns> inputs;
j_tx["spent_outputs"] = j_spent_outputs;
if (xmr_accounts->select_inputs_for_tx(tx.id, inputs))
{
json j_spent_outputs = json::array();
uint64_t total_spent {0};
for (XmrTransactionWithOutsAndIns input: inputs)
{
total_spent += input.amount;
j_spent_outputs.push_back(input.spent_output());
}
j_tx["total_sent"] = total_spent;
j_tx["spent_outputs"] = j_spent_outputs;
}
j_txs.push_back(j_tx);
total_received += total_spent;
}
j_response["transactions"] = j_txs;
j_txs.push_back(j_tx);
} // if (!txs.empty())
} // for (XmrTransaction tx: txs)
} // if (xmr_accounts->select_txs(acc.id, txs))
j_response["total_received"] = total_received;
} // if (xmr_accounts->select(xmr_address, acc))
j_response["transactions"] = j_txs;
} // if (xmr_accounts->select_txs_for_account_spendability_check(acc.id, txs))
} // if (xmr_accounts->select(xmr_address, acc))
string response_body = j_response.dump();
@ -292,11 +249,15 @@ YourMoneroRequests::get_address_info(const shared_ptr< Session > session, const
// select this account if its existing one
if (xmr_accounts->select(xmr_address, acc))
{
//@todo: this needs to be set in the loop as in earlier function
uint64_t total_received {0};
// ping the search thread that we still need it.
// otherwise it will finish after some time.
CurrentBlockchainStatus::ping_search_thread(xmr_address);
j_response["total_received"] = acc.total_received;
j_response["total_received"] = total_received;
j_response["start_height"] = acc.start_height;
j_response["scanned_block_height"] = acc.scanned_block_height;
j_response["blockchain_height"] = CurrentBlockchainStatus::get_current_blockchain_height();
@ -308,31 +269,24 @@ YourMoneroRequests::get_address_info(const shared_ptr< Session > session, const
// retrieve txs from mysql associated with the given address
if (xmr_accounts->select_txs_with_inputs_and_outputs(acc.id, txs))
{
// we found some txs.
json j_spent_outputs = json::array();
if (!txs.empty())
for (XmrTransactionWithOutsAndIns tx: txs)
{
//
json j_spent_outputs = json::array();
for (XmrTransactionWithOutsAndIns tx: txs)
if (tx.key_image.is_null)
{
if (tx.key_image.is_null)
{
continue;
}
j_spent_outputs.push_back(tx.spent_output());
total_sent += tx.amount;
continue;
}
j_response["spent_outputs"] = j_spent_outputs;
j_spent_outputs.push_back(tx.spent_output());
total_sent += tx.amount;
}
j_response["total_sent"] = total_sent;
j_response["spent_outputs"] = j_spent_outputs;
} // if (!txs.empty())
j_response["total_sent"] = total_sent;
} // if (xmr_accounts->select_txs_with_inputs_and_outputs(acc.id, txs))

@ -89,6 +89,10 @@ struct XmrTransaction : public Transactions
SELECT * FROM `Transactions` WHERE `account_id` = (%0q) AND `hash` = (%1q)
)";
static constexpr const char* DELETE_STMT = R"(
DELETE FROM `Transactions` WHERE `id` = (%0q)
)";
static constexpr const char* INSERT_STMT = R"(
INSERT IGNORE INTO `Transactions` (`hash`, `prefix_hash`, `account_id`,
`total_received`, `total_sent`, `unlock_time`,

Loading…
Cancel
Save