First working version of OutputInputIdentification class completed

pull/4/head
moneroexamples 7 years ago
parent 0c3ebe807f
commit 429a620193

@ -143,7 +143,7 @@ OutputInputIdentification::identify_outputs()
void
OutputInputIdentification::identify_inputs(
const vector<string>& known_outputs_keys)
const vector<pair<string, uint64_t>>& known_outputs_keys)
{
vector<txin_to_key> input_key_imgs = xmreg::get_key_images(*tx);
@ -187,45 +187,29 @@ OutputInputIdentification::identify_inputs(
// if the key exists. Its much faster than going to mysql
// for this.
if (std::find(
auto it = std::find_if(
known_outputs_keys.begin(),
known_outputs_keys.end(),
output_public_key_str)
== known_outputs_keys.end())
[&](const pair<string, uint64_t>& known_output)
{
return output_public_key_str == known_output.first;
});
if (it == known_outputs_keys.end())
{
// this mixins's output is unknown.
++count;
continue;
}
// this seems to be our mixin.
// save it into identified_inputs vector
XmrOutput out;
if (xmr_accounts->output_exists(output_public_key_str, out))
{
cout << "input uses some mixins which are our outputs"
<< out << endl;
// seems that this key image is ours.
// so save it to database for later use.
XmrInput in_data;
in_data.account_id = acc->id;
in_data.tx_id = 0; // for now zero, later we set it
in_data.output_id = out.id;
in_data.key_image = pod_to_hex(in_key.k_image);
in_data.amount = out.amount; // must match corresponding output's amount
in_data.timestamp = blk_timestamp_mysql_format;
inputs_found.push_back(in_data);
// a key image has only one real mixin. Rest is fake.
// so if we find a candidate, break the search.
// break;
} // if (xmr_accounts->output_exists(output_public_key_str, out))
identified_inputs.push_back(input_info {
pod_to_hex(in_key.k_image),
(*it).second, // amount
output_public_key_str});
count++;
@ -233,8 +217,6 @@ OutputInputIdentification::identify_inputs(
} // for (const txin_to_key& in_key: input_key_imgs)
}
}

@ -5,6 +5,7 @@
#ifndef RESTBED_XMR_OUTPUTINPUTIDENTIFICATION_H
#define RESTBED_XMR_OUTPUTINPUTIDENTIFICATION_H
#include "CurrentBlockchainStatus.h"
#include "tools.h"
namespace xmreg
@ -89,12 +90,13 @@ public:
uint64_t total_received;
vector<output_info> identified_outputs;
vector<input_info> identified_inputs;
OutputInputIdentification(const account_public_address* _a,
const secret_key* _v,
const transaction* _tx);
/*
/**
* FIRST step. search for the incoming xmr using address, viewkey and
* outputs public keys.
*/
@ -104,10 +106,22 @@ public:
/**
* SECOND step. search for possible our inputs.
* We do this by comparing mixin public keys with
* our output keys. If a metch is found, we assume
* our known output keys. If a metch is found, we assume
* that associated input is ours
*
* The known_outputs_keys parameter is optional. But when we have
* it, the identification is faster as we just check mixins public keys
* if they are in known_outputs_keys.
*
* searching without known_outputs_keys is not implemented yet here
* but it was done for the onion explorer. so later basically just
* copy and past here.
*
* known_outputs_keys is pair of <output public key, output amount>
*
*/
void identify_inputs(const vector<string>& known_outputs_keys);
void identify_inputs(
const vector<pair<string, uint64_t>>& known_outputs_keys);
private:

