You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

490 lines
18 KiB
HTML

<div>
<H4 style="margin:5px">Tx hash: {{tx_hash}}</H4>
{{#enable_mixins_details}}
<H5 style="margin:5px">Tx prefix hash: {{tx_prefix_hash}}</H5>
{{/enable_mixins_details}}
<H5 style="margin:5px">Tx public key: <span id="tx_pub_key">{{tx_pub_key}}</span></H5>
{{#has_payment_id}}
<H5 style="margin:5px">Payment id: {{payment_id}}</H5>
<H5 style="margin:5px">Payment id as ascii: {{payment_id_as_ascii}}</H5>
{{/has_payment_id}}
{{#has_payment_id8}}
<H5 style="margin:5px">Payment id (encrypted): {{payment_id8}}</H5>
{{/has_payment_id8}}
{{#have_prev_hash}}
<H5>Previous tx: <a href="/tx/{{prev_hash}}">{{prev_hash}}</a></H5>
{{/have_prev_hash}}
{{#have_next_hash}}
<H5>Next tx: <a href="/tx/{{next_hash}}">{{next_hash}}</a></H5>
{{/have_next_hash}}
<table class="center" style="width: 80%; margin-top:10px">
{{^have_raw_tx}}
<tr>
<td>Timestamp: {{blk_timestamp_uint}}</td>
<td>Timestamp [UCT]: {{blk_timestamp}}</td>
<td>Age [y:d:h:m:s]: {{delta_time}}</td>
</tr>
{{/have_raw_tx}}
<tr>
<td>Block: <a href="/block/{{blk_height}}">{{blk_height}}</a></td>
<td>Fee: {{tx_fee}}</td>
<td>Tx size: {{tx_size}} kB</td>
</tr>
<tr>
<td>Tx version: {{tx_version}}</td>
<td>No of confirmations: {{confirmations}}</td>
<td>RingCT/type: {{#is_ringct}}yes/{{rct_type}}{{/is_ringct}}{{^is_ringct}}no{{/is_ringct}}</td>
{{#enable_js}}
<!-- the hidden filed is used in JavaScriped based decoding and proving txs -->
<input type="hidden" id="is_ringct" value="{{#is_ringct}}yes{{/is_ringct}}{{^is_ringct}}no{{/is_ringct}}"/>
<input type="hidden" id="ringct_type" value="{{rct_type}}"/>
{{/enable_js}}
</tr>
<tr>
<td colspan="3">Extra: {{extra}}</td>
</tr>
</table>
<h3>{{outputs_no}} output(s) for total of {{outputs_xmr_sum}} xmr</h3>
<div class="center">
<table class="center">
<tr>
<td>stealth address</td>
<td>amount</td>
<td>amount idx</td>
</tr>
{{#outputs}}
<tr>
<td>{{output_idx}}: {{out_pub_key}}</td>
<td>{{amount}}</td>
<td>{{amount_idx}} of {{num_outputs}}</td>
</tr>
{{/outputs}}
{{#enable_js}}
<!-- the hidden filed is used in JavaScriped based decoding and proving txs -->
<input type="hidden" id="tx_outputs" value="{{#outputs}}{{unformated_output_idx}},{{out_pub_key}},{{amount}};{{/outputs}}"/>
{{/enable_js}}
</table>
</div>
{{^have_raw_tx}}
<div class="center" style="width:90%">
<div class="tabs">
<div class="tab">
<input type="radio" id="tab-1" name="tab-group-1" checked>
<label for="tab-1">Decode outputs</label>
<div class="content">
<h4 style="margin: 0px">Check which outputs belong to given Monero address/subaddress and viewkey</h4>
<h5 style="margin: 0px">
For RingCT transactions, outputs' amounts are also decoded
<br/>
Note: address/subaddress and viewkey are sent to the server, as the calculations are done on the server side
</h5>
<form action="/myoutputs" method="post" style="width:100%; margin-top:2px" class="style-1">
<input type="hidden" name="tx_hash" value="{{tx_hash}}"><br/>
<input type="text" name="xmr_address" size="90" placeholder="Monero address/subaddress"><br/>
<input type="text" name="viewkey" size="90" placeholder="Private viewkey" style="margin-top:5px"><br/>
<input type="hidden" name="raw_tx_data" value="{{raw_tx_data}}">
<!--above raw_tx_data field only used when checking raw tx data through tx pusher-->
{{#enable_js}}
<!-- if have js, DONOT submit the form to server.
change submit button, to just a button -->
<button type="button" style="margin-top:5px" id="decode_btn" >Decode outputs</button>
{{/enable_js}}
{{^enable_js}}
<input type="submit" value="Decode outputs" style="margin-top:5px" >
{{/enable_js}}
</form>
</div>
</div>
<div class="tab">
<input type="radio" id="tab-2" name="tab-group-1">
<label for="tab-2">Prove sending</label>
<div class="content">
<h4 style="margin: 0px">Prove to someone that you have sent them Monero in this transaction</h4>
<h5 style="margin: 0px">
Tx private key can be obtained using <i>get_tx_key</i>
command in <i>monero-wallet-cli</i> command line tool
<br/>
Note: address/subaddress and tx private key are sent to the server, as the calculations are done on the server side
</h5>
<form action="/prove" method="post" style="width:100%;margin-top:2px" class="style-1">
<input type="hidden" name="txhash" value="{{tx_hash}}"><br/>
<input type="text" name="txprvkey" size="90" placeholder="Tx private key"><br/>
<input type="hidden" name="raw_tx_data" value="{{raw_tx_data}}">
<!--above raw_tx_data field only used when checking raw tx data through tx pusher-->
<input type="text" name="xmraddress" size="90" placeholder="Recipient's monero address/subaddress" style="margin-top:5px"><br/>
{{#enable_js}}
<!-- if have js, DONOT submit the form to server.
change submit button, to just a button -->
<button type="button" style="margin-top:5px" id="prove_btn">Prove sending</button>
{{/enable_js}}
{{^enable_js}}
<input type="submit" value="Prove sending" style="margin-top:5px">
{{/enable_js}}
</form>
</div>
</div>
</div>
</div>
{{/have_raw_tx}}
{{#enable_js}}
<!-- to disply results from deconding and proving txs using js -->
<div id="decode-prove-results" class="center" style="width: 80%; margin-top:10px">
</div>
<script>
// here we handle button presses from the above forms
// to decode and prove txs.
$(document).ready(function() {
// we need output pubplic keys, their indexes and amounts.
// all this is already avaliable on the html, but we can use
// musch frramework to produce js array for this
var is_rct = ($("#is_ringct").val() === "yes");
var rct_type = parseInt($("#ringct_type").val());
var tx_public_key = $("#tx_pub_key").text();
// get the tx publick key outputs from the hidden field
var tx_outputs_tmp = $("#tx_outputs").val().split(';');
var tx_outputs = [];
for (var i = 0; i < tx_outputs_tmp.length - 1; i++) {
tx_outputs.push(tx_outputs_tmp[i].split(','));
}
console.log(is_rct, rct_type, tx_outputs);
$("#decode_btn").click(function() {
var address = $("input[name=xmr_address]").val();
var viewkey = $("input[name=viewkey]").val();
var address_decoded = decode_address(address);
var key_derivation = generate_key_derivation(tx_public_key, viewkey);
console.log(tx_public_key, address, viewkey, key_derivation);
console.log(address_decoded);
// go over each tx output, and check if it is ours or not
var decoding_results_str = '<h4>Output decoding results</h4>';
decoding_results_str += '<table class="center">';
tx_outputs.forEach(function(output) {
var output_idx = parseInt(output[0]);
var output_pub_key = output[1];
var amount = output[2];
var pubkey_generated = derive_public_key(key_derivation, output_idx, address_decoded.spend);
var mine_output = (output_pub_key == pubkey_generated);
var mine_output_str = "false";
if (mine_output) {
mine_output_str = '<span style="color: #008009;font-weight: bold">true</span>';
}
decoding_results_str += "<tr>"
+"<td>" + output_idx + "</td>"
+"<td>" + output_pub_key + "</td>"
+"<td>" + mine_output_str + "</td>"
+"<td>" + amount + "</td>"
+"</tr>";
console.log(output[1], pubkey_generated);
});
decoding_results_str += "</table>"
$("#decode-prove-results").html(decoding_results_str);
});
$("#prove_btn").click(function() {
$("#decode-prove-results").html("Prove button pressed");
var address = $("input[name=xmraddress]").val();
var txprvkey = $("input[name=txprvkey]").val();
var address_decoded = decode_address(address);
console.log(address, txprvkey);
});
//decode amount and mask and check against commitment
// from https://xmr.llcoins.net/js/site.js
function decodeRct(rv, i, der){
var key = derivation_to_scalar(der, i);
var ecdh = decode_rct_ecdh(rv.ecdhInfo[i], key);
console.log(ecdh);
var Ctmp = commit(ecdh.amount, ecdh.mask);
console.log(Ctmp);
if (Ctmp !== rv.outPk[i]){
throw "mismatched commitments!";
}
ecdh.amount = s2d(ecdh.amount);
return ecdh;
}
//creates a Pedersen commitment from an amount (in scalar form) and a mask
//C = bG + aH where b = mask, a = amount
// from https://xmr.llcoins.net/js/site.js
function commit(amount, mask){
if (!valid_hex(mask) || mask.length !== 64 || !valid_hex(amount) || amount.length !== 64){
throw "invalid amount or mask!";
}
var C = ge_double_scalarmult_base_vartime(amount, H, mask);
return C;
}
// // from https://xmr.llcoins.net/js/site.js
function s2d(scalar){
return JSBigInt.parse(swapEndian(scalar), 16).toString();
}
//switch byte order for hex string
// from https://xmr.llcoins.net/js/site.js
function swapEndian(hex){
if (hex.length % 2 !== 0){return "length must be a multiple of 2!";}
var data = "";
for (var i=1; i <= hex.length / 2; i++){
data += hex.substr(0 - 2 * i, 2);
}
return data;
}
});
</script>
{{/enable_js}}
{{#has_inputs}}
{{#enable_mixins_details}}
<h3>Inputs' ring size time scale (from {{min_mix_time}} till {{max_mix_time}};
resolution: {{timescales_scale}} days{{#have_raw_tx}}; R - real ring member {{/have_raw_tx}})
</h3>
<div class="center">
<ul class="center">
{{#timescales}}
<li style="list-style-type: none; text-align: center; font-size: 8px">|{{timescale}}|</li>
{{/timescales}}
</ul>
</div>
{{/enable_mixins_details}}
{{^inputs_xmr_sum_not_zero}}
<h3>{{inputs_no}} input(s) for total of {{inputs_xmr_sum}} xmr</h3>
{{/inputs_xmr_sum_not_zero}}
{{#inputs_xmr_sum_not_zero}}
{{^have_any_unknown_amount}}
<h3>{{inputs_no}} inputs(s) for total of {{inputs_xmr_sum}} xmr</h3>
{{/have_any_unknown_amount}}
{{#have_any_unknown_amount}}
<h3>{{inputs_no}} inputs(s) for total of at least {{inputs_xmr_sum}} xmr</h3>
{{/have_any_unknown_amount}}
{{/inputs_xmr_sum_not_zero}}
{{#show_part_of_inputs}}
<h5 style="margin-top: 2px">
Only {{max_no_of_inputs_to_show}} inputs are shown. To see all,
click "<a href="/tx/{{tx_hash}}/1">more details</a>"
</h5>
{{/show_part_of_inputs}}
<div class="center">
<table class="center">
{{#inputs}}
<tr>
<td style="text-align: left;">
key image {{input_idx}}: {{in_key_img}}
{{#have_raw_tx}}
Already spent:
{{#already_spent}}
<span style="color: red; font-weight: bold;">True</span>
{{/already_spent}}
{{^already_spent}}
False
{{/already_spent}}
{{/have_raw_tx}}
</td>
<td>amount: {{amount}}</td>
</tr>
<tr>
<td colspan="2">
{{#enable_mixins_details}}
<table style="width:100%; margin-bottom:20px">
<tr>
<td>ring members</td>
{{#have_raw_tx}}
<td>Is it real?</td>
{{/have_raw_tx}}
<td>blk</td>
<td>ring size</td>
<td>in/out</td>
<td>timestamp</td>
<td>age [y:d:h:m:s]</td>
</tr>
{{#mixins}}
<tr>
<td> - {{mix_idx}}: <a href="/tx/{{mix_tx_hash}}">{{mix_pub_key}}</a></td>
{{#have_raw_tx}}
{{#mix_is_it_real}}
<td><span style="color: #008009;font-weight: bold">{{mix_is_it_real}}</span></td>
{{/mix_is_it_real}}
{{^mix_is_it_real}}
<td>{{mix_is_it_real}}</td>
{{/mix_is_it_real}}
{{/have_raw_tx}}
<td>{{mix_blk}}</td>
<td>{{mix_mixin_no}}</td>
<td>{{mix_inputs_no}}/{{mix_outputs_no}}</td>
<td>{{mix_timestamp}}</td>
<td>{{mix_age}}</td>
</tr>
{{/mixins}}
</table>
{{/enable_mixins_details}}
{{^enable_mixins_details}}
<table style="width:100%; margin-bottom:20px">
<tr>
<td>ring members</td>
{{#have_raw_tx}}
<td>Is it real?</td>
{{/have_raw_tx}}
<td>blk</td>
</tr>
{{#mixins}}
<tr>
<td> - {{mix_idx}}: {{mix_pub_key}}</td>
{{#have_raw_tx}}
{{#mix_is_it_real}}
<td><span style="color: #008009;font-weight: bold">{{mix_is_it_real}}</span></td>
{{/mix_is_it_real}}
{{^mix_is_it_real}}
<td>{{mix_is_it_real}}</td>
{{/mix_is_it_real}}
{{/have_raw_tx}}
<td>{{mix_blk}}</td>
</tr>
{{/mixins}}
</table>
{{/enable_mixins_details}}
</td>
</tr>
<!--
{{#with_ring_signatures}}
<tr>
<td colspan="2">
<table style="width:100%; margin-bottom:20px">
<tr>
<td>Ring signature</td>
</tr>
{{#ring_sigs}}
<tr>
<td>{{ring_sig}}</td>
</tr>
{{/ring_sigs}}
</table>
</td>
</tr>
{{/with_ring_signatures}}
-->
{{/inputs}}
</table>
</div>
{{/has_inputs}}
{{^have_raw_tx}}
{{^with_ring_signatures}}
{{#show_more_details_link}}
<h5 style="margin-top:1px"><a href="/tx/{{tx_hash}}/1">More details</a></h5>
{{/show_more_details_link}}
{{/with_ring_signatures}}
{{#with_ring_signatures}}
<label id="show-decoded-inputs" for="toggle-1">Show JSON representation of tx</label>
<input type="checkbox" id="toggle-1">
<div id="decoded-inputs">
<div class="center">
<code style="white-space: pre-wrap; font-size: 10px">
{{tx_json}}
</code>
</div>
</div>
<br/><br/>
<h5 style="margin-top:1px"><a href="/tx/{{tx_hash}}">Less details</a></h5>
{{/with_ring_signatures}}
{{/have_raw_tx}}
{{#show_cache_times}}
<div class="center">
{{#construction_time}}
<h6 style="margin-top: 1px;color:#949490">
Tx details construction time: {{construction_time}} s
{{#from_cache}}
<br/>Tx read from the tx cache
{{/from_cache}}
</h6>
{{/construction_time}}
</div>
{{/show_cache_times}}
</div>