mirror of
https://git.wownero.com/wownero/onion-wownero-blockchain-explorer.git
synced 2024-08-15 00:33:12 +00:00
added signed outputs's keys file checker
This commit is contained in:
parent
d96a0f9829
commit
4a81039cf0
6 changed files with 351 additions and 27 deletions
28
main.cpp
28
main.cpp
|
@ -223,6 +223,34 @@ int main(int ac, const char* av[]) {
|
|||
});
|
||||
|
||||
|
||||
CROW_ROUTE(app, "/rawoutputkeys")
|
||||
([&](const crow::request& req) {
|
||||
return xmrblocks.show_rawoutputkeys();
|
||||
});
|
||||
|
||||
CROW_ROUTE(app, "/checkrawoutputkeys").methods("POST"_method)
|
||||
([&](const crow::request& req) {
|
||||
|
||||
map<std::string, std::string> post_body = xmreg::parse_crow_post_data(req.body);
|
||||
|
||||
if (post_body.count("rawoutputkeysdata") == 0)
|
||||
{
|
||||
return string("Raw output keys data not given");
|
||||
}
|
||||
|
||||
if (post_body.count("viewkey") == 0)
|
||||
{
|
||||
return string("Viewkey not provided. Cant decrypt key image file without it");
|
||||
}
|
||||
|
||||
string raw_data = post_body["rawoutputkeysdata"];
|
||||
string viewkey = post_body["viewkey"];
|
||||
|
||||
return xmrblocks.show_checkcheckrawoutput(raw_data, viewkey);
|
||||
});
|
||||
|
||||
|
||||
|
||||
CROW_ROUTE(app, "/search").methods("GET"_method)
|
||||
([&](const crow::request& req) {
|
||||
return xmrblocks.search(string(req.url_params.get("value")));
|
||||
|
|
240
src/page.h
240
src/page.h
|
@ -25,24 +25,26 @@
|
|||
#include <limits>
|
||||
#include <ctime>
|
||||
|
||||
#define TMPL_DIR "./templates"
|
||||
#define TMPL_PARIALS_DIR TMPL_DIR "/partials"
|
||||
#define TMPL_CSS_STYLES TMPL_DIR "/css/style.css"
|
||||
#define TMPL_INDEX TMPL_DIR "/index.html"
|
||||
#define TMPL_INDEX2 TMPL_DIR "/index2.html"
|
||||
#define TMPL_MEMPOOL TMPL_DIR "/mempool.html"
|
||||
#define TMPL_HEADER TMPL_DIR "/header.html"
|
||||
#define TMPL_FOOTER TMPL_DIR "/footer.html"
|
||||
#define TMPL_BLOCK TMPL_DIR "/block.html"
|
||||
#define TMPL_TX TMPL_DIR "/tx.html"
|
||||
#define TMPL_ADDRESS TMPL_DIR "/address.html"
|
||||
#define TMPL_MY_OUTPUTS TMPL_DIR "/my_outputs.html"
|
||||
#define TMPL_SEARCH_RESULTS TMPL_DIR "/search_results.html"
|
||||
#define TMPL_MY_RAWTX TMPL_DIR "/rawtx.html"
|
||||
#define TMPL_MY_CHECKRAWTX TMPL_DIR "/checkrawtx.html"
|
||||
#define TMPL_MY_PUSHRAWTX TMPL_DIR "/pushrawtx.html"
|
||||
#define TMPL_MY_RAWKEYIMGS TMPL_DIR "/rawkeyimgs.html"
|
||||
#define TMPL_MY_CHECKRAWKEYIMGS TMPL_DIR "/checkrawkeyimgs.html"
|
||||
#define TMPL_DIR "./templates"
|
||||
#define TMPL_PARIALS_DIR TMPL_DIR "/partials"
|
||||
#define TMPL_CSS_STYLES TMPL_DIR "/css/style.css"
|
||||
#define TMPL_INDEX TMPL_DIR "/index.html"
|
||||
#define TMPL_INDEX2 TMPL_DIR "/index2.html"
|
||||
#define TMPL_MEMPOOL TMPL_DIR "/mempool.html"
|
||||
#define TMPL_HEADER TMPL_DIR "/header.html"
|
||||
#define TMPL_FOOTER TMPL_DIR "/footer.html"
|
||||
#define TMPL_BLOCK TMPL_DIR "/block.html"
|
||||
#define TMPL_TX TMPL_DIR "/tx.html"
|
||||
#define TMPL_ADDRESS TMPL_DIR "/address.html"
|
||||
#define TMPL_MY_OUTPUTS TMPL_DIR "/my_outputs.html"
|
||||
#define TMPL_SEARCH_RESULTS TMPL_DIR "/search_results.html"
|
||||
#define TMPL_MY_RAWTX TMPL_DIR "/rawtx.html"
|
||||
#define TMPL_MY_CHECKRAWTX TMPL_DIR "/checkrawtx.html"
|
||||
#define TMPL_MY_PUSHRAWTX TMPL_DIR "/pushrawtx.html"
|
||||
#define TMPL_MY_RAWKEYIMGS TMPL_DIR "/rawkeyimgs.html"
|
||||
#define TMPL_MY_CHECKRAWKEYIMGS TMPL_DIR "/checkrawkeyimgs.html"
|
||||
#define TMPL_MY_RAWOUTPUTKEYS TMPL_DIR "/rawoutputkeys.html"
|
||||
#define TMPL_MY_CHECKRAWOUTPUTKEYS TMPL_DIR "/checkrawoutputkeys.html"
|
||||
|
||||
namespace xmreg {
|
||||
|
||||
|
@ -2010,11 +2012,31 @@ public:
|
|||
{"testnet" , testnet}
|
||||
};
|
||||
|
||||
// read checkrawtx.html
|
||||
// read rawkeyimgs.html
|
||||
string rawkeyimgs_html = xmreg::read(TMPL_MY_RAWKEYIMGS);
|
||||
|
||||
// add header and footer
|
||||
string full_page = rawkeyimgs_html + xmreg::read(TMPL_FOOTER);
|
||||
string full_page = rawkeyimgs_html + get_footer();
|
||||
|
||||
add_css_style(context);
|
||||
|
||||
// render the page
|
||||
return mstch::render(full_page, context);
|
||||
}
|
||||
|
||||
string
|
||||
show_rawoutputkeys()
|
||||
{
|
||||
// initalize page template context map
|
||||
mstch::map context {
|
||||
{"testnet" , testnet}
|
||||
};
|
||||
|
||||
// read rawoutputkeys.html
|
||||
string rawoutputkeys_html = xmreg::read(TMPL_MY_RAWOUTPUTKEYS);
|
||||
|
||||
// add header and footer
|
||||
string full_page = rawoutputkeys_html + get_footer();
|
||||
|
||||
add_css_style(context);
|
||||
|
||||
|
@ -2047,7 +2069,7 @@ public:
|
|||
string checkrawkeyimgs_html = xmreg::read(TMPL_MY_CHECKRAWKEYIMGS);
|
||||
|
||||
// add footer
|
||||
string full_page = checkrawkeyimgs_html + xmreg::read(TMPL_FOOTER);
|
||||
string full_page = checkrawkeyimgs_html + get_footer();
|
||||
|
||||
add_css_style(context);
|
||||
|
||||
|
@ -2378,11 +2400,173 @@ public:
|
|||
return mstch::render(full_page, context);
|
||||
}
|
||||
|
||||
string
|
||||
show_checkcheckrawoutput(string raw_data, string viewkey_str)
|
||||
{
|
||||
|
||||
// remove white characters
|
||||
boost::trim(raw_data);
|
||||
boost::erase_all(raw_data, "\r\n");
|
||||
boost::erase_all(raw_data, "\n");
|
||||
|
||||
// remove white characters
|
||||
boost::trim(viewkey_str);
|
||||
|
||||
string decoded_raw_data = epee::string_encoding::base64_decode(raw_data);
|
||||
secret_key prv_view_key;
|
||||
|
||||
// initalize page template context map
|
||||
mstch::map context{
|
||||
{"testnet", testnet},
|
||||
{"has_error", false},
|
||||
{"error_msg", string{}},
|
||||
};
|
||||
|
||||
|
||||
// read page template
|
||||
string checkoutputkeys_html = xmreg::read(TMPL_MY_CHECKRAWOUTPUTKEYS);
|
||||
|
||||
// add footer
|
||||
string full_page = checkoutputkeys_html + get_footer();
|
||||
|
||||
add_css_style(context);
|
||||
|
||||
if (viewkey_str.empty())
|
||||
{
|
||||
string error_msg = fmt::format("View key not given. Cant decode "
|
||||
"the key image data without it!");
|
||||
|
||||
context["has_error"] = true;
|
||||
context["error_msg"] = error_msg;
|
||||
|
||||
return mstch::render(full_page, context);
|
||||
}
|
||||
|
||||
if (!xmreg::parse_str_secret_key(viewkey_str, prv_view_key))
|
||||
{
|
||||
string error_msg = fmt::format("Cant parse the private key: " + viewkey_str);
|
||||
|
||||
context["has_error"] = true;
|
||||
context["error_msg"] = error_msg;
|
||||
|
||||
return mstch::render(full_page, context);
|
||||
}
|
||||
|
||||
const size_t magiclen = strlen(OUTPUT_EXPORT_FILE_MAGIC);
|
||||
|
||||
|
||||
if (!strncmp(decoded_raw_data.c_str(), OUTPUT_EXPORT_FILE_MAGIC, magiclen) == 0)
|
||||
{
|
||||
string error_msg = fmt::format("This does not seem to be output keys export data.");
|
||||
|
||||
context["has_error"] = true;
|
||||
context["error_msg"] = error_msg;
|
||||
|
||||
return mstch::render(full_page, context);
|
||||
}
|
||||
|
||||
// decrypt key images data using private view key
|
||||
decoded_raw_data = xmreg::decrypt(
|
||||
std::string(decoded_raw_data, magiclen),
|
||||
prv_view_key, true);
|
||||
|
||||
|
||||
// header is public spend and keys
|
||||
const size_t header_lenght = 2 * sizeof(crypto::public_key);
|
||||
|
||||
// get xmr address stored in this key image file
|
||||
const account_public_address* xmr_address =
|
||||
reinterpret_cast<const account_public_address*>(
|
||||
decoded_raw_data.data());
|
||||
|
||||
context.insert({"address" , REMOVE_HASH_BRAKETS(xmreg::print_address(*xmr_address, testnet))});
|
||||
context.insert({"viewkey" , REMOVE_HASH_BRAKETS(fmt::format("{:s}", prv_view_key))});
|
||||
context.insert({"has_total_xmr" , false});
|
||||
context.insert({"total_xmr" , string{}});
|
||||
context.insert({"output_keys" , mstch::array{}});
|
||||
|
||||
mstch::array& output_keys_ctx = boost::get<mstch::array>(context["output_keys"]);
|
||||
|
||||
unique_ptr<xmreg::MyLMDB> mylmdb;
|
||||
|
||||
if (bf::is_directory(lmdb2_path))
|
||||
{
|
||||
mylmdb = make_unique<xmreg::MyLMDB>(lmdb2_path);
|
||||
}
|
||||
else
|
||||
{
|
||||
cout << "Custom lmdb database seem does not exist at: " << lmdb2_path << endl;
|
||||
}
|
||||
|
||||
std::vector<tools::wallet2::transfer_details> outputs;
|
||||
|
||||
try
|
||||
{
|
||||
std::string body(decoded_raw_data, header_lenght);
|
||||
std::stringstream iss;
|
||||
iss << body;
|
||||
boost::archive::binary_iarchive ar(iss);
|
||||
|
||||
ar >> outputs;
|
||||
|
||||
//size_t n_outputs = m_wallet->import_outputs(outputs);
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
|
||||
string error_msg = fmt::format("Failed to import outputs: {:s}", e.what());
|
||||
|
||||
context["has_error"] = true;
|
||||
context["error_msg"] = error_msg;
|
||||
|
||||
return mstch::render(full_page, context);
|
||||
}
|
||||
|
||||
uint64_t total_xmr {0};
|
||||
uint64_t output_no {0};
|
||||
|
||||
for (const tools::wallet2::transfer_details& td: outputs)
|
||||
{
|
||||
|
||||
const transaction_prefix& txp = td.m_tx;
|
||||
|
||||
txout_to_key txout_key = boost::get<txout_to_key>(
|
||||
txp.vout[td.m_internal_output_index].target);
|
||||
|
||||
uint64_t xmr_amount = td.amount();
|
||||
|
||||
uint64_t blk_timestamp = core_storage
|
||||
->get_db().get_block_timestamp(td.m_block_height);
|
||||
|
||||
mstch::map output_info {
|
||||
{"output_no" , fmt::format("{:03d}", output_no)},
|
||||
{"output_pub_key" , REMOVE_HASH_BRAKETS(fmt::format("{:s}", txout_key.key))},
|
||||
{"amount" , xmreg::xmr_amount_to_str(xmr_amount)},
|
||||
{"tx_hash" , REMOVE_HASH_BRAKETS(fmt::format("{:s}", td.m_txid))},
|
||||
{"timestamp" , xmreg::timestamp_to_str(blk_timestamp)},
|
||||
{"is_ringct" , td.m_rct}
|
||||
};
|
||||
|
||||
++output_no;
|
||||
|
||||
total_xmr += xmr_amount;
|
||||
|
||||
output_keys_ctx.push_back(output_info);
|
||||
}
|
||||
|
||||
if (total_xmr > 0)
|
||||
{
|
||||
context["has_total_xmr"] = true;
|
||||
context["total_xmr"] = xmreg::xmr_amount_to_str(total_xmr);
|
||||
}
|
||||
|
||||
return mstch::render(full_page, context);;
|
||||
}
|
||||
|
||||
|
||||
string
|
||||
search(string search_text)
|
||||
{
|
||||
|
||||
// remove white characters
|
||||
boost::trim(search_text);
|
||||
|
||||
|
@ -3950,6 +4134,14 @@ private:
|
|||
|
||||
string
|
||||
get_full_page(string& middle)
|
||||
{
|
||||
return xmreg::read(TMPL_HEADER)
|
||||
+ middle
|
||||
+ get_footer();
|
||||
}
|
||||
|
||||
string
|
||||
get_footer()
|
||||
{
|
||||
// set last git commit date based on
|
||||
// autogenrated version.h during compilation
|
||||
|
@ -3960,9 +4152,7 @@ private:
|
|||
|
||||
string footer_html = mstch::render(xmreg::read(TMPL_FOOTER), footer_context);
|
||||
|
||||
return xmreg::read(TMPL_HEADER)
|
||||
+ middle
|
||||
+ footer_html;
|
||||
return footer_html;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
66
src/templates/checkrawoutputkeys.html
Normal file
66
src/templates/checkrawoutputkeys.html
Normal file
|
@ -0,0 +1,66 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<META HTTP-EQUIV="CACHE-CONTROL" CONTENT="NO-CACHE">
|
||||
{{#refresh}}
|
||||
<meta http-equiv="refresh" content="10">
|
||||
{{/refresh}}
|
||||
<title>Onion Monero Blockchain Explorer</title>
|
||||
<!--<link rel="stylesheet" type="text/css" href="/css/style.css">-->
|
||||
<style type="text/css">
|
||||
{{#css_styles}}{{/css_styles}}
|
||||
</style>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
|
||||
<div class="center">
|
||||
<h1 class="center"><a href="/">Onion Monero Signed Output Keys Checker</a></h1>
|
||||
<h4 style="font-size: 15px; margin: 0px">(no javascript - no cookies - no web analytics trackers - no images - open sourced)</h4>
|
||||
</div>
|
||||
|
||||
|
||||
{{#has_error}}
|
||||
<h4 style="color:red">Attempt failed</h4>
|
||||
<h4>{{error_msg}}</h4>
|
||||
{{/has_error}}
|
||||
{{^has_error}}
|
||||
<h4>Output keys for address: {{address}}</h4>
|
||||
<h4>Viewkey: {{viewkey}}</h4>
|
||||
{{#has_total_xmr}}
|
||||
<h4>Total value of xmr received: {{total_xmr}}</h4>
|
||||
{{/has_total_xmr}}
|
||||
|
||||
<div class="center">
|
||||
|
||||
<form method="post" style="width:100%; margin-top:15px" class="style-1">
|
||||
<table class="center" style="width:80%">
|
||||
<tr>
|
||||
<td>Output no.</td>
|
||||
<td>Public key</td>
|
||||
<td>Timestamp</td>
|
||||
<td>RingCT</td>
|
||||
<td>Amount</td>
|
||||
</tr>
|
||||
{{#output_keys}}
|
||||
<input type="hidden" id="key_img_{{key_image}}" name="key_sig_pair_{{key_image}}" value="{{signature}}">
|
||||
<tr>
|
||||
<td>{{output_no}}</td>
|
||||
<td><a href="/tx/{{tx_hash}}">{{output_pub_key}}</a></td>
|
||||
<td>{{timestamp}}</td>
|
||||
<td>{{is_ringct}}</td>
|
||||
<td>{{amount}}</td>
|
||||
|
||||
</tr>
|
||||
{{/output_keys}}
|
||||
</table>
|
||||
<br/>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
|
||||
{{/has_error}}
|
||||
|
||||
</div>
|
|
@ -3,7 +3,8 @@
|
|||
<h3 style="font-size: 12px; margin-top: 20px">
|
||||
|
||||
Server time: {{server_timestamp}} | <a href="/rawtx">Tx pusher </a>
|
||||
| <a href="/rawkeyimgs">Key images checker</a> |
|
||||
| <a href="/rawkeyimgs">Key images checker</a>
|
||||
| <a href="/rawoutputkeys">Output keys checker</a> |
|
||||
|
||||
{{#refresh}}
|
||||
<a href="/">Autorefresh is ON (10 s)</a>
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
<div class="center">
|
||||
<form action="/checkrawkeyimgs" method="post" style="width:100%; margin-top:15px" class="style-1">
|
||||
Paste base64 encoded, signed key images data here<br/>
|
||||
(In Linux, can get base64 signed raw tx data: <i>base64 signed_key_images | xclip -selection clipboard</i>)<br/>
|
||||
(In Linux, can get base64 signed raw tx data: <i>base64 your_key_images_file | xclip -selection clipboard</i>)<br/>
|
||||
<textarea name="rawkeyimgsdata" rows="20" cols="80"></textarea><br/><br/>
|
||||
Viewkey (<i>key image file data is encoded using your viewkey. Thus is needed for decryption</i>)
|
||||
<br/>
|
||||
|
|
39
src/templates/rawoutputkeys.html
Normal file
39
src/templates/rawoutputkeys.html
Normal file
|
@ -0,0 +1,39 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<META HTTP-EQUIV="CACHE-CONTROL" CONTENT="NO-CACHE">
|
||||
{{#refresh}}
|
||||
<meta http-equiv="refresh" content="10">
|
||||
{{/refresh}}
|
||||
<title>Onion Monero Blockchain Explorer</title>
|
||||
<!--<link rel="stylesheet" type="text/css" href="/css/style.css">-->
|
||||
<style type="text/css">
|
||||
{{#css_styles}}{{/css_styles}}
|
||||
</style>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
|
||||
<div class="center">
|
||||
<h1 class="center"><a href="/">Onion Monero Signed Output Keys Checker</a></h1>
|
||||
<h4 style="font-size: 15px; margin: 0px">(no javascript - no cookies - no web analytics trackers - no images - open sourced)</h4>
|
||||
</div>
|
||||
|
||||
<div class="center">
|
||||
<form action="/checkrawoutputkeys" method="post" style="width:100%; margin-top:15px" class="style-1">
|
||||
Paste base64 encoded, signed output keys data here<br/>
|
||||
(In Linux, can get base64 signed raw tx data: <i>base64 your_output_keys_filename | xclip -selection clipboard</i>)<br/>
|
||||
|
||||
<textarea name="rawoutputkeysdata" rows="20" cols="80"></textarea><br/><br/>
|
||||
Viewkey (<i>output keys file data is encoded using your viewkey. Thus is needed for decryption</i>)
|
||||
<br/>
|
||||
<input type="text" name="viewkey" size="80">
|
||||
<br/>
|
||||
<input type="submit" name="action" value="check">
|
||||
</form>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
Loading…
Reference in a new issue