@ -221,7 +221,7 @@ TxSearch::search()
}
// now add the found outputs into Outputs tables
for (auto &out_info: oi_identification.identified_outputs)
for (auto& out_info: oi_identification.identified_outputs)
{
XmrOutput out_data;
@ -248,7 +248,7 @@ TxSearch::search()
}
// add the new output to our cash of known outputs
known_outputs_keys.push_back(out_info.pub_key);
known_outputs_keys.push_back(make_pair(out_info.pub_key, out_info.amount));
} // for (auto &out_k_idx: found_mine_outputs)
@ -270,79 +270,37 @@ TxSearch::search()
// SECOND component: Checking for our key images, i.e., inputs.
vector<txin_to_key> input_key_imgs = xmreg::get_key_images(tx);
oi_identification.identify_inputs(known_outputs_keys);
// here we will keep what we find.
vector<XmrInput> inputs_found;
// make timescale maps for mixins in input
for (const txin_to_key& in_key: input_key_imgs)
if (!oi_identification.identified_inputs.empty())
{
// get absolute offsets of mixins
std::vector<uint64_t> absolute_offsets
= cryptonote::relative_output_offsets_to_absolute(
in_key.key_offsets);
// some inputs were identified as ours in a given tx.
// so now, go over those inputs, and check if
// get detail info for each found mixin output from database
// get public keys of outputs used in the mixins that match to the offests
std::vector<cryptonote::output_data_t> mixin_outputs;
vector<XmrInput> inputs_found;
if (!CurrentBlockchainStatus::get_output_keys(in_key.amount,
absolute_offsets,
mixin_outputs))
{
cerr << "Mixins key images not found" << endl;
continue;
}
//cout << "in_key.k_image): " << pod_to_hex(in_key.k_image) << endl;
// mixin counter
size_t count = 0;
// for each found output public key check if its ours or not
for (const uint64_t& abs_offset: absolute_offsets)
for (auto& in_info: oi_identification.identified_inputs)
{
// get basic information about mixn's output
cryptonote::output_data_t output_data = mixin_outputs.at(count);
string output_public_key_str = pod_to_hex(output_data.pubkey);
//cout << " - output_public_key_str: " << output_public_key_str << endl;
// before going to the mysql, check our known outputs cash
// if the key exists. Its much faster than going to mysql
// for this.
if (std::find(
known_outputs_keys.begin(),
known_outputs_keys.end(),
output_public_key_str)
== known_outputs_keys.end())
{
// this mixins's output is unknown.
++count;
continue;
}
XmrOutput out;
if (xmr_accounts->output_exists(output_public_key_str, out))
if (xmr_accounts->output_exists(in_info.out_pub_key, out))
{
cout << "input uses some mixins which are our outputs"
<< out << endl;
// seems that this key image is ours.
// so save it to database for later use.
// so get it infromatoin from database into XmrInput
// database structure that will be written later
// on into database.
XmrInput in_data;
in_data.account_id = acc->id;
in_data.tx_id = 0; // for now zero, later we set it
in_data.output_id = out.id;
in_data.key_image = pod_to_hex(in_key.k_image);
in_data.key_image = in_info.key_img;
in_data.amount = out.amount; // must match corresponding output's amount
in_data.timestamp = blk_timestamp_mysql_format;
@ -355,71 +313,68 @@ TxSearch::search()
} // if (xmr_accounts->output_exists(output_public_key_str, out))
count++;
} // for (auto& in_info: oi_identification.identified_inputs)
} // for (const cryptonote::output_data_t& output_data: outputs)
} // for (const txin_to_key& in_key: input_key_imgs)
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};
for (const XmrInput& in_data: inputs_found)
if (!inputs_found.empty())
{
total_sent += in_data.amount;
}
// seems we have some inputs found. time
// to write it to mysql. But first,
// check if this tx is written in mysql.
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.hash = oi_identification.tx_hash_str;
tx_data.prefix_hash = oi_identification.tx_prefix_hash_str;
tx_data.account_id = acc->id;
tx_data.total_received = 0; // because this is spending, total_recieved is 0
tx_data.total_sent = total_sent;
tx_data.unlock_time = 0; // unlock_time is not used for now, so whatever
tx_data.height = searched_blk_no;
tx_data.coinbase = oi_identification.tx_is_coinbase;
tx_data.spendable = is_spendable;
tx_data.payment_id = CurrentBlockchainStatus::get_payment_id_as_string(tx);
tx_data.mixin = get_mixin_no(tx) - 1;
tx_data.timestamp = blk_timestamp_mysql_format;
// insert tx_data into mysql's Transactions table
tx_mysql_id = xmr_accounts->insert_tx(tx_data);
// calculate how much we preasumply spent.
uint64_t total_sent {0};
if (tx_mysql_id == 0)
for (const XmrInput& in_data: inputs_found)
{
//cerr << "tx_mysql_id is zero!" << endl;
//throw TxSearchException("tx_mysql_id is zero!");
total_sent += in_data.amount;
}
} // if (tx_mysql_id == 0)
// save all input found into database
for (XmrInput& in_data: inputs_found)
{
in_data.tx_id = tx_mysql_id;
uint64_t in_mysql_id = xmr_accounts->insert_input(in_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.hash = oi_identification.tx_hash_str;
tx_data.prefix_hash = oi_identification.tx_prefix_hash_str;
tx_data.account_id = acc->id;
tx_data.total_received = 0; // because this is spending, total_recieved is 0
tx_data.total_sent = total_sent;
tx_data.unlock_time = 0; // unlock_time is not used for now, so whatever
tx_data.height = searched_blk_no;
tx_data.coinbase = oi_identification.tx_is_coinbase;
tx_data.spendable = is_spendable;
tx_data.payment_id = CurrentBlockchainStatus::get_payment_id_as_string(tx);
tx_data.mixin = get_mixin_no(tx) - 1;
tx_data.timestamp = blk_timestamp_mysql_format;
// insert tx_data into mysql's Transactions table
tx_mysql_id = xmr_accounts->insert_tx(tx_data);
if (tx_mysql_id == 0)
{
//cerr << "tx_mysql_id is zero!" << endl;
//throw TxSearchException("tx_mysql_id is zero!");
}
} // if (tx_mysql_id == 0)
// save all input found into database
for (XmrInput& in_data: inputs_found)
{
in_data.tx_id = tx_mysql_id; // set tx id now. before we made it 0
uint64_t in_mysql_id = xmr_accounts->insert_input(in_data);
}
} // if (!inputs_found.empty())
} // if (!inputs_found.empty())
} // if (!oi_identification.identified_inputs.empty())
} // for (const transaction& tx: blk_txs)
@ -493,7 +448,7 @@ TxSearch::populate_known_outputs()
{
for (const XmrOutput& out: outs)
{
known_outputs_keys.push_back(out.out_pub_key);
known_outputs_keys.push_back(make_pair(out.out_pub_key, out.amount));
}
}

@ -53,7 +53,9 @@ class TxSearch
// used as a cash to fast look up of
// our public keys in key images. Saves a lot of
// mysql queries to Outputs table.
vector<string> known_outputs_keys;
//
// out_pk, amount
vector<pair<string, uint64_t>> known_outputs_keys;
// this manages all mysql queries
// its better to when each thread has its own mysql connection object.

Loading…
Cancel
Save