basic transactions search added

pull/1/head
moneroexamples 8 years ago
parent 6f7c582b4a
commit 3485483cf2

@ -108,22 +108,25 @@ class MysqlTransactions
public:
bool
select(const string& address, vector<XmrTransaction>& txs)
select(const uint64_t& address_id, vector<XmrTransaction>& txs)
{
//
// static shared_ptr<Query> query;
//
// if (!query)
// {
// Query q = MySqlConnector::getInstance().query(
// XmrTransaction::SELECT_STMT);
// q.parse();
// query = shared_ptr<Query>(new Query(q));
// }
static shared_ptr<Query> query;
if (!query)
{
Query q = MySqlConnector::getInstance().query(
XmrTransaction::SELECT_STMT);
q.parse();
query = shared_ptr<Query>(new Query(q));
}
Query query = MySqlConnector::getInstance().query(XmrTransaction::SELECT_STMT);
query.parse();
try
{
query->storein(txs, address);
query.storein(txs, address_id);
if (!txs.empty())
{
@ -142,6 +145,53 @@ public:
return false;
}
uint64_t
insert(const XmrTransaction& tx_data)
{
// static shared_ptr<Query> query;
//
// if (!query)
// {
// Query q = MySqlConnector::getInstance().query(XmrTransaction::INSERT_STMT);
// q.parse();
// query = shared_ptr<Query>(new Query(q));
// }
Query query = MySqlConnector::getInstance().query(XmrTransaction::INSERT_STMT);
query.parse();
// cout << query << endl;
try
{
SimpleResult sr = query.execute(tx_data.hash,
tx_data.account_id,
tx_data.total_received,
tx_data.total_sent,
tx_data.unlock_time,
tx_data.height,
tx_data.coinbase,
tx_data.payment_id,
tx_data.mixin,
tx_data.timestamp);
if (sr.rows() == 1)
return sr.insert_id();
}
catch (mysqlpp::Exception& e)
{
MYSQL_EXCEPTION_MSG(e);
return 0;
}
return 0;
}
};
@ -149,6 +199,8 @@ public:
class MySqlAccounts
{
MysqlTransactions mysql_tx;
public:
@ -156,22 +208,22 @@ public:
select(const string& address, XmrAccount& account)
{
static shared_ptr<Query> query;
if (!query)
{
Query q = MySqlConnector::getInstance().query(XmrAccount::SELECT_STMT);
q.parse();
query = shared_ptr<Query>(new Query(q));
}
// static shared_ptr<Query> query;
//
// if (!query)
// {
// Query q = MySqlConnector::getInstance().query(XmrAccount::SELECT_STMT);
// q.parse();
// query = shared_ptr<Query>(new Query(q));
// }
// Query query = conn.query(XmrAccount::SELECT_STMT);
// query.parse();
Query query = MySqlConnector::getInstance().query(XmrAccount::SELECT_STMT);
query.parse();
try
{
vector<XmrAccount> res;
query->storein(res, address);
query.storein(res, address);
if (!res.empty())
{
@ -196,22 +248,22 @@ public:
select(const int64_t& acc_id, XmrAccount& account)
{
static shared_ptr<Query> query;
//static shared_ptr<Query> query;
if (!query)
{
Query q = MySqlConnector::getInstance().query(XmrAccount::SELECT_STMT2);
q.parse();
query = shared_ptr<Query>(new Query(q));
}
// if (!query)
// {
// Query q = MySqlConnector::getInstance().query(XmrAccount::SELECT_STMT2);
// q.parse();
// query = shared_ptr<Query>(new Query(q));
// }
// Query query = conn.query(XmrAccount::SELECT_STMT2);
// query.parse();
Query query = MySqlConnector::getInstance().query(XmrAccount::SELECT_STMT2);
query.parse();
try
{
vector<XmrAccount> res;
query->storein(res, acc_id);
query.storein(res, acc_id);
if (!res.empty())
{
@ -232,24 +284,24 @@ public:
insert(const string& address, const uint64_t& scanned_block_height = 0)
{
static shared_ptr<Query> query;
// static shared_ptr<Query> query;
if (!query)
{
Query q = MySqlConnector::getInstance().query(XmrAccount::INSERT_STMT);
q.parse();
query = shared_ptr<Query>(new Query(q));
}
// if (!query)
// {
// Query q = MySqlConnector::getInstance().query(XmrAccount::INSERT_STMT);
// q.parse();
// query = shared_ptr<Query>(new Query(q));
// }
// Query query = conn.query(XmrAccount::INSERT_STMT);
// query.parse();
Query query = MySqlConnector::getInstance().query(XmrAccount::INSERT_STMT);
query.parse();
// cout << query << endl;
try
{
SimpleResult sr = query->execute(address, scanned_block_height);
SimpleResult sr = query.execute(address, scanned_block_height);
if (sr.rows() == 1)
return sr.insert_id();
@ -264,6 +316,39 @@ public:
return 0;
}
uint64_t
insert_tx(const XmrTransaction& tx_data)
{
return mysql_tx.insert(tx_data);
}
bool
select_txs(const string& xmr_address, vector<XmrTransaction>& txs)
{
// having address first get its address_id
// a placeholder for exciting or new account data
xmreg::XmrAccount acc;
// select this account if its existing one
if (!select(xmr_address, acc))
{
cerr << "Address" << xmr_address << "does not exist in database" << endl;
return false;
}
return mysql_tx.select(acc.id, txs);
}
bool
select_txs(const uint64_t& account_id, vector<XmrTransaction>& txs)
{
return mysql_tx.select(account_id, txs);
}
bool
update(XmrAccount& acc_orginal, XmrAccount& acc_new)
{

@ -89,11 +89,9 @@ public:
throw TxSearchException("searched_blk_no > CurrentBlockchainStatus::current_height");
}
while(continue_search)
{
while(continue_search) {
if (searched_blk_no > CurrentBlockchainStatus::current_height)
{
if (searched_blk_no > CurrentBlockchainStatus::current_height) {
fmt::print("searched_blk_no {:d} and current_height {:d}\n",
searched_blk_no, CurrentBlockchainStatus::current_height);
@ -106,33 +104,34 @@ public:
}
//
cout << " - searching tx of: " << acc << endl;
//cout << " - searching tx of: " << acc << endl;
// get block cointaining this tx
block blk;
if (!CurrentBlockchainStatus::get_block(searched_blk_no, blk))
{
if (!CurrentBlockchainStatus::get_block(searched_blk_no, blk)) {
cerr << "Cant get block of height: " + to_string(searched_blk_no) << endl;
searched_blk_no =- 2; // just go back one block, and retry
searched_blk_no = -2; // just go back one block, and retry
continue;
}
// for each tx in the given block look, get ouputs
list<cryptonote::transaction> blk_txs;
list <cryptonote::transaction> blk_txs;
if (!CurrentBlockchainStatus::get_block_txs(blk, blk_txs))
{
if (!CurrentBlockchainStatus::get_block_txs(blk, blk_txs)) {
throw TxSearchException("Cant get transactions in block: " + to_string(searched_blk_no));
}
//std::lock_guard<std::mutex> lck (mtx);
fmt::print(" - searching block {:d} of hash {:s} \n",
searched_blk_no, pod_to_hex(get_block_hash(blk)));
// if (searched_blk_no % 10 == 0)
// {
// // print status every 10th block
//
// fmt::print(" - searching block {:d} of hash {:s} \n",
// searched_blk_no, pod_to_hex(get_block_hash(blk)));
// }
for (transaction& tx: blk_txs)
{
@ -164,6 +163,10 @@ public:
throw TxSearchException("");
}
uint64_t total_received {0};
bool found_mine_outputs {false};
for (auto& out: outputs)
{
txout_to_key txout_k = std::get<0>(out);
@ -225,15 +228,88 @@ public:
pod_to_hex(txout_k.key));
cout << msg << endl;
total_received += amount;
found_mine_outputs = true;
}
} // for (const auto& out: outputs)
if (found_mine_outputs)
{
crypto::hash payment_id = null_hash;
crypto::hash8 payment_id8 = null_hash8;
get_payment_id(tx, payment_id, payment_id8);
string payment_id_str {""};
if (payment_id != null_hash)
{
payment_id_str = pod_to_hex(payment_id);
}
else if (payment_id8 != null_hash8)
{
payment_id_str = pod_to_hex(payment_id8);
}
XmrTransaction tx_data;
tx_data.hash = pod_to_hex(tx_hash);
tx_data.account_id = acc.id;
tx_data.total_received = total_received;
tx_data.total_sent = 0; // at this stage we don't have any
// info about spendings
tx_data.unlock_time = 0;
tx_data.height = searched_blk_no;
tx_data.coinbase = is_coinbase(tx);
tx_data.payment_id = payment_id_str;
tx_data.mixin = get_mixin_no(tx) - 1;
tx_data.timestamp = XmrTransaction::timestamp_to_DateTime(blk.timestamp);
// insert tx_data into mysql's Transactions table
uint64_t tx_mysql_id = xmr_accounts.insert_tx(tx_data);
// once tx was added, update Accounts table
XmrAccount updated_acc = acc;
updated_acc.total_received = acc.total_received + tx_data.total_received;
if (xmr_accounts.update(acc, updated_acc))
{
// iff success, set acc to updated_acc;
acc = updated_acc;
}
}
} // for (const transaction& tx: blk_txs)
if (searched_blk_no % 10)
{
// every 10 blocks updated scanned_block_height
XmrAccount updated_acc = acc;
updated_acc.scanned_block_height = searched_blk_no;
if (xmr_accounts.update(acc, updated_acc))
{
// iff success, set acc to updated_acc;
acc = updated_acc;
}
}
++searched_blk_no;
std::this_thread::sleep_for(std::chrono::seconds(1));
//std::this_thread::sleep_for(std::chrono::seconds(1));
}
}

@ -183,18 +183,54 @@ public:
{
json j_request = body_to_json(body);
// if (show_logs)
// print_json_log("get_address_txs request: ", j_request);
if (show_logs)
print_json_log("get_address_txs request: ", j_request);
string xmr_address = j_request["address"];
// initializa json response
json j_response {
{ "total_received", "0"},
{ "scanned_height", 2012455},
{ "scanned_block_height", 1195848},
{ "start_height", 2012455},
{ "transaction_height", 2012455},
{ "blockchain_height", 1195848}
{ "scanned_height", 0},
{ "scanned_block_height", 0},
{ "start_height", 0},
{ "transaction_height", 0},
{ "blockchain_height", 0}
};
// a placeholder for exciting or new account data
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["scanned_block_height"] = acc.scanned_block_height;
j_response["blockchain_height"] = CurrentBlockchainStatus::get_current_blockchain_height();
vector<XmrTransaction> txs;
// retrive txs from mysql associated with the given address
if (xmr_accounts->select_txs(acc.id, txs))
{
// we found some txs.
if (!txs.empty())
{
json j_txs = json::array();
for (XmrTransaction tx: txs)
{
j_txs.push_back(tx.to_json());
}
j_response["transactions"] = j_txs;
}
}
}
string response_body = j_response.dump();
auto response_headers = make_headers({{ "Content-Length", to_string(response_body.size())}});

@ -54,6 +54,17 @@ struct XmrAccount : public Accounts
using Accounts::Accounts;
XmrAccount():Accounts()
{
address = "";
scanned_height = 0;
scanned_block_height = 0;
start_height = 0;
transaction_height = 0;
blockchain_height = 0;
total_sent = 0;
}
// viewkey is not stored in mysql db or anywhere
// so need to be populated when user logs in.
string viewkey;
@ -83,7 +94,7 @@ ostream& operator<< (std::ostream& os, const XmrAccount& acc) {
};
sql_create_10(Transactions, 1, 2,
sql_create_11(Transactions, 1, 2,
sql_bigint_unsigned, id,
sql_varchar , hash,
sql_bigint_unsigned, account_id,
@ -92,6 +103,7 @@ sql_create_10(Transactions, 1, 2,
sql_bigint_unsigned, unlock_time,
sql_bigint_unsigned, height,
sql_bool , coinbase,
sql_varchar , payment_id,
sql_bigint_unsigned, mixin,
sql_timestamp , timestamp);
@ -101,13 +113,26 @@ struct XmrTransaction : public Transactions
{
static constexpr const char* SELECT_STMT = R"(
SELECT * FROM `Transactions` WHERE `address_id` = (%0q)
SELECT * FROM `Transactions` WHERE `account_id` = (%0q)
)";
static constexpr const char* SELECT_STMT2 = R"(
SELECT * FROM `Transactions` WHERE `id` = (%0q)
)";
static constexpr const char* INSERT_STMT = R"(
INSERT IGNORE INTO `Transactions` (`hash`, `account_id`, `total_received`,
`total_sent`, `unlock_time`, `height`,
`coinbase`, `payment_id`, `mixin`,
`timestamp`)
VALUES (%0q, %1q, %2q,
%3q, %4q, %5q,
%6q, %7q, %8q,
%9q);
)";
using Transactions::Transactions;
json
@ -119,12 +144,20 @@ struct XmrTransaction : public Transactions
{"total_received" , total_received},
{"total_sent" , total_sent},
{"height" , height},
{"coinbase" , bool {coinbase}},
{"mixin" , mixin},
{"timestamp" , timestamp}
};
return j;
}
static DateTime
timestamp_to_DateTime(time_t timestamp)
{
return DateTime(timestamp);
}
friend std::ostream& operator<< (std::ostream& stream, const XmrTransaction& acc);
};

Loading…
Cancel
Save