Merge pull request #75 from moneroexamples/update_to_current_monero

Update to current monero
master
moneroexamples 7 years ago committed by GitHub
commit 7eca176e6a

@ -100,7 +100,7 @@ set(LIBRARIES
cryptonote_protocol cryptonote_protocol
cryptonote_basic cryptonote_basic
daemonizer daemonizer
cryptoxmr cncrypto
blocks blocks
lmdb lmdb
ringct ringct

@ -25,8 +25,16 @@ Monero C++ libraries, but also demonstrates how to use:
Tor users: Tor users:
- [http://libwh5lvouddzei4.onion/] - bleading edge version.
- [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)).
- [http://libwh5lvouddzei4.onion/] - bleading edge version.
Clearnet versions:
- [http://139.162.32.245:8081/](http://139.162.32.245:8081/) - down for now.
- [https://xmrchain.net/](https://xmrchain.net/) - https enabled, most popular and very stable.
- [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.
- [https://MoneroExplorer.com/](https://moneroexplorer.com/) - nice looking one, https enabled.
Clearnet versions: Clearnet versions:
@ -37,18 +45,18 @@ Clearnet versions:
- [https://MoneroExplorer.com/](https://moneroexplorer.com/) - nice looking one, https enabled. - [https://MoneroExplorer.com/](https://moneroexplorer.com/) - nice looking one, 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.
- [http://monerochain.com/](http://monerochain.com/) - JSON API based, multiple nodes. - [http://monerochain.com/](http://monerochain.com/) - JSON API based, multiple nodes.
- [http://66.85.74.134:8081/](http://66.85.74.134:8081/) - fluffynet subnet explorer.
Clearnet testnet Monero version: Clearnet testnet Monero version:
- [http://139.162.32.245:8082/](http://139.162.32.245:8082/) - bleeding edge version, no https. - [http://139.162.32.245:8082/](http://139.162.32.245:8082/) - bleeding edge version, no https.
- [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://testnet.MoneroExplorer.com/](https://testnet.moneroexplorer.com/) - https enabled. - [https://testnet.MoneroExplorer.com/](https://testnet.moneroexplorer.com/) - https enabled.
i2p users (main Monero network):
i2p users (main Monero network) - down for now: - [http://7o4gezpkye6ekibhgpkg7v626ze4idsirapufzrefkdysa6zxhha.b32.i2p/](http://7o4gezpkye6ekibhgpkg7v626ze4idsirapufzrefkdysa6zxhha.b32.i2p/)
- [http://monerotools.i2p](http://monerotools.i2p)
Alternative block explorers: Alternative block explorers:
@ -63,26 +71,27 @@ The key features of the Onion Monero Blockchain Explorer are:
- no javascript, no cookies, no web analytics trackers, no images, - no javascript, no cookies, no web analytics trackers, no images,
- open sourced, - open sourced,
- made fully in C++, - made fully in C++,
- the only explorer showing encrypted payments ID, - showing encrypted payments ID,
- the only explorer showing ring signatures, - showing ring signatures,
- the only explorer showing transaction extra field, - showing transaction extra field,
- the only explorer showing public components of Monero addresses, - showing public components of Monero addresses,
- the only explorer that can show which outputs and mixins belong to the given Monero address and viewkey, - decoding which outputs and mixins belong to the given Monero address and viewkey,
- the only explorer that can be used to prove that you send Monero to someone, - can prove that you send Monero to someone,
- the only explorer showing detailed information about mixins, such as, mixins' - detailed information about mixins, such as, mixins'
age, timescale, mixin of mixins, age, timescale, mixin of mixins,
- the only explorer showing number of amount output indices, - showing number of amount output indices,
- the only explorer supporting Monero testnet network, - support Monero testnet network,
- the only explorer providing tx checker and pusher for online pushing of transactions, - tx checker and pusher for online pushing of transactions,
- the only explorer able to estimate possible spendings based on address and viewkey, - estimate possible spendings based on address and viewkey,
- the only explorer that can provide total amount of all miner fees. - can provide total amount of all miner fees.
- decoding encrypted payment id.
## Compilation on Ubuntu 16.04 ## Compilation on Ubuntu 16.04
##### Compile latest Monero ##### Compile latest Monero
Download and compile recent Monero release into your home folder: Download and compile recent Monero into your home folder:
```bash ```bash
# first install monero dependecines # first install monero dependecines
@ -97,9 +106,6 @@ git clone https://github.com/monero-project/monero
cd monero/ cd monero/
# checkout last monero version
git checkout -b last_release v0.10.3.1
make make
``` ```
@ -155,7 +161,6 @@ Go to your browser: http://127.0.0.1:8081
## The explorer's command line options ## The explorer's command line options
``` ```
./xmrblocks -h
xmrblocks, Onion Monero Blockchain Explorer: xmrblocks, Onion Monero Blockchain Explorer:
-h [ --help ] [=arg(=1)] (=0) produce help message -h [ --help ] [=arg(=1)] (=0) produce help message
-t [ --testnet ] [=arg(=1)] (=0) use testnet blockchain -t [ --testnet ] [=arg(=1)] (=0) use testnet blockchain
@ -168,8 +173,6 @@ xmrblocks, Onion Monero Blockchain Explorer:
enable key images file checker enable key images file checker
--enable-output-key-checker [=arg(=1)] (=0) --enable-output-key-checker [=arg(=1)] (=0)
enable outputs key file checker enable outputs key file checker
--enable-mempool-cache arg (=1) enable caching of transactions from the
mempool
--enable-json-api arg (=1) enable JSON REST api --enable-json-api arg (=1) enable JSON REST api
--enable-tx-cache [=arg(=1)] (=0) enable caching of transaction details --enable-tx-cache [=arg(=1)] (=0) enable caching of transaction details
--show-cache-times [=arg(=1)] (=0) show times of getting data from cache --show-cache-times [=arg(=1)] (=0) show times of getting data from cache
@ -194,6 +197,8 @@ xmrblocks, Onion Monero Blockchain Explorer:
for network info availability for network info availability
--mempool-info-timeout arg (=5000) maximum time, in milliseconds, to wait --mempool-info-timeout arg (=5000) maximum time, in milliseconds, to wait
for mempool data for the front page for mempool data for the front page
--mempool-refresh-time arg (=5) time, in seconds, for each refresh of
mempool state
-b [ --bc-path ] arg path to lmdb folder of the blockchain, -b [ --bc-path ] arg path to lmdb folder of the blockchain,
e.g., ~/.bitmonero/lmdb e.g., ~/.bitmonero/lmdb
--ssl-crt-file arg path to crt file for ssl (https) --ssl-crt-file arg path to crt file for ssl (https)
@ -285,7 +290,7 @@ The explorer has JSON api. For the API, it uses conventions defined by [JSend](h
#### api/transaction/<tx_hash> #### api/transaction/<tx_hash>
```bash ```bash
curl -w "\n" -X GET "http://139.162.32.245:8081/api/transaction/6093260dbe79fd6277694d14789dc8718f1bd54457df8bab338c2efa3bb0f03d" curl -w "\n" -X GET "http://127.0.0.1:8081/api/transaction/6093260dbe79fd6277694d14789dc8718f1bd54457df8bab338c2efa3bb0f03d"
``` ```
Partial results shown: Partial results shown:
@ -347,7 +352,7 @@ Transactions in last 25 blocks
```bash ```bash
curl -w "\n" -X GET "http://139.162.32.245:8081/api/transactions" curl -w "\n" -X GET "http://127.0.0.1:8081/api/transactions"
``` ```
Partial results shown: Partial results shown:
@ -397,7 +402,7 @@ Partial results shown:
```bash ```bash
curl -w "\n" -X GET "http://139.162.32.245:8081/api/transactions?page=2&limit=10" curl -w "\n" -X GET "http://127.0.0.1:8081/api/transactions?page=2&limit=10"
``` ```
Result analogical to the one above. Result analogical to the one above.
@ -447,7 +452,7 @@ Partial results shown:
Return all txs in the mempool. Return all txs in the mempool.
```bash ```bash
curl -w "\n" -X GET "http://139.162.32.245:8081/api/mempool" curl -w "\n" -X GET "http://127.0.0.1:8081/api/mempool"
``` ```
Partial results shown: Partial results shown:
@ -490,7 +495,7 @@ if no specific limit given.
Return number of newest mempool txs, e.g., only 10. Return number of newest mempool txs, e.g., only 10.
```bash ```bash
curl -w "\n" -X GET "http://139.162.32.245:8081/api/mempool?limit=10" curl -w "\n" -X GET "http://127.0.0.1:8081/api/mempool?limit=10"
``` ```
Result analogical to the one above. Result analogical to the one above.
@ -498,7 +503,7 @@ Result analogical to the one above.
#### api/search/<block_number|tx_hash|block_hash> #### api/search/<block_number|tx_hash|block_hash>
```bash ```bash
curl -w "\n" -X GET "http://139.162.32.245:8081/api/search/1293669" curl -w "\n" -X GET "http://127.0.0.1:8081/api/search/1293669"
``` ```
Partial results shown: Partial results shown:
@ -546,7 +551,7 @@ Checking outputs:
```bash ```bash
# we use here official Monero project's donation address as an example # we use here official Monero project's donation address as an example
curl -w "\n" -X GET "http://139.162.32.245:8081/api/outputs?txhash=17049bc5f2d9fbca1ce8dae443bbbbed2fc02f1ee003ffdd0571996905faa831&address=44AFFq5kSiGBoZ4NMDwYtN18obc8AemS33DBLWs3H7otXft3XjrpDtQGv7SqSsaBYBb98uNbr2VBBEt7f2wfn3RVGQBEP3A&viewkey=f359631075708155cc3d92a32b75a7d02a5dcf27756707b47a2b31b21c389501&txprove=0" curl -w "\n" -X GET "http://127.0.0.1:8081/api/outputs?txhash=17049bc5f2d9fbca1ce8dae443bbbbed2fc02f1ee003ffdd0571996905faa831&address=44AFFq5kSiGBoZ4NMDwYtN18obc8AemS33DBLWs3H7otXft3XjrpDtQGv7SqSsaBYBb98uNbr2VBBEt7f2wfn3RVGQBEP3A&viewkey=f359631075708155cc3d92a32b75a7d02a5dcf27756707b47a2b31b21c389501&txprove=0"
``` ```
```json ```json
@ -582,7 +587,7 @@ For the viewkey, we use `tx_private_key` (although the GET variable is still cal
```bash ```bash
# this is for testnet transaction # this is for testnet transaction
curl -w "\n" -X GET "http://139.162.32.245:8082/api/outputs?txhash=94782a8c0aa8d8768afa0c040ef0544b63eb5148ca971a024ac402cad313d3b3&address=9wUf8UcPUtb2huK7RphBw5PFCyKosKxqtGxbcKBDnzTCPrdNfJjLjtuht87zhTgsffCB21qmjxjj18Pw7cBnRctcKHrUB7N&viewkey=e94b5bfc599d2f741d6f07e3ab2a83f915e96fb374dfb2cd3dbe730e34ecb40b&txprove=1" curl -w "\n" -X GET "http://127.0.0.1:8082/api/outputs?txhash=94782a8c0aa8d8768afa0c040ef0544b63eb5148ca971a024ac402cad313d3b3&address=9wUf8UcPUtb2huK7RphBw5PFCyKosKxqtGxbcKBDnzTCPrdNfJjLjtuht87zhTgsffCB21qmjxjj18Pw7cBnRctcKHrUB7N&viewkey=e94b5bfc599d2f741d6f07e3ab2a83f915e96fb374dfb2cd3dbe730e34ecb40b&txprove=1"
``` ```
```json ```json
@ -617,7 +622,7 @@ Result analogical to the one above.
#### api/networkinfo #### api/networkinfo
```bash ```bash
curl -w "\n" -X GET "http://139.162.32.245:8081/api/networkinfo" curl -w "\n" -X GET "http://127.0.0.1:8081/api/networkinfo"
``` ```
```json ```json
@ -647,10 +652,65 @@ curl -w "\n" -X GET "http://139.162.32.245:8081/api/networkinfo"
} }
``` ```
#### api/outputsblocks
Search for our outputs in last few blocks (up to 5 blocks), using provided address and viewkey.
```bash
# testnet address
curl -w "\n" -X GET http://127.0.0.1:8081/api/outputsblocks?address=9sDyNU82ih1gdhDgrqHbEcfSDFASjFgxL9B9v5f1AytFUrYsVEj7bD9Pyx5Sw2qLk8HgGdFM8qj5DNecqGhm24Ce6QwEGDi&viewkey=807079280293998634d66e745562edaaca45c0a75c8290603578b54e9397e90a&limit=5&mempool=1
```
Example result:
```json
{
{
"data": {
"address": "0182d5be0f708cecf2b6f9889738bde5c930fad846d5b530e021afd1ae7e24a687ad50af3a5d38896655669079ad0163b4a369f6c852cc816dace5fc7792b72f",
"height": 960526,
"limit": "5",
"mempool": true,
"outputs": [
{
"amount": 33000000000000,
"block_no": 0,
"in_mempool": true,
"output_idx": 1,
"output_pubkey": "2417b24fc99b2cbd9459278b532b37f15eab6b09bbfc44f9d17e15cd25d5b44f",
"payment_id": "",
"tx_hash": "9233708004c51d15f44e86ac1a3b99582ed2bede4aaac6e2dd71424a9147b06f"
},
{
"amount": 2000000000000,
"block_no": 960525,
"in_mempool": false,
"output_idx": 0,
"output_pubkey": "9984101f5471dda461f091962f1f970b122d4469077aed6b978a910dc3ed4576",
"payment_id": "0000000000000055",
"tx_hash": "37825d0feb2e96cd10fa9ec0b990ac2e97d2648c0f23e4f7d68d2298996acefd"
},
{
"amount": 96947454120000,
"block_no": 960525,
"in_mempool": false,
"output_idx": 1,
"output_pubkey": "e4bded8e2a9ec4d41682a34d0a37596ec62742b28e74b897fcc00a47fcaa8629",
"payment_id": "0000000000000000000000000000000000000000000000000000000000001234",
"tx_hash": "4fad5f2bdb6dbd7efc2ce7efa3dd20edbd2a91640ce35e54c6887f0ee5a1a679"
}
],
"viewkey": "807079280293998634d66e745562edaaca45c0a75c8290603578b54e9397e90a"
},
"status": "success"
}
```
#### api/emission #### api/emission
```bash ```bash
curl -w "\n" -X GET "http://139.162.32.245:8081/api/emission" curl -w "\n" -X GET "http://127.0.0.1:8081/api/emission"
``` ```
```json ```json
@ -666,6 +726,34 @@ curl -w "\n" -X GET "http://139.162.32.245:8081/api/emission"
Emission only works when the emission monitoring thread is enabled. Emission only works when the emission monitoring thread is enabled.
#### api/version
```bash
curl -w "\n" -X GET "http://127.0.0.1:8081/api/version"
```
```json
{
"data": {
"api": 65536,
"blockchain_height": 1357031,
"git_branch_name": "update_to_current_monero",
"last_git_commit_date": "2017-07-25",
"last_git_commit_hash": "a549f25",
"monero_version_full": "0.10.3.1-ab594cfe"
},
"status": "success"
}
```
api number is store as `uint32_t`. In this case `65536` represents
major version 1 and minor version 0.
In JavaScript to get these numbers, one can do as follows:
```javascript
var api_major = response.data.api >> 16;
var api_minor = response.data.api & 0xffff;
```
#### api/rawblock/<block_number|block_hash> #### api/rawblock/<block_number|block_hash>

@ -30,7 +30,7 @@
set(LIBS common;blocks;cryptonote_basic;cryptonote_core; set(LIBS common;blocks;cryptonote_basic;cryptonote_core;
cryptonote_protocol;daemonizer;mnemonics;epee;lmdb; cryptonote_protocol;daemonizer;mnemonics;epee;lmdb;
blockchain_db;ringct;wallet) blockchain_db;ringct;wallet;cncrypto)
set(Xmr_INCLUDE_DIRS "${CPP_MONERO_DIR}") set(Xmr_INCLUDE_DIRS "${CPP_MONERO_DIR}")
@ -57,13 +57,6 @@ foreach (l ${LIBS})
endforeach() endforeach()
if (EXISTS ${MONERO_BUILD_DIR}/src/crypto/libcncrypto.a)
add_library(cryptoxmr STATIC IMPORTED)
set_property(TARGET cryptoxmr
PROPERTY IMPORTED_LOCATION ${MONERO_BUILD_DIR}/src/crypto/libcncrypto.a)
endif()
if (EXISTS ${MONERO_BUILD_DIR}/external/easylogging++/libeasylogging.a) if (EXISTS ${MONERO_BUILD_DIR}/external/easylogging++/libeasylogging.a)
add_library(easylogging STATIC IMPORTED) add_library(easylogging STATIC IMPORTED)
set_property(TARGET easylogging set_property(TARGET easylogging

@ -156,7 +156,7 @@ namespace crow
struct Wrapped struct Wrapped
{ {
template <typename ... Args> template <typename ... Args>
void set(Func f, typename std::enable_if< void set2(Func f, typename std::enable_if<
!std::is_same<typename std::tuple_element<0, std::tuple<Args..., void>>::type, const request&>::value !std::is_same<typename std::tuple_element<0, std::tuple<Args..., void>>::type, const request&>::value
, int>::type = 0) , int>::type = 0)
{ {
@ -190,7 +190,7 @@ namespace crow
}; };
template <typename ... Args> template <typename ... Args>
void set(Func f, typename std::enable_if< void set2(Func f, typename std::enable_if<
std::is_same<typename std::tuple_element<0, std::tuple<Args..., void>>::type, const request&>::value && std::is_same<typename std::tuple_element<0, std::tuple<Args..., void>>::type, const request&>::value &&
!std::is_same<typename std::tuple_element<1, std::tuple<Args..., void, void>>::type, response&>::value !std::is_same<typename std::tuple_element<1, std::tuple<Args..., void, void>>::type, response&>::value
, int>::type = 0) , int>::type = 0)
@ -205,7 +205,7 @@ namespace crow
} }
template <typename ... Args> template <typename ... Args>
void set(Func f, typename std::enable_if< void set2(Func f, typename std::enable_if<
std::is_same<typename std::tuple_element<0, std::tuple<Args..., void>>::type, const request&>::value && std::is_same<typename std::tuple_element<0, std::tuple<Args..., void>>::type, const request&>::value &&
std::is_same<typename std::tuple_element<1, std::tuple<Args..., void, void>>::type, response&>::value std::is_same<typename std::tuple_element<1, std::tuple<Args..., void, void>>::type, response&>::value
, int>::type = 0) , int>::type = 0)
@ -394,7 +394,7 @@ namespace crow
#else #else
template <typename Func, unsigned ... Indices> template <typename Func, unsigned ... Indices>
#endif #endif
std::function<void(const request&, response&, const routing_params&)> std::function<void(const request&, response&, const routing_params&)>
wrap(Func f, black_magic::seq<Indices...>) wrap(Func f, black_magic::seq<Indices...>)
{ {
#ifdef CROW_MSVC_WORKAROUND #ifdef CROW_MSVC_WORKAROUND
@ -403,16 +403,14 @@ namespace crow
using function_t = utility::function_traits<Func>; using function_t = utility::function_traits<Func>;
#endif #endif
if (!black_magic::is_parameter_tag_compatible( if (!black_magic::is_parameter_tag_compatible(
black_magic::get_parameter_tag_runtime(rule_.c_str()), black_magic::get_parameter_tag_runtime(rule_.c_str()),
black_magic::compute_parameter_tag_from_args_list< black_magic::compute_parameter_tag_from_args_list<
typename function_t::template arg<Indices>...>::value)) typename function_t::template arg<Indices>...>::value))
{ {
throw std::runtime_error("route_dynamic: Handler type is mismatched with URL parameters: " + rule_); throw std::runtime_error("route_dynamic: Handler type is mismatched with URL parameters: " + rule_);
} }
auto ret = detail::routing_handler_call_helper::Wrapped<Func, typename function_t::template arg<Indices>...>(); auto ret = detail::routing_handler_call_helper::Wrapped<Func, typename function_t::template arg<Indices>...>();
ret.template set< ret.template set2<typename function_t::template arg<Indices>...>(std::move(f));
typename function_t::template arg<Indices>...
>(std::move(f));
return ret; return ret;
} }

@ -1,57 +0,0 @@
//
// Created by mwo on 24/05/15.
//
// source: http://codereview.stackexchange.com/questions/13176/infix-iterator-code
// infix_iterator.h
#if !defined(INFIX_ITERATOR_H_)
#define INFIX_ITERATOR_H_
#include <ostream>
#include <iterator>
#include <string>
template <class T, class charT=char, class traits=std::char_traits<charT> >
class infix_ostream_iterator :
public std::iterator<std::output_iterator_tag, void, void, void, void>
{
std::basic_ostream<charT,traits> *os;
std::basic_string<charT> delimiter;
std::basic_string<charT> real_delim;
public:
typedef charT char_type;
typedef traits traits_type;
typedef std::basic_ostream<charT, traits> ostream_type;
infix_ostream_iterator(ostream_type &s)
: os(&s)
{}
infix_ostream_iterator(ostream_type &s, charT const *d)
: os(&s),
real_delim(d)
{}
infix_ostream_iterator<T, charT, traits> &operator=(T const &item)
{
*os << delimiter << item;
delimiter = real_delim;
return *this;
}
infix_ostream_iterator<T, charT, traits> &operator*() {
return *this;
}
infix_ostream_iterator<T, charT, traits> &operator++() {
return *this;
}
infix_ostream_iterator<T, charT, traits> &operator++(int) {
return *this;
}
};
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -1,36 +0,0 @@
#ifndef MEMBER_CHECKER_H
#define MEMBER_CHECKER_H
#define DEFINE_MEMBER_CHECKER(member) \
template<typename T, typename V = bool> \
struct has_ ## member : false_type { }; \
\
template<typename T> \
struct has_ ## member<T, \
typename enable_if< \
!is_same<decltype(declval<T>().member), void>::value, \
bool \
>::type \
> : true_type { };
#define HAS_MEMBER(C, member) \
has_ ## member<C>::value
// first getter if the member veriable is present, so we return its value
// second getter, when the member is not present, so we return empty value, e.g., empty string
#define DEFINE_MEMBER_GETTER(member, ret_value) \
template<typename T> \
typename enable_if<HAS_MEMBER(T, member), ret_value>::type \
get_ ## member (T t){ \
return t.member; \
} \
\
template<typename T> \
typename enable_if<!HAS_MEMBER(T, member), ret_value>::type \
get_ ## member (T t){ \
return ret_value(); \
}
#endif // MEMBER_CHECKER_H

@ -1,10 +1,11 @@
#define CROW_ENABLE_SSL #define CROW_ENABLE_SSL
#include "ext/crow/crow.h"
#include "src/page.h"
#include "ext/crow/crow.h"
#include "src/CmdLineOptions.h" #include "src/CmdLineOptions.h"
#include "src/MicroCore.h" #include "src/MicroCore.h"
#include "src/page.h"
#include <fstream> #include <fstream>
#include <regex> #include <regex>
@ -49,15 +50,14 @@ main(int ac, const char* av[])
auto no_blocks_on_index_opt = opts.get_option<string>("no-blocks-on-index"); auto no_blocks_on_index_opt = opts.get_option<string>("no-blocks-on-index");
auto testnet_url = opts.get_option<string>("testnet-url"); auto testnet_url = opts.get_option<string>("testnet-url");
auto mainnet_url = opts.get_option<string>("mainnet-url"); auto mainnet_url = opts.get_option<string>("mainnet-url");
auto network_info_timeout_opt = opts.get_option<string>("network-info-timeout");
auto mempool_info_timeout_opt = opts.get_option<string>("mempool-info-timeout"); auto mempool_info_timeout_opt = opts.get_option<string>("mempool-info-timeout");
auto mempool_refresh_time_opt = opts.get_option<string>("mempool-refresh-time");
auto testnet_opt = opts.get_option<bool>("testnet"); auto testnet_opt = opts.get_option<bool>("testnet");
auto enable_key_image_checker_opt = opts.get_option<bool>("enable-key-image-checker"); auto enable_key_image_checker_opt = opts.get_option<bool>("enable-key-image-checker");
auto enable_output_key_checker_opt = opts.get_option<bool>("enable-output-key-checker"); auto enable_output_key_checker_opt = opts.get_option<bool>("enable-output-key-checker");
auto enable_autorefresh_option_opt = opts.get_option<bool>("enable-autorefresh-option"); auto enable_autorefresh_option_opt = opts.get_option<bool>("enable-autorefresh-option");
auto enable_pusher_opt = opts.get_option<bool>("enable-pusher"); auto enable_pusher_opt = opts.get_option<bool>("enable-pusher");
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_mempool_cache_opt = opts.get_option<bool>("enable-mempool-cache");
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_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");
@ -72,7 +72,6 @@ main(int ac, const char* av[])
bool enable_autorefresh_option {*enable_autorefresh_option_opt}; bool enable_autorefresh_option {*enable_autorefresh_option_opt};
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_mempool_cache {*enable_mempool_cache_opt};
bool enable_json_api {*enable_json_api_opt}; bool enable_json_api {*enable_json_api_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};
@ -155,22 +154,20 @@ main(int ac, const char* av[])
deamon_url = "http:://127.0.0.1:28081"; deamon_url = "http:://127.0.0.1:28081";
} }
uint64_t network_info_timeout {1000};
uint64_t mempool_info_timeout {5000}; uint64_t mempool_info_timeout {5000};
try try
{ {
network_info_timeout = boost::lexical_cast<uint64_t>(*network_info_timeout_opt);
mempool_info_timeout = boost::lexical_cast<uint64_t>(*mempool_info_timeout_opt); mempool_info_timeout = boost::lexical_cast<uint64_t>(*mempool_info_timeout_opt);
} }
catch (boost::bad_lexical_cast &e) catch (boost::bad_lexical_cast &e)
{ {
cout << "Cant cast " << (*network_info_timeout_opt) cout << "Cant cast " << (*mempool_info_timeout_opt) <<" into numbers. Using default values."
<< " or/and " << (*mempool_info_timeout_opt) <<" into numbers. Using default values."
<< endl; << endl;
} }
uint64_t mempool_refresh_time {10};
if (enable_emission_monitor == true) if (enable_emission_monitor == true)
@ -204,6 +201,36 @@ main(int ac, const char* av[])
xmreg::CurrentBlockchainStatus::start_monitor_blockchain_thread(); xmreg::CurrentBlockchainStatus::start_monitor_blockchain_thread();
} }
xmreg::MempoolStatus::blockchain_path
= blockchain_path;
xmreg::MempoolStatus::testnet
= testnet;
xmreg::MempoolStatus::deamon_url
= deamon_url;
xmreg::MempoolStatus::set_blockchain_variables(
&mcore, core_storage);
try
{
mempool_refresh_time = boost::lexical_cast<uint64_t>(*mempool_refresh_time_opt);
}
catch (boost::bad_lexical_cast &e)
{
cout << "Cant cast " << (*mempool_refresh_time_opt)
<<" into number. Using default value."
<< endl;
}
// launch the status monitoring thread so that it keeps track of blockchain
// info, e.g., current height. Information from this thread is used
// by tx searching threads that are launched for each user independently,
// when they log back or create new account.
xmreg::MempoolStatus::mempool_refresh_time = mempool_refresh_time;
xmreg::MempoolStatus::start_mempool_status_thread();
// create instance of page class which // create instance of page class which
// contains logic for the website // contains logic for the website
xmreg::page xmrblocks(&mcore, xmreg::page xmrblocks(&mcore,
@ -215,12 +242,10 @@ main(int ac, const char* av[])
enable_output_key_checker, enable_output_key_checker,
enable_autorefresh_option, enable_autorefresh_option,
enable_mixin_details, enable_mixin_details,
enable_mempool_cache,
enable_tx_cache, enable_tx_cache,
enable_block_cache, enable_block_cache,
show_cache_times, show_cache_times,
no_blocks_on_index, no_blocks_on_index,
network_info_timeout,
mempool_info_timeout, mempool_info_timeout,
*testnet_url, *testnet_url,
*mainnet_url); *mainnet_url);
@ -406,6 +431,17 @@ main(int ac, const char* av[])
return xmrblocks.mempool(true); return xmrblocks.mempool(true);
}); });
// alias to "/mempool"
CROW_ROUTE(app, "/txpool")
([&](const crow::request& req) {
return xmrblocks.mempool(true);
});
// CROW_ROUTE(app, "/altblocks")
// ([&](const crow::request& req) {
// return xmrblocks.altblocks();
// });
CROW_ROUTE(app, "/robots.txt") CROW_ROUTE(app, "/robots.txt")
([&]() { ([&]() {
string text = "User-agent: *\n" string text = "User-agent: *\n"
@ -531,6 +567,45 @@ main(int ac, const char* av[])
return r; return r;
}); });
CROW_ROUTE(app, "/api/outputsblocks").methods("GET"_method)
([&](const crow::request &req) {
string limit = regex_search(req.raw_url, regex {"limit=\\d+"}) ?
req.url_params.get("limit") : "3";
string address = regex_search(req.raw_url, regex {"address=\\w+"}) ?
req.url_params.get("address") : "";
string viewkey = regex_search(req.raw_url, regex {"viewkey=\\w+"}) ?
req.url_params.get("viewkey") : "";
bool in_mempool_aswell {false};
try
{
in_mempool_aswell = regex_search(req.raw_url, regex {"mempool=[01]"}) ?
boost::lexical_cast<bool>(req.url_params.get("mempool")) :
false;
}
catch (const boost::bad_lexical_cast &e)
{
cerr << "Cant parse tx_prove as bool. Using default value" << endl;
}
myxmr::jsonresponse r{xmrblocks.json_outputsblocks(limit, address, viewkey, in_mempool_aswell)};
return r;
});
CROW_ROUTE(app, "/api/version")
([&](const crow::request &req) {
myxmr::jsonresponse r{xmrblocks.json_version()};
return r;
});
} }
if (enable_autorefresh_option) if (enable_autorefresh_option)
@ -561,12 +636,24 @@ main(int ac, const char* av[])
if (enable_emission_monitor == true) if (enable_emission_monitor == true)
{ {
// finish Emission monitoring thread in a cotrolled manner. // finish Emission monitoring thread in a cotrolled manner.
cout << "Waiting for emission monitoring thread to finish." << endl;
xmreg::CurrentBlockchainStatus::m_thread.interrupt(); xmreg::CurrentBlockchainStatus::m_thread.interrupt();
xmreg::CurrentBlockchainStatus::m_thread.join(); xmreg::CurrentBlockchainStatus::m_thread.join();
cout << "Emission monitoring thread joined." << endl; cout << "Emission monitoring thread finished." << endl;
} }
// finish mempool thread
cout << "Waiting for mempool monitoring thread to finish." << endl;
xmreg::MempoolStatus::m_thread.interrupt();
xmreg::MempoolStatus::m_thread.join();
cout << "Mempool monitoring thread finished." << endl;
cout << "The explorer is terminating." << endl; cout << "The explorer is terminating." << endl;
return EXIT_SUCCESS; return EXIT_SUCCESS;

@ -14,7 +14,7 @@ set(SOURCE_FILES
CmdLineOptions.cpp CmdLineOptions.cpp
page.h page.h
rpccalls.cpp rpccalls.h rpccalls.cpp rpccalls.h
version.h.in CurrentBlockchainStatus.cpp) version.h.in CurrentBlockchainStatus.cpp MempoolStatus.cpp MempoolStatus.h)
# make static library called libmyxrm # make static library called libmyxrm
# that we are going to link to # that we are going to link to

@ -33,8 +33,6 @@ namespace xmreg
"enable key images file checker") "enable key images file checker")
("enable-output-key-checker", value<bool>()->default_value(false)->implicit_value(true), ("enable-output-key-checker", value<bool>()->default_value(false)->implicit_value(true),
"enable outputs key file checker") "enable outputs key file checker")
("enable-mempool-cache", value<bool>()->default_value(true),
"enable caching of transactions from the mempool")
("enable-json-api", value<bool>()->default_value(true), ("enable-json-api", value<bool>()->default_value(true),
"enable JSON REST api") "enable JSON REST api")
("enable-tx-cache", value<bool>()->default_value(false)->implicit_value(true), ("enable-tx-cache", value<bool>()->default_value(false)->implicit_value(true),
@ -55,10 +53,10 @@ namespace xmreg
"you can specify mainnet url, if you run it on testnet. link will show on front page to mainnet explorer") "you can specify mainnet url, if you run it on testnet. link will show on front page to mainnet explorer")
("no-blocks-on-index", value<string>()->default_value("10"), ("no-blocks-on-index", value<string>()->default_value("10"),
"number of last blocks to be shown on index page") "number of last blocks to be shown on index page")
("network-info-timeout", value<string>()->default_value("1000"),
"maximum time, in milliseconds, to wait for network info availability")
("mempool-info-timeout", value<string>()->default_value("5000"), ("mempool-info-timeout", value<string>()->default_value("5000"),
"maximum time, in milliseconds, to wait for mempool data for the front page") "maximum time, in milliseconds, to wait for mempool data for the front page")
("mempool-refresh-time", value<string>()->default_value("5"),
"time, in seconds, for each refresh of mempool state")
("bc-path,b", value<string>(), ("bc-path,b", value<string>(),
"path to lmdb folder of the blockchain, e.g., ~/.bitmonero/lmdb") "path to lmdb folder of the blockchain, e.g., ~/.bitmonero/lmdb")
("ssl-crt-file", value<string>(), ("ssl-crt-file", value<string>(),

@ -0,0 +1,299 @@
//
// Created by mwo on 28/05/17.
//
#include "MempoolStatus.h"
#include "rpccalls.h"
namespace xmreg
{
using namespace std;
void
MempoolStatus::set_blockchain_variables(MicroCore *_mcore,
Blockchain *_core_storage)
{
mcore = _mcore;
core_storage = _core_storage;
}
void
MempoolStatus::start_mempool_status_thread()
{
// to protect from deviation by zero below.
mempool_refresh_time = std::max<uint64_t>(1, mempool_refresh_time);
if (!is_running)
{
m_thread = boost::thread{[]()
{
try
{
uint64_t loop_index {0};
// so that network status is checked every minute
uint64_t loop_index_divider = std::max<uint64_t>(1, 60 / mempool_refresh_time);
while (true)
{
// we just query network status every minute. No sense
// to do it as frequently as getting mempool data.
if (loop_index % loop_index_divider == 0)
{
if (!MempoolStatus::read_network_info())
{
network_info local_copy = current_network_info;
cerr << " Cant read network info "<< endl;
local_copy.current = false;
current_network_info = local_copy;
}
else
{
cout << "Current network info read, ";
loop_index == 0;
}
}
if (MempoolStatus::read_mempool())
{
vector<mempool_tx> current_mempool_txs = get_mempool_txs();
cout << "mempool status txs: "
<< current_mempool_txs.size()
<< endl;
}
// when we reach top of the blockchain, update
// the emission amount every minute.
boost::this_thread::sleep_for(
boost::chrono::seconds(mempool_refresh_time));
++loop_index;
} // while (true)
}
catch (boost::thread_interrupted&)
{
cout << "Mempool status thread interrupted." << endl;
return;
}
}}; // m_thread = boost::thread{[]()
is_running = true;
} // if (!is_running)
}
bool
MempoolStatus::read_mempool()
{
rpccalls rpc {deamon_url};
string error_msg;
// we populate this variable instead of global mempool_txs
// mempool_txs will be changed only when this function completes.
// this ensures that we don't sent out partial mempool txs to
// other places.
vector<mempool_tx> local_copy_of_mempool_txs;
// get txs in the mempool
std::vector<tx_info> mempool_tx_info;
if (!rpc.get_mempool(mempool_tx_info))
{
cerr << "Getting mempool failed " << endl;
return false;
}
// if dont have tx_blob member, construct tx
// from json obtained from the rpc call
uint64_t mempool_size_kB {0};
for (size_t i = 0; i < mempool_tx_info.size(); ++i)
{
// get transaction info of the tx in the mempool
const tx_info& _tx_info = mempool_tx_info.at(i);
crypto::hash mem_tx_hash = null_hash;
if (epee::string_tools::hex_to_pod(_tx_info.id_hash, mem_tx_hash))
{
transaction tx;
if (!xmreg::make_tx_from_json(_tx_info.tx_json, tx))
{
cerr << "Cant make tx from _tx_info.tx_json" << endl;
return false;
}
crypto::hash tx_hash_reconstructed = get_transaction_hash(tx);
if (mem_tx_hash != tx_hash_reconstructed)
{
cerr << "Hash of reconstructed tx from json does not match "
"what we should get!"
<< endl;
return false;
}
mempool_size_kB += _tx_info.blob_size;
local_copy_of_mempool_txs.push_back(mempool_tx {tx_hash_reconstructed, tx});
mempool_tx& last_tx = local_copy_of_mempool_txs.back();
// key images of inputs
vector<txin_to_key> input_key_imgs;
// public keys and xmr amount of outputs
vector<pair<txout_to_key, uint64_t>> output_pub_keys;
// sum xmr in inputs and ouputs in the given tx
const array<uint64_t, 4>& sum_data = summary_of_in_out_rct(
tx, output_pub_keys, input_key_imgs);
last_tx.receive_time = _tx_info.receive_time;
last_tx.sum_outputs = sum_data[0];
last_tx.sum_inputs = sum_data[1];
last_tx.no_outputs = output_pub_keys.size();
last_tx.no_inputs = input_key_imgs.size();
last_tx.mixin_no = sum_data[2];
last_tx.num_nonrct_inputs = sum_data[3];
last_tx.fee_str = xmreg::xmr_amount_to_str(_tx_info.fee, "{: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.timestamp_str = xmreg::timestamp_to_str_gm(_tx_info.receive_time);
last_tx.txsize = fmt::format("{:0.2f}",
static_cast<double>(_tx_info.blob_size)/1024.0);
} // if (hex_to_pod(_tx_info.id_hash, mem_tx_hash))
} // for (size_t i = 0; i < mempool_tx_info.size(); ++i)
Guard lck (mempool_mutx);
// clear current mempool txs vector
// repopulate it with each execution of read_mempool()
// not very efficient but good enough for now.
mempool_no = local_copy_of_mempool_txs.size();
mempool_size = mempool_size_kB;
mempool_txs = std::move(local_copy_of_mempool_txs);
return true;
}
bool
MempoolStatus::read_network_info()
{
rpccalls rpc {deamon_url};
COMMAND_RPC_GET_INFO::response rpc_network_info;
if (!rpc.get_network_info(rpc_network_info))
{
return false;
}
uint64_t fee_estimated;
string error_msg;
if (!rpc.get_dynamic_per_kb_fee_estimate(
FEE_ESTIMATE_GRACE_BLOCKS,
fee_estimated, error_msg))
{
cerr << "rpc.get_dynamic_per_kb_fee_estimate failed" << endl;
return false;
}
(void) error_msg;
network_info local_copy;
local_copy.status = network_info::get_status_uint(rpc_network_info.status);
local_copy.height = rpc_network_info.height;
local_copy.target_height = rpc_network_info.target_height;
local_copy.difficulty = rpc_network_info.difficulty;
local_copy.target = rpc_network_info.target;
local_copy.hash_rate = (rpc_network_info.difficulty/rpc_network_info.target);
local_copy.tx_count = rpc_network_info.tx_count;
local_copy.tx_pool_size = rpc_network_info.tx_pool_size;
local_copy.alt_blocks_count = rpc_network_info.alt_blocks_count;
local_copy.outgoing_connections_count = rpc_network_info.outgoing_connections_count;
local_copy.incoming_connections_count = rpc_network_info.incoming_connections_count;
local_copy.white_peerlist_size = rpc_network_info.white_peerlist_size;
local_copy.testnet = rpc_network_info.testnet;
local_copy.cumulative_difficulty = rpc_network_info.cumulative_difficulty;
local_copy.block_size_limit = rpc_network_info.block_size_limit;
local_copy.start_time = rpc_network_info.start_time;
epee::string_tools::hex_to_pod(rpc_network_info.top_block_hash, local_copy.top_block_hash);
local_copy.fee_per_kb = fee_estimated;
local_copy.info_timestamp = static_cast<uint64_t>(std::time(nullptr));
local_copy.current = true;
current_network_info = local_copy;
return true;
}
vector<MempoolStatus::mempool_tx>
MempoolStatus::get_mempool_txs()
{
Guard lck (mempool_mutx);
return mempool_txs;
}
vector<MempoolStatus::mempool_tx>
MempoolStatus::get_mempool_txs(uint64_t no_of_tx)
{
Guard lck (mempool_mutx);
no_of_tx = std::min<uint64_t>(no_of_tx, mempool_txs.size());
return vector<mempool_tx>(mempool_txs.begin(), mempool_txs.begin() + no_of_tx);
}
bool
MempoolStatus::is_thread_running()
{
return is_running;
}
bf::path MempoolStatus::blockchain_path {"/home/mwo/.bitmonero/lmdb"};
string MempoolStatus::deamon_url {"http:://127.0.0.1:18081"};
bool MempoolStatus::testnet {false};
atomic<bool> MempoolStatus::is_running {false};
boost::thread MempoolStatus::m_thread;
Blockchain* MempoolStatus::core_storage {nullptr};
xmreg::MicroCore* MempoolStatus::mcore {nullptr};
vector<MempoolStatus::mempool_tx> MempoolStatus::mempool_txs;
atomic<MempoolStatus::network_info> MempoolStatus::current_network_info;
atomic<uint64_t> MempoolStatus::mempool_no {0}; // no of txs
atomic<uint64_t> MempoolStatus::mempool_size {0}; // size in bytes.
uint64_t MempoolStatus::mempool_refresh_time {10};
mutex MempoolStatus::mempool_mutx;
}

@ -0,0 +1,155 @@
//
// Created by mwo on 28/05/17.
//
#ifndef XMRBLOCKS_MEMPOOLSTATUS_H
#define XMRBLOCKS_MEMPOOLSTATUS_H
#include "MicroCore.h"
#include <boost/algorithm/string.hpp>
#include <iostream>
#include <memory>
#include <thread>
#include <mutex>
#include <atomic>
namespace xmreg
{
struct MempoolStatus
{
using Guard = std::lock_guard<std::mutex>;
struct mempool_tx
{
crypto::hash tx_hash;
transaction tx;
uint64_t receive_time {0};
uint64_t sum_inputs {0};
uint64_t sum_outputs {0};
uint64_t no_inputs {0};
uint64_t no_outputs {0};
uint64_t num_nonrct_inputs {0};
uint64_t mixin_no {0};
string fee_str;
string xmr_inputs_str;
string xmr_outputs_str;
string timestamp_str;
string txsize;
};
// to keep network_info in cache
// and to show previous info in case current querry for
// the current info timesout.
struct network_info
{
uint64_t status {0};
uint64_t height {0};
uint64_t target_height {0};
uint64_t difficulty {0};
uint64_t target {0};
uint64_t tx_count {0};
uint64_t tx_pool_size {0};
uint64_t alt_blocks_count {0};
uint64_t outgoing_connections_count {0};
uint64_t incoming_connections_count {0};
uint64_t white_peerlist_size {0};
uint64_t grey_peerlist_size {0};
bool testnet {false};
crypto::hash top_block_hash;
uint64_t cumulative_difficulty {0};
uint64_t block_size_limit {0};
uint64_t start_time {0};
uint64_t hash_rate {0};
uint64_t fee_per_kb {0};
uint64_t info_timestamp {0};
bool current {false};
static uint64_t
get_status_uint(const string& status)
{
if (status == CORE_RPC_STATUS_OK)
return 1;
if (status == CORE_RPC_STATUS_BUSY)
return 2;
// default
return 0;
}
static string
get_status_string(const uint64_t& status)
{
if (status == 1)
return CORE_RPC_STATUS_OK;
if (status == 2)
return CORE_RPC_STATUS_BUSY;
// default
return 0;
}
};
static boost::thread m_thread;
static mutex mempool_mutx;
static atomic<bool> is_running;
static uint64_t mempool_refresh_time;
static atomic<uint64_t> mempool_no; // no of txs
static atomic<uint64_t> mempool_size; // size in bytes.
static bf::path blockchain_path;
static string deamon_url;
static bool testnet;
// make object for accessing the blockchain here
static MicroCore* mcore;
static Blockchain* core_storage;
// vector of mempool transactions that all threads
// can refer to
// <recieved_time, transaction>
static vector<mempool_tx> mempool_txs;
static atomic<network_info> current_network_info;
static void
set_blockchain_variables(MicroCore* _mcore,
Blockchain* _core_storage);
static void
start_mempool_status_thread();
static bool
read_mempool();
static bool
read_network_info();
static vector<mempool_tx>
get_mempool_txs();
// get first no_of_tx from the vector
static vector<mempool_tx>
get_mempool_txs(uint64_t no_of_tx);
static bool
is_thread_running();
};
}
#endif //XMRBLOCKS_MEMPOOLSTATUS_H

File diff suppressed because it is too large Load Diff

@ -61,10 +61,6 @@ rpccalls::get_current_height()
<< deamon_url << endl; << deamon_url << endl;
return 0; return 0;
} }
else
{
cout << "rpc call /getheight OK: " << endl;
}
return res.height; return res.height;
} }
@ -76,26 +72,29 @@ rpccalls::get_mempool(vector<tx_info>& mempool_txs)
COMMAND_RPC_GET_TRANSACTION_POOL::request req; COMMAND_RPC_GET_TRANSACTION_POOL::request req;
COMMAND_RPC_GET_TRANSACTION_POOL::response res; COMMAND_RPC_GET_TRANSACTION_POOL::response res;
std::lock_guard<std::mutex> guard(m_daemon_rpc_mutex); bool r;
if (!connect_to_monero_deamon())
{ {
cerr << "get_mempool: not connected to deamon" << endl; std::lock_guard<std::mutex> guard(m_daemon_rpc_mutex);
return false;
}
bool r = epee::net_utils::invoke_http_json( if (!connect_to_monero_deamon())
"/get_transaction_pool", {
req, res, m_http_client, timeout_time_ms); cerr << "get_mempool: not connected to deamon" << endl;
return false;
}
if (!r) r = epee::net_utils::invoke_http_json(
"/get_transaction_pool",
req, res, m_http_client, timeout_time_ms);
}
if (!r || res.status != CORE_RPC_STATUS_OK)
{ {
cerr << "Error connecting to Monero deamon at " cerr << "Error connecting to Monero deamon at "
<< deamon_url << endl; << deamon_url << endl;
return false; return false;
} }
mempool_txs = res.transactions; mempool_txs = res.transactions;
// mempool txs are not sorted base on their arival time, // mempool txs are not sorted base on their arival time,
@ -107,7 +106,6 @@ rpccalls::get_mempool(vector<tx_info>& mempool_txs)
return t1.receive_time > t2.receive_time; return t1.receive_time > t2.receive_time;
}); });
return true; return true;
} }
@ -151,8 +149,10 @@ bool
rpccalls::get_network_info(COMMAND_RPC_GET_INFO::response& response) rpccalls::get_network_info(COMMAND_RPC_GET_INFO::response& response)
{ {
epee::json_rpc::request<cryptonote::COMMAND_RPC_GET_INFO::request> req_t = AUTO_VAL_INIT(req_t); epee::json_rpc::request<cryptonote::COMMAND_RPC_GET_INFO::request>
epee::json_rpc::response<cryptonote::COMMAND_RPC_GET_INFO::response, std::string> resp_t = AUTO_VAL_INIT(resp_t); req_t = AUTO_VAL_INIT(req_t);
epee::json_rpc::response<cryptonote::COMMAND_RPC_GET_INFO::response, std::string>
resp_t = AUTO_VAL_INIT(resp_t);
bool r {false}; bool r {false};
@ -165,7 +165,7 @@ rpccalls::get_network_info(COMMAND_RPC_GET_INFO::response& response)
if (!connect_to_monero_deamon()) if (!connect_to_monero_deamon())
{ {
cerr << "get_mempool: not connected to deamon" << endl; cerr << "get_network_info: not connected to deamon" << endl;
return false; return false;
} }
@ -226,12 +226,12 @@ rpccalls::get_dynamic_per_kb_fee_estimate(
bool r {false}; bool r {false};
std::lock_guard<std::mutex> guard(m_daemon_rpc_mutex);
{ {
std::lock_guard<std::mutex> guard(m_daemon_rpc_mutex);
if (!connect_to_monero_deamon()) if (!connect_to_monero_deamon())
{ {
cerr << "get_current_height: not connected to deamon" << endl; cerr << "get_dynamic_per_kb_fee_estimate: not connected to deamon" << endl;
return false; return false;
} }
@ -271,6 +271,74 @@ rpccalls::get_dynamic_per_kb_fee_estimate(
fee = resp_t.result.fee; fee = resp_t.result.fee;
return true; return true;
}
bool
rpccalls::get_block(string const& blk_hash, block& blk, string& error_msg)
{
epee::json_rpc::request<COMMAND_RPC_GET_BLOCK::request> req_t;
epee::json_rpc::response<COMMAND_RPC_GET_BLOCK::response, std::string> resp_t;
req_t.jsonrpc = "2.0";
req_t.id = epee::serialization::storage_entry(0);
req_t.method = "getblock";
req_t.params.hash = blk_hash;
bool r {false};
{
std::lock_guard<std::mutex> guard(m_daemon_rpc_mutex);
if (!connect_to_monero_deamon())
{
cerr << "get_block: not connected to deamon" << endl;
return false;
}
r = epee::net_utils::invoke_http_json("/json_rpc",
req_t, resp_t,
m_http_client);
}
string err;
if (r)
{
if (resp_t.result.status == CORE_RPC_STATUS_BUSY)
{
err = "daemon is busy. Please try again later.";
}
else if (resp_t.result.status != CORE_RPC_STATUS_OK)
{
err = resp_t.result.status;
}
if (!err.empty())
{
cerr << "Error connecting to Monero deamon due to "
<< err << endl;
return false;
}
}
else
{
cerr << "get_block: error connecting to Monero deamon at "
<< deamon_url << endl;
return false;
}
std::string block_bin_blob;
if(!epee::string_tools::parse_hexstr_to_binbuff(resp_t.result.blob, block_bin_blob))
return false;
return parse_and_validate_block_from_blob(block_bin_blob, blk);
} }
} }

@ -10,6 +10,51 @@
#include <mutex> #include <mutex>
namespace
{
// can be used to check if given class/struct exist
// from: https://stackoverflow.com/a/10722840/248823
template <typename T>
struct has_destructor
{
// has destructor
template <typename A>
static std::true_type test(decltype(declval<A>().~A()) *)
{
return std::true_type();
}
// no constructor
template <typename A>
static std::false_type test(...)
{
return std::false_type();
}
/* This will be either `std::true_type` or `std::false_type` */
typedef decltype(test<T>(0)) type;
static const bool value = type::value;
};
}
namespace cryptonote
{
// declare struct in monero's cryptonote namespace.
// monero should provide definition for this,
// but we need to have it declared as we are going to
// check if its definition exist or not. depending on this
// we decide what gets to be defined as
// get_alt_blocks(vector<string>& alt_blocks_hashes);
struct COMMAND_RPC_GET_ALT_BLOCKS_HASHES;
}
namespace xmreg namespace xmreg
{ {
@ -18,6 +63,7 @@ using namespace crypto;
using namespace std; using namespace std;
class rpccalls class rpccalls
{ {
string deamon_url ; string deamon_url ;
@ -58,6 +104,84 @@ public:
uint64_t& fee, uint64_t& fee,
string& error_msg); string& error_msg);
/**
* This must be in the header for now, as it will be tempalte function
*
* @param alt_blocks_hashes
* @return bool
*/
template<typename T = COMMAND_RPC_GET_ALT_BLOCKS_HASHES>
typename enable_if<has_destructor<T>::value, bool>::type
get_alt_blocks(vector<string>& alt_blocks_hashes)
{
// definition of COMMAND_RPC_GET_ALT_BLOCKS_HASHES exist
// so perform rpc call to get this information
bool r {false};
typename T::request req;
typename T::response resp;
{
std::lock_guard<std::mutex> guard(m_daemon_rpc_mutex);
if (!connect_to_monero_deamon())
{
cerr << "get_alt_blocks: not connected to deamon" << endl;
return false;
}
r = epee::net_utils::invoke_http_json("/get_alt_blocks_hashes",
req, resp,
m_http_client);
}
string err;
if (r)
{
if (resp.status == CORE_RPC_STATUS_BUSY)
{
err = "daemon is busy. Please try again later.";
}
else if (resp.status != CORE_RPC_STATUS_OK)
{
err = "daemon rpc failed. Please try again later.";
}
if (!err.empty())
{
cerr << "Error connecting to Monero deamon due to "
<< err << endl;
return false;
}
}
else
{
cerr << "Error connecting to Monero deamon at "
<< deamon_url << endl;
return false;
}
alt_blocks_hashes = resp.blks_hashes;
return true;
}
template<typename T = COMMAND_RPC_GET_ALT_BLOCKS_HASHES>
typename enable_if<!has_destructor<T>::value, bool>::type
get_alt_blocks(vector<string>& alt_blocks_hashes)
{
cerr << "COMMAND_RPC_GET_ALT_BLOCKS_HASHES does not exist!" << endl;
// definition of COMMAND_RPC_GET_ALT_BLOCKS_HASHES does NOT exist
// so dont do anything
return false;
}
bool
get_block(string const& blk_hash, block& blk, string& error_msg);
}; };

@ -0,0 +1,25 @@
<h2 style="margin-bottom: 0px">
Alternative blocks
</h2>
<h4 style="font-size: 14px; margin-top: 0px">(no of alt blocks: {{no_alt_blocks}})</h4>
<div class="center">
<table class="center" style="width:80%">
<tr>
<td>height</td>
<td>age</td>
<td>hash</td>
<td>txs no</td>
</tr>
{{#blocks}}
<tr>
<td>{{height}}</td>
<td>{{age}}</td>
<td>{{hash}}</td>
<td>{{no_of_txs}}</td>
</tr>
{{/blocks}}
</table>
</div>

@ -1,7 +1,7 @@
<div class="center"> <div class="center">
<h6 style="margin-top:10px"> <h6 style="margin-top:10px">
<a href="https://github.com/moneroexamples/onion-monero-blockchain-explorer">source code</a> <a href="https://github.com/moneroexamples/onion-monero-blockchain-explorer">source code</a>
| explorer version: {{git_branch_name}}-{{last_git_commit_date}}-{{last_git_commit_hash}} | explorer version (api): {{git_branch_name}}-{{last_git_commit_date}}-{{last_git_commit_hash}} ({{api}})
| monero version: {{monero_version_full}} | monero version: {{monero_version_full}}
</h6> </h6>
</div> </div>

@ -2,9 +2,9 @@
<div class="center"> <div class="center">
<h3 style="font-size: 12px; margin-top: 20px"> <h3 style="font-size: 12px; margin-top: 20px">
Server time: {{server_timestamp}} | <a href="/mempool">Memory pool</a> Server time: {{server_timestamp}} | <a href="/txpool">Transaction pool</a>
{{#enable_pusher}} {{#enable_pusher}}
| <a href="/rawtx">Tx pusher </a> | <a href="/rawtx">Transaction pusher </a>
{{/enable_pusher}} {{/enable_pusher}}
{{#enable_key_image_checker}} {{#enable_key_image_checker}}
| <a href="/rawkeyimgs">Key images checker</a> | <a href="/rawkeyimgs">Key images checker</a>
@ -39,7 +39,7 @@
Network difficulty: {{difficulty}} Network difficulty: {{difficulty}}
| Hash rate: {{hash_rate}} | Hash rate: {{hash_rate}}
| Fee per kb: {{fee_per_kb}} | Fee per kb: {{fee_per_kb}}
| Alternative blocks no: {{alt_blocks_no}} | Median block size limit: {{block_size_limit}} kB
{{^is_current_info}} {{^is_current_info}}
| Data from {{age}} {{age_format}} ago | Data from {{age}} {{age_format}} ago
{{/is_current_info}} {{/is_current_info}}
@ -66,8 +66,6 @@
<h4 style="font-size: 14px; margin-top: 0px">(Median size of these blocks: {{blk_size_median}} kB)</h4> <h4 style="font-size: 14px; margin-top: 0px">(Median size of these blocks: {{blk_size_median}} kB)</h4>
<div class="center"> <div class="center">
<table class="center"> <table class="center">

@ -1,7 +1,7 @@
<h2 style="margin-bottom: 0px"> <h2 style="margin-bottom: 0px">
Memory pool Transaction pool
</h2> </h2>
<h4 style="font-size: 14px; margin-top: 0px">(no of txs: {{mempool_size}}, size: {{mempool_size_kB}} kB)</h4> <h4 style="font-size: 12px; margin-top: 0px">(no of txs: {{mempool_size}}, size: {{mempool_size_kB}} kB, updated every {{ mempool_refresh_time }} seconds)</h4>
<div class="center"> <div class="center">
<table class="center" style="width:80%"> <table class="center" style="width:80%">
@ -30,24 +30,11 @@
{{^mempool_fits_on_front_page}} {{^mempool_fits_on_front_page}}
{{#partial_mempool_shown}} {{#partial_mempool_shown}}
<div class="center" style="text-align: center; margin-bottom: 10px"> <div class="center" style="text-align: center; margin-bottom: 10px">
<a href="/mempool">Only {{no_of_mempool_tx_of_frontpage}} txs shown. Click here to see all of them</a> <a href="/txpool">Only {{no_of_mempool_tx_of_frontpage}} txs shown. Click here to see all of them</a>
</div> </div>
{{/partial_mempool_shown}} {{/partial_mempool_shown}}
{{/mempool_fits_on_front_page}} {{/mempool_fits_on_front_page}}
{{#show_cache_times}}
<div class="center">
<h6 style="margin-top: 1px;color:#949490">
Mempoool tx details construction time: {{construction_time_total}} s
<br/>
includes {{construction_time_cached}} s from mempool cache ({{cache_hits}} hits)
and {{construction_time_non_cached}} s from non cache ({{cache_misses}} misses)
</h6>
</div>
{{/show_cache_times}}
</div> </div>

@ -1,15 +1,15 @@
<h2 style="margin-bottom: 0px"> <h2 style="margin-bottom: 0px">
Memory pool Transaction pool
</h2> </h2>
<h4 style="font-size: 14px; margin-top: 0px"></h4> <h4 style="font-size: 14px; margin-top: 0px"></h4>
<div class="center info" style="text-align: center;width:80%;color:#949490"> <div class="center info" style="text-align: center;width:80%;color:#949490">
<p>Mempool data preparation for the front page failed. <p>Txpool data preparation for the front page failed.
Its processing Its processing
{{#network_info}}{{^is_pool_size_zero}}({{tx_pool_size}} txs){{/is_pool_size_zero}}{{/network_info}} {{#network_info}}{{^is_pool_size_zero}}({{tx_pool_size}} txs){{/is_pool_size_zero}}{{/network_info}}
took longer than expected and it timed out. took longer than expected and it timed out.
To view the mempool without time constrain, To view the txpool without time constrain,
go to dedicated mempool page: <a href="/mempool">memory pool</a> go to dedicated txpool page: <a href="/txpool">memory pool</a>
</p> </p>

@ -151,7 +151,7 @@
{{#show_part_of_inputs}} {{#show_part_of_inputs}}
<h5 style="margin-top: 2px"> <h5 style="margin-top: 2px">
Only {{max_no_of_inputs_to_show}} are inputs shown. To see all, Only {{max_no_of_inputs_to_show}} inputs are shown. To see all,
click "<a href="/tx/{{tx_hash}}/1">more details</a>" click "<a href="/tx/{{tx_hash}}/1">more details</a>"
</h5> </h5>
{{/show_part_of_inputs}} {{/show_part_of_inputs}}

@ -18,7 +18,7 @@
{{^has_error}} {{^has_error}}
<h4 style="color:green">Success</h4> <h4 style="color:green">Success</h4>
<h4> <h4>
Your tx should be already in the mempool waiting to be included Your tx should be already in the txpool waiting to be included
in an upcoming block. in an upcoming block.
</h4> </h4>

@ -3,7 +3,7 @@
{{#no_results}} {{#no_results}}
<h4 style="margin-bottom:2px">Nothing in the blockchain has been found that matches the search term :-(</h4> <h4 style="margin-bottom:2px">Nothing in the blockchain has been found that matches the search term :-(</h4>
<h5 style="margin:2px">Note: there might be 10 block delay between what can be searchable (e.g., key images)</h5> <h5 style="margin:2px">Note: there might be some delay when newest txs become searchable</h5>
{{/no_results}} {{/no_results}}
{{#to_many_results}} {{#to_many_results}}

@ -1,8 +1,22 @@
<div> <div>
{{#txs}} {{#has_error}}
{{>tx_details}} <h4 style="color:red">Attempt failed</h4>
{{/txs}} {{#error_tx_not_found}}
<h4>Tx {{tx_hash}} not found. </h4>
<div class="center" style="text-align: center;width:80%">
<p> If this is newly made tx, it can take some time (up to minute)
for it to get propagated to all nodes' txpools.
<br/><br/>
Please refresh in 10-20 seconds to check if its here then.
</p>
</div>
{{/error_tx_not_found}}
{{/has_error}}
{{^has_error}}
{{#txs}}
{{>tx_details}}
{{/txs}}
{{/has_error}}
</div> </div>

@ -894,16 +894,6 @@ namespace xmreg
return make_pair(empty_time, scale); return make_pair(empty_time, scale);
} }
// useful reference to get epoch time in correct timezon
// http://www.boost.org/doc/libs/1_41_0/doc/html/date_time/examples.html#date_time.examples.seconds_since_epoch
time_t
ptime_to_time_t(const pt::ptime& in_ptime)
{
static pt::ptime epoch(gt::date(1970, 1, 1));
pt::time_duration::sec_type no_seconds = (in_ptime - epoch).total_seconds();
return time_t(no_seconds);
}
bool bool
decode_ringct(const rct::rctSig& rv, decode_ringct(const rct::rctSig& rv,
const crypto::public_key pub, const crypto::public_key pub,

@ -13,9 +13,10 @@
#define REMOVE_HASH_BRAKETS(a_hash) \ #define REMOVE_HASH_BRAKETS(a_hash) \
a_hash.substr(1, a_hash.size()-2) a_hash.substr(1, a_hash.size()-2)
#include "monero_headers.h" #include "monero_headers.h"
#include "../ext/infix_iterator.h"
#include "../ext/fmt/ostream.h" #include "../ext/fmt/ostream.h"
#include "../ext/fmt/format.h" #include "../ext/fmt/format.h"
#include "../ext/json.hpp" #include "../ext/json.hpp"
@ -23,14 +24,14 @@
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <boost/optional.hpp> #include <boost/optional.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <string> #include <string>
#include <vector> #include <vector>
#include <array>
#include <iterator> #include <iterator>
#include <algorithm> #include <algorithm>
#include <type_traits>
/** /**
* Some helper functions used in the example. * Some helper functions used in the example.
@ -45,9 +46,6 @@ namespace xmreg
using namespace std; using namespace std;
namespace bf = boost::filesystem; namespace bf = boost::filesystem;
namespace pt = boost::posix_time;
namespace gt = boost::gregorian;
namespace lt = boost::local_time;
using json = nlohmann::json; using json = nlohmann::json;
@ -139,7 +137,7 @@ namespace xmreg
vector<pair<txout_to_key, uint64_t>>& output_pub_keys, vector<pair<txout_to_key, uint64_t>>& output_pub_keys,
vector<txin_to_key>& input_key_imgs); vector<txin_to_key>& input_key_imgs);
// this version for mempool txs from json // this version for mempool txs from json
array<uint64_t, 6> array<uint64_t, 6>
summary_of_in_out_rct(const json& _json); summary_of_in_out_rct(const json& _json);
@ -216,30 +214,11 @@ namespace xmreg
read(string filename); read(string filename);
/**
* prints an iterable such as vector
*/
template<typename T>
void print_iterable(const T & elems) {
infix_ostream_iterator<typename T::value_type>
oiter(std::cout, ",");
std::cout << "[";
std::copy(elems.begin(), elems.end(),oiter);
std::cout << "]" << std::endl;
}
pair<string, double> pair<string, double>
timestamps_time_scale(const vector<uint64_t>& timestamps, timestamps_time_scale(const vector<uint64_t>& timestamps,
uint64_t timeN, uint64_t resolution = 80, uint64_t timeN, uint64_t resolution = 80,
uint64_t time0 = 1397818193 /* timestamp of the second block */); uint64_t time0 = 1397818193 /* timestamp of the second block */);
time_t
ptime_to_time_t(const pt::ptime& in_ptime);
bool bool
decode_ringct(const rct::rctSig & rv, decode_ringct(const rct::rctSig & rv,
const crypto::public_key pub, const crypto::public_key pub,

Loading…
Cancel
Save