diff --git a/src/CurrentBlockchainStatus.cpp b/src/CurrentBlockchainStatus.cpp index b7543fc..f9fb867 100755 --- a/src/CurrentBlockchainStatus.cpp +++ b/src/CurrentBlockchainStatus.cpp @@ -831,7 +831,7 @@ CurrentBlockchainStatus::get_searched_blk_no(const string& address, if (!search_thread_exist(address)) { // thread does not exist - OMERROR << "thread for " << address << " does not exist"; + OMERROR << "thread for " << address.substr(0,6) << " does not exist"; return false; } @@ -850,7 +850,7 @@ CurrentBlockchainStatus::get_known_outputs_keys( if (!search_thread_exist(address)) { // thread does not exist - OMERROR << "thread for " << address << " does not exist"; + OMERROR << "thread for " << address.substr(0,6) << " does not exist"; return false; } @@ -881,7 +881,8 @@ CurrentBlockchainStatus::get_xmr_address_viewkey( if (!search_thread_exist(address_str)) { // thread does not exist - OMERROR << "thread for " << address_str << " does not exist"; + OMERROR << "thread for " << address_str.substr(0,6) + << " does not exist"; return false; } @@ -903,7 +904,8 @@ CurrentBlockchainStatus::find_txs_in_mempool( if (searching_threads.count(address_str) == 0) { // thread does not exist - OMERROR << "thread for " << address_str << " does not exist"; + OMERROR << "thread for " + << address_str.substr(0,6) << " does not exist"; return false; } diff --git a/src/TxSearch.cpp b/src/TxSearch.cpp index e588d0a..df50b98 100755 --- a/src/TxSearch.cpp +++ b/src/TxSearch.cpp @@ -85,549 +85,556 @@ try while(continue_search) { - seconds loop_timestamp {current_timestamp}; +seconds loop_timestamp {current_timestamp}; - uint64_t last_block_height = current_bc_status->current_height; +uint64_t last_block_height = current_bc_status->current_height; - uint64_t h1 = searched_blk_no; - uint64_t h2 = std::min(h1 + blocks_lookahead - 1, last_block_height); +uint64_t h1 = searched_blk_no; +uint64_t h2 = std::min(h1 + blocks_lookahead - 1, last_block_height); - vector blocks; - - blocks = current_bc_status->get_blocks_range(h1, h2); +vector blocks; - if (blocks.empty()) - { - - if (h1 <= h2) - { - OMERROR << address_prefix - << ": cant get blocks from " << h1 - << " to " << h2; - stop(); - } - else - { - OMINFO << address_prefix - << ": waiting for new block. " - "Last scanned was " << h2; - } - - std::this_thread::sleep_for( - std::chrono::seconds( - current_bc_status->get_bc_setup() - .refresh_block_status_every) - ); - - loop_timestamp = get_current_timestamp(); - - // if thread has lived longer than thread_search_li - // without last_ping_timestamp being updated, - // stop the thread - if (loop_timestamp - last_ping_timestamp > thread_search_life) - { - OMINFO << address_prefix - + ": search thread stopped."; - stop(); - } - - // update current_height of blockchain, as maybe top block(s) - // were dropped due to reorganization. - //CurrentBlockchainStatus::update_current_blockchain_height(); +blocks = current_bc_status->get_blocks_range(h1, h2); - // if any txs that we already indexed got orphaned as a - // consequence of this - // MySqlAccounts::select_txs_for_account_spendability_check - // should - // update database accordingly when get_address_txs is executed. +if (blocks.empty()) +{ - continue; + if (h1 <= h2) + { + OMERROR << address_prefix + << ": cant get blocks from " << h1 + << " to " << h2; + stop(); + } + else + { + OMINFO << address_prefix + << ": waiting for new block. " + "Last scanned was " << h2; } - OMINFO << address_prefix + ": analyzing " - << blocks.size() << " blocks from " - << h1 << " to " << h2 - << " out of " << last_block_height << " blocks"; + std::this_thread::sleep_for( + std::chrono::seconds( + current_bc_status->get_bc_setup() + .refresh_block_status_every) + ); - vector txs_hashes_from_blocks; - vector txs_in_blocks; - vector txs_data; + loop_timestamp = get_current_timestamp(); - if (!current_bc_status->get_txs_in_blocks(blocks, - txs_hashes_from_blocks, - txs_in_blocks, - txs_data)) + // if thread has lived longer than thread_search_li + // without last_ping_timestamp being updated, + // stop the thread + if (loop_timestamp - last_ping_timestamp > thread_search_life) { - OMERROR << address_prefix - + ": cant get tx in blocks from " - << h1 << " to " << h2; - return; + OMINFO << address_prefix + + ": search thread stopped."; + stop(); } - // we will only create mysql DateTime object once, anything is found - // in a given block; - unique_ptr blk_timestamp_mysql_format; + // update current_height of blockchain, as maybe top block(s) + // were dropped due to reorganization. + //CurrentBlockchainStatus::update_current_blockchain_height(); - // searching for our incoming and outgoing xmr has two components. - // - // FIRST. to search for the incoming xmr, we use address, viewkey and - // outputs public key. Its straight forward, as this is what viewkey was - // designed to do. - // - // SECOND. Searching for spendings (i.e., key images) is more difficult, - // because we dont have spendkey. But what we can do is, we can look for - // candidate key images. And this can be achieved by checking if any mixin - // in associated with the given key image, is our output. If it is our output, - // then we assume its our key image (i.e. we spend this output). - // Off course this is only - // assumption as our outputs can be used in key images of others for their - // mixin purposes. Thus, we sent to the front end the list of key images - // that we think are yours, and the frontend, because it has spend key, - // can filter out false positives. - - size_t tx_idx {0}; - - for (auto const& tx_tuple: txs_data) - { - crypto::hash const& tx_hash = txs_hashes_from_blocks[tx_idx]; - transaction const& tx = txs_in_blocks[tx_idx++]; - uint64_t blk_height = std::get<0>(tx_tuple); - uint64_t blk_timestamp = std::get<1>(tx_tuple); - bool is_coinbase = std::get<2>(tx_tuple); - bool is_rct = (tx.version == 2); - uint8_t rct_type = (is_rct ? tx.rct_signatures.type : 0); + // if any txs that we already indexed got orphaned as a + // consequence of this + // MySqlAccounts::select_txs_for_account_spendability_check + // should + // update database accordingly when get_address_txs is executed. - //cout << "\n\n\n" << blk_height << '\n'; + continue; +} - // Class that is responsible for identification of our outputs - // and inputs in a given tx. +OMINFO << address_prefix + ": analyzing " + << blocks.size() << " blocks from " + << h1 << " to " << h2 + << " out of " << last_block_height << " blocks"; - auto identifier = make_identifier(tx, - make_unique(&address, &viewkey), - make_unique(&address, &viewkey, - &known_outputs_keys, - &mcore_addapter)); - identifier.identify(); +vector txs_hashes_from_blocks; +vector txs_in_blocks; +vector txs_data; - // flag indicating whether the txs in the given block are - // spendable. - // this is true when block number is more than 10 blocks - // from current blockchain height. - // if tx.unlock_time is not given (its value is 0), we set it - // here. For coinbase its always given, so no need to check - // for that +if (!current_bc_status->get_txs_in_blocks(blocks, + txs_hashes_from_blocks, + txs_in_blocks, + txs_data)) +{ + OMERROR << address_prefix + + ": cant get tx in blocks from " + << h1 << " to " << h2; + return; +} - uint64_t tx_unlock_time = tx.unlock_time; +// we will only create mysql DateTime object once, anything is found +// in a given block; +unique_ptr blk_timestamp_mysql_format; - if (tx_unlock_time == 0) - tx_unlock_time = blk_height - + CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE; +// searching for our incoming and outgoing xmr has two components. +// +// FIRST. to search for the incoming xmr, we use address, viewkey and +// outputs public key. Its straight forward, as this is what viewkey was +// designed to do. +// +// SECOND. Searching for spendings (i.e., key images) is more difficult, +// because we dont have spendkey. But what we can do is, we can look for +// candidate key images. And this can be achieved by checking if any mixin +// in associated with the given key image, is our output. If it is our output, +// then we assume its our key image (i.e. we spend this output). +// Off course this is only +// assumption as our outputs can be used in key images of others for their +// mixin purposes. Thus, we sent to the front end the list of key images +// that we think are yours, and the frontend, because it has spend key, +// can filter out false positives. + +size_t tx_idx {0}; + +for (auto const& tx_tuple: txs_data) +{ + crypto::hash const& tx_hash = txs_hashes_from_blocks[tx_idx]; + transaction const& tx = txs_in_blocks[tx_idx++]; + uint64_t blk_height = std::get<0>(tx_tuple); + uint64_t blk_timestamp = std::get<1>(tx_tuple); + bool is_coinbase = std::get<2>(tx_tuple); + bool is_rct = (tx.version == 2); + uint8_t rct_type = (is_rct ? tx.rct_signatures.type : 0); + + //cout << "\n\n\n" << blk_height << '\n'; + + // Class that is responsible for identification of our outputs + // and inputs in a given tx. + + auto identifier = make_identifier(tx, + make_unique(&address, &viewkey), + make_unique(&address, &viewkey, + &known_outputs_keys, + &mcore_addapter)); + identifier.identify(); + + // flag indicating whether the txs in the given block are + // spendable. + // this is true when block number is more than 10 blocks + // from current blockchain height. + // if tx.unlock_time is not given (its value is 0), we set it + // here. For coinbase its always given, so no need to check + // for that + + uint64_t tx_unlock_time = tx.unlock_time; + + if (tx_unlock_time == 0) + tx_unlock_time = blk_height + + CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE; + + bool is_spendable = current_bc_status->is_tx_unlocked( + tx_unlock_time, blk_height); + + // this is id of txs in lmdb blockchain table. + // it will be used mostly to sort txs in the frontend. + uint64_t blockchain_tx_id {0}; + + // FIRSt step. + // + //oi_identification.identify_outputs(); + auto const& outputs_identified + = identifier.get()->get(); - bool is_spendable = current_bc_status->is_tx_unlocked( - tx_unlock_time, blk_height); + auto total_received = calc_total_xmr(outputs_identified); - // this is id of txs in lmdb blockchain table. - // it will be used mostly to sort txs in the frontend. - uint64_t blockchain_tx_id {0}; + vector amount_specific_indices; - // FIRSt step. - // - //oi_identification.identify_outputs(); - auto const& outputs_identified - = identifier.get()->get(); + uint64_t tx_mysql_id {0}; - auto total_received = calc_total_xmr(outputs_identified); + // create pointer to mysql transaction object + // that we will initilize if we find something. + unique_ptr mysql_transaction; - vector amount_specific_indices; + // if we identified some outputs as ours, + // save them into mysql. + if (!outputs_identified.empty()) + { + auto tx_hash_str = pod_to_hex(tx_hash); + auto tx_hash_prefix_str + = pod_to_hex(get_transaction_prefix_hash(tx)); + auto tx_pub_key_str + = pod_to_hex(identifier.get_tx_pub_key()); + uint64_t mixin_no {0}; + if (!is_coinbase) + mixin_no = xmreg::get_mixin_no(tx); - uint64_t tx_mysql_id {0}; - // create pointer to mysql transaction object - // that we will initilize if we find something. - unique_ptr mysql_transaction; + if (!blk_timestamp_mysql_format) + { + blk_timestamp_mysql_format + = unique_ptr( + new DateTime( + static_cast(blk_timestamp))); + } - // if we identified some outputs as ours, - // save them into mysql. - if (!outputs_identified.empty()) + if (!mysql_transaction) { - auto tx_hash_str = pod_to_hex(tx_hash); - auto tx_hash_prefix_str - = pod_to_hex(get_transaction_prefix_hash(tx)); - auto tx_pub_key_str - = pod_to_hex(identifier.get_tx_pub_key()); - uint64_t mixin_no {0}; - if (!is_coinbase) - mixin_no = xmreg::get_mixin_no(tx); + // start mysql transaction here + mysql_transaction + = unique_ptr( + new mysqlpp::Transaction( + xmr_accounts->get_connection() + ->get_connection())); + + // when we rescan blockchain some txs can already + // be present in the mysql. So remove them, and their + // associated data in that case to repopulate fresh + // tx data + if (!delete_existing_tx_if_exists(tx_hash_str)) + throw TxSearchException("Cant delete tx " + + tx_hash_str); + } - if (!blk_timestamp_mysql_format) - { - blk_timestamp_mysql_format - = unique_ptr( - new DateTime( - static_cast(blk_timestamp))); - } + if (!current_bc_status->tx_exist(tx_hash, blockchain_tx_id)) + { + OMERROR << "Tx " << tx_hash_str + << " not found in blockchain !"; + throw TxSearchException("Cant get tx from blockchain: " + + tx_hash_str); + } - if (!mysql_transaction) - { - // start mysql transaction here - mysql_transaction - = unique_ptr( - new mysqlpp::Transaction( - xmr_accounts->get_connection() - ->get_connection())); - - // when we rescan blockchain some txs can already - // be present in the mysql. So remove them, and their - // associated data in that case to repopulate fresh - // tx data - if (!delete_existing_tx_if_exists(tx_hash_str)) - throw TxSearchException("Cant delete tx " - + tx_hash_str); + OMINFO << address_prefix + + ": found some outputs in block " + << blk_height << ", tx: " + << tx_hash_str; + + + XmrTransaction tx_data; + + tx_data.id = mysqlpp::null; + tx_data.hash = tx_hash_str; + tx_data.prefix_hash = tx_hash_prefix_str; + tx_data.tx_pub_key = tx_pub_key_str; + tx_data.account_id = acc->id.data; + tx_data.blockchain_tx_id = blockchain_tx_id; + tx_data.total_received = total_received; + tx_data.total_sent = 0; // at this stage we don't have + // anyinfo about spendings + + // this is current block + // + unlock time + // for regular tx, + // the unlock time is + // default of 10 blocks. + // for coinbase tx it is 60 blocks + tx_data.unlock_time = tx_unlock_time; + + tx_data.height = blk_height; + tx_data.coinbase = is_coinbase; + tx_data.is_rct = is_rct; + tx_data.rct_type = rct_type; + tx_data.spendable = is_spendable; + tx_data.payment_id = current_bc_status + ->get_payment_id_as_string(tx); + tx_data.mixin = mixin_no; + tx_data.timestamp = *blk_timestamp_mysql_format; - } - - if (!current_bc_status->tx_exist(tx_hash, blockchain_tx_id)) - { - OMERROR << "Tx " << tx_hash_str - << " not found in blockchain !"; - throw TxSearchException("Cant get tx from blockchain: " - + tx_hash_str); - } - OMINFO << address_prefix - + ": found some outputs in block " - << blk_height << ", tx: " - << tx_hash_str; - - - XmrTransaction tx_data; - - tx_data.id = mysqlpp::null; - tx_data.hash = tx_hash_str; - tx_data.prefix_hash = tx_hash_prefix_str; - tx_data.tx_pub_key = tx_pub_key_str; - tx_data.account_id = acc->id.data; - tx_data.blockchain_tx_id = blockchain_tx_id; - tx_data.total_received = total_received; - tx_data.total_sent = 0; // at this stage we don't have - // anyinfo about spendings - - // this is current block - // + unlock time - // for regular tx, - // the unlock time is - // default of 10 blocks. - // for coinbase tx it is 60 blocks - tx_data.unlock_time = tx_unlock_time; - - tx_data.height = blk_height; - tx_data.coinbase = is_coinbase; - tx_data.is_rct = is_rct; - tx_data.rct_type = rct_type; - tx_data.spendable = is_spendable; - tx_data.payment_id = current_bc_status - ->get_payment_id_as_string(tx); - tx_data.mixin = mixin_no; - tx_data.timestamp = *blk_timestamp_mysql_format; - - - // insert tx_data into mysql's Transactions table - tx_mysql_id = xmr_accounts->insert(tx_data); - - // get amount specific (i.e., global) indices of outputs - if (!current_bc_status->get_amount_specific_indices( - tx_hash, amount_specific_indices)) - { - OMERROR << address_prefix - + ": cant get_amount_specific_indices!"; - throw TxSearchException( - "cant get_amount_specific_indices!"); - } + // insert tx_data into mysql's Transactions table + tx_mysql_id = xmr_accounts->insert(tx_data); - if (tx_mysql_id == 0) - { - OMERROR << address_prefix - + ": tx_mysql_id is zero!" - << tx_data; - throw TxSearchException("tx_mysql_id is zero!"); - } + // get amount specific (i.e., global) indices of outputs + if (!current_bc_status->get_amount_specific_indices( + tx_hash, amount_specific_indices)) + { + OMERROR << address_prefix + + ": cant get_amount_specific_indices!"; + throw TxSearchException( + "cant get_amount_specific_indices!"); + } - vector outputs_found; + if (tx_mysql_id == 0) + { + OMERROR << address_prefix + + ": tx_mysql_id is zero!" + << tx_data; + throw TxSearchException("tx_mysql_id is zero!"); + } + + vector outputs_found; + + // now add the found outputs into Outputs tables + for (auto&& out_info: outputs_identified) + { + XmrOutput out_data; + + out_data.id = mysqlpp::null; + out_data.account_id = acc->id.data; + out_data.tx_id = tx_mysql_id; + out_data.out_pub_key = pod_to_hex(out_info.pub_key); + out_data.tx_pub_key = tx_pub_key_str; + out_data.amount = out_info.amount; + out_data.out_index = out_info.idx_in_tx; + out_data.rct_outpk = pod_to_hex(out_info.rtc_outpk); + out_data.rct_mask = pod_to_hex(out_info.rtc_mask); + out_data.rct_amount = pod_to_hex(out_info.rtc_amount); + out_data.global_index = amount_specific_indices + .at(out_data.out_index); + out_data.mixin = tx_data.mixin; + out_data.timestamp = tx_data.timestamp; + + outputs_found.push_back(std::move(out_data)); - // now add the found outputs into Outputs tables - for (auto&& out_info: outputs_identified) { - XmrOutput out_data; - - out_data.id = mysqlpp::null; - out_data.account_id = acc->id.data; - out_data.tx_id = tx_mysql_id; - out_data.out_pub_key = pod_to_hex(out_info.pub_key); - out_data.tx_pub_key = tx_pub_key_str; - out_data.amount = out_info.amount; - out_data.out_index = out_info.idx_in_tx; - out_data.rct_outpk = pod_to_hex(out_info.rtc_outpk); - out_data.rct_mask = pod_to_hex(out_info.rtc_mask); - out_data.rct_amount = pod_to_hex(out_info.rtc_amount); - out_data.global_index = amount_specific_indices - .at(out_data.out_index); - out_data.mixin = tx_data.mixin; - out_data.timestamp = tx_data.timestamp; - - outputs_found.push_back(std::move(out_data)); + // add the outputs found into known_outputs_keys map + std::lock_guard lck ( + getting_known_outputs_keys); + known_outputs_keys.insert( + {out_info.pub_key, out_info.amount}); + } - { - // add the outputs found into known_outputs_keys map - std::lock_guard lck ( - getting_known_outputs_keys); - known_outputs_keys.insert( - {out_info.pub_key, out_info.amount}); - } + } // for (auto& out_info: outputs_identified) - } // for (auto& out_info: outputs_identified) + // insert all outputs found into mysql's outputs table + uint64_t no_rows_inserted + = xmr_accounts->insert(outputs_found); - // insert all outputs found into mysql's outputs table - uint64_t no_rows_inserted - = xmr_accounts->insert(outputs_found); + if (no_rows_inserted == 0) + { + throw TxSearchException("no_rows_inserted is zero!"); + } - if (no_rows_inserted == 0) - { - throw TxSearchException("no_rows_inserted is zero!"); - } + } // if (!found_mine_outputs.empty()) - } // if (!found_mine_outputs.empty()) + // SECOND component: Checking for our key images, i.e., inputs. - // SECOND component: Checking for our key images, i.e., inputs. + // no need mutex here, as this will be exectued only after + // the above. there is no threads here. - // no need mutex here, as this will be exectued only after - // the above. there is no threads here. + auto const& inputs_identfied = identifier.get()->get(); - auto const& inputs_identfied = identifier.get()->get(); + if (!inputs_identfied.empty()) + { + // some inputs were identified as ours in a given tx. + // so now, go over those inputs, and check + // get detail info for each found mixin output from database + + auto tx_hash_str = pod_to_hex(tx_hash); + auto tx_hash_prefix_str + = pod_to_hex(get_transaction_prefix_hash(tx)); + auto tx_pub_key_str + = pod_to_hex(identifier.get_tx_pub_key()); + uint64_t mixin_no {0}; + if (mixin_no == 0 && !is_coinbase) + mixin_no = xmreg::get_mixin_no(tx); + + if (!blk_timestamp_mysql_format) + { + blk_timestamp_mysql_format + = unique_ptr( + new DateTime( + static_cast(blk_timestamp))); + } - if (!inputs_identfied.empty()) + if (!mysql_transaction) { - // some inputs were identified as ours in a given tx. - // so now, go over those inputs, and check - // get detail info for each found mixin output from database - - auto tx_hash_str = pod_to_hex(tx_hash); - auto tx_hash_prefix_str - = pod_to_hex(get_transaction_prefix_hash(tx)); - auto tx_pub_key_str - = pod_to_hex(identifier.get_tx_pub_key()); - uint64_t mixin_no {0}; - if (mixin_no == 0 && !is_coinbase) - mixin_no = xmreg::get_mixin_no(tx); - - if (!blk_timestamp_mysql_format) + // start mysql transaction here if not already present + mysql_transaction + = unique_ptr( + new mysqlpp::Transaction( + xmr_accounts->get_connection() + ->get_connection())); + + // when we rescan blockchain some txs can already + // be present in the mysql. So remove them, and their + // associated data in that case to repopulate fresh tx data + + // this will only execture if no outputs were found + // above. So there is no risk of deleting same tx twice + if (!delete_existing_tx_if_exists(tx_hash_str)) { - blk_timestamp_mysql_format - = unique_ptr( - new DateTime( - static_cast(blk_timestamp))); + throw TxSearchException( + "Cant delete tx " + tx_hash_str); } + } - if (!mysql_transaction) + if (blockchain_tx_id == 0) + { + if (!current_bc_status + ->tx_exist(tx_hash, blockchain_tx_id)) { - // start mysql transaction here if not already present - mysql_transaction - = unique_ptr( - new mysqlpp::Transaction( - xmr_accounts->get_connection() - ->get_connection())); - - // when we rescan blockchain some txs can already - // be present in the mysql. So remove them, and their - // associated data in that case to repopulate fresh tx data - - // this will only execture if no outputs were found - // above. So there is no risk of deleting same tx twice - if (!delete_existing_tx_if_exists(tx_hash_str)) - { - throw TxSearchException( - "Cant delete tx " + tx_hash_str); - } + OMERROR << address_prefix + ": tx " + << tx_hash_str + << "not found in blockchain !"; + throw TxSearchException( + "Cant get tx from blockchain: " + + tx_hash_str); } + } - if (blockchain_tx_id == 0) - { - if (!current_bc_status - ->tx_exist(tx_hash, blockchain_tx_id)) - { - OMERROR << address_prefix + ": tx " - << tx_hash_str - << "not found in blockchain !"; - throw TxSearchException( - "Cant get tx from blockchain: " - + tx_hash_str); - } - } + OMINFO << address_prefix + + ": found some possible " + "inputs in block " + << blk_height << ", tx: " + << tx_hash_str; - OMINFO << address_prefix - + ": found some possible " - "inputs in block " - << blk_height << ", tx: " - << tx_hash_str; + vector inputs_found; - vector inputs_found; + for (auto& in_info: inputs_identfied) + { + XmrOutput out; - for (auto& in_info: inputs_identfied) + if (xmr_accounts->output_exists( + pod_to_hex(in_info.out_pub_key), out)) { - XmrOutput out; - if (xmr_accounts->output_exists( - pod_to_hex(in_info.out_pub_key), out)) - { + // seems that this key image is ours. + // so get it information from database into XmrInput + // database structure that will be written later + // on into database. - // seems that this key image is ours. - // so get it information from database into XmrInput - // database structure that will be written later - // on into database. + XmrInput in_data; - XmrInput in_data; + in_data.id = mysqlpp::null; + in_data.account_id = acc->id.data; + in_data.tx_id = 0; // later we set it + in_data.output_id = out.id.data; + in_data.key_image = pod_to_hex(in_info.key_img); + in_data.amount = out.amount; + // must match corresponding + // output's amount + in_data.timestamp = *blk_timestamp_mysql_format; - in_data.id = mysqlpp::null; - in_data.account_id = acc->id.data; - in_data.tx_id = 0; // later we set it - in_data.output_id = out.id.data; - in_data.key_image = pod_to_hex(in_info.key_img); - in_data.amount = out.amount; - // must match corresponding - // output's amount - in_data.timestamp = *blk_timestamp_mysql_format; + inputs_found.push_back(in_data); - inputs_found.push_back(in_data); + } // if (xmr_accounts->output_exists(o - } // if (xmr_accounts->output_exists(o + } // for (auto& in_info: inputs_identfied) - } // for (auto& in_info: inputs_identfied) + if (!inputs_found.empty()) + { + // seems we have some inputs found. time + // to write it to mysql. But first, + // check if this tx is written in mysql. - if (!inputs_found.empty()) - { - // seems we have some inputs found. time - // to write it to mysql. But first, - // check if this tx is written in mysql. + // calculate how much we preasumply spent. + uint64_t total_sent {0}; - // calculate how much we preasumply spent. - uint64_t total_sent {0}; + for (const XmrInput& in_data: inputs_found) + total_sent += in_data.amount; - for (const XmrInput& in_data: inputs_found) - total_sent += in_data.amount; + if (tx_mysql_id == 0) + { + // this txs hasnt been seen in step first. + // it means that it only contains potentially our + // key images. It does not have our outputs. + // so write it to mysql as ours, with + // total received of 0. + + XmrTransaction tx_data; + + tx_data.id = mysqlpp::null; + tx_data.hash = tx_hash_str; + tx_data.prefix_hash = tx_hash_prefix_str; + tx_data.tx_pub_key = tx_pub_key_str; + tx_data.account_id = acc->id.data; + tx_data.blockchain_tx_id = blockchain_tx_id; + tx_data.total_received = 0; // because this is + //spending, + //total_recieved is 0 + tx_data.total_sent = total_sent; + tx_data.unlock_time = tx_unlock_time; + tx_data.height = blk_height; + tx_data.coinbase = is_coinbase; + tx_data.is_rct = is_rct; + tx_data.rct_type = rct_type; + tx_data.spendable = is_spendable; + tx_data.payment_id = current_bc_status + ->get_payment_id_as_string(tx); + tx_data.mixin = mixin_no; + tx_data.timestamp = *blk_timestamp_mysql_format; + + // insert tx_data into mysql's Transactions table + tx_mysql_id = xmr_accounts->insert(tx_data); if (tx_mysql_id == 0) { - // this txs hasnt been seen in step first. - // it means that it only contains potentially our - // key images. It does not have our outputs. - // so write it to mysql as ours, with - // total received of 0. - - XmrTransaction tx_data; - - tx_data.id = mysqlpp::null; - tx_data.hash = tx_hash_str; - tx_data.prefix_hash = tx_hash_prefix_str; - tx_data.tx_pub_key = tx_pub_key_str; - tx_data.account_id = acc->id.data; - tx_data.blockchain_tx_id = blockchain_tx_id; - tx_data.total_received = 0; // because this is - //spending, - //total_recieved is 0 - tx_data.total_sent = total_sent; - tx_data.unlock_time = tx_unlock_time; - tx_data.height = blk_height; - tx_data.coinbase = is_coinbase; - tx_data.is_rct = is_rct; - tx_data.rct_type = rct_type; - tx_data.spendable = is_spendable; - tx_data.payment_id = current_bc_status - ->get_payment_id_as_string(tx); - tx_data.mixin = mixin_no; - tx_data.timestamp = *blk_timestamp_mysql_format; - - // insert tx_data into mysql's Transactions table - tx_mysql_id = xmr_accounts->insert(tx_data); - - if (tx_mysql_id == 0) - { - OMERROR << address_prefix - + ": tx_mysql_id is zero!" - << tx_data; - - //cerr << "tx_mysql_id is zero!" << endl; - throw TxSearchException("tx_mysql_id is zero!"); - // it did not insert this tx, because maybe - // it already - // exisits in the MySQL. So maybe can now - // check if we have it and get tx_mysql_id this - // way. - } - - } // if (tx_mysql_id == 0) - - // save all input found into database at once - // but first update tx_mysql_id for these inputs - for (XmrInput& in_data: inputs_found) - in_data.tx_id = tx_mysql_id; // set tx id now. - //before we made it 0 - - uint64_t no_rows_inserted - = xmr_accounts->insert(inputs_found); - - if (no_rows_inserted == 0) - { - throw TxSearchException( - "no_rows_inserted is zero!"); + OMERROR << address_prefix + + ": tx_mysql_id is zero!" + << tx_data; + + //cerr << "tx_mysql_id is zero!" << endl; + throw TxSearchException("tx_mysql_id is zero!"); + // it did not insert this tx, because maybe + // it already + // exisits in the MySQL. So maybe can now + // check if we have it and get tx_mysql_id this + // way. } - } // if (!inputs_found.empty()) + } // if (tx_mysql_id == 0) + + // save all input found into database at once + // but first update tx_mysql_id for these inputs + for (XmrInput& in_data: inputs_found) + in_data.tx_id = tx_mysql_id; // set tx id now. + //before we made it 0 + + uint64_t no_rows_inserted + = xmr_accounts->insert(inputs_found); + + if (no_rows_inserted == 0) + { + throw TxSearchException( + "no_rows_inserted is zero!"); + } - } // if (!oi_identification.identified_inputs.empty()) + } // if (!inputs_found.empty()) - // if we get to this point, we assume that all tx related - // tables are ready - // to be written, i.e., Transactions, - // Outputs and Inputs. If so, write - // all this into database. + } // if (!oi_identification.identified_inputs.empty()) - if (mysql_transaction) - mysql_transaction->commit(); + // if we get to this point, we assume that all tx related + // tables are ready + // to be written, i.e., Transactions, + // Outputs and Inputs. If so, write + // all this into database. - } // for (auto const& tx_pair: txs_map) + if (mysql_transaction) + mysql_transaction->commit(); - // update scanned_block_height every given interval - // or when we reached top of the blockchain +} // for (auto const& tx_pair: txs_map) - XmrAccount updated_acc = *acc; +// update scanned_block_height every given interval +// or when we reached top of the blockchain - updated_acc.scanned_block_height = h2; - updated_acc.scanned_block_timestamp - = DateTime(static_cast( - blocks.back().timestamp)); +XmrAccount updated_acc = *acc; - if (xmr_accounts->update(*acc, updated_acc)) - { - // iff success, set acc to updated_acc; - //cout << "scanned_block_height updated\n"; - *acc = updated_acc; - } +updated_acc.scanned_block_height = h2; +updated_acc.scanned_block_timestamp + = DateTime(static_cast( + blocks.back().timestamp)); - //current_timestamp = loop_timestamp; - // update this only when this variable is false - // otherwise a new search block value can - // be overwritten to h2, instead of the new value - if (!searched_block_got_updated) - searched_blk_no = h2 + 1; +if (xmr_accounts->update(*acc, updated_acc)) +{ + // iff success, set acc to updated_acc; + //cout << "scanned_block_height updated\n"; + *acc = updated_acc; +} + +//current_timestamp = loop_timestamp; +// update this only when this variable is false +// otherwise a new search block value can +// be overwritten to h2, instead of the new value +if (!searched_block_got_updated) + searched_blk_no = h2 + 1; - searched_block_got_updated = false; +searched_block_got_updated = false; } // while(continue_search) -} +} +catch(std::exception const& e) +{ + OMERROR << address_prefix + + ": exception in TxSearch: " + << e.what(); + set_exception_ptr(); +} catch(...) { OMERROR << address_prefix @@ -751,7 +758,6 @@ uint64_t recieve_time = mtx.first; const transaction& tx = mtx.second; const crypto::hash tx_hash = get_transaction_hash(tx); -const bool coinbase = is_coinbase(tx); bool is_rct = (tx.version == 2); uint8_t rct_type = (is_rct ? tx.rct_signatures.type : 0); @@ -786,6 +792,7 @@ if (!outputs_identified.empty()) = pod_to_hex(get_transaction_prefix_hash(tx)); auto tx_pub_key_str = pod_to_hex(identifier.get_tx_pub_key()); + auto is_coinbase = cryptonote::is_coinbase(tx); uint64_t mixin_no {0}; if (!is_coinbase) mixin_no = xmreg::get_mixin_no(tx); @@ -840,6 +847,7 @@ if (!inputs_identfied.empty()) auto tx_pub_key_str = pod_to_hex(identifier.get_tx_pub_key()); uint64_t mixin_no {0}; + auto is_coinbase = cryptonote::is_coinbase(tx); if (!is_coinbase) mixin_no = xmreg::get_mixin_no(tx); diff --git a/src/xmregcore b/src/xmregcore index 96d8208..9b05088 160000 --- a/src/xmregcore +++ b/src/xmregcore @@ -1 +1 @@ -Subproject commit 96d82080fc2756da0cd274982c373c8fbb14261f +Subproject commit 9b050883c60f79a8465a2a711993c61531b2cfe8