diff --git a/src/page.h b/src/page.h index 3c701e5..b766230 100644 --- a/src/page.h +++ b/src/page.h @@ -456,6 +456,9 @@ namespace xmreg { // get reference to blocks template map to be field below mstch::array& txs = boost::get(context["blk_txs"]); + // timescale representation for each tx in the block + vector mixin_timescales_str; + // for each transaction in the memory pool for (size_t i = 0; i < blk.tx_hashes.size(); ++i) { @@ -480,6 +483,12 @@ namespace xmreg { // add fee to the rest sum_fees += txd.fee; + + // get mixins in time scale for visual representation + //string mixin_times_scale = xmreg::timestamps_time_scale(mixin_timestamps, + // server_timestamp); + + // add tx details mstch map to context txs.push_back(txd.get_mstch_map()); } @@ -536,17 +545,100 @@ namespace xmreg { } string - show_tx(string _tx_hash) + show_tx(string tx_hash_str) { + // parse tx hash string to hash object + crypto::hash tx_hash; + + if (!xmreg::parse_str_secret_key(tx_hash_str, tx_hash)) + { + cerr << "Cant parse tx hash: " << tx_hash_str << endl; + return string("Cant parse tx hash: " + tx_hash_str); + } + + // get transaction + transaction tx; + + if (!mcore->get_tx(tx_hash, tx)) + { + cerr << "Cant get tx: " << tx_hash << endl; + return string("Cant get tx: " + tx_hash_str); + } + + tx_details txd = get_tx_details(tx); + uint64_t _blk_height {0}; // initalise page tempate map with basic info about blockchain mstch::map context { - {"tx_hash" , _tx_hash}, + {"tx_hash" , tx_hash_str}, {"blk_height" , _blk_height} }; + string server_time_str = xmreg::timestamp_to_str(server_timestamp, "%F"); + + mstch::array inputs; + mstch::array mixins_timescales; + + // make timescale maps for mixins in input + for (const txin_to_key& in_key: txd.input_key_imgs) + { + // get absolute offsets of mixins + std::vector absolute_offsets + = cryptonote::relative_output_offsets_to_absolute( + in_key.key_offsets); + + // get public keys of outputs used in the mixins that match to the offests + std::vector outputs; + core_storage->get_db().get_output_key(in_key.amount, + absolute_offsets, + outputs); + + vector mixin_timestamps; + + size_t count = 0; + + inputs.push_back{mstch::map { + {"in_key_img", fmt::format("{:s}", in_key.k_image)}, + {"in_amount", amount} + }; + + // for each found output public key find its block to get timestamp + for (const uint64_t &i: absolute_offsets) + { + cryptonote::output_data_t output_data = outputs.at(count); + + // get block of given height, as we want to get its timestamp + cryptonote::block blk; + + if (!mcore->get_block_by_height(output_data.height, blk)) + { + cerr << "- cant get block of height: " << output_data.height << endl; + return fmt::format("- cant get block of height: {}\n", output_data.height); + } + + // get mixin timestamp from its orginal block + mixin_timestamps.push_back(blk.timestamp); + + ++count; + } + + // get mixins in time scale for visual representation + string mixin_times_scale = xmreg::timestamps_time_scale(mixin_timestamps, + server_timestamp, 80); + // add beginning and end to the mixin_times_scale + string timescale_str = string("Genesis<") + + mixin_times_scale + + string(">") + server_time_str; + + // save the string timescales for later to show + mixins_timescales.push_back(mstch::map {{"timescale", timescale_str}}); + } + + context["inputs"] = inputs; + context["timescales"] = mixins_timescales; + // read tx.html string tx_html = xmreg::read(TMPL_TX); @@ -601,43 +693,6 @@ namespace xmreg { return txd; } - string - mixins_time_scale(const vector& timestamps) - { - string empty_time = string("___________________________________") - + string("___________________________________") - + string("___________________________________") - + string("___________________________________"); - - size_t time_axis_length = empty_time.size(); - - cout << "time_axis_length: " << time_axis_length << endl; - - uint64_t time0 = 10; - uint64_t timeN = 30; - - uint64_t interval_length = timeN-time0; - - double scale = double(interval_length) / double(time_axis_length); - - for (const auto& timestamp: timestamps) - { - - if (timestamp < time0 || timestamp > timeN) - { - cout << "Out of range" << endl; - continue; - } - - uint64_t timestamp_place = double(timestamp-time0)/double(interval_length)*(time_axis_length-1); - //cout << timestamp_place << endl; - empty_time[timestamp_place] = '*'; - } - - return string("Genesis ") + empty_time + string(" Now"); - } - - pair get_age(uint64_t timestamp1, uint64_t timestamp2) { diff --git a/src/templates/tx.html b/src/templates/tx.html index 53b9f25..e88eca4 100644 --- a/src/templates/tx.html +++ b/src/templates/tx.html @@ -52,6 +52,13 @@ +

Mixins time scale

+
    + {{#timescales}} +
  • {{timescale}}
  • + {{/timescales}} +
+

Outputs ({{outputs_no}})

{{#have_txs}} diff --git a/src/tools.cpp b/src/tools.cpp index 0e895ad..6102f7a 100644 --- a/src/tools.cpp +++ b/src/tools.cpp @@ -527,5 +527,36 @@ namespace xmreg std::istreambuf_iterator()); } + string + timestamps_time_scale(const vector& timestamps, + uint64_t timeN, uint64_t resolution, uint64_t time0) + { + string empty_time = string(resolution, '_'); + + size_t time_axis_length = empty_time.size(); + + uint64_t interval_length = timeN-time0; + + double scale = double(interval_length) / double(time_axis_length); + + for (const auto& timestamp: timestamps) + { + + if (timestamp < time0 || timestamp > timeN) + { + cout << "Out of range" << endl; + continue; + } + + uint64_t timestamp_place = double(timestamp-time0)/double(interval_length)*(time_axis_length-1); + //cout << timestamp_place << endl; + empty_time[timestamp_place + 1] = '*'; + } + + return empty_time; + } + + + } diff --git a/src/tools.h b/src/tools.h index e8604ae..fb29269 100644 --- a/src/tools.h +++ b/src/tools.h @@ -199,6 +199,12 @@ namespace xmreg std::cout << "]" << std::endl; } + string + timestamps_time_scale(const vector& timestamps, + uint64_t timeN, uint64_t resolution = 80, + uint64_t time0 = 1397818193 /* timestamp of the second block */); + + } #endif //XMREG01_TOOLS_H