mirror of
https://git.wownero.com/wownero/onion-wownero-blockchain-explorer.git
synced 2024-08-15 00:33:12 +00:00
Merge pull request #75 from moneroexamples/update_to_current_monero
Update to current monero
This commit is contained in:
commit
7eca176e6a
27 changed files with 8502 additions and 5896 deletions
|
@ -100,7 +100,7 @@ set(LIBRARIES
|
||||||
cryptonote_protocol
|
cryptonote_protocol
|
||||||
cryptonote_basic
|
cryptonote_basic
|
||||||
daemonizer
|
daemonizer
|
||||||
cryptoxmr
|
cncrypto
|
||||||
blocks
|
blocks
|
||||||
lmdb
|
lmdb
|
||||||
ringct
|
ringct
|
||||||
|
|
156
README.md
156
README.md
|
@ -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
|
|
||||||
|
|
10308
ext/json.hpp
10308
ext/json.hpp
File diff suppressed because it is too large
Load diff
1913
ext/lmdb++.h
1913
ext/lmdb++.h
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
|
|
113
main.cpp
113
main.cpp
|
@ -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>(),
|
||||||
|
|
299
src/MempoolStatus.cpp
Normal file
299
src/MempoolStatus.cpp
Normal file
|
@ -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;
|
||||||
|
}
|
155
src/MempoolStatus.h
Normal file
155
src/MempoolStatus.h
Normal file
|
@ -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
|
961
src/page.h
961
src/page.h
File diff suppressed because it is too large
Load diff
112
src/rpccalls.cpp
112
src/rpccalls.cpp
|
@ -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;
|
|
||||||
|
if (!connect_to_monero_deamon())
|
||||||
|
{
|
||||||
|
cerr << "get_mempool: not connected to deamon" << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = epee::net_utils::invoke_http_json(
|
||||||
|
"/get_transaction_pool",
|
||||||
|
req, res, m_http_client, timeout_time_ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool r = epee::net_utils::invoke_http_json(
|
if (!r || res.status != CORE_RPC_STATUS_OK)
|
||||||
"/get_transaction_pool",
|
|
||||||
req, res, m_http_client, timeout_time_ms);
|
|
||||||
|
|
||||||
if (!r)
|
|
||||||
{
|
{
|
||||||
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
124
src/rpccalls.h
124
src/rpccalls.h
|
@ -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);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
25
src/templates/altblocks.html
Normal file
25
src/templates/altblocks.html
Normal file
|
@ -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,
|
||||||
|
|
31
src/tools.h
31
src/tools.h
|
@ -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…
Add table
Add a link
Reference in a new issue