mirror of
https://git.wownero.com/wownero/onion-wownero-blockchain-explorer.git
synced 2024-08-15 00:33:12 +00:00
Merge pull request #149 from moneroexamples/devel
For Monero version 0.13
This commit is contained in:
commit
e6006acf48
17 changed files with 17728 additions and 13310 deletions
|
@ -6,9 +6,7 @@ set(PROJECT_NAME
|
||||||
|
|
||||||
project(${PROJECT_NAME})
|
project(${PROJECT_NAME})
|
||||||
|
|
||||||
set(CMAKE_CXX_FLAGS
|
set(CMAKE_CXX_STANDARD 11)
|
||||||
"${CMAKE_CXX_FLAGS} -std=c++14")
|
|
||||||
|
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wa,-mbig-obj -O3")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wa,-mbig-obj -O3")
|
||||||
|
@ -119,7 +117,7 @@ set(LIBRARIES
|
||||||
checkpoints
|
checkpoints
|
||||||
version
|
version
|
||||||
epee
|
epee
|
||||||
pcsclite
|
sodium
|
||||||
${Boost_LIBRARIES}
|
${Boost_LIBRARIES}
|
||||||
pthread
|
pthread
|
||||||
unbound
|
unbound
|
||||||
|
@ -130,7 +128,7 @@ set(LIBRARIES
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
set(LIBRARIES ${LIBRARIES} "-framework IOKit -framework PCSC")
|
set(LIBRARIES ${LIBRARIES} "-framework IOKit -framework PCSC")
|
||||||
else()
|
else()
|
||||||
set(LIBRARIES ${LIBRARIES} atomic)
|
set(LIBRARIES ${LIBRARIES} atomic pcsclite)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin" AND NOT WIN32)
|
if (NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin" AND NOT WIN32)
|
||||||
|
|
14
README.md
14
README.md
|
@ -28,24 +28,22 @@ Tor users:
|
||||||
- [http://dvwae436pd7nt4bc.onion](http://dvwae436pd7nt4bc.onion) (Front-end templates are [maintained by @suhz](https://github.com/suhz/onion-monero-blockchain-explorer/tree/moneroexplorer.com/src/templates)).
|
- [http://dvwae436pd7nt4bc.onion](http://dvwae436pd7nt4bc.onion) (Front-end templates are [maintained by @suhz](https://github.com/suhz/onion-monero-blockchain-explorer/tree/moneroexplorer.com/src/templates)).
|
||||||
|
|
||||||
Clearnet versions:
|
Clearnet versions:
|
||||||
- [https://labor.serveo.net/](https://labor.serveo.net/) - temprorary link (slow), bleading edge version.
|
|
||||||
- [https://xmrchain.net/](https://xmrchain.net/) - https enabled, most popular and very stable.
|
- [https://xmrchain.net/](https://xmrchain.net/) - https enabled, most popular and very stable.
|
||||||
- [https://MoneroExplorer.com/](https://moneroexplorer.com/) - nice looking one, https enabled.
|
- [https://MoneroExplorer.com/](https://moneroexplorer.com/) - nice looking one, https enabled.
|
||||||
- [https://monerohash.com/explorer/](https://monerohash.com/explorer/) - nice looking one, https enabled.
|
- [https://monerohash.com/explorer/](https://monerohash.com/explorer/) - nice looking one, https enabled.
|
||||||
- [http://explore.MoneroWorld.com](http://explore.moneroworld.com) - same as the second one.
|
- [http://explore.MoneroWorld.com](http://explore.moneroworld.com) - same as the second one.
|
||||||
- [https://moneroexplorer.pro/](https://moneroexplorer.pro/) - nice looking one, https enabled.
|
|
||||||
- [http://monerochain.com/](http://monerochain.com/) - JSON API based, multiple nodes.
|
- [http://monerochain.com/](http://monerochain.com/) - JSON API based, multiple nodes.
|
||||||
- [https://blox.minexmr.com/](https://blox.minexmr.com/) - - https enabled.
|
- [https://blox.minexmr.com/](https://blox.minexmr.com/) - - https enabled.
|
||||||
|
|
||||||
Testnet version:
|
Testnet version:
|
||||||
|
|
||||||
- [http://nimis.serveo.net/](http://nimis.serveo.net/) - bleeding edge version (down currently).
|
|
||||||
- [https://testnet.xmrchain.com/](https://testnet.xmrchain.com/) - https enabled.
|
- [https://testnet.xmrchain.com/](https://testnet.xmrchain.com/) - https enabled.
|
||||||
- [https://explorer.monero-otc.com/](https://explorer.monero-otc.com/) - https enabled.
|
- [https://explorer.monero-otc.com/](https://explorer.monero-otc.com/) - https enabled.
|
||||||
|
|
||||||
Stagenet version:
|
Stagenet version:
|
||||||
|
|
||||||
- [http://162.210.173.150:8083/](http://162.210.173.150:8083/) - recent version.
|
- [https://stagenet.xmrchain.net/](https://stagenet.xmrchain.net/)
|
||||||
|
- [http://162.210.173.150:8083/](http://162.210.173.150:8083/)
|
||||||
|
|
||||||
i2p users (main Monero network):
|
i2p users (main Monero network):
|
||||||
|
|
||||||
|
@ -54,7 +52,6 @@ i2p users (main Monero network):
|
||||||
Alternative block explorers:
|
Alternative block explorers:
|
||||||
|
|
||||||
- [http://moneroblocks.info](http://moneroblocks.info/)
|
- [http://moneroblocks.info](http://moneroblocks.info/)
|
||||||
- [https://monerobase.com](https://monerobase.com/)
|
|
||||||
- [https://monerovision.com](https://monerovision.com)
|
- [https://monerovision.com](https://monerovision.com)
|
||||||
- [http://chainradar.com](http://chainradar.com/xmr/blocks)
|
- [http://chainradar.com](http://chainradar.com/xmr/blocks)
|
||||||
|
|
||||||
|
@ -93,7 +90,7 @@ Current development branch:
|
||||||
|
|
||||||
## Compilation on Ubuntu 16.04/18.04
|
## Compilation on Ubuntu 16.04/18.04
|
||||||
|
|
||||||
##### Compile latest Monero development version
|
##### Compile latest Monero version (0.13)
|
||||||
|
|
||||||
Download and compile recent Monero into your home folder:
|
Download and compile recent Monero into your home folder:
|
||||||
|
|
||||||
|
@ -110,10 +107,8 @@ git clone --recursive https://github.com/monero-project/monero
|
||||||
|
|
||||||
cd monero/
|
cd monero/
|
||||||
|
|
||||||
# checkout last monero version
|
|
||||||
git checkout -b last_release v0.12.1.0
|
|
||||||
|
|
||||||
make
|
USE_SINGLE_BUILDDIR=1 make
|
||||||
```
|
```
|
||||||
|
|
||||||
##### Compile and run the explorer
|
##### Compile and run the explorer
|
||||||
|
@ -697,7 +692,6 @@ curl -w "\n" -X GET http://127.0.0.1:8081/api/outputsblocks?address=9sDyNU82ih1
|
||||||
Example result:
|
Example result:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
|
||||||
{
|
{
|
||||||
"data": {
|
"data": {
|
||||||
"address": "0182d5be0f708cecf2b6f9889738bde5c930fad846d5b530e021afd1ae7e24a687ad50af3a5d38896655669079ad0163b4a369f6c852cc816dace5fc7792b72f",
|
"address": "0182d5be0f708cecf2b6f9889738bde5c930fad846d5b530e021afd1ae7e24a687ad50af3a5d38896655669079ad0163b4a369f6c852cc816dace5fc7792b72f",
|
||||||
|
|
19421
ext/json.hpp
19421
ext/json.hpp
File diff suppressed because it is too large
Load diff
97
main.cpp
97
main.cpp
|
@ -44,6 +44,7 @@ main(int ac, const char* av[])
|
||||||
}
|
}
|
||||||
|
|
||||||
auto port_opt = opts.get_option<string>("port");
|
auto port_opt = opts.get_option<string>("port");
|
||||||
|
auto bindaddr_opt = opts.get_option<string>("bindaddr");
|
||||||
auto bc_path_opt = opts.get_option<string>("bc-path");
|
auto bc_path_opt = opts.get_option<string>("bc-path");
|
||||||
auto deamon_url_opt = opts.get_option<string>("deamon-url");
|
auto deamon_url_opt = opts.get_option<string>("deamon-url");
|
||||||
auto ssl_crt_file_opt = opts.get_option<string>("ssl-crt-file");
|
auto ssl_crt_file_opt = opts.get_option<string>("ssl-crt-file");
|
||||||
|
@ -63,6 +64,7 @@ main(int ac, const char* av[])
|
||||||
auto enable_js_opt = opts.get_option<bool>("enable-js");
|
auto enable_js_opt = opts.get_option<bool>("enable-js");
|
||||||
auto enable_mixin_details_opt = opts.get_option<bool>("enable-mixin-details");
|
auto enable_mixin_details_opt = opts.get_option<bool>("enable-mixin-details");
|
||||||
auto enable_json_api_opt = opts.get_option<bool>("enable-json-api");
|
auto enable_json_api_opt = opts.get_option<bool>("enable-json-api");
|
||||||
|
auto enable_as_hex_opt = opts.get_option<bool>("enable-as-hex");
|
||||||
auto enable_tx_cache_opt = opts.get_option<bool>("enable-tx-cache");
|
auto enable_tx_cache_opt = opts.get_option<bool>("enable-tx-cache");
|
||||||
auto enable_block_cache_opt = opts.get_option<bool>("enable-block-cache");
|
auto enable_block_cache_opt = opts.get_option<bool>("enable-block-cache");
|
||||||
auto show_cache_times_opt = opts.get_option<bool>("show-cache-times");
|
auto show_cache_times_opt = opts.get_option<bool>("show-cache-times");
|
||||||
|
@ -90,6 +92,7 @@ main(int ac, const char* av[])
|
||||||
bool enable_output_key_checker {*enable_output_key_checker_opt};
|
bool enable_output_key_checker {*enable_output_key_checker_opt};
|
||||||
bool enable_mixin_details {*enable_mixin_details_opt};
|
bool enable_mixin_details {*enable_mixin_details_opt};
|
||||||
bool enable_json_api {*enable_json_api_opt};
|
bool enable_json_api {*enable_json_api_opt};
|
||||||
|
bool enable_as_hex {*enable_as_hex_opt};
|
||||||
bool enable_tx_cache {*enable_tx_cache_opt};
|
bool enable_tx_cache {*enable_tx_cache_opt};
|
||||||
bool enable_block_cache {*enable_block_cache_opt};
|
bool enable_block_cache {*enable_block_cache_opt};
|
||||||
bool enable_emission_monitor {*enable_emission_monitor_opt};
|
bool enable_emission_monitor {*enable_emission_monitor_opt};
|
||||||
|
@ -100,9 +103,13 @@ main(int ac, const char* av[])
|
||||||
uint32_t log_level = 0;
|
uint32_t log_level = 0;
|
||||||
mlog_configure("", true);
|
mlog_configure("", true);
|
||||||
|
|
||||||
|
(void) log_level;
|
||||||
|
|
||||||
//cast port number in string to uint
|
//cast port number in string to uint
|
||||||
uint16_t app_port = boost::lexical_cast<uint16_t>(*port_opt);
|
uint16_t app_port = boost::lexical_cast<uint16_t>(*port_opt);
|
||||||
|
|
||||||
|
string bindaddr = *bindaddr_opt;
|
||||||
|
|
||||||
// cast no_blocks_on_index_opt to uint
|
// cast no_blocks_on_index_opt to uint
|
||||||
uint64_t no_blocks_on_index = boost::lexical_cast<uint64_t>(*no_blocks_on_index_opt);
|
uint64_t no_blocks_on_index = boost::lexical_cast<uint64_t>(*no_blocks_on_index_opt);
|
||||||
|
|
||||||
|
@ -259,6 +266,7 @@ main(int ac, const char* av[])
|
||||||
nettype,
|
nettype,
|
||||||
enable_pusher,
|
enable_pusher,
|
||||||
enable_js,
|
enable_js,
|
||||||
|
enable_as_hex,
|
||||||
enable_key_image_checker,
|
enable_key_image_checker,
|
||||||
enable_output_key_checker,
|
enable_output_key_checker,
|
||||||
enable_autorefresh_option,
|
enable_autorefresh_option,
|
||||||
|
@ -282,7 +290,7 @@ main(int ac, const char* av[])
|
||||||
};
|
};
|
||||||
|
|
||||||
CROW_ROUTE(app, "/")
|
CROW_ROUTE(app, "/")
|
||||||
([&](const crow::request& req) {
|
([&]() {
|
||||||
return crow::response(xmrblocks.index2());
|
return crow::response(xmrblocks.index2());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -292,20 +300,43 @@ main(int ac, const char* av[])
|
||||||
});
|
});
|
||||||
|
|
||||||
CROW_ROUTE(app, "/block/<uint>")
|
CROW_ROUTE(app, "/block/<uint>")
|
||||||
([&](const crow::request& req, size_t block_height) {
|
([&](size_t block_height) {
|
||||||
return crow::response(xmrblocks.show_block(block_height));
|
return crow::response(xmrblocks.show_block(block_height));
|
||||||
});
|
});
|
||||||
|
|
||||||
CROW_ROUTE(app, "/block/<string>")
|
CROW_ROUTE(app, "/block/<string>")
|
||||||
([&](const crow::request& req, string block_hash) {
|
([&](string block_hash) {
|
||||||
return crow::response(xmrblocks.show_block(remove_bad_chars(block_hash)));
|
return crow::response(xmrblocks.show_block(remove_bad_chars(block_hash)));
|
||||||
});
|
});
|
||||||
|
|
||||||
CROW_ROUTE(app, "/tx/<string>")
|
CROW_ROUTE(app, "/tx/<string>")
|
||||||
([&](const crow::request& req, string tx_hash) {
|
([&](string tx_hash) {
|
||||||
return crow::response(xmrblocks.show_tx(remove_bad_chars(tx_hash)));
|
return crow::response(xmrblocks.show_tx(remove_bad_chars(tx_hash)));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (enable_as_hex)
|
||||||
|
{
|
||||||
|
CROW_ROUTE(app, "/txhex/<string>")
|
||||||
|
([&](string tx_hash) {
|
||||||
|
return crow::response(xmrblocks.show_tx_hex(remove_bad_chars(tx_hash)));
|
||||||
|
});
|
||||||
|
|
||||||
|
CROW_ROUTE(app, "/ringmembershex/<string>")
|
||||||
|
([&](string tx_hash) {
|
||||||
|
return crow::response(xmrblocks.show_ringmembers_hex(remove_bad_chars(tx_hash)));
|
||||||
|
});
|
||||||
|
|
||||||
|
CROW_ROUTE(app, "/blockhex/<uint>")
|
||||||
|
([&](size_t block_height) {
|
||||||
|
return crow::response(xmrblocks.show_block_hex(block_height, false));
|
||||||
|
});
|
||||||
|
|
||||||
|
CROW_ROUTE(app, "/blockhexcomplete/<uint>")
|
||||||
|
([&](size_t block_height) {
|
||||||
|
return crow::response(xmrblocks.show_block_hex(block_height, true));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
CROW_ROUTE(app, "/tx/<string>/<uint>")
|
CROW_ROUTE(app, "/tx/<string>/<uint>")
|
||||||
([&](string tx_hash, uint16_t with_ring_signatures)
|
([&](string tx_hash, uint16_t with_ring_signatures)
|
||||||
{
|
{
|
||||||
|
@ -403,7 +434,7 @@ main(int ac, const char* av[])
|
||||||
if (enable_pusher)
|
if (enable_pusher)
|
||||||
{
|
{
|
||||||
CROW_ROUTE(app, "/rawtx")
|
CROW_ROUTE(app, "/rawtx")
|
||||||
([&](const crow::request& req) {
|
([&]() {
|
||||||
return xmrblocks.show_rawtx();
|
return xmrblocks.show_rawtx();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -433,7 +464,7 @@ main(int ac, const char* av[])
|
||||||
if (enable_key_image_checker)
|
if (enable_key_image_checker)
|
||||||
{
|
{
|
||||||
CROW_ROUTE(app, "/rawkeyimgs")
|
CROW_ROUTE(app, "/rawkeyimgs")
|
||||||
([&](const crow::request& req) {
|
([&]() {
|
||||||
return xmrblocks.show_rawkeyimgs();
|
return xmrblocks.show_rawkeyimgs();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -464,7 +495,7 @@ main(int ac, const char* av[])
|
||||||
if (enable_output_key_checker)
|
if (enable_output_key_checker)
|
||||||
{
|
{
|
||||||
CROW_ROUTE(app, "/rawoutputkeys")
|
CROW_ROUTE(app, "/rawoutputkeys")
|
||||||
([&](const crow::request& req) {
|
([&]() {
|
||||||
return xmrblocks.show_rawoutputkeys();
|
return xmrblocks.show_rawoutputkeys();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -499,13 +530,13 @@ main(int ac, const char* av[])
|
||||||
});
|
});
|
||||||
|
|
||||||
CROW_ROUTE(app, "/mempool")
|
CROW_ROUTE(app, "/mempool")
|
||||||
([&](const crow::request& req) {
|
([&]() {
|
||||||
return xmrblocks.mempool(true);
|
return xmrblocks.mempool(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
// alias to "/mempool"
|
// alias to "/mempool"
|
||||||
CROW_ROUTE(app, "/txpool")
|
CROW_ROUTE(app, "/txpool")
|
||||||
([&](const crow::request& req) {
|
([&]() {
|
||||||
return xmrblocks.mempool(true);
|
return xmrblocks.mempool(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -526,52 +557,52 @@ main(int ac, const char* av[])
|
||||||
cout << "Enable JavaScript checking of outputs and proving txs\n";
|
cout << "Enable JavaScript checking of outputs and proving txs\n";
|
||||||
|
|
||||||
CROW_ROUTE(app, "/js/jquery.min.js")
|
CROW_ROUTE(app, "/js/jquery.min.js")
|
||||||
([&](const crow::request& req) {
|
([&]() {
|
||||||
return xmrblocks.get_js_file("jquery.min.js");
|
return xmrblocks.get_js_file("jquery.min.js");
|
||||||
});
|
});
|
||||||
|
|
||||||
CROW_ROUTE(app, "/js/crc32.js")
|
CROW_ROUTE(app, "/js/crc32.js")
|
||||||
([&](const crow::request& req) {
|
([&]() {
|
||||||
return xmrblocks.get_js_file("crc32.js");
|
return xmrblocks.get_js_file("crc32.js");
|
||||||
});
|
});
|
||||||
|
|
||||||
CROW_ROUTE(app, "/js/biginteger.js")
|
CROW_ROUTE(app, "/js/biginteger.js")
|
||||||
([&](const crow::request& req) {
|
([&]() {
|
||||||
return xmrblocks.get_js_file("biginteger.js");
|
return xmrblocks.get_js_file("biginteger.js");
|
||||||
});
|
});
|
||||||
|
|
||||||
CROW_ROUTE(app, "/js/crypto.js")
|
CROW_ROUTE(app, "/js/crypto.js")
|
||||||
([&](const crow::request& req) {
|
([&]() {
|
||||||
return xmrblocks.get_js_file("crypto.js");
|
return xmrblocks.get_js_file("crypto.js");
|
||||||
});
|
});
|
||||||
|
|
||||||
CROW_ROUTE(app, "/js/config.js")
|
CROW_ROUTE(app, "/js/config.js")
|
||||||
([&](const crow::request& req) {
|
([&]() {
|
||||||
return xmrblocks.get_js_file("config.js");
|
return xmrblocks.get_js_file("config.js");
|
||||||
});
|
});
|
||||||
|
|
||||||
CROW_ROUTE(app, "/js/nacl-fast-cn.js")
|
CROW_ROUTE(app, "/js/nacl-fast-cn.js")
|
||||||
([&](const crow::request& req) {
|
([&]() {
|
||||||
return xmrblocks.get_js_file("nacl-fast-cn.js");
|
return xmrblocks.get_js_file("nacl-fast-cn.js");
|
||||||
});
|
});
|
||||||
|
|
||||||
CROW_ROUTE(app, "/js/base58.js")
|
CROW_ROUTE(app, "/js/base58.js")
|
||||||
([&](const crow::request& req) {
|
([&]() {
|
||||||
return xmrblocks.get_js_file("base58.js");
|
return xmrblocks.get_js_file("base58.js");
|
||||||
});
|
});
|
||||||
|
|
||||||
CROW_ROUTE(app, "/js/cn_util.js")
|
CROW_ROUTE(app, "/js/cn_util.js")
|
||||||
([&](const crow::request& req) {
|
([&]() {
|
||||||
return xmrblocks.get_js_file("cn_util.js");
|
return xmrblocks.get_js_file("cn_util.js");
|
||||||
});
|
});
|
||||||
|
|
||||||
CROW_ROUTE(app, "/js/sha3.js")
|
CROW_ROUTE(app, "/js/sha3.js")
|
||||||
([&](const crow::request& req) {
|
([&]() {
|
||||||
return xmrblocks.get_js_file("sha3.js");
|
return xmrblocks.get_js_file("sha3.js");
|
||||||
});
|
});
|
||||||
|
|
||||||
CROW_ROUTE(app, "/js/all_in_one.js")
|
CROW_ROUTE(app, "/js/all_in_one.js")
|
||||||
([&](const crow::request& req) {
|
([&]() {
|
||||||
// /js/all_in_one.js file does not exist. it is generated on the fly
|
// /js/all_in_one.js file does not exist. it is generated on the fly
|
||||||
// from the above real files.
|
// from the above real files.
|
||||||
return xmrblocks.get_js_file("all_in_one.js");
|
return xmrblocks.get_js_file("all_in_one.js");
|
||||||
|
@ -585,7 +616,7 @@ main(int ac, const char* av[])
|
||||||
cout << "Enable JSON API\n";
|
cout << "Enable JSON API\n";
|
||||||
|
|
||||||
CROW_ROUTE(app, "/api/transaction/<string>")
|
CROW_ROUTE(app, "/api/transaction/<string>")
|
||||||
([&](const crow::request &req, string tx_hash) {
|
([&](string tx_hash) {
|
||||||
|
|
||||||
myxmr::jsonresponse r{xmrblocks.json_transaction(remove_bad_chars(tx_hash))};
|
myxmr::jsonresponse r{xmrblocks.json_transaction(remove_bad_chars(tx_hash))};
|
||||||
|
|
||||||
|
@ -593,15 +624,23 @@ main(int ac, const char* av[])
|
||||||
});
|
});
|
||||||
|
|
||||||
CROW_ROUTE(app, "/api/rawtransaction/<string>")
|
CROW_ROUTE(app, "/api/rawtransaction/<string>")
|
||||||
([&](const crow::request &req, string tx_hash) {
|
([&](string tx_hash) {
|
||||||
|
|
||||||
myxmr::jsonresponse r{xmrblocks.json_rawtransaction(remove_bad_chars(tx_hash))};
|
myxmr::jsonresponse r{xmrblocks.json_rawtransaction(remove_bad_chars(tx_hash))};
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
CROW_ROUTE(app, "/api/detailedtransaction/<string>")
|
||||||
|
([&](string tx_hash) {
|
||||||
|
|
||||||
|
myxmr::jsonresponse r{xmrblocks.json_detailedtransaction(remove_bad_chars(tx_hash))};
|
||||||
|
|
||||||
|
return r;
|
||||||
|
});
|
||||||
|
|
||||||
CROW_ROUTE(app, "/api/block/<string>")
|
CROW_ROUTE(app, "/api/block/<string>")
|
||||||
([&](const crow::request &req, string block_no_or_hash) {
|
([&](string block_no_or_hash) {
|
||||||
|
|
||||||
myxmr::jsonresponse r{xmrblocks.json_block(remove_bad_chars(block_no_or_hash))};
|
myxmr::jsonresponse r{xmrblocks.json_block(remove_bad_chars(block_no_or_hash))};
|
||||||
|
|
||||||
|
@ -609,7 +648,7 @@ main(int ac, const char* av[])
|
||||||
});
|
});
|
||||||
|
|
||||||
CROW_ROUTE(app, "/api/rawblock/<string>")
|
CROW_ROUTE(app, "/api/rawblock/<string>")
|
||||||
([&](const crow::request &req, string block_no_or_hash) {
|
([&](string block_no_or_hash) {
|
||||||
|
|
||||||
myxmr::jsonresponse r{xmrblocks.json_rawblock(remove_bad_chars(block_no_or_hash))};
|
myxmr::jsonresponse r{xmrblocks.json_rawblock(remove_bad_chars(block_no_or_hash))};
|
||||||
|
|
||||||
|
@ -650,7 +689,7 @@ main(int ac, const char* av[])
|
||||||
});
|
});
|
||||||
|
|
||||||
CROW_ROUTE(app, "/api/search/<string>")
|
CROW_ROUTE(app, "/api/search/<string>")
|
||||||
([&](const crow::request &req, string search_value) {
|
([&](string search_value) {
|
||||||
|
|
||||||
myxmr::jsonresponse r{xmrblocks.json_search(remove_bad_chars(search_value))};
|
myxmr::jsonresponse r{xmrblocks.json_search(remove_bad_chars(search_value))};
|
||||||
|
|
||||||
|
@ -658,7 +697,7 @@ main(int ac, const char* av[])
|
||||||
});
|
});
|
||||||
|
|
||||||
CROW_ROUTE(app, "/api/networkinfo")
|
CROW_ROUTE(app, "/api/networkinfo")
|
||||||
([&](const crow::request &req) {
|
([&]() {
|
||||||
|
|
||||||
myxmr::jsonresponse r{xmrblocks.json_networkinfo()};
|
myxmr::jsonresponse r{xmrblocks.json_networkinfo()};
|
||||||
|
|
||||||
|
@ -666,7 +705,7 @@ main(int ac, const char* av[])
|
||||||
});
|
});
|
||||||
|
|
||||||
CROW_ROUTE(app, "/api/emission")
|
CROW_ROUTE(app, "/api/emission")
|
||||||
([&](const crow::request &req) {
|
([&]() {
|
||||||
|
|
||||||
myxmr::jsonresponse r{xmrblocks.json_emission()};
|
myxmr::jsonresponse r{xmrblocks.json_emission()};
|
||||||
|
|
||||||
|
@ -742,7 +781,7 @@ main(int ac, const char* av[])
|
||||||
});
|
});
|
||||||
|
|
||||||
CROW_ROUTE(app, "/api/version")
|
CROW_ROUTE(app, "/api/version")
|
||||||
([&](const crow::request &req) {
|
([&]() {
|
||||||
|
|
||||||
myxmr::jsonresponse r{xmrblocks.json_version()};
|
myxmr::jsonresponse r{xmrblocks.json_version()};
|
||||||
|
|
||||||
|
@ -766,13 +805,13 @@ main(int ac, const char* av[])
|
||||||
if (use_ssl)
|
if (use_ssl)
|
||||||
{
|
{
|
||||||
cout << "Staring in ssl mode" << endl;
|
cout << "Staring in ssl mode" << endl;
|
||||||
app.port(app_port).ssl_file(ssl_crt_file, ssl_key_file)
|
app.bindaddr(bindaddr).port(app_port).ssl_file(ssl_crt_file, ssl_key_file)
|
||||||
.multithreaded().run();
|
.multithreaded().run();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
cout << "Staring in non-ssl mode" << endl;
|
cout << "Staring in non-ssl mode" << endl;
|
||||||
app.port(app_port).multithreaded().run();
|
app.bindaddr(bindaddr).port(app_port).multithreaded().run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -45,12 +45,16 @@ namespace xmreg
|
||||||
"enable caching of block details")
|
"enable caching of block details")
|
||||||
("enable-js", value<bool>()->default_value(false)->implicit_value(true),
|
("enable-js", value<bool>()->default_value(false)->implicit_value(true),
|
||||||
"enable checking outputs and proving txs using JavaScript on client side")
|
"enable checking outputs and proving txs using JavaScript on client side")
|
||||||
|
("enable-as-hex", value<bool>()->default_value(false)->implicit_value(true),
|
||||||
|
"enable links to provide hex represtations of a tx and a block")
|
||||||
("enable-autorefresh-option", value<bool>()->default_value(false)->implicit_value(true),
|
("enable-autorefresh-option", value<bool>()->default_value(false)->implicit_value(true),
|
||||||
"enable users to have the index page on autorefresh")
|
"enable users to have the index page on autorefresh")
|
||||||
("enable-emission-monitor", value<bool>()->default_value(false)->implicit_value(true),
|
("enable-emission-monitor", value<bool>()->default_value(false)->implicit_value(true),
|
||||||
"enable Monero total emission monitoring thread")
|
"enable Monero total emission monitoring thread")
|
||||||
("port,p", value<string>()->default_value("8081"),
|
("port,p", value<string>()->default_value("8081"),
|
||||||
"default explorer port")
|
"default explorer port")
|
||||||
|
("bindaddr,x", value<string>()->default_value("0.0.0.0"),
|
||||||
|
"default bind address for the explorer")
|
||||||
("testnet-url", value<string>()->default_value(""),
|
("testnet-url", value<string>()->default_value(""),
|
||||||
"you can specify testnet url, if you run it on mainnet or stagenet. link will show on front page to testnet explorer")
|
"you can specify testnet url, if you run it on mainnet or stagenet. link will show on front page to testnet explorer")
|
||||||
("stagenet-url", value<string>()->default_value(""),
|
("stagenet-url", value<string>()->default_value(""),
|
||||||
|
|
|
@ -137,8 +137,8 @@ CurrentBlockchainStatus::calculate_emission_in_blocks(
|
||||||
|
|
||||||
uint64_t coinbase_amount = get_outs_money_amount(blk.miner_tx);
|
uint64_t coinbase_amount = get_outs_money_amount(blk.miner_tx);
|
||||||
|
|
||||||
std::list<transaction> txs;
|
vector<transaction> txs;
|
||||||
std::list<crypto::hash> missed_txs;
|
vector<crypto::hash> missed_txs;
|
||||||
|
|
||||||
uint64_t tx_fee_amount = 0;
|
uint64_t tx_fee_amount = 0;
|
||||||
|
|
||||||
|
|
|
@ -139,10 +139,13 @@ MempoolStatus::read_mempool()
|
||||||
|
|
||||||
mempool_size_kB += _tx_info.blob_size;
|
mempool_size_kB += _tx_info.blob_size;
|
||||||
|
|
||||||
local_copy_of_mempool_txs.push_back(mempool_tx {tx_hash, tx});
|
local_copy_of_mempool_txs.push_back(mempool_tx{});
|
||||||
|
|
||||||
mempool_tx& last_tx = local_copy_of_mempool_txs.back();
|
mempool_tx& last_tx = local_copy_of_mempool_txs.back();
|
||||||
|
|
||||||
|
last_tx.tx_hash = tx_hash;
|
||||||
|
last_tx.tx = tx;
|
||||||
|
|
||||||
// key images of inputs
|
// key images of inputs
|
||||||
vector<txin_to_key> input_key_imgs;
|
vector<txin_to_key> input_key_imgs;
|
||||||
|
|
||||||
|
@ -168,7 +171,7 @@ MempoolStatus::read_mempool()
|
||||||
last_tx.mixin_no = sum_data[2];
|
last_tx.mixin_no = sum_data[2];
|
||||||
last_tx.num_nonrct_inputs = sum_data[3];
|
last_tx.num_nonrct_inputs = sum_data[3];
|
||||||
|
|
||||||
last_tx.fee_str = xmreg::xmr_amount_to_str(_tx_info.fee, "{:0.3f}", false);
|
last_tx.fee_str = xmreg::xmr_amount_to_str(_tx_info.fee, "{:0.4f}", false);
|
||||||
last_tx.payed_for_kB_str = fmt::format("{:0.4f}", payed_for_kB);
|
last_tx.payed_for_kB_str = fmt::format("{:0.4f}", payed_for_kB);
|
||||||
last_tx.xmr_inputs_str = xmreg::xmr_amount_to_str(last_tx.sum_inputs , "{:0.3f}");
|
last_tx.xmr_inputs_str = xmreg::xmr_amount_to_str(last_tx.sum_inputs , "{:0.3f}");
|
||||||
last_tx.xmr_outputs_str = xmreg::xmr_amount_to_str(last_tx.sum_outputs, "{:0.3f}");
|
last_tx.xmr_outputs_str = xmreg::xmr_amount_to_str(last_tx.sum_outputs, "{:0.3f}");
|
||||||
|
@ -264,6 +267,7 @@ MempoolStatus::read_network_info()
|
||||||
local_copy.cumulative_difficulty = rpc_network_info.cumulative_difficulty;
|
local_copy.cumulative_difficulty = rpc_network_info.cumulative_difficulty;
|
||||||
local_copy.block_size_limit = rpc_network_info.block_size_limit;
|
local_copy.block_size_limit = rpc_network_info.block_size_limit;
|
||||||
local_copy.block_size_median = rpc_network_info.block_size_median;
|
local_copy.block_size_median = rpc_network_info.block_size_median;
|
||||||
|
local_copy.block_weight_limit = rpc_network_info.block_weight_limit;
|
||||||
local_copy.start_time = rpc_network_info.start_time;
|
local_copy.start_time = rpc_network_info.start_time;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -72,6 +72,7 @@ struct MempoolStatus
|
||||||
uint64_t cumulative_difficulty {0};
|
uint64_t cumulative_difficulty {0};
|
||||||
uint64_t block_size_limit {0};
|
uint64_t block_size_limit {0};
|
||||||
uint64_t block_size_median {0};
|
uint64_t block_size_median {0};
|
||||||
|
uint64_t block_weight_limit {0};
|
||||||
char block_size_limit_str[10]; // needs to be trivially copyable
|
char block_size_limit_str[10]; // needs to be trivially copyable
|
||||||
char block_size_median_str[10]; // std::string is not trivially copyable
|
char block_size_median_str[10]; // std::string is not trivially copyable
|
||||||
uint64_t start_time {0};
|
uint64_t start_time {0};
|
||||||
|
|
|
@ -80,6 +80,12 @@ MicroCore::get_core()
|
||||||
return m_blockchain_storage;
|
return m_blockchain_storage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tx_memory_pool&
|
||||||
|
MicroCore::get_mempool()
|
||||||
|
{
|
||||||
|
return m_mempool;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get block by its height
|
* Get block by its height
|
||||||
*
|
*
|
||||||
|
@ -210,78 +216,6 @@ MicroCore::find_output_in_tx(const transaction& tx,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns tx hash in a given block which
|
|
||||||
* contains given output's public key
|
|
||||||
*/
|
|
||||||
bool
|
|
||||||
MicroCore::get_tx_hash_from_output_pubkey(const public_key& output_pubkey,
|
|
||||||
const uint64_t& block_height,
|
|
||||||
crypto::hash& tx_hash,
|
|
||||||
cryptonote::transaction& tx_found)
|
|
||||||
{
|
|
||||||
|
|
||||||
tx_hash = null_hash;
|
|
||||||
|
|
||||||
// get block of given height
|
|
||||||
block blk;
|
|
||||||
if (!get_block_by_height(block_height, blk))
|
|
||||||
{
|
|
||||||
cerr << "Cant get block of height: " << block_height << endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// get all transactions in the block found
|
|
||||||
// initialize the first list with transaction for solving
|
|
||||||
// the block i.e. coinbase.
|
|
||||||
list<transaction> txs {blk.miner_tx};
|
|
||||||
list<crypto::hash> missed_txs;
|
|
||||||
|
|
||||||
if (!m_blockchain_storage.get_transactions(blk.tx_hashes, txs, missed_txs))
|
|
||||||
{
|
|
||||||
cerr << "Cant find transcations in block: " << block_height << endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!missed_txs.empty())
|
|
||||||
{
|
|
||||||
cerr << "Transactions not found in blk: " << block_height << endl;
|
|
||||||
|
|
||||||
for (const crypto::hash& h : missed_txs)
|
|
||||||
{
|
|
||||||
cerr << " - tx hash: " << h << endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// search outputs in each transactions
|
|
||||||
// until output with pubkey of interest is found
|
|
||||||
for (const transaction& tx : txs)
|
|
||||||
{
|
|
||||||
|
|
||||||
tx_out found_out;
|
|
||||||
|
|
||||||
// we dont need here output_index
|
|
||||||
size_t output_index;
|
|
||||||
|
|
||||||
if (find_output_in_tx(tx, output_pubkey, found_out, output_index))
|
|
||||||
{
|
|
||||||
// we found the desired public key
|
|
||||||
tx_hash = get_transaction_hash(tx);
|
|
||||||
tx_found = tx;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
uint64_t
|
uint64_t
|
||||||
MicroCore::get_blk_timestamp(uint64_t blk_height)
|
MicroCore::get_blk_timestamp(uint64_t blk_height)
|
||||||
{
|
{
|
||||||
|
@ -332,6 +266,28 @@ init_blockchain(const string& path,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
MicroCore::get_block_complete_entry(block const& b, block_complete_entry& bce)
|
||||||
|
{
|
||||||
|
bce.block = cryptonote::block_to_blob(b);
|
||||||
|
|
||||||
|
for (const auto &tx_hash: b.tx_hashes)
|
||||||
|
{
|
||||||
|
transaction tx;
|
||||||
|
|
||||||
|
if (!get_tx(tx_hash, tx))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
cryptonote::blobdata txblob = tx_to_blob(tx);
|
||||||
|
|
||||||
|
bce.txs.push_back(txblob);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
string
|
string
|
||||||
MicroCore::get_blkchain_path()
|
MicroCore::get_blkchain_path()
|
||||||
{
|
{
|
||||||
|
|
|
@ -44,6 +44,9 @@ namespace xmreg
|
||||||
Blockchain&
|
Blockchain&
|
||||||
get_core();
|
get_core();
|
||||||
|
|
||||||
|
tx_memory_pool&
|
||||||
|
get_mempool();
|
||||||
|
|
||||||
bool
|
bool
|
||||||
get_block_by_height(const uint64_t& height, block& blk);
|
get_block_by_height(const uint64_t& height, block& blk);
|
||||||
|
|
||||||
|
@ -59,15 +62,12 @@ namespace xmreg
|
||||||
tx_out& out,
|
tx_out& out,
|
||||||
size_t& output_index);
|
size_t& output_index);
|
||||||
|
|
||||||
bool
|
|
||||||
get_tx_hash_from_output_pubkey(const public_key& output_pubkey,
|
|
||||||
const uint64_t& block_height,
|
|
||||||
crypto::hash& tx_hash,
|
|
||||||
transaction& tx_found);
|
|
||||||
|
|
||||||
uint64_t
|
uint64_t
|
||||||
get_blk_timestamp(uint64_t blk_height);
|
get_blk_timestamp(uint64_t blk_height);
|
||||||
|
|
||||||
|
bool
|
||||||
|
get_block_complete_entry(block const& b, block_complete_entry& bce);
|
||||||
|
|
||||||
string
|
string
|
||||||
get_blkchain_path();
|
get_blkchain_path();
|
||||||
|
|
||||||
|
|
528
src/page.h
528
src/page.h
|
@ -30,6 +30,7 @@
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <future>
|
#include <future>
|
||||||
|
#include <visitor/render_node.hpp>
|
||||||
|
|
||||||
|
|
||||||
#define TMPL_DIR "./templates"
|
#define TMPL_DIR "./templates"
|
||||||
|
@ -66,7 +67,7 @@
|
||||||
#define JS_SHA3 TMPL_DIR "/js/sha3.js"
|
#define JS_SHA3 TMPL_DIR "/js/sha3.js"
|
||||||
|
|
||||||
#define ONIONEXPLORER_RPC_VERSION_MAJOR 1
|
#define ONIONEXPLORER_RPC_VERSION_MAJOR 1
|
||||||
#define ONIONEXPLORER_RPC_VERSION_MINOR 0
|
#define ONIONEXPLORER_RPC_VERSION_MINOR 1
|
||||||
#define MAKE_ONIONEXPLORER_RPC_VERSION(major,minor) (((major)<<16)|(minor))
|
#define MAKE_ONIONEXPLORER_RPC_VERSION(major,minor) (((major)<<16)|(minor))
|
||||||
#define ONIONEXPLORER_RPC_VERSION \
|
#define ONIONEXPLORER_RPC_VERSION \
|
||||||
MAKE_ONIONEXPLORER_RPC_VERSION(ONIONEXPLORER_RPC_VERSION_MAJOR, ONIONEXPLORER_RPC_VERSION_MINOR)
|
MAKE_ONIONEXPLORER_RPC_VERSION(ONIONEXPLORER_RPC_VERSION_MAJOR, ONIONEXPLORER_RPC_VERSION_MINOR)
|
||||||
|
@ -113,6 +114,71 @@ namespace std
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* visitor to produce json representations of
|
||||||
|
* values stored in mstch::node
|
||||||
|
*/
|
||||||
|
class mstch_node_to_json: public boost::static_visitor<nlohmann::json>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
|
||||||
|
// enabled for numeric types
|
||||||
|
template<typename T>
|
||||||
|
typename std::enable_if<std::is_arithmetic<T>::value, nlohmann::json>::type
|
||||||
|
operator()(T const& value) const {
|
||||||
|
return nlohmann::json {value};
|
||||||
|
}
|
||||||
|
|
||||||
|
nlohmann::json operator()(std::string const& value) const {
|
||||||
|
return nlohmann::json {value};
|
||||||
|
}
|
||||||
|
|
||||||
|
nlohmann::json operator()(mstch::map const& n_map) const
|
||||||
|
{
|
||||||
|
nlohmann::json j;
|
||||||
|
|
||||||
|
for (auto const& kv: n_map)
|
||||||
|
j[kv.first] = boost::apply_visitor(mstch_node_to_json(), kv.second);
|
||||||
|
|
||||||
|
return j;
|
||||||
|
}
|
||||||
|
|
||||||
|
nlohmann::json operator()(mstch::array const& n_array) const
|
||||||
|
{
|
||||||
|
nlohmann::json j;
|
||||||
|
|
||||||
|
for (auto const& v: n_array)
|
||||||
|
j.push_back(boost::apply_visitor(mstch_node_to_json(), v));
|
||||||
|
|
||||||
|
return j;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// catch other types that are non-numeric and not listed above
|
||||||
|
template<typename T>
|
||||||
|
typename std::enable_if<!std::is_arithmetic<T>::value, nlohmann::json>::type
|
||||||
|
operator()(const T&) const {
|
||||||
|
return nlohmann::json {};
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace mstch
|
||||||
|
{
|
||||||
|
namespace internal
|
||||||
|
{
|
||||||
|
// add conversion from mstch::map to nlohmann::json
|
||||||
|
void
|
||||||
|
to_json(nlohmann::json& j, mstch::map const &m)
|
||||||
|
{
|
||||||
|
for (auto const& kv: m)
|
||||||
|
j[kv.first] = boost::apply_visitor(mstch_node_to_json(), kv.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
namespace xmreg
|
namespace xmreg
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -124,6 +190,8 @@ using namespace std;
|
||||||
using epee::string_tools::pod_to_hex;
|
using epee::string_tools::pod_to_hex;
|
||||||
using epee::string_tools::hex_to_pod;
|
using epee::string_tools::hex_to_pod;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The tx_details struct
|
* @brief The tx_details struct
|
||||||
*
|
*
|
||||||
|
@ -189,8 +257,8 @@ struct tx_details
|
||||||
|
|
||||||
mixin_str = std::to_string(mixin_no);
|
mixin_str = std::to_string(mixin_no);
|
||||||
fee_str = fmt::format("{:0.6f}", xmr_amount);
|
fee_str = fmt::format("{:0.6f}", xmr_amount);
|
||||||
fee_short_str = fmt::format("{:0.3f}", xmr_amount);
|
fee_short_str = fmt::format("{:0.4f}", xmr_amount);
|
||||||
payed_for_kB_str = fmt::format("{:0.3f}", payed_for_kB);
|
payed_for_kB_str = fmt::format("{:0.4f}", payed_for_kB);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -298,6 +366,7 @@ class page
|
||||||
bool enable_mixins_details;
|
bool enable_mixins_details;
|
||||||
bool enable_tx_cache;
|
bool enable_tx_cache;
|
||||||
bool enable_block_cache;
|
bool enable_block_cache;
|
||||||
|
bool enable_as_hex;
|
||||||
bool show_cache_times;
|
bool show_cache_times;
|
||||||
|
|
||||||
|
|
||||||
|
@ -348,6 +417,7 @@ public:
|
||||||
cryptonote::network_type _nettype,
|
cryptonote::network_type _nettype,
|
||||||
bool _enable_pusher,
|
bool _enable_pusher,
|
||||||
bool _enable_js,
|
bool _enable_js,
|
||||||
|
bool _enable_as_hex,
|
||||||
bool _enable_key_image_checker,
|
bool _enable_key_image_checker,
|
||||||
bool _enable_output_key_checker,
|
bool _enable_output_key_checker,
|
||||||
bool _enable_autorefresh_option,
|
bool _enable_autorefresh_option,
|
||||||
|
@ -367,6 +437,7 @@ public:
|
||||||
nettype {_nettype},
|
nettype {_nettype},
|
||||||
enable_pusher {_enable_pusher},
|
enable_pusher {_enable_pusher},
|
||||||
enable_js {_enable_js},
|
enable_js {_enable_js},
|
||||||
|
enable_as_hex {_enable_as_hex},
|
||||||
enable_key_image_checker {_enable_key_image_checker},
|
enable_key_image_checker {_enable_key_image_checker},
|
||||||
enable_output_key_checker {_enable_output_key_checker},
|
enable_output_key_checker {_enable_output_key_checker},
|
||||||
enable_autorefresh_option {_enable_autorefresh_option},
|
enable_autorefresh_option {_enable_autorefresh_option},
|
||||||
|
@ -512,12 +583,12 @@ public:
|
||||||
|
|
||||||
uint64_t local_copy_server_timestamp = server_timestamp;
|
uint64_t local_copy_server_timestamp = server_timestamp;
|
||||||
|
|
||||||
// number of last blocks to show
|
|
||||||
uint64_t no_of_last_blocks {no_blocks_on_index + 1};
|
|
||||||
|
|
||||||
// get the current blockchain height. Just to check
|
// get the current blockchain height. Just to check
|
||||||
uint64_t height = core_storage->get_current_blockchain_height();
|
uint64_t height = core_storage->get_current_blockchain_height();
|
||||||
|
|
||||||
|
// number of last blocks to show
|
||||||
|
uint64_t no_of_last_blocks = std::min(no_blocks_on_index + 1, height);
|
||||||
|
|
||||||
// initalise page tempate map with basic info about blockchain
|
// initalise page tempate map with basic info about blockchain
|
||||||
mstch::map context {
|
mstch::map context {
|
||||||
{"testnet" , testnet},
|
{"testnet" , testnet},
|
||||||
|
@ -583,7 +654,7 @@ public:
|
||||||
crypto::hash blk_hash = core_storage->get_block_id_by_height(i);
|
crypto::hash blk_hash = core_storage->get_block_id_by_height(i);
|
||||||
|
|
||||||
// get block size in kB
|
// get block size in kB
|
||||||
double blk_size = static_cast<double>(core_storage->get_db().get_block_size(i))/1024.0;
|
double blk_size = static_cast<double>(core_storage->get_db().get_block_weight(i))/1024.0;
|
||||||
|
|
||||||
string blk_size_str = fmt::format("{:0.2f}", blk_size);
|
string blk_size_str = fmt::format("{:0.2f}", blk_size);
|
||||||
|
|
||||||
|
@ -716,8 +787,8 @@ public:
|
||||||
// get all transactions in the block found
|
// get all transactions in the block found
|
||||||
// initialize the first list with transaction for solving
|
// initialize the first list with transaction for solving
|
||||||
// the block i.e. coinbase.
|
// the block i.e. coinbase.
|
||||||
list<cryptonote::transaction> blk_txs {blk.miner_tx};
|
vector<cryptonote::transaction> blk_txs {blk.miner_tx};
|
||||||
list<crypto::hash> missed_txs;
|
vector<crypto::hash> missed_txs;
|
||||||
|
|
||||||
if (!core_storage->get_transactions(blk.tx_hashes, blk_txs, missed_txs))
|
if (!core_storage->get_transactions(blk.tx_hashes, blk_txs, missed_txs))
|
||||||
{
|
{
|
||||||
|
@ -814,14 +885,12 @@ public:
|
||||||
// perapre network info mstch::map for the front page
|
// perapre network info mstch::map for the front page
|
||||||
string hash_rate;
|
string hash_rate;
|
||||||
|
|
||||||
if (testnet || stagenet)
|
if (current_network_info.hash_rate > 1e6)
|
||||||
{
|
|
||||||
hash_rate = std::to_string(current_network_info.hash_rate) + " H/s";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
hash_rate = fmt::format("{:0.3f} MH/s", current_network_info.hash_rate/1.0e6);
|
hash_rate = fmt::format("{:0.3f} MH/s", current_network_info.hash_rate/1.0e6);
|
||||||
}
|
else if (current_network_info.hash_rate > 1e3)
|
||||||
|
hash_rate = fmt::format("{:0.3f} kH/s", current_network_info.hash_rate/1.0e3);
|
||||||
|
else
|
||||||
|
hash_rate = fmt::format("{:d} H/s", current_network_info.hash_rate);
|
||||||
|
|
||||||
pair<string, string> network_info_age = get_age(local_copy_server_timestamp,
|
pair<string, string> network_info_age = get_age(local_copy_server_timestamp,
|
||||||
current_network_info.info_timestamp);
|
current_network_info.info_timestamp);
|
||||||
|
@ -1157,7 +1226,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// get block size in bytes
|
// get block size in bytes
|
||||||
uint64_t blk_size = core_storage->get_db().get_block_size(_blk_height);
|
uint64_t blk_size = core_storage->get_db().get_block_weight(_blk_height);
|
||||||
|
|
||||||
// miner reward tx
|
// miner reward tx
|
||||||
transaction coinbase_tx = blk.miner_tx;
|
transaction coinbase_tx = blk.miner_tx;
|
||||||
|
@ -1175,6 +1244,10 @@ public:
|
||||||
_blk_height, current_blockchain_height);
|
_blk_height, current_blockchain_height);
|
||||||
|
|
||||||
// initalise page tempate map with basic info about blockchain
|
// initalise page tempate map with basic info about blockchain
|
||||||
|
|
||||||
|
string blk_pow_hash_str = pod_to_hex(get_block_longhash(blk, _blk_height));
|
||||||
|
uint64_t blk_difficulty = core_storage->get_db().get_block_difficulty(_blk_height);
|
||||||
|
|
||||||
mstch::map context {
|
mstch::map context {
|
||||||
{"testnet" , testnet},
|
{"testnet" , testnet},
|
||||||
{"stagenet" , stagenet},
|
{"stagenet" , stagenet},
|
||||||
|
@ -1184,6 +1257,7 @@ public:
|
||||||
{"blk_timestamp_epoch" , blk.timestamp},
|
{"blk_timestamp_epoch" , blk.timestamp},
|
||||||
{"prev_hash" , prev_hash_str},
|
{"prev_hash" , prev_hash_str},
|
||||||
{"next_hash" , next_hash_str},
|
{"next_hash" , next_hash_str},
|
||||||
|
{"enable_as_hex" , enable_as_hex},
|
||||||
{"have_next_hash" , have_next_hash},
|
{"have_next_hash" , have_next_hash},
|
||||||
{"have_prev_hash" , have_prev_hash},
|
{"have_prev_hash" , have_prev_hash},
|
||||||
{"have_txs" , have_txs},
|
{"have_txs" , have_txs},
|
||||||
|
@ -1192,6 +1266,8 @@ public:
|
||||||
{"blk_age" , age.first},
|
{"blk_age" , age.first},
|
||||||
{"delta_time" , delta_time},
|
{"delta_time" , delta_time},
|
||||||
{"blk_nonce" , blk.nonce},
|
{"blk_nonce" , blk.nonce},
|
||||||
|
{"blk_pow_hash" , blk_pow_hash_str},
|
||||||
|
{"blk_difficulty" , blk_difficulty},
|
||||||
{"age_format" , age.second},
|
{"age_format" , age.second},
|
||||||
{"major_ver" , std::to_string(blk.major_version)},
|
{"major_ver" , std::to_string(blk.major_version)},
|
||||||
{"minor_ver" , std::to_string(blk.minor_version)},
|
{"minor_ver" , std::to_string(blk.minor_version)},
|
||||||
|
@ -1524,6 +1600,152 @@ public:
|
||||||
return mstch::render(template_file["tx"], context, partials);
|
return mstch::render(template_file["tx"], context, partials);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string
|
||||||
|
show_tx_hex(string tx_hash_str)
|
||||||
|
{
|
||||||
|
transaction tx;
|
||||||
|
crypto::hash tx_hash;
|
||||||
|
|
||||||
|
if (!get_tx(tx_hash_str, tx, tx_hash))
|
||||||
|
return string {"Cant get tx: "} + tx_hash_str;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return tx_to_hex(tx);
|
||||||
|
}
|
||||||
|
catch (std::exception const& e)
|
||||||
|
{
|
||||||
|
cerr << e.what() << endl;
|
||||||
|
return string {"Failed to obtain hex of tx due to: "} + e.what();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string
|
||||||
|
show_block_hex(size_t block_height, bool complete_blk)
|
||||||
|
{
|
||||||
|
|
||||||
|
// get transaction
|
||||||
|
block blk;
|
||||||
|
|
||||||
|
if (!mcore->get_block_by_height(block_height, blk))
|
||||||
|
{
|
||||||
|
cerr << "Cant get block in blockchain: " << block_height
|
||||||
|
<< ". \n Check mempool now\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (complete_blk == false)
|
||||||
|
{
|
||||||
|
// get only block data as hex
|
||||||
|
|
||||||
|
return epee::string_tools::buff_to_hex_nodelimer(
|
||||||
|
t_serializable_object_to_blob(blk));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// get block_complete_entry (block and its txs) as hex
|
||||||
|
|
||||||
|
block_complete_entry complete_block_data;
|
||||||
|
|
||||||
|
if (!mcore->get_block_complete_entry(blk, complete_block_data))
|
||||||
|
{
|
||||||
|
cerr << "Failed to obtain complete block data " << endl;
|
||||||
|
return string {"Failed to obtain complete block data "};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string complete_block_data_str;
|
||||||
|
|
||||||
|
if(!epee::serialization::store_t_to_binary(
|
||||||
|
complete_block_data, complete_block_data_str))
|
||||||
|
{
|
||||||
|
cerr << "Failed to serialize complete_block_data\n";
|
||||||
|
return string {"Failed to obtain complete block data"};
|
||||||
|
}
|
||||||
|
|
||||||
|
return epee::string_tools
|
||||||
|
::buff_to_hex_nodelimer(complete_block_data_str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (std::exception const& e)
|
||||||
|
{
|
||||||
|
cerr << e.what() << endl;
|
||||||
|
return string {"Failed to obtain hex of a block due to: "} + e.what();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string
|
||||||
|
show_ringmembers_hex(string const& tx_hash_str)
|
||||||
|
{
|
||||||
|
transaction tx;
|
||||||
|
crypto::hash tx_hash;
|
||||||
|
|
||||||
|
if (!get_tx(tx_hash_str, tx, tx_hash))
|
||||||
|
return string {"Cant get tx: "} + tx_hash_str;
|
||||||
|
|
||||||
|
vector<txin_to_key> input_key_imgs = xmreg::get_key_images(tx);
|
||||||
|
|
||||||
|
// key: vector of absolute_offsets and associated amount (last value),
|
||||||
|
// value: vector of output_info_of_mixins
|
||||||
|
std::map<vector<uint64_t>, vector<string>> all_mixin_outputs;
|
||||||
|
|
||||||
|
// make timescale maps for mixins in input
|
||||||
|
for (txin_to_key const& in_key: input_key_imgs)
|
||||||
|
{
|
||||||
|
// get absolute offsets of mixins
|
||||||
|
std::vector<uint64_t> 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<cryptonote::output_data_t> mixin_outputs;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// before proceeding with geting the outputs based on
|
||||||
|
// the amount and absolute offset
|
||||||
|
// check how many outputs there are for that amount
|
||||||
|
// go to next input if a too large offset was found
|
||||||
|
if (are_absolute_offsets_good(absolute_offsets, in_key)
|
||||||
|
== false)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
core_storage->get_db().get_output_key(in_key.amount,
|
||||||
|
absolute_offsets,
|
||||||
|
mixin_outputs);
|
||||||
|
}
|
||||||
|
catch (OUTPUT_DNE const& e)
|
||||||
|
{
|
||||||
|
cerr << "get_output_keys: " << e.what() << endl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add accociated amount to these offsets so that we can differentiate
|
||||||
|
// between same offsets, but for different amounts
|
||||||
|
absolute_offsets.push_back(in_key.amount);
|
||||||
|
|
||||||
|
for (auto const& mo: mixin_outputs)
|
||||||
|
all_mixin_outputs[absolute_offsets].emplace_back(pod_to_hex(mo));
|
||||||
|
|
||||||
|
} // for (txin_to_key const& in_key: input_key_imgs)
|
||||||
|
|
||||||
|
if (all_mixin_outputs.empty())
|
||||||
|
return string {"No ring members to serialize"};
|
||||||
|
|
||||||
|
// archive all_mixin_outputs vector
|
||||||
|
std::ostringstream oss;
|
||||||
|
boost::archive::portable_binary_oarchive archive(oss);
|
||||||
|
archive << all_mixin_outputs;
|
||||||
|
|
||||||
|
// return as all_mixin_outputs vector hex
|
||||||
|
return epee::string_tools
|
||||||
|
::buff_to_hex_nodelimer(oss.str());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
string
|
string
|
||||||
show_my_outputs(string tx_hash_str,
|
show_my_outputs(string tx_hash_str,
|
||||||
string xmr_address_str,
|
string xmr_address_str,
|
||||||
|
@ -1726,9 +1948,9 @@ public:
|
||||||
|
|
||||||
string shortcut_url = domain
|
string shortcut_url = domain
|
||||||
+ (tx_prove ? "/prove" : "/myoutputs")
|
+ (tx_prove ? "/prove" : "/myoutputs")
|
||||||
+ "/" + tx_hash_str
|
+ '/' + tx_hash_str
|
||||||
+ "/" + xmr_address_str
|
+ '/' + xmr_address_str
|
||||||
+ "/" + viewkey_str;
|
+ '/' + viewkey_str;
|
||||||
|
|
||||||
|
|
||||||
string viewkey_str_partial = viewkey_str;
|
string viewkey_str_partial = viewkey_str;
|
||||||
|
@ -1771,9 +1993,8 @@ public:
|
||||||
key_derivation derivation;
|
key_derivation derivation;
|
||||||
std::vector<key_derivation> additional_derivations(txd.additional_pks.size());
|
std::vector<key_derivation> additional_derivations(txd.additional_pks.size());
|
||||||
|
|
||||||
//cout << multiple_tx_secret_keys.size() << " " << txd.additional_pks.size() + 1 << '\n';
|
if (tx_prove && multiple_tx_secret_keys.size()
|
||||||
|
!= txd.additional_pks.size() + 1)
|
||||||
if (tx_prove && multiple_tx_secret_keys.size() != txd.additional_pks.size() + 1)
|
|
||||||
{
|
{
|
||||||
return string("This transaction includes additional tx pubkeys whose "
|
return string("This transaction includes additional tx pubkeys whose "
|
||||||
"size doesn't match with the provided tx secret keys");
|
"size doesn't match with the provided tx secret keys");
|
||||||
|
@ -1813,7 +2034,8 @@ public:
|
||||||
|
|
||||||
if (decrypted_payment_id8 != null_hash8)
|
if (decrypted_payment_id8 != null_hash8)
|
||||||
{
|
{
|
||||||
if (mcore->get_device()->decrypt_payment_id(decrypted_payment_id8, pub_key, prv_view_key))
|
if (mcore->get_device()->decrypt_payment_id(
|
||||||
|
decrypted_payment_id8, pub_key, prv_view_key))
|
||||||
{
|
{
|
||||||
context["decrypted_payment_id8"] = pod_to_hex(decrypted_payment_id8);
|
context["decrypted_payment_id8"] = pod_to_hex(decrypted_payment_id8);
|
||||||
}
|
}
|
||||||
|
@ -1850,7 +2072,8 @@ public:
|
||||||
|
|
||||||
bool with_additional = false;
|
bool with_additional = false;
|
||||||
|
|
||||||
if (!mine_output && txd.additional_pks.size() == txd.output_pub_keys.size())
|
if (!mine_output && txd.additional_pks.size()
|
||||||
|
== txd.output_pub_keys.size())
|
||||||
{
|
{
|
||||||
derive_public_key(additional_derivations[output_idx],
|
derive_public_key(additional_derivations[output_idx],
|
||||||
output_idx,
|
output_idx,
|
||||||
|
@ -1875,15 +2098,17 @@ public:
|
||||||
|
|
||||||
bool r;
|
bool r;
|
||||||
|
|
||||||
r = decode_ringct(tx.rct_signatures,
|
r = decode_ringct(
|
||||||
with_additional ? additional_derivations[output_idx] : derivation,
|
tx.rct_signatures,
|
||||||
|
with_additional
|
||||||
|
? additional_derivations[output_idx] : derivation,
|
||||||
output_idx,
|
output_idx,
|
||||||
tx.rct_signatures.ecdhInfo[output_idx].mask,
|
tx.rct_signatures.ecdhInfo[output_idx].mask,
|
||||||
rct_amount);
|
rct_amount);
|
||||||
|
|
||||||
if (!r)
|
if (!r)
|
||||||
{
|
{
|
||||||
cerr << "\nshow_my_outputs: Cant decode ringCT! " << endl;
|
cerr << "\nshow_my_outputs: Cant decode RingCT!\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
outp.second = rct_amount;
|
outp.second = rct_amount;
|
||||||
|
@ -1927,9 +2152,14 @@ public:
|
||||||
// parefct matches must be equal to number of inputs in a tx.
|
// parefct matches must be equal to number of inputs in a tx.
|
||||||
uint64_t no_of_matched_mixins {0};
|
uint64_t no_of_matched_mixins {0};
|
||||||
|
|
||||||
|
// Hold all possible mixins that we found. This is only used so that
|
||||||
|
// we get number of all posibilities, and their total xmr amount
|
||||||
|
// (useful for unit testing)
|
||||||
|
// public_key , amount
|
||||||
|
std::vector<std::pair<crypto::public_key, uint64_t>> all_possible_mixins;
|
||||||
|
|
||||||
for (const txin_to_key& in_key: input_key_imgs)
|
for (const txin_to_key& in_key: input_key_imgs)
|
||||||
{
|
{
|
||||||
|
|
||||||
// get absolute offsets of mixins
|
// get absolute offsets of mixins
|
||||||
std::vector<uint64_t> absolute_offsets
|
std::vector<uint64_t> absolute_offsets
|
||||||
= cryptonote::relative_output_offsets_to_absolute(
|
= cryptonote::relative_output_offsets_to_absolute(
|
||||||
|
@ -1941,7 +2171,8 @@ public:
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// before proceeding with geting the outputs based on the amount and absolute offset
|
// before proceeding with geting the outputs based on
|
||||||
|
// the amount and absolute offset
|
||||||
// check how many outputs there are for that amount
|
// check how many outputs there are for that amount
|
||||||
// go to next input if a too large offset was found
|
// go to next input if a too large offset was found
|
||||||
if (are_absolute_offsets_good(absolute_offsets, in_key) == false)
|
if (are_absolute_offsets_good(absolute_offsets, in_key) == false)
|
||||||
|
@ -2009,10 +2240,9 @@ public:
|
||||||
|
|
||||||
string out_msg = fmt::format(
|
string out_msg = fmt::format(
|
||||||
"Output with amount {:d} and index {:d} does not exist!",
|
"Output with amount {:d} and index {:d} does not exist!",
|
||||||
in_key.amount, abs_offset
|
in_key.amount, abs_offset);
|
||||||
);
|
|
||||||
|
|
||||||
cerr << out_msg << endl;
|
cerr << out_msg << '\n';
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2028,7 +2258,6 @@ public:
|
||||||
if (!mcore->get_tx(tx_out_idx.first, mixin_tx))
|
if (!mcore->get_tx(tx_out_idx.first, mixin_tx))
|
||||||
{
|
{
|
||||||
cerr << "Cant get tx: " << tx_out_idx.first << endl;
|
cerr << "Cant get tx: " << tx_out_idx.first << endl;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2036,33 +2265,35 @@ public:
|
||||||
|
|
||||||
mixins.push_back(mstch::map{
|
mixins.push_back(mstch::map{
|
||||||
{"mixin_pub_key" , out_pub_key_str},
|
{"mixin_pub_key" , out_pub_key_str},
|
||||||
make_pair<string, mstch::array>("mixin_outputs" , mstch::array{}),
|
make_pair<string, mstch::array>("mixin_outputs"
|
||||||
{"has_mixin_outputs" , false}
|
, mstch::array{}),
|
||||||
});
|
{"has_mixin_outputs" , false}});
|
||||||
|
|
||||||
mstch::array& mixin_outputs = boost::get<mstch::array>(
|
mstch::array& mixin_outputs = boost::get<mstch::array>(
|
||||||
boost::get<mstch::map>(mixins.back())["mixin_outputs"]
|
boost::get<mstch::map>(mixins.back())["mixin_outputs"]);
|
||||||
);
|
|
||||||
|
|
||||||
mstch::node& has_mixin_outputs
|
mstch::node& has_mixin_outputs
|
||||||
= boost::get<mstch::map>(mixins.back())["has_mixin_outputs"];
|
= boost::get<mstch::map>(mixins.back())["has_mixin_outputs"];
|
||||||
|
|
||||||
|
|
||||||
bool found_something {false};
|
bool found_something {false};
|
||||||
|
|
||||||
|
|
||||||
public_key mixin_tx_pub_key
|
public_key mixin_tx_pub_key
|
||||||
= xmreg::get_tx_pub_key_from_received_outs(mixin_tx);
|
= xmreg::get_tx_pub_key_from_received_outs(mixin_tx);
|
||||||
std::vector<public_key> mixin_additional_tx_pub_keys = cryptonote::get_additional_tx_pub_keys_from_extra(mixin_tx);
|
|
||||||
|
std::vector<public_key> mixin_additional_tx_pub_keys
|
||||||
|
= cryptonote::get_additional_tx_pub_keys_from_extra(mixin_tx);
|
||||||
|
|
||||||
string mixin_tx_pub_key_str = pod_to_hex(mixin_tx_pub_key);
|
string mixin_tx_pub_key_str = pod_to_hex(mixin_tx_pub_key);
|
||||||
|
|
||||||
// public transaction key is combined with our viewkey
|
// public transaction key is combined with our viewkey
|
||||||
// to create, so called, derived key.
|
// to create, so called, derived key.
|
||||||
key_derivation derivation;
|
key_derivation derivation;
|
||||||
std::vector<key_derivation> additional_derivations(mixin_additional_tx_pub_keys.size());
|
|
||||||
|
|
||||||
if (!generate_key_derivation(mixin_tx_pub_key, prv_view_key, derivation))
|
std::vector<key_derivation> additional_derivations(
|
||||||
|
mixin_additional_tx_pub_keys.size());
|
||||||
|
|
||||||
|
if (!generate_key_derivation(mixin_tx_pub_key,
|
||||||
|
prv_view_key, derivation))
|
||||||
{
|
{
|
||||||
cerr << "Cant get derived key for: " << "\n"
|
cerr << "Cant get derived key for: " << "\n"
|
||||||
<< "pub_tx_key: " << mixin_tx_pub_key << " and "
|
<< "pub_tx_key: " << mixin_tx_pub_key << " and "
|
||||||
|
@ -2072,11 +2303,13 @@ public:
|
||||||
}
|
}
|
||||||
for (size_t i = 0; i < mixin_additional_tx_pub_keys.size(); ++i)
|
for (size_t i = 0; i < mixin_additional_tx_pub_keys.size(); ++i)
|
||||||
{
|
{
|
||||||
if (!generate_key_derivation(mixin_additional_tx_pub_keys[i], prv_view_key, additional_derivations[i]))
|
if (!generate_key_derivation(mixin_additional_tx_pub_keys[i],
|
||||||
|
prv_view_key,
|
||||||
|
additional_derivations[i]))
|
||||||
{
|
{
|
||||||
cerr << "Cant get derived key for: " << "\n"
|
cerr << "Cant get derived key for: " << "\n"
|
||||||
<< "pub_tx_key: " << mixin_additional_tx_pub_keys[i] << " and "
|
<< "pub_tx_key: " << mixin_additional_tx_pub_keys[i]
|
||||||
<< "prv_view_key" << prv_view_key << endl;
|
<< " and prv_view_key" << prv_view_key << endl;
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -2090,23 +2323,28 @@ public:
|
||||||
mixin_outputs.push_back(mstch::map{
|
mixin_outputs.push_back(mstch::map{
|
||||||
{"mix_tx_hash" , mixin_tx_hash_str},
|
{"mix_tx_hash" , mixin_tx_hash_str},
|
||||||
{"mix_tx_pub_key" , mixin_tx_pub_key_str},
|
{"mix_tx_pub_key" , mixin_tx_pub_key_str},
|
||||||
make_pair<string, mstch::array>("found_outputs" , mstch::array{}),
|
make_pair<string, mstch::array>("found_outputs"
|
||||||
|
, mstch::array{}),
|
||||||
{"has_found_outputs", false}
|
{"has_found_outputs", false}
|
||||||
});
|
});
|
||||||
|
|
||||||
mstch::array& found_outputs = boost::get<mstch::array>(
|
mstch::array& found_outputs = boost::get<mstch::array>(
|
||||||
boost::get<mstch::map>(mixin_outputs.back())["found_outputs"]
|
boost::get<mstch::map>(
|
||||||
|
mixin_outputs.back())["found_outputs"]
|
||||||
);
|
);
|
||||||
|
|
||||||
mstch::node& has_found_outputs
|
mstch::node& has_found_outputs
|
||||||
= boost::get<mstch::map>(mixin_outputs.back())["has_found_outputs"];
|
= boost::get<mstch::map>(
|
||||||
|
mixin_outputs.back())["has_found_outputs"];
|
||||||
|
|
||||||
|
uint64_t ringct_amount {0};
|
||||||
|
|
||||||
// for each output in mixin tx, find the one from key_image
|
// for each output in mixin tx, find the one from key_image
|
||||||
// and check if its ours.
|
// and check if its ours.
|
||||||
for (const auto& mix_out: output_pub_keys)
|
for (const auto& mix_out: output_pub_keys)
|
||||||
{
|
{
|
||||||
|
|
||||||
txout_to_key txout_k = std::get<0>(mix_out);
|
txout_to_key const& txout_k = std::get<0>(mix_out);
|
||||||
uint64_t amount = std::get<1>(mix_out);
|
uint64_t amount = std::get<1>(mix_out);
|
||||||
uint64_t output_idx_in_tx = std::get<2>(mix_out);
|
uint64_t output_idx_in_tx = std::get<2>(mix_out);
|
||||||
|
|
||||||
|
@ -2131,14 +2369,19 @@ public:
|
||||||
|
|
||||||
// check if generated public key matches the current output's key
|
// check if generated public key matches the current output's key
|
||||||
bool mine_output = (txout_k.key == tx_pubkey_generated);
|
bool mine_output = (txout_k.key == tx_pubkey_generated);
|
||||||
|
|
||||||
bool with_additional = false;
|
bool with_additional = false;
|
||||||
if (!mine_output && mixin_additional_tx_pub_keys.size() == output_pub_keys.size())
|
|
||||||
|
if (!mine_output && mixin_additional_tx_pub_keys.size()
|
||||||
|
== output_pub_keys.size())
|
||||||
{
|
{
|
||||||
derive_public_key(additional_derivations[output_idx_in_tx],
|
derive_public_key(additional_derivations[output_idx_in_tx],
|
||||||
output_idx_in_tx,
|
output_idx_in_tx,
|
||||||
address_info.address.m_spend_public_key,
|
address_info.address.m_spend_public_key,
|
||||||
tx_pubkey_generated);
|
tx_pubkey_generated);
|
||||||
|
|
||||||
mine_output = (txout_k.key == tx_pubkey_generated);
|
mine_output = (txout_k.key == tx_pubkey_generated);
|
||||||
|
|
||||||
with_additional = true;
|
with_additional = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2154,16 +2397,17 @@ public:
|
||||||
|
|
||||||
bool r;
|
bool r;
|
||||||
|
|
||||||
r = decode_ringct(mixin_tx.rct_signatures,
|
r = decode_ringct(
|
||||||
with_additional ? additional_derivations[output_idx_in_tx] : derivation,
|
mixin_tx.rct_signatures,
|
||||||
|
with_additional
|
||||||
|
? additional_derivations[output_idx_in_tx] : derivation,
|
||||||
output_idx_in_tx,
|
output_idx_in_tx,
|
||||||
mixin_tx.rct_signatures.ecdhInfo[output_idx_in_tx].mask,
|
mixin_tx.rct_signatures.ecdhInfo[output_idx_in_tx].mask,
|
||||||
rct_amount);
|
rct_amount);
|
||||||
|
|
||||||
if (!r)
|
if (!r)
|
||||||
{
|
cerr << "show_my_outputs: key images: "
|
||||||
cerr << "show_my_outputs: key images: Cant decode ringCT!" << endl;
|
"Cant decode RingCT!\n";
|
||||||
}
|
|
||||||
|
|
||||||
amount = rct_amount;
|
amount = rct_amount;
|
||||||
|
|
||||||
|
@ -2190,11 +2434,9 @@ public:
|
||||||
});
|
});
|
||||||
|
|
||||||
//cout << "txout_k.key == output_data.pubkey" << endl;
|
//cout << "txout_k.key == output_data.pubkey" << endl;
|
||||||
//cout << pod_to_hex(txout_k.key) << " == " << pod_to_hex(output_data.pubkey) << endl;
|
|
||||||
|
|
||||||
if (mine_output)
|
if (mine_output)
|
||||||
{
|
{
|
||||||
|
|
||||||
found_something = true;
|
found_something = true;
|
||||||
show_key_images = true;
|
show_key_images = true;
|
||||||
|
|
||||||
|
@ -2202,9 +2444,7 @@ public:
|
||||||
// public key of an outputs used in ring signature,
|
// public key of an outputs used in ring signature,
|
||||||
// matches a public key in a mixin_tx
|
// matches a public key in a mixin_tx
|
||||||
if (txout_k.key != output_data.pubkey)
|
if (txout_k.key != output_data.pubkey)
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
// sum up only first output matched found in each input
|
// sum up only first output matched found in each input
|
||||||
if (no_of_output_matches_found == 0)
|
if (no_of_output_matches_found == 0)
|
||||||
|
@ -2222,6 +2462,7 @@ public:
|
||||||
else if (mixin_tx.version == 2) // ringct
|
else if (mixin_tx.version == 2) // ringct
|
||||||
{
|
{
|
||||||
sum_mixin_xmr += amount;
|
sum_mixin_xmr += amount;
|
||||||
|
ringct_amount += amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
no_of_matched_mixins++;
|
no_of_matched_mixins++;
|
||||||
|
@ -2247,11 +2488,9 @@ public:
|
||||||
// << ", key_img == input_key: " << (key_img == in_key.k_image)
|
// << ", key_img == input_key: " << (key_img == in_key.k_image)
|
||||||
// << endl;
|
// << endl;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
no_of_output_matches_found++;
|
no_of_output_matches_found++;
|
||||||
|
|
||||||
}
|
} // if (mine_output)
|
||||||
|
|
||||||
} // for (const pair<txout_to_key, uint64_t>& mix_out: txd.output_pub_keys)
|
} // for (const pair<txout_to_key, uint64_t>& mix_out: txd.output_pub_keys)
|
||||||
|
|
||||||
|
@ -2259,12 +2498,17 @@ public:
|
||||||
|
|
||||||
has_mixin_outputs = found_something;
|
has_mixin_outputs = found_something;
|
||||||
|
|
||||||
|
// all_possible_mixins_amount += amount;
|
||||||
|
|
||||||
|
if (found_something)
|
||||||
|
all_possible_mixins.push_back(
|
||||||
|
{mixin_tx_pub_key,
|
||||||
|
in_key.amount == 0 ? ringct_amount : in_key.amount});
|
||||||
|
|
||||||
++count;
|
++count;
|
||||||
|
|
||||||
} // for (const cryptonote::output_data_t& output_data: mixin_outputs)
|
} // for (const cryptonote::output_data_t& output_data: mixin_outputs)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // for (const txin_to_key& in_key: input_key_imgs)
|
} // for (const txin_to_key& in_key: input_key_imgs)
|
||||||
|
|
||||||
|
|
||||||
|
@ -2283,6 +2527,23 @@ public:
|
||||||
|
|
||||||
uint64_t possible_spending {0};
|
uint64_t possible_spending {0};
|
||||||
|
|
||||||
|
//cout << "\nall_possible_mixins: " << all_possible_mixins.size() << '\n';
|
||||||
|
|
||||||
|
// useful for unit testing as it provides total xmr sum
|
||||||
|
// of possible mixins
|
||||||
|
uint64_t all_possible_mixins_amount1 {0};
|
||||||
|
|
||||||
|
for (auto& p: all_possible_mixins)
|
||||||
|
all_possible_mixins_amount1 += p.second;
|
||||||
|
|
||||||
|
//cout << "\all_possible_mixins_amount: " << all_possible_mixins_amount1 << '\n';
|
||||||
|
|
||||||
|
//cout << "\nmixins: " << mix << '\n';
|
||||||
|
|
||||||
|
context["no_all_possible_mixins"] = static_cast<uint64_t>(all_possible_mixins.size());
|
||||||
|
context["all_possible_mixins_amount"] = all_possible_mixins_amount1;
|
||||||
|
|
||||||
|
|
||||||
// show spending only if sum of mixins is more than
|
// show spending only if sum of mixins is more than
|
||||||
// what we get + fee, and number of perferctly matched
|
// what we get + fee, and number of perferctly matched
|
||||||
// mixis is equal to number of inputs
|
// mixis is equal to number of inputs
|
||||||
|
@ -2657,7 +2918,7 @@ public:
|
||||||
"Its prefix is: {:s}",
|
"Its prefix is: {:s}",
|
||||||
data_prefix);
|
data_prefix);
|
||||||
|
|
||||||
cout << msg << endl;
|
cerr << msg << endl;
|
||||||
|
|
||||||
return string(msg);
|
return string(msg);
|
||||||
}
|
}
|
||||||
|
@ -2666,6 +2927,11 @@ public:
|
||||||
crypto::hash tx_prefix_hash_from_blob;
|
crypto::hash tx_prefix_hash_from_blob;
|
||||||
cryptonote::transaction tx_from_blob;
|
cryptonote::transaction tx_from_blob;
|
||||||
|
|
||||||
|
// std::stringstream ss;
|
||||||
|
// ss << tx_data_blob;
|
||||||
|
// binary_archive<false> ba(ss);
|
||||||
|
// serialization::serialize(ba, tx_from_blob);
|
||||||
|
|
||||||
if (!cryptonote::parse_and_validate_tx_from_blob(tx_data_blob,
|
if (!cryptonote::parse_and_validate_tx_from_blob(tx_data_blob,
|
||||||
tx_from_blob,
|
tx_from_blob,
|
||||||
tx_hash_from_blob,
|
tx_hash_from_blob,
|
||||||
|
@ -3965,6 +4231,8 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Lets use this json api convention for success and error
|
* Lets use this json api convention for success and error
|
||||||
* https://labs.omniti.com/labs/jsend
|
* https://labs.omniti.com/labs/jsend
|
||||||
|
@ -4214,6 +4482,56 @@ public:
|
||||||
return j_response;
|
return j_response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
json
|
||||||
|
json_detailedtransaction(string tx_hash_str)
|
||||||
|
{
|
||||||
|
json j_response {
|
||||||
|
{"status", "fail"},
|
||||||
|
{"data" , json {}}
|
||||||
|
};
|
||||||
|
|
||||||
|
json& j_data = j_response["data"];
|
||||||
|
|
||||||
|
transaction tx;
|
||||||
|
|
||||||
|
bool found_in_mempool {false};
|
||||||
|
uint64_t tx_timestamp {0};
|
||||||
|
string error_message;
|
||||||
|
|
||||||
|
if (!find_tx_for_json(tx_hash_str, tx, found_in_mempool, tx_timestamp, error_message))
|
||||||
|
{
|
||||||
|
j_data["title"] = error_message;
|
||||||
|
return j_response;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get detailed tx information
|
||||||
|
mstch::map tx_context = construct_tx_context(tx, 1 /*full detailed */);
|
||||||
|
|
||||||
|
// remove some page specific and html stuff
|
||||||
|
tx_context.erase("timescales");
|
||||||
|
tx_context.erase("tx_json");
|
||||||
|
tx_context.erase("tx_json_raw");
|
||||||
|
tx_context.erase("enable_mixins_details");
|
||||||
|
tx_context.erase("with_ring_signatures");
|
||||||
|
tx_context.erase("show_part_of_inputs");
|
||||||
|
tx_context.erase("show_more_details_link");
|
||||||
|
tx_context.erase("max_no_of_inputs_to_show");
|
||||||
|
tx_context.erase("inputs_xmr_sum_not_zero");
|
||||||
|
tx_context.erase("have_raw_tx");
|
||||||
|
tx_context.erase("have_any_unknown_amount");
|
||||||
|
tx_context.erase("has_error");
|
||||||
|
tx_context.erase("error_msg");
|
||||||
|
tx_context.erase("server_time");
|
||||||
|
tx_context.erase("construction_time");
|
||||||
|
|
||||||
|
j_data = tx_context;
|
||||||
|
|
||||||
|
j_response["status"] = "success";
|
||||||
|
|
||||||
|
return j_response;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Lets use this json api convention for success and error
|
* Lets use this json api convention for success and error
|
||||||
* https://labs.omniti.com/labs/jsend
|
* https://labs.omniti.com/labs/jsend
|
||||||
|
@ -4293,7 +4611,7 @@ public:
|
||||||
|
|
||||||
|
|
||||||
// get block size in bytes
|
// get block size in bytes
|
||||||
uint64_t blk_size = core_storage->get_db().get_block_size(block_height);
|
uint64_t blk_size = core_storage->get_db().get_block_weight(block_height);
|
||||||
|
|
||||||
// miner reward tx
|
// miner reward tx
|
||||||
transaction coinbase_tx = blk.miner_tx;
|
transaction coinbase_tx = blk.miner_tx;
|
||||||
|
@ -4522,7 +4840,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// get block size in bytes
|
// get block size in bytes
|
||||||
double blk_size = core_storage->get_db().get_block_size(i);
|
double blk_size = core_storage->get_db().get_block_weight(i);
|
||||||
|
|
||||||
crypto::hash blk_hash = core_storage->get_block_id_by_height(i);
|
crypto::hash blk_hash = core_storage->get_block_id_by_height(i);
|
||||||
|
|
||||||
|
@ -4541,8 +4859,8 @@ public:
|
||||||
|
|
||||||
json& j_txs = j_blocks.back()["txs"];
|
json& j_txs = j_blocks.back()["txs"];
|
||||||
|
|
||||||
list<cryptonote::transaction> blk_txs {blk.miner_tx};
|
vector<cryptonote::transaction> blk_txs {blk.miner_tx};
|
||||||
list<crypto::hash> missed_txs;
|
vector<crypto::hash> missed_txs;
|
||||||
|
|
||||||
if (!core_storage->get_transactions(blk.tx_hashes, blk_txs, missed_txs))
|
if (!core_storage->get_transactions(blk.tx_hashes, blk_txs, missed_txs))
|
||||||
{
|
{
|
||||||
|
@ -5107,8 +5425,8 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// get transactions in the given block
|
// get transactions in the given block
|
||||||
list <cryptonote::transaction> blk_txs{blk.miner_tx};
|
vector<cryptonote::transaction> blk_txs{blk.miner_tx};
|
||||||
list <crypto::hash> missed_txs;
|
vector<crypto::hash> missed_txs;
|
||||||
|
|
||||||
if (!core_storage->get_transactions(blk.tx_hashes, blk_txs, missed_txs))
|
if (!core_storage->get_transactions(blk.tx_hashes, blk_txs, missed_txs))
|
||||||
{
|
{
|
||||||
|
@ -5225,7 +5543,7 @@ public:
|
||||||
|
|
||||||
string emission_blk_no = std::to_string(current_values.blk_no - 1);
|
string emission_blk_no = std::to_string(current_values.blk_no - 1);
|
||||||
string emission_coinbase = xmr_amount_to_str(current_values.coinbase, "{:0.3f}");
|
string emission_coinbase = xmr_amount_to_str(current_values.coinbase, "{:0.3f}");
|
||||||
string emission_fee = xmr_amount_to_str(current_values.fee, "{:0.3f}", false);
|
string emission_fee = xmr_amount_to_str(current_values.fee, "{:0.4f}", false);
|
||||||
|
|
||||||
j_data = json {
|
j_data = json {
|
||||||
{"blk_no" , current_values.blk_no - 1},
|
{"blk_no" , current_values.blk_no - 1},
|
||||||
|
@ -5893,6 +6211,7 @@ private:
|
||||||
context["inputs_xmr_sum"] = xmreg::xmr_amount_to_str(inputs_xmr_sum);
|
context["inputs_xmr_sum"] = xmreg::xmr_amount_to_str(inputs_xmr_sum);
|
||||||
context["server_time"] = server_time_str;
|
context["server_time"] = server_time_str;
|
||||||
context["enable_mixins_details"] = detailed_view;
|
context["enable_mixins_details"] = detailed_view;
|
||||||
|
context["enable_as_hex"] = enable_as_hex;
|
||||||
context["show_part_of_inputs"] = show_part_of_inputs;
|
context["show_part_of_inputs"] = show_part_of_inputs;
|
||||||
context["max_no_of_inputs_to_show"] = max_no_of_inputs_to_show;
|
context["max_no_of_inputs_to_show"] = max_no_of_inputs_to_show;
|
||||||
|
|
||||||
|
@ -6140,6 +6459,32 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
find_tx_for_json(
|
||||||
|
string const& tx_hash_str,
|
||||||
|
transaction& tx,
|
||||||
|
bool& found_in_mempool,
|
||||||
|
uint64_t& tx_timestamp,
|
||||||
|
string& error_message)
|
||||||
|
{
|
||||||
|
// parse tx hash string to hash object
|
||||||
|
crypto::hash tx_hash;
|
||||||
|
|
||||||
|
if (!xmreg::parse_str_secret_key(tx_hash_str, tx_hash))
|
||||||
|
{
|
||||||
|
error_message = fmt::format("Cant parse tx hash: {:s}", tx_hash_str);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!find_tx(tx_hash, tx, found_in_mempool, tx_timestamp))
|
||||||
|
{
|
||||||
|
error_message = fmt::format("Cant find tx hash: {:s}", tx_hash_str);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
search_mempool(crypto::hash tx_hash,
|
search_mempool(crypto::hash tx_hash,
|
||||||
vector<MempoolStatus::mempool_tx>& found_txs)
|
vector<MempoolStatus::mempool_tx>& found_txs)
|
||||||
|
@ -6344,6 +6689,41 @@ private:
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
get_tx(string const& tx_hash_str,
|
||||||
|
transaction& tx,
|
||||||
|
crypto::hash& tx_hash)
|
||||||
|
{
|
||||||
|
if (!epee::string_tools::hex_to_pod(tx_hash_str, tx_hash))
|
||||||
|
{
|
||||||
|
string msg = fmt::format("Cant parse {:s} as tx hash!", tx_hash_str);
|
||||||
|
cerr << msg << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get transaction
|
||||||
|
|
||||||
|
if (!mcore->get_tx(tx_hash, tx))
|
||||||
|
{
|
||||||
|
cerr << "Cant get tx in blockchain: " << tx_hash
|
||||||
|
<< ". \n Check mempool now\n";
|
||||||
|
|
||||||
|
vector<MempoolStatus::mempool_tx> found_txs;
|
||||||
|
|
||||||
|
search_mempool(tx_hash, found_txs);
|
||||||
|
|
||||||
|
if (found_txs.empty())
|
||||||
|
{
|
||||||
|
// tx is nowhere to be found :-(
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
tx = found_txs.at(0).tx;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
add_js_files(mstch::map& context)
|
add_js_files(mstch::map& context)
|
||||||
{
|
{
|
||||||
|
|
|
@ -275,9 +275,9 @@ rpccalls::get_dynamic_per_kb_fee_estimate(
|
||||||
uint64_t& fee,
|
uint64_t& fee,
|
||||||
string& error_msg)
|
string& error_msg)
|
||||||
{
|
{
|
||||||
epee::json_rpc::request<COMMAND_RPC_GET_PER_KB_FEE_ESTIMATE::request>
|
epee::json_rpc::request<COMMAND_RPC_GET_BASE_FEE_ESTIMATE::request>
|
||||||
req_t = AUTO_VAL_INIT(req_t);
|
req_t = AUTO_VAL_INIT(req_t);
|
||||||
epee::json_rpc::response<COMMAND_RPC_GET_PER_KB_FEE_ESTIMATE::response, std::string>
|
epee::json_rpc::response<COMMAND_RPC_GET_BASE_FEE_ESTIMATE::response, std::string>
|
||||||
resp_t = AUTO_VAL_INIT(resp_t);
|
resp_t = AUTO_VAL_INIT(resp_t);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,11 @@
|
||||||
<td>Total fees:</td><td>{{sum_fees}}</td>
|
<td>Total fees:</td><td>{{sum_fees}}</td>
|
||||||
<td>No of txs:</td><td>{{no_txs}}</td>
|
<td>No of txs:</td><td>{{no_txs}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>PoW hash:</td><td>{{blk_pow_hash}}</td>
|
||||||
|
<td>Difficulty:</td><td>{{blk_difficulty}}</td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<h3>Miner reward transaction</h3>
|
<h3>Miner reward transaction</h3>
|
||||||
|
@ -79,4 +84,12 @@
|
||||||
</table>
|
</table>
|
||||||
{{/have_txs}}
|
{{/have_txs}}
|
||||||
|
|
||||||
|
|
||||||
|
{{#enable_as_hex}}
|
||||||
|
<h5 style="margin-top:1px">
|
||||||
|
<a href="/blockhex/{{blk_height}}">Block as hex</a>
|
||||||
|
| <a href="/blockhexcomplete/{{blk_height}}">Complete block as hex</a>
|
||||||
|
</h5>
|
||||||
|
{{/enable_as_hex}}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -152,6 +152,12 @@
|
||||||
it is impossible to know whether this is your real spending. <br/>
|
it is impossible to know whether this is your real spending. <br/>
|
||||||
So do not take this number seriously.
|
So do not take this number seriously.
|
||||||
It is probably totally wrong anyway.</span>
|
It is probably totally wrong anyway.</span>
|
||||||
|
<br/>
|
||||||
|
<span style="font-size: 14px">
|
||||||
|
Number of possible our mixins is {{no_all_possible_mixins}}
|
||||||
|
for {{all_possible_mixins_amount}} xmr
|
||||||
|
(amount as uint64).
|
||||||
|
</span>
|
||||||
</h3>
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -531,7 +531,13 @@
|
||||||
{{^have_raw_tx}}
|
{{^have_raw_tx}}
|
||||||
{{^with_ring_signatures}}
|
{{^with_ring_signatures}}
|
||||||
{{#show_more_details_link}}
|
{{#show_more_details_link}}
|
||||||
<h5 style="margin-top:1px"><a href="/tx/{{tx_hash}}/1">More details</a></h5>
|
<h5 style="margin-top:1px">
|
||||||
|
<a href="/tx/{{tx_hash}}/1">More details</a>
|
||||||
|
{{#enable_as_hex}}
|
||||||
|
| <a href="/txhex/{{tx_hash}}">Tx as hex</a>
|
||||||
|
| <a href="/ringmembershex/{{tx_hash}}">Tx ring members as hex</a>
|
||||||
|
{{/enable_as_hex}}
|
||||||
|
</h5>
|
||||||
{{/show_more_details_link}}
|
{{/show_more_details_link}}
|
||||||
{{/with_ring_signatures}}
|
{{/with_ring_signatures}}
|
||||||
{{#with_ring_signatures}}
|
{{#with_ring_signatures}}
|
||||||
|
|
|
@ -935,7 +935,7 @@ decode_ringct(rct::rctSig const& rv,
|
||||||
switch (rv.type)
|
switch (rv.type)
|
||||||
{
|
{
|
||||||
case rct::RCTTypeSimple:
|
case rct::RCTTypeSimple:
|
||||||
case rct::RCTTypeSimpleBulletproof:
|
case rct::RCTTypeBulletproof:
|
||||||
amount = rct::decodeRctSimple(rv,
|
amount = rct::decodeRctSimple(rv,
|
||||||
rct::sk2rct(scalar1),
|
rct::sk2rct(scalar1),
|
||||||
i,
|
i,
|
||||||
|
@ -943,7 +943,6 @@ decode_ringct(rct::rctSig const& rv,
|
||||||
hw::get_device("default"));
|
hw::get_device("default"));
|
||||||
break;
|
break;
|
||||||
case rct::RCTTypeFull:
|
case rct::RCTTypeFull:
|
||||||
case rct::RCTTypeFullBulletproof:
|
|
||||||
amount = rct::decodeRct(rv,
|
amount = rct::decodeRct(rv,
|
||||||
rct::sk2rct(scalar1),
|
rct::sk2rct(scalar1),
|
||||||
i,
|
i,
|
||||||
|
@ -1048,7 +1047,7 @@ decrypt(const std::string &ciphertext,
|
||||||
}
|
}
|
||||||
|
|
||||||
crypto::chacha_key key;
|
crypto::chacha_key key;
|
||||||
crypto::generate_chacha_key(&skey, sizeof(skey), key);
|
crypto::generate_chacha_key(&skey, sizeof(skey), key, 1);
|
||||||
|
|
||||||
const crypto::chacha_iv &iv = *(const crypto::chacha_iv*)&ciphertext[0];
|
const crypto::chacha_iv &iv = *(const crypto::chacha_iv*)&ciphertext[0];
|
||||||
|
|
||||||
|
@ -1266,4 +1265,10 @@ pause_execution(uint64_t no_seconds, const string& text)
|
||||||
cout << endl;
|
cout << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string
|
||||||
|
tx_to_hex(transaction const& tx)
|
||||||
|
{
|
||||||
|
return epee::string_tools::buff_to_hex_nodelimer(t_serializable_object_to_blob(tx));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -370,6 +370,9 @@ calc_median(It it_begin, It it_end)
|
||||||
void
|
void
|
||||||
pause_execution(uint64_t no_seconds, const string& text = "now");
|
pause_execution(uint64_t no_seconds, const string& text = "now");
|
||||||
|
|
||||||
|
string
|
||||||
|
tx_to_hex(transaction const& tx);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //XMREG01_TOOLS_H
|
#endif //XMREG01_TOOLS_H
|
Loading…
Add table
Add a link
Reference in a new issue