|
|
|
@ -85,19 +85,19 @@ 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<block> blocks;
|
|
|
|
|
vector<block> blocks;
|
|
|
|
|
|
|
|
|
|
blocks = current_bc_status->get_blocks_range(h1, h2);
|
|
|
|
|
blocks = current_bc_status->get_blocks_range(h1, h2);
|
|
|
|
|
|
|
|
|
|
if (blocks.empty())
|
|
|
|
|
{
|
|
|
|
|
if (blocks.empty())
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
if (h1 <= h2)
|
|
|
|
|
{
|
|
|
|
@ -142,53 +142,53 @@ while(continue_search)
|
|
|
|
|
// update database accordingly when get_address_txs is executed.
|
|
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
OMINFO << address_prefix + ": analyzing "
|
|
|
|
|
OMINFO << address_prefix + ": analyzing "
|
|
|
|
|
<< blocks.size() << " blocks from "
|
|
|
|
|
<< h1 << " to " << h2
|
|
|
|
|
<< " out of " << last_block_height << " blocks";
|
|
|
|
|
|
|
|
|
|
vector<crypto::hash> txs_hashes_from_blocks;
|
|
|
|
|
vector<transaction> txs_in_blocks;
|
|
|
|
|
vector<CurrentBlockchainStatus::txs_tuple_t> txs_data;
|
|
|
|
|
vector<crypto::hash> txs_hashes_from_blocks;
|
|
|
|
|
vector<transaction> txs_in_blocks;
|
|
|
|
|
vector<CurrentBlockchainStatus::txs_tuple_t> txs_data;
|
|
|
|
|
|
|
|
|
|
if (!current_bc_status->get_txs_in_blocks(blocks,
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// we will only create mysql DateTime object once, anything is found
|
|
|
|
|
// in a given block;
|
|
|
|
|
unique_ptr<DateTime> blk_timestamp_mysql_format;
|
|
|
|
|
|
|
|
|
|
// 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};
|
|
|
|
|
// we will only create mysql DateTime object once, anything is found
|
|
|
|
|
// in a given block;
|
|
|
|
|
unique_ptr<DateTime> blk_timestamp_mysql_format;
|
|
|
|
|
|
|
|
|
|
for (auto const& tx_tuple: txs_data)
|
|
|
|
|
{
|
|
|
|
|
// 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);
|
|
|
|
@ -597,36 +597,43 @@ while(continue_search)
|
|
|
|
|
if (mysql_transaction)
|
|
|
|
|
mysql_transaction->commit();
|
|
|
|
|
|
|
|
|
|
} // for (auto const& tx_pair: txs_map)
|
|
|
|
|
} // for (auto const& tx_pair: txs_map)
|
|
|
|
|
|
|
|
|
|
// update scanned_block_height every given interval
|
|
|
|
|
// or when we reached top of the blockchain
|
|
|
|
|
// update scanned_block_height every given interval
|
|
|
|
|
// or when we reached top of the blockchain
|
|
|
|
|
|
|
|
|
|
XmrAccount updated_acc = *acc;
|
|
|
|
|
XmrAccount updated_acc = *acc;
|
|
|
|
|
|
|
|
|
|
updated_acc.scanned_block_height = h2;
|
|
|
|
|
updated_acc.scanned_block_timestamp
|
|
|
|
|
updated_acc.scanned_block_height = h2;
|
|
|
|
|
updated_acc.scanned_block_timestamp
|
|
|
|
|
= DateTime(static_cast<time_t>(
|
|
|
|
|
blocks.back().timestamp));
|
|
|
|
|
|
|
|
|
|
if (xmr_accounts->update(*acc, updated_acc))
|
|
|
|
|
{
|
|
|
|
|
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)
|
|
|
|
|
//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(...)
|
|
|
|
|
{
|
|
|
|
@ -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);
|
|
|
|
|
|
|
|
|
|