Compare commits

...

189 Commits

Author SHA1 Message Date
wowario 8129bc88c1
comment out store_t_to_binary 2021-05-09 22:51:07 +03:00
wowario 1644a31c88 wowified 2021-05-09 22:01:27 +03:00
moneroexamples 2a43e2b9d6
Merge pull request #231 from bigreddmachine/patch-1
Saw a few typos while reading through docs.
2021-05-08 12:34:51 +08:00
Mike C 723a564ba8
Saw a few typos while reading through docs. 2021-05-06 21:52:04 -04:00
moneroexamples 4aefc0da77
Update README.md 2021-04-25 11:49:27 +08:00
moneroexamples 7d0f2fbc87
Update README.md 2021-04-25 11:47:00 +08:00
moneroexamples 58b002cb98
Merge pull request #230 from AtilioA/patch-1
Fix typos
2021-04-12 18:42:58 +08:00
Atílio Antônio 05e7573d91
Fix typos 2021-04-11 10:10:20 -03:00
moneroexamples 175f563194
Merge pull request #229 from moneroexamples/api_tx
Api tx
2021-04-04 15:03:13 +08:00
moneroexamples d31999849a readme and cmake updates 2021-03-27 19:41:31 +08:00
moneroexamples 3c0b4f53bb Add tx_hash to mixins in api/transaction api
https://github.com/moneroexamples/onion-monero-blockchain-explorer/issues/213
2021-03-26 19:44:18 +08:00
moneroexamples 97e756a574
Merge pull request #226 from moneroexamples/revert-224-devel
Revert "addopt byte_slice"
2021-01-29 16:02:37 +08:00
moneroexamples 0f576100ae
Revert "addopt byte_slice" 2021-01-29 16:01:48 +08:00
moneroexamples 18125278ae
Merge pull request #224 from moneroexamples/devel
addopt byte_slice
2021-01-23 15:27:29 +08:00
moneroexamples 29824f1e3e addopt byte_slice 2020-12-18 16:29:42 +08:00
moneroexamples 729af780cf
Update readme to ubuntu 20.04 2020-09-23 21:01:03 +08:00
moneroexamples a715f9c37b Added RCTTypeCLSAG to decode_ringct
https://github.com/moneroexamples/onion-monero-blockchain-explorer/issues/217
2020-09-06 14:41:23 +08:00
moneroexamples 70ffcf68d8
Merge pull request #218 from selsta/mac-system-unbound
cmake: fix build with system unbound on mac
2020-09-05 14:36:25 +08:00
selsta f56113c6ac
cmake: fix build with system unbound on mac 2020-09-04 17:05:38 +02:00
moneroexamples 09653279d1 Fix: monero_crypto_amd64_64_24k_generate_subaddress_public_key
https://github.com/moneroexamples/onion-monero-blockchain-explorer/issues/215#issuecomment-680397635
2020-08-29 13:12:18 +08:00
moneroexamples 4c59750ed2 miniupnpc added 2020-08-24 20:14:43 +08:00
moneroexamples 38f2700fd5
Merge pull request #214 from jmacxx/add_tx_timestamp
Add tx_timestamp to resultset in api/outputs
2020-08-22 11:19:16 +08:00
jmacxx f639419680
Add tx_timestamp to resultset in api/outputs
This would enable the caller to validate that the trade date is not older than expected.
2020-08-21 19:45:20 -05:00
moneroexamples 395d8f4a61
Merge pull request #212 from jmacxx/add_tx_confirmations
Add tx_confirmations to resultset in api/outputs
2020-08-12 18:34:20 +08:00
jmacxx 76bd39a3ec
Add tx_confirmations to resultset in api/outputs
Adding the count of confirmations (tx_confirmations) enables this
API to prove that an XMR transaction has been both sent and
confirmed in the blockchain.
2020-08-10 11:10:12 -05:00
moneroexamples 5fd419de96
Links updates 2020-07-01 20:04:27 +08:00
moneroexamples 039f42e79c
Dead link removed 2020-06-13 20:44:25 +08:00
moneroexamples f12b46cb97
Merge pull request #209 from moneroexamples/devel
For monero v0.16
2020-05-31 09:46:16 +08:00
moneroexamples 9c9d9bede8 Merge branch 'devel' of github.com:moneroexamples/onion-monero-blockchain-explorer into devel 2020-05-31 09:45:21 +08:00
moneroexamples 03a6da502f
Merge pull request #207 from stoffu/osx-cmake
fix link issue on macOS
2020-05-08 06:42:58 +08:00
stoffu c3ffc5b819
fix link issue on macOS 2020-05-07 14:53:38 +09:00
moneroexamples b89275838f
Links updated 2020-04-26 07:04:25 +08:00
moneroexamples ad5eae6c79
Merge pull request #206 from moneroexamples/devel
Some minor fixes merged
2020-04-26 07:03:16 +08:00
moneroexamples b60a147b8b Remove payment id to ascii conversion
https://github.com/moneroexamples/onion-monero-blockchain-explorer/issues/204
2020-02-15 11:07:52 +08:00
moneroexamples cd64eef13a Remove payment id indicators
https://github.com/moneroexamples/onion-monero-blockchain-explorer/issues/203
2020-01-13 07:25:41 +08:00
moneroexamples 746798813e Fix: wrong mempool age
https://github.com/moneroexamples/onion-monero-blockchain-explorer/issues/202
2020-01-07 19:42:11 +08:00
moneroexamples 2b7b07f3be
Merge pull request #201 from moneroexamples/devel
Add --daemon-login option
2019-12-26 07:14:44 +08:00
moneroexamples ebf58cce82 readme updated 2019-12-26 07:12:25 +08:00
moneroexamples 7ae0315482 Add --daemon-login user:pass option
https://github.com/moneroexamples/onion-monero-blockchain-explorer/issues/200
2019-12-15 17:05:49 +08:00
moneroexamples 896eca03c4 rpc and readme updated 2019-12-15 14:34:45 +08:00
moneroexamples e7091da33a
Merge pull request #199 from normoes/add_autorefresh_content_type
Add autorefresh Content-Type.
2019-12-09 06:49:57 +08:00
Norman Moeschter 79f360acef
Add autorefresh Content-Type. 2019-12-08 16:26:52 +00:00
moneroexamples 271931fe56
https://monero.exan.tech/ added to list of links 2019-11-28 10:38:12 +08:00
moneroexamples 7c3a3a95df
Merge pull request #196 from moneroexamples/devel
For monero v0.15
2019-11-25 18:40:27 +08:00
moneroexamples 101203e2bd add --enable-randomx flag 2019-11-05 08:06:11 +08:00
moneroexamples 6a85c3f1e6 readme updated 2019-10-24 16:25:29 +08:00
moneroexamples 69df5ef4b1
Merge pull request #194 from moneroexamples/remove_caches
block and tx caches removed
2019-10-23 19:58:18 +08:00
moneroexamples 21ce4b12d8 fix: wrong difficult on the front page
https://github.com/moneroexamples/onion-monero-blockchain-explorer/issues/195
2019-10-22 09:58:31 +08:00
moneroexamples afca5e9dd6 fix coinbase txs 2019-10-20 06:48:22 +08:00
moneroexamples 143018b5aa remove caches from html template 2019-10-19 08:20:00 +08:00
moneroexamples ad91f74acd add try catch to MicroCore::get_tx 2019-10-16 15:51:00 +08:00
moneroexamples 8663f43f40 block and tx caches removed 2019-10-16 12:30:18 +08:00
moneroexamples 829911cce9 code cleaning 2019-10-05 13:46:59 +08:00
moneroexamples 7f1b7ae3fe fork rx-slow-hash.c 2019-10-05 08:16:07 +08:00
moneroexamples 5583adcc9d fix rx_vm issue 2019-09-26 18:52:35 +08:00
moneroexamples 2e4086ba74 Merge branch 'devel' into randomx 2019-09-26 13:50:14 +08:00
moneroexamples 7dd08632c9 updated to current monero master 2019-09-26 10:54:58 +08:00
moneroexamples dc642db809 Merge branch 'devel' into randomx 2019-09-26 10:09:42 +08:00
moneroexamples e0b47695c0 update cmake to check for other monero path 2019-09-05 15:02:23 +08:00
moneroexamples 5e7e90b9f6
Merge pull request #188 from normoes/autorefresh_tx_page
Add autorefresh on /tx page.
2019-08-23 05:03:58 +08:00
Norman Moeschter 782ca6bc6a
Add autorefresh on /tx page. 2019-08-21 21:48:32 +02:00
moneroexamples 0471556e7e Merge branch 'master' into randomx 2019-06-24 17:49:30 +08:00
moneroexamples 07cc804319
Merge pull request #183 from stoffu/boost-1.7
crow: fix for Boost 1.70
2019-06-24 15:58:28 +08:00
stoffu 76a0efa8ee
crow: fix for Boost 1.70 2019-06-24 14:04:58 +09:00
moneroexamples ae1af46490 Merge branch 'master' into randomx 2019-06-17 16:36:40 +08:00
moneroexamples 89e6b48c2c
Merge pull request #181 from stoffu/diff-128-fix
Display 128bit network difficulty properly
2019-06-17 16:31:30 +08:00
stoffu 2b5646d87c
Display 128bit network difficulty properly 2019-06-17 13:35:29 +09:00
moneroexamples a3bef31ed6
Merge pull request #180 from moneroexamples/devel
For monero v0.14.1
2019-06-16 10:28:57 +08:00
moneroexamples fcc4eec0b7
Update README.md 2019-06-16 08:45:38 +08:00
moneroexamples b81ba5f14d
updated to monero v0.14.1 2019-06-16 08:45:16 +08:00
moneroexamples 993bc23b8c add initial state of registers 2019-06-05 16:46:24 +08:00
moneroexamples dcc4641157 add randomx registers 2019-06-04 18:54:08 +08:00
moneroexamples d32cc0df05 updated to latest randomx 2019-06-02 12:30:59 +08:00
moneroexamples 636179ac53 add mutex to get_randomx_code 2019-05-28 07:57:48 +08:00
moneroexamples a8c3f4072a Merge branch 'randomx' of github.com:moneroexamples/onion-monero-blockchain-explorer into randomx 2019-05-27 13:05:12 +08:00
moneroexamples fd7d0e8800 try to initialize rx_vm if null 2019-05-27 13:05:03 +08:00
moneroexamples a8d3d67099 asm x86 added 2019-05-27 13:05:03 +08:00
moneroexamples 3c15b14759 basic disply of randmox code added 2019-05-27 13:05:03 +08:00
moneroexamples a86e0ca3f1 randomx adding started 2019-05-27 13:05:03 +08:00
moneroexamples 3f9e58316b js removed 2019-05-27 13:05:03 +08:00
moneroexamples de73d22d31 compile against randomx 2019-05-27 13:05:03 +08:00
moneroexamples 2e32839740 concurrency option added 2019-05-27 11:38:46 +08:00
moneroexamples da8368a88d try to initialize rx_vm if null 2019-05-26 12:50:28 +08:00
moneroexamples e22bab9bae asm x86 added 2019-05-25 15:54:32 +08:00
moneroexamples b7ad51e228 basic disply of randmox code added 2019-05-25 13:49:49 +08:00
moneroexamples a7f8900ba6 randomx adding started 2019-05-25 12:46:50 +08:00
moneroexamples 62cd2228fc js removed 2019-05-22 11:48:03 +08:00
moneroexamples 3b5d91588f Merge branch 'randomx' of github.com:moneroexamples/onion-monero-blockchain-explorer into randomx 2019-05-22 10:48:15 +08:00
moneroexamples be6a5cde11 compile against randomx 2019-05-22 10:47:59 +08:00
moneroexamples 7fca3a5df7 add domain_url 2019-05-22 10:38:35 +08:00
moneroexamples 2d9f428f55 compile against randomx 2019-05-19 12:26:53 +08:00
moneroexamples 86dea80659 disable favicon 2019-05-12 15:03:51 +08:00
moneroexamples fb73c1c106
Merge pull request #175 from stoffu/nossl
turn off SSL when connecting to the daemon
2019-04-05 15:06:32 +08:00
stoffu bb3a14ffb5
turn off SSL when connecting to the daemon 2019-04-05 15:24:41 +09:00
moneroexamples ae385ac6b2
Merge pull request #174 from stoffu/diff-128
support 128 bit difficulty type
2019-04-02 11:06:07 +08:00
stoffu d57980fc11
support 128 bit difficulty type 2019-04-02 10:45:23 +09:00
moneroexamples 221fdbf8a8 Fix: no viable conversion from 'cryptonote::difficulty_type
https://github.com/moneroexamples/onion-monero-blockchain-explorer/issues/173
2019-04-02 07:44:06 +08:00
moneroexamples 271addafac make it work with master and release-v0.13 branches 2019-03-16 12:02:44 +08:00
moneroexamples 5a6fab88c8
https://exp.xmr.sk added to clearnet explorers 2019-03-13 16:01:08 +08:00
moneroexamples 73ed903eff add htmlresponse to other endpoints 2019-03-13 08:55:05 +08:00
moneroexamples d45b6b9c46 test content type html response
https://github.com/moneroexamples/onion-monero-blockchain-explorer/issues/160#issuecomment-472205835
2019-03-13 07:19:38 +08:00
moneroexamples 40c08b86f2
Explorer ulrs updated 2019-02-28 08:22:06 +08:00
moneroexamples b108c22a0d
Update README.md 2019-02-27 23:14:51 +08:00
moneroexamples 4711f0bf3a
How to git pull devel branch info added 2019-02-27 23:12:40 +08:00
moneroexamples c05dfcf34a Decoding outputs on v0.14.0.0
https://github.com/moneroexamples/onion-monero-blockchain-explorer/issues/167
2019-02-27 21:48:11 +08:00
moneroexamples 68c474ccb6 Merge branch 'devel' 2019-02-27 16:38:44 +08:00
moneroexamples 6477bbaf98 updated to monero branch release-v013 2019-02-27 16:33:42 +08:00
moneroexamples 8062714896 git clone command corrected 2019-02-19 07:51:49 +08:00
moneroexamples e2bf4a8d68
release-v0.13 info added 2019-02-19 05:35:57 +08:00
moneroexamples 12f5479742 fix: make it compile with recent monero 2019-01-17 14:18:06 +08:00
moneroexamples c7f7719800
Merge pull request #162 from fuwa0529/monero-config-dir
make more directories configurable
2018-12-31 12:21:01 +08:00
fuwa 9fa7828f39 make more directories configurable 2018-12-31 11:33:21 +08:00
moneroexamples a654ce9ea7 Use zeros as default value for payment_id8e 2018-12-04 10:12:17 +08:00
moneroexamples c2c5e0b5f0 outputs fields added 2018-11-30 15:35:11 +08:00
moneroexamples 05f032ee36 block info added 2018-11-30 11:58:57 +08:00
moneroexamples a61e35d4a2 add amount and payment id to show_ringmemberstx_jsonhex 2018-11-30 11:51:46 +08:00
moneroexamples c92e5aa80e sender and recipient placeholders added to show_ringmemberstx_jsonhex 2018-11-30 11:04:08 +08:00
moneroexamples b96ed8de74 show_ringmemberstx_jsonhex added 2018-11-29 12:48:53 +08:00
moneroexamples 57819bec1c fix: get_output_key requires epee::span now 2018-11-28 14:58:03 +08:00
moneroexamples 90cd28c16c show_ringmemberstx_hex added 2018-11-26 13:38:05 +08:00
moneroexamples db8b46eb22 remove ring size from index page and txpool 2018-11-07 16:05:15 +08:00
moneroexamples e2a7325331 Merge branch 'devel' 2018-10-26 08:58:33 +08:00
moneroexamples 910b129963
Merge pull request #156 from stoffu/hidapi
build: replace PCSC with HIDAPI
2018-10-26 08:47:28 +08:00
stoffu f168b4e83a
build: replace PCSC with HIDAPI 2018-10-26 08:39:54 +09:00
moneroexamples a46b1e767a Change fee per kB to fee per byte 2018-10-23 09:45:00 +08:00
moneroexamples 3fbf6497c0 spelling 2018-10-22 10:31:16 +08:00
moneroexamples 7453999415 Fees are shown in micromonero now
https://github.com/moneroexamples/onion-monero-blockchain-explorer/
issues/151
2018-10-22 10:14:15 +08:00
moneroexamples 77d2a98e2f sort txpool txs 2018-10-22 09:23:13 +08:00
moneroexamples ce6f81fd2a Fix for txpool: Failed to parse transaction from blob
https://github.com/moneroexamples/onion-monero-blockchain-explorer/
issues/152
2018-10-22 08:41:59 +08:00
moneroexamples 0d8b568579 Merge branch 'master' of github.com:moneroexamples/onion-monero-blockchain-explorer 2018-10-22 08:21:08 +08:00
moneroexamples afd168cd6c Fix: txpool: Failed to parse transaction from blob
Gets txpool from lmdb now, instead of using RPC call as before.

https://github.com/moneroexamples/onion-monero-blockchain-explorer/
issues/152
2018-10-22 08:19:42 +08:00
moneroexamples e6006acf48
Merge pull request #149 from moneroexamples/devel
For Monero version 0.13
2018-10-17 08:03:18 +08:00
moneroexamples 4bac6731d5 JSON in readme corrected 2018-10-17 07:46:34 +08:00
moneroexamples 71238c481c Readme updated 2018-10-17 07:04:01 +08:00
moneroexamples 66965a562f readme updated 2018-09-19 07:34:18 +08:00
moneroexamples a372972f30 add USE_SINGLE_BUILDDIR=1 to readme 2018-09-15 08:27:46 +08:00
moneroexamples 6a1a6c48f8 port back to C++11 from C++14
https://github.com/moneroexamples/onion-monero-blockchain-explorer/
issues/144
2018-09-14 12:58:03 +08:00
moneroexamples 029d89b98c
Merge pull request #143 from stoffu/support-newbp
Support newbp
2018-09-12 08:19:15 +08:00
stoffu 639be9d767
increase precision of printed fee 2018-09-12 08:55:40 +09:00
stoffu e29a7ba133
fix compile error from boost variant initialization 2018-09-12 08:50:03 +09:00
stoffu 78b6fa32ab
support for the new Bulletproofs format 2018-09-12 08:49:06 +09:00
moneroexamples 083078a47c no_all_possible_mixins added to detailed view 2018-09-06 12:53:36 +08:00
moneroexamples 5fea46c28a fix: no_of_last_blocks if greater than blockchain height
https://github.com/moneroexamples/onion-monero-blockchain-explorer/
issues/141
2018-09-03 07:41:46 +08:00
moneroexamples 3125d4ae0a Formating 2018-08-30 14:33:43 +08:00
moneroexamples a9a9360e11 add amount to map key in show_ringmembers_hex 2018-08-30 14:22:05 +08:00
moneroexamples 33b544d8d7 show_ringmembers_hex modified to use abolute_offsets also 2018-08-28 13:35:55 +08:00
moneroexamples b4631e95e0 sodium dependency added 2018-08-24 14:05:59 +08:00
moneroexamples 306b9b7aad get_tx private method added 2018-08-23 08:32:08 +08:00
moneroexamples 2b78eb4ef1 ring members output info as hex added 2018-08-22 14:44:50 +08:00
moneroexamples 8c8a42656c fix: crypto::generate_chacha_key does not compile 2018-08-20 12:11:35 +08:00
moneroexamples 3e1631643e blockhexcomplete url added 2018-08-07 11:53:25 +08:00
moneroexamples d9c042a1a6 fix: hex also for tx in the mempool 2018-07-24 13:05:37 +08:00
moneroexamples 22a9f6517e --enable-as-hex option added 2018-07-24 12:06:03 +08:00
moneroexamples 2264d1d722 As hex link added to tx details
https://github.com/moneroexamples/onion-monero-blockchain-explorer/issues/133
2018-07-08 15:25:50 +08:00
moneroexamples b408e4b924 improve formating of hash rate 2018-07-07 08:46:02 +08:00
moneroexamples 7bb80afea8 improve formating of hash rate 2018-07-07 08:41:40 +08:00
moneroexamples cfcef1d749 fix: compilation error due to get_transactions
https://github.com/moneroexamples/onion-monero-blockchain-explorer/issues/134
2018-07-04 15:45:39 +08:00
moneroexamples 6948392191
Merge pull request #130 from moneroexamples/tx_full_details_json_call
Adding detailedtransaction json api call
2018-06-22 14:16:25 +08:00
moneroexamples ea0a518af7 adding some code that might be useful later 2018-06-22 14:15:51 +08:00
moneroexamples ad2defbab7 ONIONEXPLORER_RPC_VERSION_MINOR increased by 1 2018-06-20 11:44:44 +08:00
moneroexamples ab12eb64dd some code cleaning 2018-06-18 13:40:54 +08:00
moneroexamples dc1ddacc9c json_detailedtransaction version added 2018-06-18 08:16:53 +08:00
moneroexamples d3e3084272 first version of mstch to json written 2018-06-17 10:53:47 +08:00
moneroexamples d308b31d74 json_detailedtransaction started 2018-06-17 10:07:50 +08:00
moneroexamples ebe4bb7765 started work on detailed info 2018-06-17 08:47:31 +08:00
moneroexamples 9905e916e4 bindaddr (-x) option added
https://github.com/moneroexamples/onion-monero-blockchain-explorer/issues/128
2018-06-17 08:44:11 +08:00
moneroexamples 3bf79c0a8e
Merge pull request #124 from stoffu/diff-pow
Add PoW and difficulty to block info page
2018-06-08 18:22:48 +08:00
stoffu 3c770f4d43
Add PoW and difficulty to block info page 2018-06-08 13:19:21 +09:00
moneroexamples fd4f57282a
Merge pull request #123 from stoffu/mac-pcsc
build: pcsclite is not available for OSX
2018-06-08 11:47:18 +08:00
stoffu 5a06e767cc
build: pcsclite is not available for OSX 2018-06-08 12:24:51 +09:00
moneroexamples 402e3cfbb5 new url added 2018-06-04 09:04:32 +08:00
moneroexamples 5716416c25 readme updated to ubuntu 18.04 2018-06-03 08:39:54 +08:00
moneroexamples 7d250254ea anon namespace removed 2018-06-01 10:38:39 +08:00
moneroexamples da9c0ccee6 readme updated to 0.12.1.0 2018-06-01 08:40:56 +08:00
moneroexamples bf39420c8a fix popping blocks
https://github.com/moneroexamples/onion-monero-blockchain-explorer/issues/119
2018-06-01 08:39:49 +08:00
moneroexamples 35db6a00ca readme corrected 2018-05-13 13:48:37 +08:00
moneroexamples 1b6c8b2bbf Decoding of key images and outputs files fixed
https://github.com/moneroexamples/onion-monero-blockchain-explorer/issues/115
2018-05-13 13:33:03 +08:00
moneroexamples 6625ae6c65 ibpcsclite-dev added to readme 2018-05-10 09:25:57 +08:00
moneroexamples c174aefd32 Merge branch 'devel' of github.com:moneroexamples/onion-monero-blockchain-explorer into devel 2018-05-10 09:20:23 +08:00
moneroexamples 404f6ddec9 Decoding of key images seems fixed. Need still do output file decoding.
https://github.com/moneroexamples/onion-monero-blockchain-explorer/issues/115
2018-05-10 09:20:07 +08:00
moneroexamples 74a0096cdc pcsclite lite added to CMakeLists 2018-05-10 09:20:07 +08:00
moneroexamples 2f1e76cb3b Decoding of key images seems fixed. Need still do output file decoding.
https://github.com/moneroexamples/onion-monero-blockchain-explorer/issues/115
2018-05-09 19:47:28 +08:00
moneroexamples 5996218958 pcsclite lite added to CMakeLists 2018-05-09 19:25:06 +08:00
moneroexamples bf8b2eb05b initialize block_size_limit_str and block_size_median_str 2018-05-02 07:23:14 +08:00
moneroexamples c103a34eba initialize block_size_limit_str and block_size_median_str 2018-05-02 07:18:11 +08:00
moneroexamples c5a89500bd Fix comile ission on ubuntu 16.04 2018-05-01 14:02:26 +08:00
moneroexamples a1d977ba2a new link added 2018-05-01 09:15:17 +08:00
moneroexamples 4c432be311 block_size_median added
https://github.com/moneroexamples/onion-monero-blockchain-explorer/issues/114#issuecomment-384878024
2018-04-28 09:46:30 +08:00
moneroexamples 7765bf06c4 small spelling mistake corrected 2018-04-27 10:00:50 +08:00
48 changed files with 19089 additions and 19596 deletions

1
.gitignore vendored
View File

@ -8,3 +8,4 @@
tests/
build/
cmake-build-debug/
.ycm_extra_conf.py

View File

@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 2.8)
cmake_minimum_required(VERSION 3.0.2)
set(PROJECT_NAME
xmrblocks)
@ -6,9 +6,7 @@ set(PROJECT_NAME
project(${PROJECT_NAME})
set(CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} -std=c++14")
set(CMAKE_CXX_STANDARD 11)
if (WIN32)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wa,-mbig-obj -O3")
@ -16,17 +14,33 @@ endif()
if (NOT MONERO_DIR)
set(MONERO_DIR ~/monero)
set(MONERO_DIR ~/wownero)
endif()
message(STATUS MONERO_DIR ": ${MONERO_DIR}")
set(MONERO_SOURCE_DIR ${MONERO_DIR}
CACHE PATH "Path to the root directory for Monero")
if (NOT MONERO_SOURCE_DIR)
set(MONERO_SOURCE_DIR ${MONERO_DIR}
CACHE PATH "Path to the root directory for Monero")
endif()
# set location of monero build tree
set(MONERO_BUILD_DIR ${MONERO_SOURCE_DIR}/build/release/
CACHE PATH "Path to the build directory for Monero")
if (NOT MONERO_BUILD_DIR)
# set location of monero build tree
set(MONERO_BUILD_DIR ${MONERO_SOURCE_DIR}/build/release/
CACHE PATH "Path to the build directory for Monero")
if (NOT EXISTS ${MONERO_BUILD_DIR})
# try different location
message(STATUS "Trying different folder for monero libraries")
set(MONERO_BUILD_DIR ${MONERO_SOURCE_DIR}/build/Linux/master/release/
CACHE PATH "Path to the build directory for Monero" FORCE)
endif()
endif()
if (NOT EXISTS ${MONERO_BUILD_DIR})
message(FATAL_ERROR "Monero libraries not found in: ${MONERO_BUILD_DIR}")
endif()
set(MY_CMAKE_DIR "${CMAKE_CURRENT_LIST_DIR}/cmake"
CACHE PATH "The path to the cmake directory of the current project")
@ -57,19 +71,43 @@ find_package(Boost COMPONENTS
find_package(Sanitizers)
if(APPLE)
include_directories(/usr/local/opt/openssl/include)
link_directories(/usr/local/opt/openssl/lib)
include_directories(/usr/local/opt/openssl@1.1/include)
link_directories(/usr/local/opt/openssl@1.1/lib)
link_directories(/usr/local/lib)
endif()
MESSAGE(STATUS "Looking for libunbound") # FindUnbound.cmake from monero repo
if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin" OR WIN32)
FIND_PATH(UNBOUND_INCLUDE_DIR
NAMES unbound.h
PATH_SUFFIXES include/ include/unbound/
PATHS "${PROJECT_SOURCE_DIR}"
${UNBOUND_ROOT}
$ENV{UNBOUND_ROOT}
/usr/local/
/usr/
)
find_library (UNBOUND_LIBRARY unbound)
if (WIN32 OR (${UNBOUND_LIBRARY} STREQUAL "UNBOUND_LIBRARY-NOTFOUND"))
add_library(unbound STATIC IMPORTED)
set_property(TARGET unbound PROPERTY IMPORTED_LOCATION ${MONERO_BUILD_DIR}/external/unbound/libunbound.a)
endif()
if("${Xmr_WALLET-CRYPTO_LIBRARIES}" STREQUAL "Xmr_WALLET-CRYPTO_LIBRARY-NOTFOUND")
set(WALLET_CRYPTO "")
else()
set(WALLET_CRYPTO ${Xmr_WALLET-CRYPTO_LIBRARIES})
endif()
# include boost headers
include_directories(${Boost_INCLUDE_DIRS})
# include monero
include_directories(${MONERO_SOURCE_DIR}/build)
include_directories("ext/mstch/include")
include_directories("ext/mstch/include/src")
include_directories("ext/crow")
# add ext/ subfolder
@ -102,23 +140,28 @@ set(LIBRARIES
mstch
wallet
blockchain_db
device
${WALLET_CRYPTO}
cryptonote_core
cryptonote_protocol
cryptonote_basic
multisig
daemonizer
cncrypto
blocks
lmdb
ringct
ringct_basic
device
common
mnemonics
easylogging
checkpoints
cncrypto
miniupnpc
version
epee
hardforks
randomx
sodium
${Boost_LIBRARIES}
pthread
unbound
@ -127,13 +170,21 @@ set(LIBRARIES
ssl)
if(APPLE)
set(LIBRARIES ${LIBRARIES} "-framework IOKit -framework PCSC")
set(LIBRARIES ${LIBRARIES} "-framework IOKit -framework Foundation")
else()
set(LIBRARIES ${LIBRARIES} atomic)
endif()
find_library(UNWIND_LIBRARY unwind)
if (${UNWIND_LIBRARY} STREQUAL "UNWIND_LIBRARY-NOTFOUND")
message (STATUS "unwind library not found")
set (UNWIND_LIBRARY "")
else ()
message (STATUS "Found unwind library: ${UNWIND_LIBRARY}")
endif ()
if (NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin" AND NOT WIN32)
set(LIBRARIES ${LIBRARIES} unwind)
set(LIBRARIES ${LIBRARIES} ${UNWIND_LIBRARY})
endif()
if (WIN32)
@ -147,4 +198,7 @@ else()
set(LIBRARIES ${LIBRARIES} dl)
endif()
find_package(HIDAPI)
set(LIBRARIES ${LIBRARIES} ${HIDAPI_LIBRARIES})
target_link_libraries(${PROJECT_NAME} ${LIBRARIES})

211
README.md
View File

@ -1,11 +1,11 @@
# Onion Monero Blockchain Explorer
Currently available Monero blockchain explorers have several limitations which are of
Currently available Monero blockchain explorers have several limitations which are of
special importance to privacy-oriented users:
- they use JavaScript,
- have images which might be used for [cookieless tracking](http://lucb1e.com/rp/cookielesscookies/),
- track users activates through google analytics,
- track users activities through google analytics,
- are closed sourced,
- are not available as hidden services,
- do not support Monero testnet nor stagenet networks,
@ -13,39 +13,32 @@ special importance to privacy-oriented users:
In this example, these limitations are addressed by development of
an Onion Monero Blockchain Explorer. The example not only shows how to use
an Onion Monero Blockchain Explorer. The example not only shows how to use
Monero C++ libraries, but also demonstrates how to use:
- [crow](https://github.com/ipkn/crow) - C++ micro web framework
- [crow](https://github.com/ipkn/crow) - C++ micro web framework
- [mstch](https://github.com/no1msd/mstch) - C++ {{mustache}} templates
- [json](https://github.com/nlohmann/json) - JSON for Modern C++
- [fmt](https://github.com/fmtlib/fmt) - Small, safe and fast string formatting library
## Addresses
## Explorer hosts
Tor users:
- [http://dvwae436pd7nt4bc.onion](http://dvwae436pd7nt4bc.onion) (Front-end templates are [maintained by @suhz](https://github.com/suhz/onion-monero-blockchain-explorer/tree/moneroexplorer.com/src/templates)).
Clearnet versions:
- [https://xmrchain.net/](https://xmrchain.net/) - https enabled, most popular and very stable.
- [https://MoneroExplorer.com/](https://moneroexplorer.com/) - nice looking one, https enabled.
- [https://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.pro/](https://moneroexplorer.pro/) - nice looking one, https enabled.
- [http://monerochain.com/](http://monerochain.com/) - JSON API based, multiple nodes.
- [https://blox.minexmr.com/](https://blox.minexmr.com/) - - https enabled.
- [https://community.xmr.to/explorer/mainnet/](https://community.xmr.to/explorer/mainnet/)
Testnet version:
- [http://nimis.serveo.net/](http://nimis.serveo.net/) - bleeding edge version (down currently).
- [https://testnet.xmrchain.com/](https://testnet.xmrchain.com/) - https enabled.
- [https://explorer.monero-otc.com/](https://explorer.monero-otc.com/) - https enabled.
Stagenet version:
- [https://community.xmr.to/explorer/testnet/](https://community.xmr.to/explorer/testnet/)
- [http://162.210.173.150:8083/](http://162.210.173.150:8083/) - recent version.
Stagenet version:
- [https://stagenet.xmrchain.net/](https://stagenet.xmrchain.net/)
- [https://community.xmr.to/explorer/stagenet/](https://community.xmr.to/explorer/stagenet/)
i2p users (main Monero network):
@ -53,17 +46,15 @@ i2p users (main Monero network):
Alternative block explorers:
- [http://moneroblocks.info](http://moneroblocks.info/)
- [https://monerobase.com](https://monerobase.com/)
- [http://chainradar.com](http://chainradar.com/xmr/blocks)
- [https://localmonero.co/blocks](https://localmonero.co/blocks)
- [https://monerovision.com](https://monerovision.com)
## Onion Monero Blockchain Explorer features
The key features of the Onion Monero Blockchain Explorer are:
- no cookies, no web analytics trackers, no images,
- by default no JavaScript, but can be enabled for client side decoding and proving transactions,
- open sourced,
- made fully in C++,
- showing encrypted payments ID,
@ -72,14 +63,15 @@ The key features of the Onion Monero Blockchain Explorer are:
- showing public components of Monero addresses,
- decoding which outputs and mixins belong to the given Monero address and viewkey,
- can prove that you send Monero to someone,
- detailed information about mixins, such as, mixins' age, timescale, mixin of mixins,
- detailed information about ring members, such as their age, timescale, and ring sizes,
- showing number of amount output indices,
- support Monero testnet network,
- support Monero testnet and stagnet networks,
- tx checker and pusher for online pushing of transactions,
- estimate possible spendings based on address and viewkey,
- can provide total amount of all miner fees.
- decoding encrypted payment id.
- can provide total amount of all miner fees,
- decoding encrypted payment id,
- decoding outputs and proving txs sent to sub-address.
- listing RandomX code for each block
## Development branch
@ -87,44 +79,29 @@ The key features of the Onion Monero Blockchain Explorer are:
Current development branch:
- https://github.com/moneroexamples/onion-monero-blockchain-explorer/tree/devel
## Compilation on Ubuntu 16.04
Note: `devel` branch of the explorer follows `master` branch of the monero!
##### Compile latest Monero development version
## Compilation on Ubuntu 18.04/20.04
Download and compile recent Monero into your home folder:
```bash
# first install monero dependecines
sudo apt update
#### Monero download and compilation
sudo apt install git build-essential cmake libboost-all-dev miniupnpc libunbound-dev graphviz doxygen libunwind8-dev pkg-config libssl-dev libcurl4-openssl-dev libgtest-dev libreadline-dev libzmq3-dev libsodium-dev
To download and compile recent Monero follow instructions
in the following link:
# go to home folder
cd ~
git clone --recursive https://github.com/monero-project/monero
cd monero/
# checkout last monero version
git checkout -b last_release v0.12.0.0
make
```
https://github.com/moneroexamples/monero-compilation/blob/master/README.md
##### Compile and run the explorer
Once the Monero is compiles, the explorer can be downloaded and compiled
Once the Monero compiles, the explorer can be downloaded and compiled
as follows:
```bash
# go to home folder if still in ~/monero
cd ~
# download the source code
# download the source code
git clone https://github.com/moneroexamples/onion-monero-blockchain-explorer.git
# enter the downloaded sourced code folder
@ -136,20 +113,10 @@ mkdir build && cd build
# create the makefile
cmake ..
# altearnatively can use: cmake -DMONERO_DIR=/path/to/monero_folder ..
# if monero is not in ~/monero
#
# also can build with ASAN (sanitizers), for example
# cmake -DSANITIZE_ADDRESS=On ..
# compile
make
```
When compilation finishes executable `xmrblocks` should be created. Before running
please make sure that `~/Downloads` folder exists and is writable.
Time zone library that explorer is using, puts there
its database of time zone offsets
To run it:
```
@ -157,7 +124,14 @@ To run it:
```
By default it will look for blockchain in its default location i.e., `~/.bitmonero/lmdb`.
You can use `--bc-path` option if its in different location.
You can use `-b` option if its in different location.
For example:
```bash
./xmrblocks -b /home/mwo/non-default-monero-location/lmdb/
```
Example output:
```bash
@ -176,51 +150,54 @@ xmrblocks, Onion Monero Blockchain Explorer:
-t [ --testnet ] [=arg(=1)] (=0) use testnet blockchain
-s [ --stagenet ] [=arg(=1)] (=0) use stagenet blockchain
--enable-pusher [=arg(=1)] (=0) enable signed transaction pusher
--enable-randomx [=arg(=1)] (=0) enable generation of randomx code
--enable-mixin-details [=arg(=1)] (=0)
enable mixin details for key images,
enable mixin details for key images,
e.g., timescale, mixin of mixins, in tx
context
--enable-key-image-checker [=arg(=1)] (=0)
enable key images file checker
--enable-output-key-checker [=arg(=1)] (=0)
enable outputs key file checker
--enable-json-api [=arg(=1)] (=1) enable JSON REST api
--enable-tx-cache [=arg(=1)] (=0) enable caching of transaction details
--show-cache-times [=arg(=1)] (=0) show times of getting data from cache
vs no cache
--enable-block-cache [=arg(=1)] (=0) enable caching of block details
--enable-js [=arg(=1)] (=0) enable checking outputs and proving txs
using JavaScript on client side
--enable-json-api [=arg(=1)] (=0) enable JSON REST api
--enable-as-hex [=arg(=1)] (=0) enable links to provide hex
represtations of a tx and a block
--enable-autorefresh-option [=arg(=1)] (=0)
enable users to have the index page on
enable users to have the index page on
autorefresh
--enable-emission-monitor [=arg(=1)] (=0)
enable Monero total emission monitoring
thread
-p [ --port ] arg (=8081) default explorer port
-x [ --bindaddr ] arg (=0.0.0.0) default bind address for the explorer
--testnet-url arg you can specify testnet url, if you run
it on mainnet or stagenet. link will
it on mainnet or stagenet. link will
show on front page to testnet explorer
--stagenet-url arg you can specify stagenet url, if you
--stagenet-url arg you can specify stagenet url, if you
run it on mainnet or testnet. link will
show on front page to stagenet explorer
--mainnet-url arg you can specify mainnet url, if you run
it on testnet or stagenet. link will
it on testnet or stagenet. link will
show on front page to mainnet explorer
--no-blocks-on-index arg (=10) number of last blocks to be shown on
--no-blocks-on-index arg (=10) number of last blocks to be shown on
index page
--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
--mempool-refresh-time arg (=5) time, in seconds, for each refresh of
--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,
-c [ --concurrency ] arg (=0) number of threads handling http
queries. Default is 0 which means it is
based you on the cpu
-b [ --bc-path ] arg path to lmdb folder of the blockchain,
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)
functionality
--ssl-key-file arg path to key file for ssl (https)
--ssl-key-file arg path to key file for ssl (https)
functionality
-d [ --deamon-url ] arg (=http:://127.0.0.1:18081)
Monero deamon url
Monero daemon url
--daemon-login arg Specify username[:password] for daemon
RPC client
```
Example usage, defined as bash aliases.
@ -233,59 +210,48 @@ alias xmrblocksmainnet='~/onion-monero-blockchain-explorer/build/xmrblocks --
alias xmrblockstestnet='~/onion-monero-blockchain-explorer/build/xmrblocks -t --port 8082 --mainnet-url "http://139.162.32.245:8081" --enable-pusher --enable-emission-monitor'
```
These are aliases similar to those used for http://139.162.32.245:8081/ and http://139.162.32.245:8082/, respectively.
## Enable Monero emission
## Enable Monero emission
Obtaining current Monero emission amount is not straight forward. Thus, by default it is
disabled. To enable it use `--enable-emission-monitor` flag, e.g.,
Obtaining current Monero emission amount is not straight forward. Thus, by default it is
disabled. To enable it use `--enable-emission-monitor` flag, e.g.,
```bash
xmrblocks --enable-emission-monitor
xmrblocks --enable-emission-monitor
```
This flag will enable emission monitoring thread. When started, the thread
will initially scan the entire blockchain, and calculate the cumulative emission based on each block.
Since it is a separate thread, the explorer will work as usual during this time.
Every 10000 blocks, the thread will save current emission in a file, by default,
in `~/.bitmonero/lmdb/emission_amount.txt`. For testnet or stagenet networks,
Since it is a separate thread, the explorer will work as usual during this time.
Every 10000 blocks, the thread will save current emission in a file, by default,
in `~/.bitmonero/lmdb/emission_amount.txt`. For testnet or stagenet networks,
it is `~/.bitmonero/testnet/lmdb/emission_amount.txt` or `~/.bitmonero/stagenet/lmdb/emission_amount.txt`. This file is used so that we don't
need to rescan entire blockchain whenever the explorer is restarted. When the
need to rescan entire blockchain whenever the explorer is restarted. When the
explorer restarts, the thread will first check if `~/.bitmonero/lmdb/emission_amount.txt`
is present, read its values, and continue from there if possible. Subsequently, only the initial
use of the tread is time consuming. Once the thread scans the entire blockchain, it updates
the emission amount using new blocks as they come. Since the explorer writes this file, there can
be only one instance of it running for mainnet, testnet and stagenet. Thus, for example, you cant have
be only one instance of it running for mainnet, testnet and stagenet. Thus, for example, you can't have
two explorers for mainnet
running at the same time, as they will be trying to write and read the same file at the same time,
leading to unexpected results. Off course having one instance for mainnet and one instance for testnet
is fine, as they write to different files.
When the emission monitor is enabled, information about current emission of coinbase and fees is
When the emission monitor is enabled, information about current emission of coinbase and fees is
displayed on the front page, e.g., :
```
Monero emission (fees) is 14485540.430 (52545.373) as of 1313448 block
```
The values given, can be checked using Monero daemon's `print_coinbase_tx_sum` command.
The values given, can be checked using Monero daemon's `print_coinbase_tx_sum` command.
For example, for the above example: `print_coinbase_tx_sum 0 1313449`.
To disable the monitor, simply restart the explorer without `--enable-emission-monitor` flag.
## Enable JavaScript for decoding proving transactions
To disable the monitor, simply restart the explorer without `--enable-emission-monitor` flag.
By default, decoding and proving tx's outputs are done on the server side. To do this on the client side
(private view and tx keys are not send to the server) JavaScript-based decoding can be enabled:
```
xmrblocks --enable-js
```
## Enable SSL (https)
By default, the explorer does not use ssl. But it has such a functionality.
By default, the explorer does not use ssl. But it has such a functionality.
As an example, you can generate your own ssl certificates as follows:
@ -299,12 +265,12 @@ openssl x509 -req -days 3650 -in server.csr -signkey server.key -out server.crt
Having the `crt` and `key` files, run `xmrblocks` in the following way:
```bash
./xmrblocks --ssl-crt-file=/tmp/server.crt --ssl-key-file=/tmp/server.key
./xmrblocks --ssl-crt-file=/tmp/server.crt --ssl-key-file=/tmp/server.key
```
Note: Because we generated our own certificate, modern browsers will complain
about it as they cant verify the signatures against any third party. So probably
for any practical use need to have properly issued ssl certificates.
about it as they can't verify the signatures against any third party. So probably
for any practical use need to have properly issued ssl certificates.
## JSON API
@ -328,8 +294,8 @@ Partial results shown:
"data": {
"block_height": 1268252,
"coinbase": false,
"confirmations": 1,
"current_height": 1268253,
"confirmations": 1057855,
"current_height": 2326107,
"extra": "01be23e277aed6b5f41f66b05244bf994c13108347366ec678ae16657f0fc3a22b",
"inputs": [
{
@ -338,11 +304,13 @@ Partial results shown:
"mixins": [
{
"block_no": 1238623,
"public_key": "0a5b853c55303c10e1326acfb085b9e246e088b1ccac7e37f7a810d46a28a914"
"public_key": "0a5b853c55303c10e1326acfb085b9e246e088b1ccac7e37f7a810d46a28a914",
"tx_hash": "686555fb053dd53f6f9eb79449e2bdcd377221f823f508158d70d4a1966fe955"
},
{
"block_no": 1246942,
"public_key": "527cf86f5abbfb006c970f7c6eb40493786d4751306f8985c6a43f98a88c0dff"
"public_key": "527cf86f5abbfb006c970f7c6eb40493786d4751306f8985c6a43f98a88c0dff",
"tx_hash": "4fa1999f9e0d2ad031dbe5594f2e8336651b6cad19dd3cee7980a01c47600f91"
}
]
}
@ -372,6 +340,7 @@ Partial results shown:
},
"status": "success"
}
```
#### api/transactions
@ -573,7 +542,7 @@ Partial results shown:
For `txprove=0` we check which outputs belong to given address and corresponding viewkey.
For `txprove=1` we use to prove to the recipient that we sent them founds.
For this, we use recipient's address and our tx private key as a viewkey value,
i.e., `viewkey=<tx_private_key>`
i.e., `viewkey=<tx_private_key>`
Checking outputs:
@ -611,10 +580,10 @@ curl -w "\n" -X GET "http://127.0.0.1:8081/api/outputs?txhash=17049bc5f2d9fbca1
Proving transfer:
We use recipient's address (i.e. not our address from which we sent xmr to recipient).
For the viewkey, we use `tx_private_key` (although the GET variable is still called `viewkey`) that we obtained by sending this txs.
For the viewkey, we use `tx_private_key` (although the GET variable is still called `viewkey`) that we obtained by sending this txs.
```bash
# this is for testnet transaction
# this is for testnet transaction
curl -w "\n" -X GET "http://127.0.0.1:8082/api/outputs?txhash=94782a8c0aa8d8768afa0c040ef0544b63eb5148ca971a024ac402cad313d3b3&address=9wUf8UcPUtb2huK7RphBw5PFCyKosKxqtGxbcKBDnzTCPrdNfJjLjtuht87zhTgsffCB21qmjxjj18Pw7cBnRctcKHrUB7N&viewkey=e94b5bfc599d2f741d6f07e3ab2a83f915e96fb374dfb2cd3dbe730e34ecb40b&txprove=1"
```
@ -682,7 +651,7 @@ curl -w "\n" -X GET "http://127.0.0.1:8081/api/networkinfo"
#### api/outputsblocks
Search for our outputs in last few blocks (up to 5 blocks), using provided address and viewkey.
Search for our outputs in last few blocks (up to 5 blocks), using provided address and viewkey.
```bash
@ -693,7 +662,6 @@ curl -w "\n" -X GET http://127.0.0.1:8081/api/outputsblocks?address=9sDyNU82ih1
Example result:
```json
{
{
"data": {
"address": "0182d5be0f708cecf2b6f9889738bde5c930fad846d5b530e021afd1ae7e24a687ad50af3a5d38896655669079ad0163b4a369f6c852cc816dace5fc7792b72f",
@ -763,7 +731,7 @@ curl -w "\n" -X GET "http://127.0.0.1:8081/api/version"
```json
{
"data": {
"api": 65536,
"api": 65536,
"blockchain_height": 1357031,
"git_branch_name": "update_to_current_monero",
"last_git_commit_date": "2017-07-25",
@ -774,7 +742,7 @@ curl -w "\n" -X GET "http://127.0.0.1:8081/api/version"
}
```
api number is store as `uint32_t`. In this case `65536` represents
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:
@ -812,4 +780,3 @@ finished and may not work as intended.
## How can you help?
Constructive criticism, code and website edits are always good. They can be made through github.

60
cmake/FindHIDAPI.cmake Normal file
View File

@ -0,0 +1,60 @@
# - try to find HIDAPI library
# from http://www.signal11.us/oss/hidapi/
#
# Cache Variables: (probably not for direct use in your scripts)
# HIDAPI_INCLUDE_DIR
# HIDAPI_LIBRARY
#
# Non-cache variables you might use in your CMakeLists.txt:
# HIDAPI_FOUND
# HIDAPI_INCLUDE_DIRS
# HIDAPI_LIBRARIES
#
# Requires these CMake modules:
# FindPackageHandleStandardArgs (known included with CMake >=2.6.2)
#
# Original Author:
# 2009-2010 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net>
# http://academic.cleardefinition.com
# Iowa State University HCI Graduate Program/VRAC
#
# Copyright Iowa State University 2009-2010.
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
find_library(HIDAPI_LIBRARY
NAMES hidapi hidapi-libusb)
find_path(HIDAPI_INCLUDE_DIR
NAMES hidapi.h
PATH_SUFFIXES
hidapi)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(HIDAPI
DEFAULT_MSG
HIDAPI_LIBRARY
HIDAPI_INCLUDE_DIR)
if(HIDAPI_FOUND)
set(HIDAPI_LIBRARIES "${HIDAPI_LIBRARY}")
if((STATIC AND UNIX AND NOT APPLE) OR (DEPENDS AND CMAKE_SYSTEM_NAME STREQUAL "Linux"))
find_library(LIBUSB-1.0_LIBRARY usb-1.0)
find_library(LIBUDEV_LIBRARY udev)
if(LIBUSB-1.0_LIBRARY)
set(HIDAPI_LIBRARIES "${HIDAPI_LIBRARIES};${LIBUSB-1.0_LIBRARY}")
if(LIBUDEV_LIBRARY)
set(HIDAPI_LIBRARIES "${HIDAPI_LIBRARIES};${LIBUDEV_LIBRARY}")
else()
message(WARNING "libudev library not found, binaries may fail to link.")
endif()
else()
message(WARNING "libusb-1.0 library not found, binaries may fail to link.")
endif()
endif()
set(HIDAPI_INCLUDE_DIRS "${HIDAPI_INCLUDE_DIR}")
endif()
mark_as_advanced(HIDAPI_INCLUDE_DIR HIDAPI_LIBRARY)

View File

@ -29,8 +29,9 @@
#------------------------------------------------------------------------------
set(LIBS common;blocks;cryptonote_basic;cryptonote_core;multisig;
cryptonote_protocol;daemonizer;mnemonics;epee;lmdb;device;
blockchain_db;ringct;wallet;cncrypto;easylogging;version;checkpoints)
cryptonote_protocol;daemonizer;mnemonics;epee;lmdb;device;wallet-crypto;
blockchain_db;ringct;wallet;cncrypto;easylogging;version;
checkpoints;randomx;hardforks;miniupnpc)
set(Xmr_INCLUDE_DIRS "${CPP_MONERO_DIR}")
@ -44,7 +45,7 @@ foreach (l ${LIBS})
find_library(Xmr_${L}_LIBRARY
NAMES ${l}
PATHS ${CMAKE_LIBRARY_PATH}
PATH_SUFFIXES "/src/${l}" "/src/" "/external/db_drivers/lib${l}" "/lib" "/src/crypto" "/contrib/epee/src" "/external/easylogging++/"
PATH_SUFFIXES "/src/${l}" "/src/" "/external/db_drivers/lib${l}" "/lib" "/src/crypto" "/src/crypto/wallet" "/contrib/epee/src" "/external/easylogging++/" "/external/${l}" "external/miniupnp/miniupnpc" "/external/RandomWOW"
NO_DEFAULT_PATH
)
@ -52,8 +53,10 @@ foreach (l ${LIBS})
message(STATUS FindMonero " Xmr_${L}_LIBRARIES ${Xmr_${L}_LIBRARY}")
add_library(${l} STATIC IMPORTED)
set_property(TARGET ${l} PROPERTY IMPORTED_LOCATION ${Xmr_${L}_LIBRARIES})
if(NOT "${Xmr_${L}_LIBRARIES}" STREQUAL "${Xmr_${L}_LIBRARY-NOTFOUND}")
add_library(${l} STATIC IMPORTED)
set_property(TARGET ${l} PROPERTY IMPORTED_LOCATION ${Xmr_${L}_LIBRARIES})
endif()
endforeach()
@ -70,8 +73,12 @@ message(STATUS ${MONERO_SOURCE_DIR}/build)
# include monero headers
include_directories(
${MONERO_SOURCE_DIR}/src
${MONERO_SOURCE_DIR}/src/crypto
${MONERO_SOURCE_DIR}/src/crypto/wallet
${MONERO_SOURCE_DIR}/external
${MONERO_SOURCE_DIR}/external/RandomWOW/src
${MONERO_SOURCE_DIR}/build
${MONERO_SOURCE_DIR}/external/easylogging++
${MONERO_SOURCE_DIR}/contrib/epee/include
${MONERO_SOURCE_DIR}/external/db_drivers/liblmdb)
${MONERO_SOURCE_DIR}/external/db_drivers/liblmdb
${MONERO_SOURCE_DIR}/generated_include/crypto/wallet)

View File

@ -1,4 +1,5 @@
# first build mstch template library
cmake_minimum_required(VERSION 3.0.2)
add_subdirectory("mstch")

View File

@ -4,6 +4,11 @@
#include <boost/asio/ssl.hpp>
#endif
#include "crow/settings.h"
#if BOOST_VERSION >= 107000
#define GET_IO_SERVICE(s) ((boost::asio::io_context&)(s).get_executor().context())
#else
#define GET_IO_SERVICE(s) ((s).get_io_service())
#endif
namespace crow
{
using namespace boost;
@ -19,7 +24,7 @@ namespace crow
boost::asio::io_service& get_io_service()
{
return socket_.get_io_service();
return GET_IO_SERVICE(socket_);
}
tcp::socket& raw_socket()
@ -94,7 +99,7 @@ namespace crow
boost::asio::io_service& get_io_service()
{
return raw_socket().get_io_service();
return GET_IO_SERVICE(raw_socket());
}
template <typename F>

19501
ext/json.hpp

File diff suppressed because it is too large Load Diff

View File

@ -1,138 +0,0 @@
#ifndef CACHE_HPP
#define CACHE_HPP
#include <cstddef>
#include <limits>
#include <memory>
#include <mutex>
#include <unordered_map>
#include "cache_policy.hpp"
namespace caches
{
// Base class for caching algorithms
template <typename Key, typename Value, typename Policy = NoCachePolicy<Key>>
class fixed_sized_cache
{
public:
using iterator = typename std::unordered_map<Key, Value>::iterator;
using const_iterator =
typename std::unordered_map<Key, Value>::const_iterator;
using operation_guard = typename std::lock_guard<std::mutex>;
fixed_sized_cache(
size_t max_size,
const Policy& policy = Policy())
: max_cache_size{max_size},
cache_policy(policy)
{
if (max_cache_size == 0)
{
max_cache_size = std::numeric_limits<size_t>::max();
}
}
void Put(const Key& key, const Value& value)
{
operation_guard{safe_op};
auto elem_it = FindElem(key);
if (elem_it == cache_items_map.end())
{
// add new element to the cache
if (Size() + 1 > max_cache_size)
{
auto disp_candidate_key = cache_policy.ReplCandidate();
Erase(disp_candidate_key);
}
Insert(key, value);
}
else
{
// update previous value
Update(key, value);
}
}
bool Contains(const Key& key)
{
operation_guard{safe_op};
auto elem_it = FindElem(key);
return elem_it != cache_items_map.end();
}
const Value& Get(const Key& key) const
{
operation_guard{safe_op};
auto elem_it = FindElem(key);
if (elem_it == cache_items_map.end())
{
throw std::range_error{"No such element in the cache"};
}
cache_policy.Touch(key);
return elem_it->second;
}
const size_t Size() const
{
operation_guard{safe_op};
return cache_items_map.size();
}
// return a key of a displacement candidate
void Clear()
{
operation_guard{safe_op};
cache_policy.Clear();
cache_items_map.clear();
}
protected:
void Insert(const Key& key, const Value& value)
{
cache_policy.Insert(key);
cache_items_map.emplace(std::make_pair(key, value));
}
void Erase(const Key& key)
{
cache_policy.Erase(key);
cache_items_map.erase(key);
}
void Update(const Key& key, const Value& value)
{
cache_policy.Touch(key);
cache_items_map[key] = value;
}
const_iterator FindElem(const Key& key) const
{
return cache_items_map.find(key);
}
private:
std::unordered_map<Key, Value> cache_items_map;
mutable Policy cache_policy;
mutable std::mutex safe_op;
size_t max_cache_size;
};
}
#endif // CACHE_HPP

View File

@ -1,77 +0,0 @@
#ifndef CACHE_POLICY_HPP
#define CACHE_POLICY_HPP
#include <unordered_set>
namespace caches
{
template <typename Key>
class ICachePolicy
{
public:
virtual ~ICachePolicy() {}
// handle element insertion in a cache
virtual void Insert(const Key& key) = 0;
// handle request to the key-element in a cache
virtual void Touch(const Key& key) = 0;
// handle element deletion from a cache
virtual void Erase(const Key& key) = 0;
// return a key of a replacement candidate
virtual const Key& ReplCandidate() const = 0;
// clear the cache
virtual void Clear() = 0;
};
template <typename Key>
class NoCachePolicy : public ICachePolicy<Key>
{
public:
NoCachePolicy() = default;
~NoCachePolicy() override = default;
void Insert(const Key& key) override
{
key_storage.emplace(key);
}
void Touch(const Key& key) override
{
// do not do anything
}
void Erase(const Key& key) override
{
key_storage.erase(key);
}
// return a key of a displacement candidate
const Key& ReplCandidate() const override
{
return *key_storage.crbegin();
}
// return a key of a displacement candidate
void Clear() override
{
key_storage.clear();
}
private:
std::unordered_set<Key> key_storage;
};
} // namespace caches
#endif // CACHE_POLICY_HPP

View File

@ -1,53 +0,0 @@
#ifndef FIFO_CACHE_POLICY_HPP
#define FIFO_CACHE_POLICY_HPP
#include <list>
#include "cache_policy.hpp"
namespace caches
{
template <typename Key>
class FIFOCachePolicy : public ICachePolicy<Key>
{
public:
FIFOCachePolicy() = default;
~FIFOCachePolicy() = default;
void Insert(const Key& key) override
{
fifo_queue.emplace_front(key);
}
// handle request to the key-element in a cache
void Touch(const Key& key) override
{
// nothing to do here in the FIFO strategy
}
// handle element deletion from a cache
void Erase(const Key& key) override
{
fifo_queue.pop_back();
}
// return a key of a replacement candidate
const Key& ReplCandidate() const override
{
return fifo_queue.back();
}
// return a key of a displacement candidate
void Clear() override
{
fifo_queue.clear();
}
private:
std::list<Key> fifo_queue;
};
} // namespace caches
#endif // FIFO_CACHE_POLICY_HPP

View File

@ -1,76 +0,0 @@
#ifndef LFU_CACHE_POLICY_HPP
#define LFU_CACHE_POLICY_HPP
#include <cstddef>
#include <unordered_map>
#include <map>
#include <iostream>
#include "cache_policy.hpp"
namespace caches
{
template <typename Key>
class LFUCachePolicy : public ICachePolicy<Key>
{
public:
using lfu_iterator = typename std::multimap<std::size_t, Key>::iterator;
LFUCachePolicy() = default;
~LFUCachePolicy() override = default;
void Insert(const Key& key) override
{
constexpr std::size_t INIT_VAL = 1;
// all new value initialized with the frequency 1
lfu_storage[key] = frequency_storage.emplace_hint(
frequency_storage.cbegin(), INIT_VAL, key);
}
void Touch(const Key& key) override
{
// get the previous frequency value of a key
auto elem_for_update = lfu_storage[key];
auto updated_elem = std::make_pair(
elem_for_update->first + 1, elem_for_update->second);
// update the previous value
frequency_storage.erase(elem_for_update);
lfu_storage[key] = frequency_storage.emplace_hint(
frequency_storage.cend(), std::move(updated_elem));
}
void Erase(const Key& key) override
{
frequency_storage.erase(lfu_storage[key]);
lfu_storage.erase(key);
}
const Key& ReplCandidate() const override
{
// at the beginning of the frequency_storage we have the
// least frequency used value
return frequency_storage.cbegin()->second;
}
// return a key of a displacement candidate
void Clear() override
{
frequency_storage.clear();
lfu_storage.clear();
}
private:
std::multimap<std::size_t, Key> frequency_storage;
std::unordered_map<Key, lfu_iterator> lfu_storage;
};
} // namespace caches
#endif // LFU_CACHE_POLICY_HPP

View File

@ -1,63 +0,0 @@
#ifndef LRU_CACHE_POLICY_HPP
#define LRU_CACHE_POLICY_HPP
#include <list>
#include <unordered_map>
#include "cache_policy.hpp"
namespace caches
{
template <typename Key>
class LRUCachePolicy : public ICachePolicy<Key>
{
public:
using lru_iterator = typename std::list<Key>::const_iterator;
LRUCachePolicy() = default;
~LRUCachePolicy() = default;
void Insert(const Key& key) override
{
lru_queue.emplace_front(key);
key_finder[key] = lru_queue.cbegin();
}
void Touch(const Key& key) override
{
// move the touched element at the beginning of the lru_queue
lru_queue.splice(lru_queue.cbegin(), lru_queue, key_finder[key]);
}
void Erase(const Key& key) override
{
// remove the least recently used element
key_finder.erase(lru_queue.back());
lru_queue.pop_back();
}
// return a key of a displacement candidate
const Key& ReplCandidate() const override
{
return lru_queue.back();
}
// return a key of a displacement candidate
void Clear() override
{
lru_queue.clear();
key_finder.clear();
}
private:
std::list<Key> lru_queue;
std::unordered_map<Key, lru_iterator> key_finder;
};
} // namespace caches
#endif // LRU_CACHE_POLICY_HPP

375
main.cpp
View File

@ -17,7 +17,16 @@ using namespace std;
namespace myxmr
{
struct jsonresponse: crow::response
struct htmlresponse: public crow::response
{
htmlresponse(string&& _body)
: crow::response {std::move(_body)}
{
add_header("Content-Type", "text/html; charset=utf-8");
}
};
struct jsonresponse: public crow::response
{
jsonresponse(const nlohmann::json& _body)
: crow::response {_body.dump()}
@ -32,6 +41,7 @@ struct jsonresponse: crow::response
int
main(int ac, const char* av[])
{
// get command line options
xmreg::CmdLineOptions opts {ac, av};
@ -44,6 +54,7 @@ main(int ac, const char* av[])
}
auto port_opt = opts.get_option<string>("port");
auto bindaddr_opt = opts.get_option<string>("bindaddr");
auto bc_path_opt = opts.get_option<string>("bc-path");
auto deamon_url_opt = opts.get_option<string>("deamon-url");
auto ssl_crt_file_opt = opts.get_option<string>("ssl-crt-file");
@ -54,22 +65,21 @@ main(int ac, const char* av[])
auto mainnet_url = opts.get_option<string>("mainnet-url");
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 daemon_login_opt = opts.get_option<string>("daemon-login");
auto testnet_opt = opts.get_option<bool>("testnet");
auto stagenet_opt = opts.get_option<bool>("stagenet");
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_autorefresh_option_opt = opts.get_option<bool>("enable-autorefresh-option");
auto enable_pusher_opt = opts.get_option<bool>("enable-pusher");
auto enable_js_opt = opts.get_option<bool>("enable-js");
auto enable_randomx_opt = opts.get_option<bool>("enable-randomx");
auto enable_mixin_details_opt = opts.get_option<bool>("enable-mixin-details");
auto enable_json_api_opt = opts.get_option<bool>("enable-json-api");
auto enable_tx_cache_opt = opts.get_option<bool>("enable-tx-cache");
auto enable_block_cache_opt = opts.get_option<bool>("enable-block-cache");
auto show_cache_times_opt = opts.get_option<bool>("show-cache-times");
auto enable_as_hex_opt = opts.get_option<bool>("enable-as-hex");
auto concurrency_opt = opts.get_option<size_t>("concurrency");
auto enable_emission_monitor_opt = opts.get_option<bool>("enable-emission-monitor");
bool testnet {*testnet_opt};
bool stagenet {*stagenet_opt};
@ -84,25 +94,27 @@ main(int ac, const char* av[])
cryptonote::network_type::STAGENET : cryptonote::network_type::MAINNET;
bool enable_pusher {*enable_pusher_opt};
bool enable_js {*enable_js_opt};
bool enable_randomx {*enable_randomx_opt};
bool enable_key_image_checker {*enable_key_image_checker_opt};
bool enable_autorefresh_option {*enable_autorefresh_option_opt};
bool enable_output_key_checker {*enable_output_key_checker_opt};
bool enable_mixin_details {*enable_mixin_details_opt};
bool enable_json_api {*enable_json_api_opt};
bool enable_tx_cache {*enable_tx_cache_opt};
bool enable_block_cache {*enable_block_cache_opt};
bool enable_as_hex {*enable_as_hex_opt};
bool enable_emission_monitor {*enable_emission_monitor_opt};
bool show_cache_times {*show_cache_times_opt};
// set monero log output level
uint32_t log_level = 0;
mlog_configure("", true);
(void) log_level;
//cast port number in string to uint
uint16_t app_port = boost::lexical_cast<uint16_t>(*port_opt);
string bindaddr = *bindaddr_opt;
// cast no_blocks_on_index_opt to uint
uint64_t no_blocks_on_index = boost::lexical_cast<uint64_t>(*no_blocks_on_index_opt);
@ -111,9 +123,41 @@ main(int ac, const char* av[])
string ssl_crt_file;
string ssl_key_file;
xmreg::rpccalls::login_opt daemon_rpc_login {};
if (daemon_login_opt)
{
string user {};
epee::wipeable_string pass {};
string daemon_login = *daemon_login_opt;
size_t colon_location = daemon_login.find_first_of(':');
if (colon_location != std::string::npos)
{
// have colon for user:password
user = daemon_login.substr(0, colon_location);
pass = daemon_login.substr(colon_location + 1);
}
else
{
user = *daemon_login_opt;
}
daemon_rpc_login = epee::net_utils::http::login {user, pass};
//cout << "colon_location: " << colon_location << endl;
// cout << "user: " << user << endl;
// cout << "pass: " << std::string(pass.data(), pass.size()) << endl;
}
// check if ssl enabled and files exist
if (ssl_crt_file_opt and ssl_key_file_opt)
if (ssl_crt_file_opt && ssl_key_file_opt)
{
if (!boost::filesystem::exists(boost::filesystem::path(*ssl_crt_file_opt)))
{
@ -148,9 +192,6 @@ main(int ac, const char* av[])
return EXIT_FAILURE;
}
cout << blockchain_path << endl;
// create instance of our MicroCore
// and make pointer to the Blockchain
xmreg::MicroCore mcore;
@ -158,7 +199,7 @@ main(int ac, const char* av[])
// initialize mcore and core_storage
if (!xmreg::init_blockchain(blockchain_path.string(),
mcore, core_storage))
mcore, core_storage, nettype))
{
cerr << "Error accessing blockchain." << endl;
return EXIT_FAILURE;
@ -166,21 +207,22 @@ main(int ac, const char* av[])
string deamon_url {*deamon_url_opt};
if (testnet && deamon_url == "http:://127.0.0.1:18081")
deamon_url = "http:://127.0.0.1:28081";
if (stagenet && deamon_url == "http:://127.0.0.1:18081")
if (testnet && deamon_url == "http:://127.0.0.1:34568")
deamon_url = "http:://127.0.0.1:11181";
if (stagenet && deamon_url == "http:://127.0.0.1:34568")
deamon_url = "http:://127.0.0.1:38081";
uint64_t mempool_info_timeout {5000};
try
{
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)
{
cout << "Cant cast " << (*mempool_info_timeout_opt) <<" into numbers. Using default values."
<< endl;
cout << "Cant cast " << (*mempool_info_timeout_opt)
<<" into numbers. Using default values.\n";
}
uint64_t mempool_refresh_time {10};
@ -224,9 +266,15 @@ main(int ac, const char* av[])
= nettype;
xmreg::MempoolStatus::deamon_url
= deamon_url;
xmreg::MempoolStatus::login
= daemon_rpc_login;
xmreg::MempoolStatus::set_blockchain_variables(
&mcore, core_storage);
xmreg::MempoolStatus::network_info initial_info;
strcpy(initial_info.block_size_limit_str, "0.0");
strcpy(initial_info.block_size_median_str, "0.0");
xmreg::MempoolStatus::current_network_info = initial_info;
try
{
@ -254,19 +302,18 @@ main(int ac, const char* av[])
deamon_url,
nettype,
enable_pusher,
enable_js,
enable_randomx,
enable_as_hex,
enable_key_image_checker,
enable_output_key_checker,
enable_autorefresh_option,
enable_mixin_details,
enable_tx_cache,
enable_block_cache,
show_cache_times,
no_blocks_on_index,
mempool_info_timeout,
*testnet_url,
*stagenet_url,
*mainnet_url);
*mainnet_url,
daemon_rpc_login);
// crow instance
crow::SimpleApp app;
@ -278,38 +325,107 @@ main(int ac, const char* av[])
};
CROW_ROUTE(app, "/")
([&](const crow::request& req) {
return crow::response(xmrblocks.index2());
([&]() {
return myxmr::htmlresponse(xmrblocks.index2());
});
CROW_ROUTE(app, "/page/<uint>")
([&](size_t page_no) {
return xmrblocks.index2(page_no);
return myxmr::htmlresponse(xmrblocks.index2(page_no));
});
CROW_ROUTE(app, "/block/<uint>")
([&](const crow::request& req, size_t block_height) {
return crow::response(xmrblocks.show_block(block_height));
([&](size_t block_height) {
return myxmr::htmlresponse(xmrblocks.show_block(block_height));
});
CROW_ROUTE(app, "/randomx/<uint>")
([&](size_t block_height) {
return myxmr::htmlresponse(xmrblocks.show_randomx(block_height));
});
CROW_ROUTE(app, "/block/<string>")
([&](const crow::request& req, string block_hash) {
return crow::response(xmrblocks.show_block(remove_bad_chars(block_hash)));
([&](string block_hash) {
return myxmr::htmlresponse(
xmrblocks.show_block(remove_bad_chars(block_hash)));
});
CROW_ROUTE(app, "/tx/<string>")
([&](const crow::request& req, string tx_hash) {
return crow::response(xmrblocks.show_tx(remove_bad_chars(tx_hash)));
([&](string tx_hash) {
return myxmr::htmlresponse(
xmrblocks.show_tx(remove_bad_chars(tx_hash)));
});
if (enable_autorefresh_option)
{
CROW_ROUTE(app, "/tx/<string>/autorefresh")
([&](string tx_hash) {
bool refresh_page {true};
uint16_t with_ring_signatures {0};
return myxmr::htmlresponse(
xmrblocks.show_tx(remove_bad_chars(tx_hash), with_ring_signatures, refresh_page));
});
}
if (enable_as_hex)
{
CROW_ROUTE(app, "/txhex/<string>")
([&](string tx_hash) {
return crow::response(
xmrblocks.show_tx_hex(remove_bad_chars(tx_hash)));
});
CROW_ROUTE(app, "/ringmembershex/<string>")
([&](string tx_hash) {
return crow::response(
xmrblocks.show_ringmembers_hex(remove_bad_chars(tx_hash)));
});
CROW_ROUTE(app, "/blockhex/<uint>")
([&](size_t block_height) {
return crow::response(
xmrblocks.show_block_hex(block_height, false));
});
CROW_ROUTE(app, "/blockhexcomplete/<uint>")
([&](size_t block_height) {
return crow::response(
xmrblocks.show_block_hex(block_height, true));
});
// CROW_ROUTE(app, "/ringmemberstxhex/<string>")
// ([&](string tx_hash) {
// return crow::response(
// xmrblocks.show_ringmemberstx_hex(remove_bad_chars(tx_hash)));
// });
CROW_ROUTE(app, "/ringmemberstxhex/<string>")
([&](string tx_hash) {
return myxmr::jsonresponse {
xmrblocks.show_ringmemberstx_jsonhex(
remove_bad_chars(tx_hash))};
});
}
CROW_ROUTE(app, "/tx/<string>/<uint>")
([&](string tx_hash, uint16_t with_ring_signatures)
{
return xmrblocks.show_tx(remove_bad_chars(tx_hash), with_ring_signatures);
return myxmr::htmlresponse(
xmrblocks.show_tx(remove_bad_chars(tx_hash),
with_ring_signatures));
});
if (enable_autorefresh_option)
{
CROW_ROUTE(app, "/tx/<string>/<uint>/autorefresh")
([&](string tx_hash, uint16_t with_ring_signature) {
bool refresh_page {true};
return myxmr::htmlresponse(
xmrblocks.show_tx(remove_bad_chars(tx_hash), with_ring_signature, refresh_page));
});
}
CROW_ROUTE(app, "/myoutputs").methods("POST"_method)
([&](const crow::request& req)
([&](const crow::request& req) -> myxmr::htmlresponse
{
map<std::string, std::string> post_body
@ -319,7 +435,7 @@ main(int ac, const char* av[])
|| post_body.count("viewkey") == 0
|| post_body.count("tx_hash") == 0)
{
return string("xmr address, viewkey or tx hash not provided");
return string("wow address, viewkey or tx hash not provided");
}
string tx_hash = remove_bad_chars(post_body["tx_hash"]);
@ -332,9 +448,12 @@ main(int ac, const char* av[])
string domain = get_domain(req);
return xmrblocks.show_my_outputs(tx_hash, xmr_address,
string response = xmrblocks.show_my_outputs(
tx_hash, xmr_address,
viewkey, raw_tx_data,
domain);
return myxmr::htmlresponse(std::move(response));
});
CROW_ROUTE(app, "/myoutputs/<string>/<string>/<string>")
@ -344,15 +463,17 @@ main(int ac, const char* av[])
string domain = get_domain(req);
return xmrblocks.show_my_outputs(remove_bad_chars(tx_hash),
return myxmr::htmlresponse(xmrblocks.show_my_outputs(
remove_bad_chars(tx_hash),
remove_bad_chars(xmr_address),
remove_bad_chars(viewkey),
string {},
domain);
domain));
});
CROW_ROUTE(app, "/prove").methods("POST"_method)
([&](const crow::request& req) {
([&](const crow::request& req) -> myxmr::htmlresponse
{
map<std::string, std::string> post_body
= xmreg::parse_crow_post_data(req.body);
@ -361,7 +482,7 @@ main(int ac, const char* av[])
|| post_body.count("txprvkey") == 0
|| post_body.count("txhash") == 0)
{
return string("xmr address, tx private key or "
return string("wow address, tx private key or "
"tx hash not provided");
}
@ -375,41 +496,45 @@ main(int ac, const char* av[])
string domain = get_domain(req);
return xmrblocks.show_prove(tx_hash,
return myxmr::htmlresponse(xmrblocks.show_prove(tx_hash,
xmr_address,
tx_prv_key,
raw_tx_data,
domain);
domain));
});
CROW_ROUTE(app, "/prove/<string>/<string>/<string>")
([&](const crow::request& req, string tx_hash,
string xmr_address, string tx_prv_key) {
string xmr_address, string tx_prv_key)
{
string domain = get_domain(req);
return xmrblocks.show_prove(remove_bad_chars(tx_hash),
return myxmr::htmlresponse(xmrblocks.show_prove(
remove_bad_chars(tx_hash),
remove_bad_chars(xmr_address),
remove_bad_chars(tx_prv_key),
string {},
domain);
domain));
});
if (enable_pusher)
{
CROW_ROUTE(app, "/rawtx")
([&](const crow::request& req) {
return xmrblocks.show_rawtx();
([&]() {
return myxmr::htmlresponse(xmrblocks.show_rawtx());
});
CROW_ROUTE(app, "/checkandpush").methods("POST"_method)
([&](const crow::request& req) {
([&](const crow::request& req) -> myxmr::htmlresponse
{
map<std::string, std::string> post_body
= xmreg::parse_crow_post_data(req.body);
if (post_body.count("rawtxdata") == 0 || post_body.count("action") == 0)
if (post_body.count("rawtxdata") == 0
|| post_body.count("action") == 0)
{
return string("Raw tx data or action not provided");
}
@ -418,9 +543,11 @@ main(int ac, const char* av[])
string action = remove_bad_chars(post_body["action"]);
if (action == "check")
return xmrblocks.show_checkrawtx(raw_tx_data, action);
return myxmr::htmlresponse(
xmrblocks.show_checkrawtx(raw_tx_data, action));
else if (action == "push")
return xmrblocks.show_pushrawtx(raw_tx_data, action);
return myxmr::htmlresponse(
xmrblocks.show_pushrawtx(raw_tx_data, action));
return string("Provided action is neither check nor push");
});
@ -429,12 +556,13 @@ main(int ac, const char* av[])
if (enable_key_image_checker)
{
CROW_ROUTE(app, "/rawkeyimgs")
([&](const crow::request& req) {
return xmrblocks.show_rawkeyimgs();
([&]() {
return myxmr::htmlresponse(xmrblocks.show_rawkeyimgs());
});
CROW_ROUTE(app, "/checkrawkeyimgs").methods("POST"_method)
([&](const crow::request& req) {
([&](const crow::request& req) -> myxmr::htmlresponse
{
map<std::string, std::string> post_body
= xmreg::parse_crow_post_data(req.body);
@ -452,7 +580,8 @@ main(int ac, const char* av[])
string raw_data = remove_bad_chars(post_body["rawkeyimgsdata"]);
string viewkey = remove_bad_chars(post_body["viewkey"]);
return xmrblocks.show_checkrawkeyimgs(raw_data, viewkey);
return myxmr::htmlresponse(
xmrblocks.show_checkrawkeyimgs(raw_data, viewkey));
});
}
@ -460,12 +589,13 @@ main(int ac, const char* av[])
if (enable_output_key_checker)
{
CROW_ROUTE(app, "/rawoutputkeys")
([&](const crow::request& req) {
return xmrblocks.show_rawoutputkeys();
([&]() {
return myxmr::htmlresponse(xmrblocks.show_rawoutputkeys());
});
CROW_ROUTE(app, "/checkrawoutputkeys").methods("POST"_method)
([&](const crow::request& req) {
([&](const crow::request& req) -> myxmr::htmlresponse
{
map<std::string, std::string> post_body
= xmreg::parse_crow_post_data(req.body);
@ -484,25 +614,29 @@ main(int ac, const char* av[])
string raw_data = remove_bad_chars(post_body["rawoutputkeysdata"]);
string viewkey = remove_bad_chars(post_body["viewkey"]);
return xmrblocks.show_checkcheckrawoutput(raw_data, viewkey);
return myxmr::htmlresponse(
xmrblocks.show_checkcheckrawoutput(raw_data, viewkey));
});
}
CROW_ROUTE(app, "/search").methods("GET"_method)
([&](const crow::request& req) {
return xmrblocks.search(remove_bad_chars(string(req.url_params.get("value"))));
return myxmr::htmlresponse(
xmrblocks.search(
remove_bad_chars(
string(req.url_params.get("value")))));
});
CROW_ROUTE(app, "/mempool")
([&](const crow::request& req) {
return xmrblocks.mempool(true);
([&]() {
return myxmr::htmlresponse(xmrblocks.mempool(true));
});
// alias to "/mempool"
CROW_ROUTE(app, "/txpool")
([&](const crow::request& req) {
return xmrblocks.mempool(true);
([&]() {
return myxmr::htmlresponse(xmrblocks.mempool(true));
});
// CROW_ROUTE(app, "/altblocks")
@ -517,71 +651,13 @@ main(int ac, const char* av[])
return text;
});
if (enable_js)
{
cout << "Enable JavaScript checking of outputs and proving txs\n";
CROW_ROUTE(app, "/js/jquery.min.js")
([&](const crow::request& req) {
return xmrblocks.get_js_file("jquery.min.js");
});
CROW_ROUTE(app, "/js/crc32.js")
([&](const crow::request& req) {
return xmrblocks.get_js_file("crc32.js");
});
CROW_ROUTE(app, "/js/biginteger.js")
([&](const crow::request& req) {
return xmrblocks.get_js_file("biginteger.js");
});
CROW_ROUTE(app, "/js/crypto.js")
([&](const crow::request& req) {
return xmrblocks.get_js_file("crypto.js");
});
CROW_ROUTE(app, "/js/config.js")
([&](const crow::request& req) {
return xmrblocks.get_js_file("config.js");
});
CROW_ROUTE(app, "/js/nacl-fast-cn.js")
([&](const crow::request& req) {
return xmrblocks.get_js_file("nacl-fast-cn.js");
});
CROW_ROUTE(app, "/js/base58.js")
([&](const crow::request& req) {
return xmrblocks.get_js_file("base58.js");
});
CROW_ROUTE(app, "/js/cn_util.js")
([&](const crow::request& req) {
return xmrblocks.get_js_file("cn_util.js");
});
CROW_ROUTE(app, "/js/sha3.js")
([&](const crow::request& req) {
return xmrblocks.get_js_file("sha3.js");
});
CROW_ROUTE(app, "/js/all_in_one.js")
([&](const crow::request& req) {
// /js/all_in_one.js file does not exist. it is generated on the fly
// from the above real files.
return xmrblocks.get_js_file("all_in_one.js");
});
} // if (enable_js)
if (enable_json_api)
{
cout << "Enable JSON API\n";
CROW_ROUTE(app, "/api/transaction/<string>")
([&](const crow::request &req, string tx_hash) {
([&](string tx_hash) {
myxmr::jsonresponse r{xmrblocks.json_transaction(remove_bad_chars(tx_hash))};
@ -589,15 +665,23 @@ main(int ac, const char* av[])
});
CROW_ROUTE(app, "/api/rawtransaction/<string>")
([&](const crow::request &req, string tx_hash) {
([&](string tx_hash) {
myxmr::jsonresponse r{xmrblocks.json_rawtransaction(remove_bad_chars(tx_hash))};
return r;
});
CROW_ROUTE(app, "/api/detailedtransaction/<string>")
([&](string tx_hash) {
myxmr::jsonresponse r{xmrblocks.json_detailedtransaction(remove_bad_chars(tx_hash))};
return r;
});
CROW_ROUTE(app, "/api/block/<string>")
([&](const crow::request &req, string block_no_or_hash) {
([&](string block_no_or_hash) {
myxmr::jsonresponse r{xmrblocks.json_block(remove_bad_chars(block_no_or_hash))};
@ -605,7 +689,7 @@ main(int ac, const char* av[])
});
CROW_ROUTE(app, "/api/rawblock/<string>")
([&](const crow::request &req, string block_no_or_hash) {
([&](string block_no_or_hash) {
myxmr::jsonresponse r{xmrblocks.json_rawblock(remove_bad_chars(block_no_or_hash))};
@ -646,7 +730,7 @@ main(int ac, const char* av[])
});
CROW_ROUTE(app, "/api/search/<string>")
([&](const crow::request &req, string search_value) {
([&](string search_value) {
myxmr::jsonresponse r{xmrblocks.json_search(remove_bad_chars(search_value))};
@ -654,7 +738,7 @@ main(int ac, const char* av[])
});
CROW_ROUTE(app, "/api/networkinfo")
([&](const crow::request &req) {
([&]() {
myxmr::jsonresponse r{xmrblocks.json_networkinfo()};
@ -662,7 +746,7 @@ main(int ac, const char* av[])
});
CROW_ROUTE(app, "/api/emission")
([&](const crow::request &req) {
([&]() {
myxmr::jsonresponse r{xmrblocks.json_emission()};
@ -719,13 +803,16 @@ main(int ac, const char* av[])
try
{
in_mempool_aswell = regex_search(req.raw_url, regex {"mempool=[01]"}) ?
boost::lexical_cast<bool>(req.url_params.get("mempool")) :
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;
cerr << "Cant parse tx_prove as bool. Using default value"
<< endl;
}
myxmr::jsonresponse r{xmrblocks.json_outputsblocks(
@ -738,7 +825,7 @@ main(int ac, const char* av[])
});
CROW_ROUTE(app, "/api/version")
([&](const crow::request &req) {
([&]() {
myxmr::jsonresponse r{xmrblocks.json_version()};
@ -753,7 +840,7 @@ main(int ac, const char* av[])
([&]() {
uint64_t page_no {0};
bool refresh_page {true};
return xmrblocks.index2(page_no, refresh_page);
return myxmr::htmlresponse(xmrblocks.index2(page_no, refresh_page));
});
}
@ -762,16 +849,24 @@ main(int ac, const char* av[])
if (use_ssl)
{
cout << "Staring in ssl mode" << endl;
app.port(app_port).ssl_file(ssl_crt_file, ssl_key_file)
app.bindaddr(bindaddr).port(app_port).ssl_file(
ssl_crt_file, ssl_key_file)
.multithreaded().run();
}
else
{
cout << "Staring in non-ssl mode" << endl;
app.port(app_port).multithreaded().run();
if (*concurrency_opt == 0)
{
app.bindaddr(bindaddr).port(app_port).multithreaded().run();
}
else
{
app.bindaddr(bindaddr).port(app_port)
.concurrency(*concurrency_opt).run();
}
}
if (enable_emission_monitor == true)
{
// finish Emission monitoring thread in a cotrolled manner.

View File

@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 2.8)
cmake_minimum_required(VERSION 3.0.2)
project(myxrm)
@ -14,7 +14,13 @@ set(SOURCE_FILES
CmdLineOptions.cpp
page.h
rpccalls.cpp rpccalls.h
version.h.in CurrentBlockchainStatus.cpp MempoolStatus.cpp MempoolStatus.h)
version.h.in
CurrentBlockchainStatus.cpp
MempoolStatus.cpp
MempoolStatus.h)
add_subdirectory(crypto)
# make static library called libmyxrm
# that we are going to link to
@ -22,3 +28,6 @@ set(SOURCE_FILES
add_library(myxrm
STATIC
${SOURCE_FILES})
target_link_libraries(myxrm mycrypto)

View File

@ -18,7 +18,7 @@ namespace xmreg
p.add("txhash", -1);
options_description desc(
"xmrblocks, Onion Monero Blockchain Explorer");
"xmrblocks, Wownero Blockchain Explorer");
desc.add_options()
("help,h", value<bool>()->default_value(false)->implicit_value(true),
@ -29,6 +29,8 @@ namespace xmreg
"use stagenet blockchain")
("enable-pusher", value<bool>()->default_value(false)->implicit_value(true),
"enable signed transaction pusher")
("enable-randomx", value<bool>()->default_value(false)->implicit_value(true),
"enable generation of randomx code")
("enable-mixin-details", value<bool>()->default_value(false)->implicit_value(true),
"enable mixin details for key images, e.g., timescale, mixin of mixins, in tx context")
("enable-key-image-checker", value<bool>()->default_value(false)->implicit_value(true),
@ -37,20 +39,16 @@ namespace xmreg
"enable outputs key file checker")
("enable-json-api", value<bool>()->default_value(false)->implicit_value(true),
"enable JSON REST api")
("enable-tx-cache", value<bool>()->default_value(false)->implicit_value(true),
"enable caching of transaction details")
("show-cache-times", value<bool>()->default_value(false)->implicit_value(true),
"show times of getting data from cache vs no cache")
("enable-block-cache", value<bool>()->default_value(false)->implicit_value(true),
"enable caching of block details")
("enable-js", value<bool>()->default_value(false)->implicit_value(true),
"enable checking outputs and proving txs using JavaScript on client side")
("enable-as-hex", value<bool>()->default_value(false)->implicit_value(true),
"enable links to provide hex represtations of a tx and a block")
("enable-autorefresh-option", value<bool>()->default_value(false)->implicit_value(true),
"enable users to have the index page on autorefresh")
("enable-emission-monitor", value<bool>()->default_value(false)->implicit_value(true),
"enable Monero total emission monitoring thread")
"enable Wownero total emission monitoring thread")
("port,p", value<string>()->default_value("8081"),
"default explorer port")
("bindaddr,x", value<string>()->default_value("0.0.0.0"),
"default bind address for the explorer")
("testnet-url", value<string>()->default_value(""),
"you can specify testnet url, if you run it on mainnet or stagenet. link will show on front page to testnet explorer")
("stagenet-url", value<string>()->default_value(""),
@ -63,14 +61,18 @@ namespace xmreg
"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")
("concurrency,c", value<size_t>()->default_value(0),
"number of threads handling http queries. Default is 0 which means it is based you on the cpu")
("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., ~/.wownero/lmdb")
("ssl-crt-file", value<string>(),
"path to crt file for ssl (https) functionality")
("ssl-key-file", value<string>(),
"path to key file for ssl (https) functionality")
("daemon-login", value<string>(),
"Specify username[:password] for daemon RPC client")
("deamon-url,d", value<string>()->default_value("http:://127.0.0.1:18081"),
"Monero deamon url");
"Monero daemon url");
store(command_line_parser(acc, avv)

View File

@ -137,8 +137,8 @@ CurrentBlockchainStatus::calculate_emission_in_blocks(
uint64_t coinbase_amount = get_outs_money_amount(blk.miner_tx);
std::list<transaction> txs;
std::list<crypto::hash> missed_txs;
vector<transaction> txs;
vector<crypto::hash> missed_txs;
uint64_t tx_fee_amount = 0;
@ -297,13 +297,13 @@ CurrentBlockchainStatus::is_thread_running()
return is_running;
}
bf::path CurrentBlockchainStatus::blockchain_path {"/home/mwo/.bitmonero/lmdb"};
bf::path CurrentBlockchainStatus::blockchain_path {"/home/mwo/.wownero/lmdb"};
cryptonote::network_type CurrentBlockchainStatus::nettype {cryptonote::network_type::MAINNET};
string CurrentBlockchainStatus::output_file {"emission_amount.txt"};
string CurrentBlockchainStatus::deamon_url {"http:://127.0.0.1:18081"};
string CurrentBlockchainStatus::deamon_url {"http:://127.0.0.1:34568"};
uint64_t CurrentBlockchainStatus::blockchain_chunk_size {10000};

View File

@ -4,7 +4,6 @@
#include "MempoolStatus.h"
#include "rpccalls.h"
namespace xmreg
{
@ -97,7 +96,7 @@ MempoolStatus::start_mempool_status_thread()
bool
MempoolStatus::read_mempool()
{
rpccalls rpc {deamon_url};
rpccalls rpc {deamon_url, login};
string error_msg;
@ -110,12 +109,33 @@ MempoolStatus::read_mempool()
// get txs in the mempool
std::vector<tx_info> mempool_tx_info;
if (!rpc.get_mempool(mempool_tx_info))
//std::vector<tx_info> pool_tx_info;
std::vector<spent_key_image_info> pool_key_image_info;
// get txpool from lmdb database instead of rpc call
if (!mcore->get_mempool().get_transactions_and_spent_keys_info(
mempool_tx_info,
pool_key_image_info,
true))
{
cerr << "Getting mempool failed " << endl;
return false;
}
(void) pool_key_image_info;
// sort txpool txs
// mempool txs are not sorted base on their arival time,
// so we sort it here.
std::sort(mempool_tx_info.begin(), mempool_tx_info.end(),
[](tx_info& t1, tx_info& t2)
{
return t1.receive_time > t2.receive_time;
});
// if dont have tx_blob member, construct tx
// from json obtained from the rpc call
@ -139,10 +159,13 @@ MempoolStatus::read_mempool()
mempool_size_kB += _tx_info.blob_size;
local_copy_of_mempool_txs.push_back(mempool_tx {tx_hash, tx});
local_copy_of_mempool_txs.push_back(mempool_tx{});
mempool_tx& last_tx = local_copy_of_mempool_txs.back();
last_tx.tx_hash = tx_hash;
last_tx.tx = tx;
// key images of inputs
vector<txin_to_key> input_key_imgs;
@ -154,7 +177,6 @@ MempoolStatus::read_mempool()
tx, output_pub_keys, input_key_imgs);
double tx_size = static_cast<double>(_tx_info.blob_size)/1024.0;
double payed_for_kB = XMR_AMOUNT(_tx_info.fee) / tx_size;
@ -168,34 +190,16 @@ MempoolStatus::read_mempool()
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}", false);
last_tx.fee_str = xmreg::xmr_amount_to_str(_tx_info.fee, "{:0.4f}", false);
last_tx.fee_micro_str = xmreg::xmr_amount_to_str(_tx_info.fee*1.0e6, "{:04.0f}", false);
last_tx.payed_for_kB_str = fmt::format("{:0.4f}", payed_for_kB);
last_tx.payed_for_kB_micro_str = fmt::format("{:04.0f}", payed_for_kB*1e6);
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}", tx_size);
last_tx.pID = '-';
crypto::hash payment_id;
crypto::hash8 payment_id8;
get_payment_id(tx, payment_id, payment_id8);
if (payment_id != null_hash)
last_tx.pID = 'l'; // legacy payment id
else if (payment_id8 != null_hash8)
last_tx.pID = 'e'; // encrypted payment id
else if (!get_additional_tx_pub_keys_from_extra(tx).empty())
{
// if multioutput tx have additional public keys,
// mark it so that it represents that it has at least
// one sub-address
last_tx.pID = 's';
}
// } // if (hex_to_pod(_tx_info.id_hash, mem_tx_hash))
} // for (size_t i = 0; i < mempool_tx_info.size(); ++i)
@ -218,7 +222,7 @@ MempoolStatus::read_mempool()
bool
MempoolStatus::read_network_info()
{
rpccalls rpc {deamon_url};
rpccalls rpc {deamon_url, login};
COMMAND_RPC_GET_INFO::response rpc_network_info;
@ -251,8 +255,11 @@ MempoolStatus::read_network_info()
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.difficulty_top64 = rpc_network_info.difficulty_top64;
local_copy.target = rpc_network_info.target;
local_copy.hash_rate = (rpc_network_info.difficulty/rpc_network_info.target);
cryptonote::difficulty_type hash_rate = cryptonote::difficulty_type(rpc_network_info.wide_difficulty) / rpc_network_info.target;
local_copy.hash_rate = (hash_rate & 0xFFFFFFFFFFFFFFFF).convert_to<uint64_t>();
local_copy.hash_rate_top64 = ((hash_rate >> 64) & 0xFFFFFFFFFFFFFFFF).convert_to<uint64_t>();
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;
@ -262,11 +269,27 @@ MempoolStatus::read_network_info()
local_copy.nettype = rpc_network_info.testnet ? cryptonote::network_type::TESTNET :
rpc_network_info.stagenet ? cryptonote::network_type::STAGENET : cryptonote::network_type::MAINNET;
local_copy.cumulative_difficulty = rpc_network_info.cumulative_difficulty;
local_copy.cumulative_difficulty_top64 = rpc_network_info.cumulative_difficulty_top64;
local_copy.block_size_limit = rpc_network_info.block_size_limit;
local_copy.block_size_median = rpc_network_info.block_size_median;
local_copy.block_weight_limit = rpc_network_info.block_weight_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);
strncpy(local_copy.block_size_limit_str, fmt::format("{:0.2f}",
static_cast<double>(
local_copy.block_size_limit ) / 2.0 / 1024.0).c_str(),
sizeof(local_copy.block_size_limit_str));
strncpy(local_copy.block_size_median_str, fmt::format("{:0.2f}",
static_cast<double>(
local_copy.block_size_median) / 1024.0).c_str(),
sizeof(local_copy.block_size_median_str));
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));
@ -302,17 +325,18 @@ 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"};
bf::path MempoolStatus::blockchain_path {"/home/mwo/.wownero/lmdb"};
string MempoolStatus::deamon_url {"http:://127.0.0.1:34568"};
cryptonote::network_type MempoolStatus::nettype {cryptonote::network_type::MAINNET};
atomic<bool> MempoolStatus::is_running {false};
boost::thread MempoolStatus::m_thread;
Blockchain* MempoolStatus::core_storage {nullptr};
xmreg::MicroCore* MempoolStatus::mcore {nullptr};
rpccalls::login_opt MempoolStatus::login {};
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;
}
}

View File

@ -7,6 +7,7 @@
#include "MicroCore.h"
#include "rpccalls.h"
#include <boost/algorithm/string.hpp>
@ -38,15 +39,13 @@ struct MempoolStatus
uint64_t mixin_no {0};
string fee_str;
string fee_micro_str;
string payed_for_kB_str;
string payed_for_kB_micro_str;
string xmr_inputs_str;
string xmr_outputs_str;
string timestamp_str;
string txsize;
char pID; // '-' - no payment ID,
// 'l' - legacy, long 64 character payment id,
// 'e' - encrypted, short, from integrated addresses
};
@ -59,6 +58,7 @@ struct MempoolStatus
uint64_t height {0};
uint64_t target_height {0};
uint64_t difficulty {0};
uint64_t difficulty_top64 {0};
uint64_t target {0};
uint64_t tx_count {0};
uint64_t tx_pool_size {0};
@ -70,11 +70,17 @@ struct MempoolStatus
cryptonote::network_type nettype {cryptonote::network_type::MAINNET};
crypto::hash top_block_hash;
uint64_t cumulative_difficulty {0};
uint64_t cumulative_difficulty_top64 {0};
uint64_t block_size_limit {0};
uint64_t block_size_median {0};
uint64_t block_weight_limit {0};
char block_size_limit_str[10]; // needs to be trivially copyable
char block_size_median_str[10]; // std::string is not trivially copyable
uint64_t start_time {0};
uint64_t current_hf_version {0};
uint64_t hash_rate {0};
uint64_t hash_rate_top64 {0};
uint64_t fee_per_kb {0};
uint64_t info_timestamp {0};
@ -122,6 +128,8 @@ struct MempoolStatus
static string deamon_url;
static cryptonote::network_type nettype;
static rpccalls::login_opt login;
// make object for accessing the blockchain here
static MicroCore* mcore;
static Blockchain* core_storage;

View File

@ -5,16 +5,6 @@
#include "MicroCore.h"
namespace
{
// NOTE: These values should match blockchain.cpp
// TODO: Refactor
const uint64_t mainnet_hard_fork_version_1_till = 1009826;
const uint64_t testnet_hard_fork_version_1_till = 624633;
}
namespace xmreg
{
/**
@ -45,31 +35,20 @@ MicroCore::MicroCore():
* Initialize m_blockchain_storage with the BlockchainLMDB object.
*/
bool
MicroCore::init(const string& _blockchain_path)
MicroCore::init(const string& _blockchain_path, network_type nt)
{
int db_flags = 0;
blockchain_path = _blockchain_path;
//db_flags |= MDB_RDONLY;
nettype = nt;
db_flags |= MDB_RDONLY;
db_flags |= MDB_NOLOCK;
//db_flags |= MDB_SYNC;
// uint64_t DEFAULT_FLAGS = MDB_NOMETASYNC | MDB_NORDAHEAD;
//db_flags = DEFAULT_FLAGS;
HardFork* m_hardfork = nullptr;
BlockchainDB* db = nullptr;
db = new BlockchainLMDB();
bool use_testnet {false};
uint64_t hard_fork_version_1_till = use_testnet ? testnet_hard_fork_version_1_till : mainnet_hard_fork_version_1_till;
m_hardfork = new HardFork(*db, 1, hard_fork_version_1_till);
try
{
// try opening lmdb database files
@ -84,13 +63,11 @@ MicroCore::init(const string& _blockchain_path)
// check if the blockchain database
// is successful opened
if(!db->is_open())
{
return false;
}
// initialize Blockchain object to manage
// the database.
return m_blockchain_storage.init(db, m_hardfork, network_type::MAINNET);
return m_blockchain_storage.init(db, nettype);
}
/**
@ -103,6 +80,12 @@ MicroCore::get_core()
return m_blockchain_storage;
}
tx_memory_pool&
MicroCore::get_mempool()
{
return m_mempool;
}
/**
* Get block by its height
*
@ -154,13 +137,31 @@ MicroCore::get_tx(const crypto::hash& tx_hash, transaction& tx)
if (m_blockchain_storage.have_tx(tx_hash))
{
// get transaction with given hash
tx = m_blockchain_storage.get_db().get_tx(tx_hash);
try
{
tx = m_blockchain_storage.get_db().get_tx(tx_hash);
}
catch (TX_DNE const& e)
{
try
{
// coinbase txs are not considered pruned
tx = m_blockchain_storage.get_db().get_pruned_tx(tx_hash);
return true;
}
catch (TX_DNE const& e)
{
cerr << "MicroCore::get_tx: " << e.what() << endl;
}
return false;
}
}
else
{
cerr << "MicroCore::get_tx tx does not exist in blockchain: " << tx_hash << endl;
return false;
}
}
return true;
@ -233,78 +234,6 @@ MicroCore::find_output_in_tx(const transaction& tx,
}
/**
* Returns tx hash in a given block which
* contains given output's public key
*/
bool
MicroCore::get_tx_hash_from_output_pubkey(const public_key& output_pubkey,
const uint64_t& block_height,
crypto::hash& tx_hash,
cryptonote::transaction& tx_found)
{
tx_hash = null_hash;
// get block of given height
block blk;
if (!get_block_by_height(block_height, blk))
{
cerr << "Cant get block of height: " << block_height << endl;
return false;
}
// get all transactions in the block found
// initialize the first list with transaction for solving
// the block i.e. coinbase.
list<transaction> txs {blk.miner_tx};
list<crypto::hash> missed_txs;
if (!m_blockchain_storage.get_transactions(blk.tx_hashes, txs, missed_txs))
{
cerr << "Cant find transcations in block: " << block_height << endl;
return false;
}
if (!missed_txs.empty())
{
cerr << "Transactions not found in blk: " << block_height << endl;
for (const crypto::hash& h : missed_txs)
{
cerr << " - tx hash: " << h << endl;
}
return false;
}
// search outputs in each transactions
// until output with pubkey of interest is found
for (const transaction& tx : txs)
{
tx_out found_out;
// we dont need here output_index
size_t output_index;
if (find_output_in_tx(tx, output_pubkey, found_out, output_index))
{
// we found the desired public key
tx_hash = get_transaction_hash(tx);
tx_found = tx;
return true;
}
}
return false;
}
uint64_t
MicroCore::get_blk_timestamp(uint64_t blk_height)
{
@ -337,11 +266,12 @@ MicroCore::~MicroCore()
bool
init_blockchain(const string& path,
MicroCore& mcore,
Blockchain*& core_storage)
Blockchain*& core_storage,
network_type nt)
{
// initialize the core using the blockchain path
if (!mcore.init(path))
if (!mcore.init(path, nt))
{
cerr << "Error accessing blockchain." << endl;
return false;
@ -354,6 +284,28 @@ init_blockchain(const string& path,
return true;
}
bool
MicroCore::get_block_complete_entry(block const& b, block_complete_entry& bce)
{
bce.block = cryptonote::block_to_blob(b);
for (const auto &tx_hash: b.tx_hashes)
{
transaction tx;
if (!get_tx(tx_hash, tx))
return false;
cryptonote::blobdata txblob = tx_to_blob(tx);
bce.txs.push_back(txblob);
}
return true;
}
string
MicroCore::get_blkchain_path()
{

View File

@ -33,15 +33,20 @@ namespace xmreg
hw::device* m_device;
network_type nettype;
public:
MicroCore();
bool
init(const string& _blockchain_path);
init(const string& _blockchain_path, network_type nt);
Blockchain&
get_core();
tx_memory_pool&
get_mempool();
bool
get_block_by_height(const uint64_t& height, block& blk);
@ -57,15 +62,12 @@ namespace xmreg
tx_out& out,
size_t& output_index);
bool
get_tx_hash_from_output_pubkey(const public_key& output_pubkey,
const uint64_t& block_height,
crypto::hash& tx_hash,
transaction& tx_found);
uint64_t
get_blk_timestamp(uint64_t blk_height);
bool
get_block_complete_entry(block const& b, block_complete_entry& bce);
string
get_blkchain_path();
@ -77,11 +79,11 @@ namespace xmreg
bool
init_blockchain(const string& path,
MicroCore& mcore,
Blockchain*& core_storage);
Blockchain*& core_storage,
network_type nt);
}

14
src/crypto/CMakeLists.txt Normal file
View File

@ -0,0 +1,14 @@
cmake_minimum_required(VERSION 3.0.2)
project(mycrypto)
set(SOURCE_FILES
rx-slow-hash.c)
# make static library called libmyxrm
# that we are going to link to
# in the root CMakeLists.txt file
add_library(mycrypto
STATIC
${SOURCE_FILES})

349
src/crypto/rx-slow-hash.c Normal file
View File

@ -0,0 +1,349 @@
// Copyright (c) 2019, The Monero Project
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "randomx.h"
#include "c_threads.h"
#include "hash-ops.h"
#include "misc_log_ex.h"
#define RX_LOGCAT "randomx"
#if defined(_MSC_VER)
#define THREADV __declspec(thread)
#else
#define THREADV __thread
#endif
typedef struct rx_state {
CTHR_MUTEX_TYPE rs_mutex;
char rs_hash[32];
uint64_t rs_height;
randomx_cache *rs_cache;
} rx_state;
static CTHR_MUTEX_TYPE rx_mutex = CTHR_MUTEX_INIT;
static CTHR_MUTEX_TYPE rx_dataset_mutex = CTHR_MUTEX_INIT;
static rx_state rx_s[2] = {{CTHR_MUTEX_INIT,{0},0,0},{CTHR_MUTEX_INIT,{0},0,0}};
static randomx_dataset *rx_dataset;
static uint64_t rx_dataset_height;
THREADV randomx_vm *rx_vm = NULL;
static THREADV int rx_toggle;
static void local_abort(const char *msg)
{
fprintf(stderr, "%s\n", msg);
#ifdef NDEBUG
_exit(1);
#else
abort();
#endif
}
/**
* @brief uses cpuid to determine if the CPU supports the AES instructions
* @return true if the CPU supports AES, false otherwise
*/
static inline int force_software_aes(void)
{
static int use = -1;
if (use != -1)
return use;
const char *env = getenv("MONERO_USE_SOFTWARE_AES");
if (!env) {
use = 0;
}
else if (!strcmp(env, "0") || !strcmp(env, "no")) {
use = 0;
}
else {
use = 1;
}
return use;
}
static void cpuid(int CPUInfo[4], int InfoType)
{
#if defined(__x86_64__)
__asm __volatile__
(
"cpuid":
"=a" (CPUInfo[0]),
"=b" (CPUInfo[1]),
"=c" (CPUInfo[2]),
"=d" (CPUInfo[3]) :
"a" (InfoType), "c" (0)
);
#endif
}
static inline int check_aes_hw(void)
{
#if defined(__x86_64__)
int cpuid_results[4];
static int supported = -1;
if(supported >= 0)
return supported;
cpuid(cpuid_results,1);
return supported = cpuid_results[2] & (1 << 25);
#else
return 0;
#endif
}
static volatile int use_rx_jit_flag = -1;
static inline int use_rx_jit(void)
{
#if defined(__x86_64__)
if (use_rx_jit_flag != -1)
return use_rx_jit_flag;
const char *env = getenv("MONERO_USE_RX_JIT");
if (!env) {
use_rx_jit_flag = 1;
}
else if (!strcmp(env, "0") || !strcmp(env, "no")) {
use_rx_jit_flag = 0;
}
else {
use_rx_jit_flag = 1;
}
return use_rx_jit_flag;
#else
return 0;
#endif
}
#define SEEDHASH_EPOCH_BLOCKS 2048 /* Must be same as BLOCKS_SYNCHRONIZING_MAX_COUNT in cryptonote_config.h */
#define SEEDHASH_EPOCH_LAG 64
void me_rx_reorg(const uint64_t split_height) {
int i;
CTHR_MUTEX_LOCK(rx_mutex);
for (i=0; i<2; i++) {
if (split_height < rx_s[i].rs_height)
rx_s[i].rs_height = 1; /* set to an invalid seed height */
}
CTHR_MUTEX_UNLOCK(rx_mutex);
}
uint64_t me_rx_seedheight(const uint64_t height) {
uint64_t s_height = (height <= SEEDHASH_EPOCH_BLOCKS+SEEDHASH_EPOCH_LAG) ? 0 :
(height - SEEDHASH_EPOCH_LAG - 1) & ~(SEEDHASH_EPOCH_BLOCKS-1);
return s_height;
}
void me_rx_seedheights(const uint64_t height, uint64_t *seedheight, uint64_t *nextheight) {
*seedheight = me_rx_seedheight(height);
*nextheight = me_rx_seedheight(height + SEEDHASH_EPOCH_LAG);
}
typedef struct seedinfo {
randomx_cache *si_cache;
unsigned long si_start;
unsigned long si_count;
} seedinfo;
static CTHR_THREAD_RTYPE rx_seedthread(void *arg) {
seedinfo *si = arg;
randomx_init_dataset(rx_dataset, si->si_cache, si->si_start, si->si_count);
CTHR_THREAD_RETURN;
}
static void rx_initdata(randomx_cache *rs_cache, const int miners, const uint64_t seedheight) {
if (miners > 1) {
unsigned long delta = randomx_dataset_item_count() / miners;
unsigned long start = 0;
int i;
seedinfo *si;
CTHR_THREAD_TYPE *st;
si = malloc(miners * sizeof(seedinfo));
if (si == NULL)
local_abort("Couldn't allocate RandomX mining threadinfo");
st = malloc(miners * sizeof(CTHR_THREAD_TYPE));
if (st == NULL) {
free(si);
local_abort("Couldn't allocate RandomX mining threadlist");
}
for (i=0; i<miners-1; i++) {
si[i].si_cache = rs_cache;
si[i].si_start = start;
si[i].si_count = delta;
start += delta;
}
si[i].si_cache = rs_cache;
si[i].si_start = start;
si[i].si_count = randomx_dataset_item_count() - start;
for (i=1; i<miners; i++) {
CTHR_THREAD_CREATE(st[i], rx_seedthread, &si[i]);
}
randomx_init_dataset(rx_dataset, rs_cache, 0, si[0].si_count);
for (i=1; i<miners; i++) {
CTHR_THREAD_JOIN(st[i]);
}
free(st);
free(si);
} else {
randomx_init_dataset(rx_dataset, rs_cache, 0, randomx_dataset_item_count());
}
rx_dataset_height = seedheight;
}
void me_rx_slow_hash(const uint64_t mainheight, const uint64_t seedheight, const char *seedhash, const void *data, size_t length,
char *hash, int miners, int is_alt) {
uint64_t s_height = me_rx_seedheight(mainheight);
int changed = 0;
int toggle = is_alt ? s_height : seedheight;
randomx_flags flags = RANDOMX_FLAG_DEFAULT;
rx_state *rx_sp;
randomx_cache *cache;
toggle = (toggle & SEEDHASH_EPOCH_BLOCKS) != 0;
CTHR_MUTEX_LOCK(rx_mutex);
/* if alt block but with same seed as mainchain, no need for alt cache */
if (is_alt && s_height == seedheight && !memcmp(rx_s[toggle].rs_hash, seedhash, sizeof(rx_s[toggle].rs_hash)))
is_alt = 0;
/* RPC could request an earlier block on mainchain */
if (!is_alt && s_height > seedheight)
is_alt = 1;
toggle ^= (is_alt != 0);
if (toggle != rx_toggle)
changed = 1;
rx_toggle = toggle;
rx_sp = &rx_s[toggle];
CTHR_MUTEX_LOCK(rx_sp->rs_mutex);
CTHR_MUTEX_UNLOCK(rx_mutex);
cache = rx_sp->rs_cache;
if (cache == NULL) {
if (use_rx_jit())
flags |= RANDOMX_FLAG_JIT;
if (cache == NULL) {
cache = randomx_alloc_cache(flags | RANDOMX_FLAG_LARGE_PAGES);
if (cache == NULL) {
mdebug(RX_LOGCAT, "Couldn't use largePages for RandomX cache");
cache = randomx_alloc_cache(flags);
}
if (cache == NULL)
local_abort("Couldn't allocate RandomX cache");
}
}
if (rx_sp->rs_height != seedheight || rx_sp->rs_cache == NULL || memcmp(seedhash, rx_sp->rs_hash, sizeof(rx_sp->rs_hash))) {
randomx_init_cache(cache, seedhash, 32);
rx_sp->rs_cache = cache;
rx_sp->rs_height = seedheight;
memcpy(rx_sp->rs_hash, seedhash, sizeof(rx_sp->rs_hash));
changed = 1;
}
if (rx_vm == NULL) {
randomx_flags flags = RANDOMX_FLAG_DEFAULT;
if (use_rx_jit()) {
flags |= RANDOMX_FLAG_JIT;
if (!miners)
flags |= RANDOMX_FLAG_SECURE;
}
if(!force_software_aes() && check_aes_hw())
flags |= RANDOMX_FLAG_HARD_AES;
if (miners) {
CTHR_MUTEX_LOCK(rx_dataset_mutex);
if (rx_dataset == NULL) {
rx_dataset = randomx_alloc_dataset(RANDOMX_FLAG_LARGE_PAGES);
if (rx_dataset == NULL) {
mdebug(RX_LOGCAT, "Couldn't use largePages for RandomX dataset");
rx_dataset = randomx_alloc_dataset(RANDOMX_FLAG_DEFAULT);
}
if (rx_dataset != NULL)
rx_initdata(rx_sp->rs_cache, miners, seedheight);
}
if (rx_dataset != NULL)
flags |= RANDOMX_FLAG_FULL_MEM;
else {
miners = 0;
mwarning(RX_LOGCAT, "Couldn't allocate RandomX dataset for miner");
}
CTHR_MUTEX_UNLOCK(rx_dataset_mutex);
}
rx_vm = randomx_create_vm(flags | RANDOMX_FLAG_LARGE_PAGES, rx_sp->rs_cache, rx_dataset);
if(rx_vm == NULL) { //large pages failed
mdebug(RX_LOGCAT, "Couldn't use largePages for RandomX VM");
rx_vm = randomx_create_vm(flags, rx_sp->rs_cache, rx_dataset);
}
if(rx_vm == NULL) {//fallback if everything fails
flags = RANDOMX_FLAG_DEFAULT | (miners ? RANDOMX_FLAG_FULL_MEM : 0);
rx_vm = randomx_create_vm(flags, rx_sp->rs_cache, rx_dataset);
}
if (rx_vm == NULL)
local_abort("Couldn't allocate RandomX VM");
} else if (miners) {
CTHR_MUTEX_LOCK(rx_dataset_mutex);
if (rx_dataset != NULL && rx_dataset_height != seedheight)
rx_initdata(cache, miners, seedheight);
CTHR_MUTEX_UNLOCK(rx_dataset_mutex);
} else if (changed) {
randomx_vm_set_cache(rx_vm, rx_sp->rs_cache);
}
/* mainchain users can run in parallel */
if (!is_alt)
CTHR_MUTEX_UNLOCK(rx_sp->rs_mutex);
randomx_calculate_hash(rx_vm, data, length, hash);
/* altchain slot users always get fully serialized */
if (is_alt)
CTHR_MUTEX_UNLOCK(rx_sp->rs_mutex);
}
void me_rx_slow_hash_allocate_state(void) {
}
void me_rx_slow_hash_free_state(void) {
if (rx_vm != NULL) {
randomx_destroy_vm(rx_vm);
rx_vm = NULL;
}
}

11557
src/page.h

File diff suppressed because it is too large Load Diff

View File

@ -8,7 +8,9 @@ namespace xmreg
{
rpccalls::rpccalls(string _deamon_url,
rpccalls::rpccalls(
string _deamon_url,
login_opt login,
uint64_t _timeout)
: deamon_url {_deamon_url},
timeout_time {_timeout}
@ -17,11 +19,12 @@ rpccalls::rpccalls(string _deamon_url,
port = std::to_string(url.port);
timeout_time_ms = std::chrono::milliseconds {timeout_time};
timeout_time_ms = std::chrono::milliseconds {timeout_time};
m_http_client.set_server(
deamon_url,
boost::optional<epee::net_utils::http::login>{});
m_http_client.set_server(
deamon_url,
login,
epee::net_utils::ssl_support_t::e_ssl_support_disabled);
}
bool
@ -275,9 +278,9 @@ rpccalls::get_dynamic_per_kb_fee_estimate(
uint64_t& fee,
string& error_msg)
{
epee::json_rpc::request<COMMAND_RPC_GET_PER_KB_FEE_ESTIMATE::request>
epee::json_rpc::request<COMMAND_RPC_GET_BASE_FEE_ESTIMATE::request>
req_t = AUTO_VAL_INIT(req_t);
epee::json_rpc::response<COMMAND_RPC_GET_PER_KB_FEE_ESTIMATE::response, std::string>
epee::json_rpc::response<COMMAND_RPC_GET_BASE_FEE_ESTIMATE::response, std::string>
resp_t = AUTO_VAL_INIT(resp_t);

View File

@ -8,6 +8,8 @@
#include "monero_headers.h"
#include "wipeable_string.h"
#include <mutex>
#include <utility>
@ -81,7 +83,10 @@ class rpccalls
public:
rpccalls(string _deamon_url = "http:://127.0.0.1:18081",
using login_opt = boost::optional<epee::net_utils::http::login>;
rpccalls(string _deamon_url = "http:://127.0.0.1:34568",
login_opt _login = login_opt {},
uint64_t _timeout = 200000);
bool

View File

@ -30,6 +30,17 @@
<td>Total fees:</td><td>{{sum_fees}}</td>
<td>No of txs:</td><td>{{no_txs}}</td>
</tr>
<tr>
<td>PoW hash:</td><td>{{blk_pow_hash}}</td>
<td>Difficulty:</td><td>{{blk_difficulty}}</td>
{{#is_randomx}}
<td colspan="2"><a href="/randomx/{{blk_height}}">RandomX source code</a></td>
{{/is_randomx}}
{{^is_randomx}}
<td></td>
{{/is_randomx}}
<td></td>
</tr>
</table>
<h3>Miner reward transaction</h3>
@ -59,8 +70,7 @@
<tr>
<td>hash</td>
<td>outputs</td>
<td>fee</td>
<td>ring size</td>
<td>fee [&#181;&#x271]</td>
<td>in/out</td>
<td>size [kB]</td>
<td>version</td>
@ -69,14 +79,21 @@
<tr>
<td><a href="/tx/{{hash}}">{{hash}}</a></td>
<td>{{sum_outputs}}</td>
<td>{{tx_fee}}</td>
<td>{{mixin}}</td>
<td>{{fee_micro}}</td>
<td>{{no_inputs}}/{{no_outputs}}</td>
<td>{{tx_size}}</td>
<td>{{version}}</td>
</tr>
{{/blk_txs}}
</table>
{{/have_txs}}
{{/have_txs}}
{{#enable_as_hex}}
<h5 style="margin-top:1px">
<a href="/blockhex/{{blk_height}}">Block as hex</a>
| <a href="/blockhexcomplete/{{blk_height}}">Complete block as hex</a>
</h5>
{{/enable_as_hex}}
</div>

View File

@ -15,7 +15,7 @@
<h4>Output keys for address: {{address}}</h4>
<h4>Viewkey: {{viewkey}}</h4>
{{#has_total_xmr}}
<h4>Total xmr: {{total_xmr}}</h4>
<h4>Total wow: {{total_xmr}}</h4>
{{/has_total_xmr}}
<div class="center">

View File

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

View File

@ -2,25 +2,24 @@
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="shortcut icon" href="about:blank">
<META HTTP-EQUIV="CACHE-CONTROL" CONTENT="NO-CACHE">
{{#refresh}}
<meta http-equiv="refresh" content="10">
{{/refresh}}
<title>Onion Monero Blockchain Explorer</title>
<title>Wownero Blockchain Explorer</title>
<!--<link rel="stylesheet" type="text/css" href="/css/style.css">-->
<style type="text/css">
{{#css_styles}}{{/css_styles}}
</style>
{{#js_files}}{{/js_files}}
</head>
<body>
<div>
<div class="center">
<h1 class="center"><a href="/">Onion Monero Blockchain Explorer</a></h1>
<h4 style="font-size: 15px; margin: 0px">({{^enable_js}}no javascript - {{/enable_js}}no cookies - no web analytics trackers - no images - open sourced)</h4>
<h1 class="center"><a href="/">Onion Wownero Blockchain Explorer</a></h1>
<h4 style="font-size: 15px; margin: 0px">(no javascript - no cookies - no web analytics trackers - no images - open sourced)</h4>
</div>

View File

@ -31,10 +31,10 @@
| <a href="{{mainnet_url}}">Go to mainnet explorer</a>
{{/mainnet_url}}
{{#testnet}}
| This is <span style="color:#ff6b62">testnet</span> blockchian
| This is <span style="color:#ff6b62">testnet</span> blockchain
{{/testnet}}
{{#stagenet}}
| This is <span style="color:#ff6b62">stagenet</span> blockchian
| This is <span style="color:#ff6b62">stagenet</span> blockchain
{{/stagenet}}
</h3>
@ -45,7 +45,7 @@
Network difficulty: {{difficulty}}
| Hard fork: v{{current_hf_version}}
| Hash rate: {{hash_rate}}
| Fee per kb: {{fee_per_kb}}
| Fee per byte: {{fee_per_kb}}
| Median block size limit: {{block_size_limit}} kB
{{^is_current_info}}
| Data from {{age}} {{age_format}} ago
@ -55,7 +55,7 @@
{{#emission}}
<h3 style="font-size: 12px; margin-top: 2px">
Monero emission (fees) is {{amount}} ({{fee_amount}}) as of {{blk_no}} block
Wownero emission is {{amount}} ({{fee_amount}} fees) as of {{blk_no}} block
</h3>
{{/emission}}
@ -71,7 +71,7 @@
<h2 style="margin-bottom: 0px">Transactions in older blocks<!--(height: {{height}})--></h2>
{{/is_page_zero}}
<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 100 blocks: {{blk_size_median}} kB)</h4>
<div class="center">
@ -81,10 +81,9 @@
<td>age {{age_format}}<!--(Δm)--></td>
<td>size [kB]<!--(Δm)--></td>
<td>transaction hash</td>
<td>fee</td>
<td>fee [&#181;&#x271]</td>
<td>outputs</td>
<td>in/out/pID</td>
<td>ring size</td>
<td>in/out</td>
<td>tx size [kB]</td>
</tr>
{{#txs}}
@ -93,10 +92,9 @@
<td>{{age}}<!--{{time_delta}}--></td>
<td>{{blk_size}}</td>
<td><a href="/tx/{{hash}}">{{hash}}</a></td>
<td>{{tx_fee_short}}</td>
<td>{{fee_micro}}</td>
<td>{{sum_outputs_short}}</td>
<td>{{no_inputs}}/{{no_outputs}}/{{pID}}</td>
<td>{{mixin}}</td>
<td>{{no_inputs}}/{{no_outputs}}</td>
<td>{{tx_size_short}}</td>
</tr>
{{/txs}}
@ -113,14 +111,3 @@
</div>
{{#show_cache_times}}
<div class="center">
<h6 style="margin-top: 1px;color:#949490">
Tx details construction time: {{construction_time_total}} s
<br/>
includes {{construction_time_cached}} s from block cache ({{cache_hits}} hits)
and {{construction_time_non_cached}} s from non cache ({{cache_misses}} misses)
</h6>
</div>
{{/show_cache_times}}

View File

@ -1,190 +0,0 @@
var cnBase58 = (function () {
var b58 = {};
var alphabet_str = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
var alphabet = [];
for (var i = 0; i < alphabet_str.length; i++) {
alphabet.push(alphabet_str.charCodeAt(i));
}
var encoded_block_sizes = [0, 2, 3, 5, 6, 7, 9, 10, 11];
var alphabet_size = alphabet.length;
var full_block_size = 8;
var full_encoded_block_size = 11;
var UINT64_MAX = new JSBigInt(2).pow(64);
function hextobin(hex) {
if (hex.length % 2 !== 0) throw "Hex string has invalid length!";
var res = new Uint8Array(hex.length / 2);
for (var i = 0; i < hex.length / 2; ++i) {
res[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);
}
return res;
}
function bintohex(bin) {
var out = [];
for (var i = 0; i < bin.length; ++i) {
out.push(("0" + bin[i].toString(16)).slice(-2));
}
return out.join("");
}
function strtobin(str) {
var res = new Uint8Array(str.length);
for (var i = 0; i < str.length; i++) {
res[i] = str.charCodeAt(i);
}
return res;
}
function bintostr(bin) {
var out = [];
for (var i = 0; i < bin.length; i++) {
out.push(String.fromCharCode(bin[i]));
}
return out.join("");
}
function uint8_be_to_64(data) {
if (data.length < 1 || data.length > 8) {
throw "Invalid input length";
}
var res = JSBigInt.ZERO;
var twopow8 = new JSBigInt(2).pow(8);
var i = 0;
switch (9 - data.length) {
case 1:
res = res.add(data[i++]);
case 2:
res = res.multiply(twopow8).add(data[i++]);
case 3:
res = res.multiply(twopow8).add(data[i++]);
case 4:
res = res.multiply(twopow8).add(data[i++]);
case 5:
res = res.multiply(twopow8).add(data[i++]);
case 6:
res = res.multiply(twopow8).add(data[i++]);
case 7:
res = res.multiply(twopow8).add(data[i++]);
case 8:
res = res.multiply(twopow8).add(data[i++]);
break;
default:
throw "Impossible condition";
}
return res;
}
function uint64_to_8be(num, size) {
var res = new Uint8Array(size);
if (size < 1 || size > 8) {
throw "Invalid input length";
}
var twopow8 = new JSBigInt(2).pow(8);
for (var i = size - 1; i >= 0; i--) {
res[i] = num.remainder(twopow8).toJSValue();
num = num.divide(twopow8);
}
return res;
}
b58.encode_block = function (data, buf, index) {
if (data.length < 1 || data.length > full_encoded_block_size) {
throw "Invalid block length: " + data.length;
}
var num = uint8_be_to_64(data);
var i = encoded_block_sizes[data.length] - 1;
// while num > 0
while (num.compare(0) === 1) {
var div = num.divRem(alphabet_size);
// remainder = num % alphabet_size
var remainder = div[1];
// num = num / alphabet_size
num = div[0];
buf[index + i] = alphabet[remainder.toJSValue()];
i--;
}
return buf;
};
b58.encode = function (hex) {
var data = hextobin(hex);
if (data.length === 0) {
return "";
}
var full_block_count = Math.floor(data.length / full_block_size);
var last_block_size = data.length % full_block_size;
var res_size = full_block_count * full_encoded_block_size + encoded_block_sizes[last_block_size];
var res = new Uint8Array(res_size);
var i;
for (i = 0; i < res_size; ++i) {
res[i] = alphabet[0];
}
for (i = 0; i < full_block_count; i++) {
res = b58.encode_block(data.subarray(i * full_block_size, i * full_block_size + full_block_size), res, i * full_encoded_block_size);
}
if (last_block_size > 0) {
res = b58.encode_block(data.subarray(full_block_count * full_block_size, full_block_count * full_block_size + last_block_size), res, full_block_count * full_encoded_block_size)
}
return bintostr(res);
};
b58.decode_block = function (data, buf, index) {
if (data.length < 1 || data.length > full_encoded_block_size) {
throw "Invalid block length: " + data.length;
}
var res_size = encoded_block_sizes.indexOf(data.length);
if (res_size <= 0) {
throw "Invalid block size";
}
var res_num = new JSBigInt(0);
var order = new JSBigInt(1);
for (var i = data.length - 1; i >= 0; i--) {
var digit = alphabet.indexOf(data[i]);
if (digit < 0) {
throw "Invalid symbol";
}
var product = order.multiply(digit).add(res_num);
// if product > UINT64_MAX
if (product.compare(UINT64_MAX) === 1) {
throw "Overflow";
}
res_num = product;
order = order.multiply(alphabet_size);
}
if (res_size < full_block_size && (new JSBigInt(2).pow(8 * res_size).compare(res_num) <= 0)) {
throw "Overflow 2";
}
buf.set(uint64_to_8be(res_num, res_size), index);
return buf;
};
b58.decode = function (enc) {
enc = strtobin(enc);
if (enc.length === 0) {
return "";
}
var full_block_count = Math.floor(enc.length / full_encoded_block_size);
var last_block_size = enc.length % full_encoded_block_size;
var last_block_decoded_size = encoded_block_sizes.indexOf(last_block_size);
if (last_block_decoded_size < 0) {
throw "Invalid encoded length";
}
var data_size = full_block_count * full_block_size + last_block_decoded_size;
var data = new Uint8Array(data_size);
for (var i = 0; i < full_block_count; i++) {
data = b58.decode_block(enc.subarray(i * full_encoded_block_size, i * full_encoded_block_size + full_encoded_block_size), data, i * full_block_size);
}
if (last_block_size > 0) {
data = b58.decode_block(enc.subarray(full_block_count * full_encoded_block_size, full_block_count * full_encoded_block_size + last_block_size), data, full_block_count * full_block_size);
}
return bintohex(data);
};
return b58;
})();

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,16 +1,16 @@
var config = {
testnet: false, // this is adjusted page.h if needed. dont need to change manually
stagenet: false, // this is adjusted page.h if needed. dont need to change manually
coinUnitPlaces: 12,
txMinConfirms: 10, // corresponds to CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE in Monero
coinUnitPlaces: 11,
txMinConfirms: 4, // corresponds to CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE in Monero
txCoinbaseMinConfirms: 60, // corresponds to CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW in Monero
coinSymbol: 'XMR',
openAliasPrefix: "xmr",
coinName: 'Monero',
coinUriPrefix: 'monero:',
addressPrefix: 18,
integratedAddressPrefix: 19,
subAddressPrefix: 42,
coinSymbol: 'WOW',
openAliasPrefix: "wow",
coinName: 'Wownero',
coinUriPrefix: 'wownero:',
addressPrefix: 4146,
integratedAddressPrefix: 6810,
subAddressPrefix: 12208,
addressPrefixTestnet: 53,
integratedAddressPrefixTestnet: 54,
subAddressPrefixTestnet: 63,
@ -20,11 +20,11 @@ var config = {
feePerKB: new JSBigInt('2000000000'),//20^10 - for testnet its not used, as fee is dynamic.
dustThreshold: new JSBigInt('1000000000'),//10^10 used for choosing outputs/change - we decompose all the way down if the receiver wants now regardless of threshold
txChargeRatio: 0.5,
defaultMixin: 4, // minimum mixin for hardfork v5
defaultMixin: 21, // minimum mixin for hardfork v9
txChargeAddress: '',
idleTimeout: 30,
idleWarningDuration: 20,
maxBlockNumber: 500000000,
avgBlockTime: 120,
avgBlockTime: 300,
debugMode: false
};

View File

@ -1,65 +0,0 @@
var crc32 = (function () {
'use strict';
var crc32 = {};
crc32.Utf8Encode = function (string) {
return unescape(encodeURIComponent(string));
};
crc32.run = function (str) {
var crc = new crc32.Type();
crc.processString(str);
return crc.checksum();
};
crc32.table = [
0, 1996959894, 3993919788, 2567524794, 124634137, 1886057615, 3915621685, 2657392035,
249268274, 2044508324, 3772115230, 2547177864, 162941995, 2125561021, 3887607047, 2428444049,
498536548, 1789927666, 4089016648, 2227061214, 450548861, 1843258603, 4107580753, 2211677639,
325883990, 1684777152, 4251122042, 2321926636, 335633487, 1661365465, 4195302755, 2366115317,
997073096, 1281953886, 3579855332, 2724688242, 1006888145, 1258607687, 3524101629, 2768942443,
901097722, 1119000684, 3686517206, 2898065728, 853044451, 1172266101, 3705015759, 2882616665,
651767980, 1373503546, 3369554304, 3218104598, 565507253, 1454621731, 3485111705, 3099436303,
671266974, 1594198024, 3322730930, 2970347812, 795835527, 1483230225, 3244367275, 3060149565,
1994146192, 31158534, 2563907772, 4023717930, 1907459465, 112637215, 2680153253, 3904427059,
2013776290, 251722036, 2517215374, 3775830040, 2137656763, 141376813, 2439277719, 3865271297,
1802195444, 476864866, 2238001368, 4066508878, 1812370925, 453092731, 2181625025, 4111451223,
1706088902, 314042704, 2344532202, 4240017532, 1658658271, 366619977, 2362670323, 4224994405,
1303535960, 984961486, 2747007092, 3569037538, 1256170817, 1037604311, 2765210733, 3554079995,
1131014506, 879679996, 2909243462, 3663771856, 1141124467, 855842277, 2852801631, 3708648649,
1342533948, 654459306, 3188396048, 3373015174, 1466479909, 544179635, 3110523913, 3462522015,
1591671054, 702138776, 2966460450, 3352799412, 1504918807, 783551873, 3082640443, 3233442989,
3988292384, 2596254646, 62317068, 1957810842, 3939845945, 2647816111, 81470997, 1943803523,
3814918930, 2489596804, 225274430, 2053790376, 3826175755, 2466906013, 167816743, 2097651377,
4027552580, 2265490386, 503444072, 1762050814, 4150417245, 2154129355, 426522225, 1852507879,
4275313526, 2312317920, 282753626, 1742555852, 4189708143, 2394877945, 397917763, 1622183637,
3604390888, 2714866558, 953729732, 1340076626, 3518719985, 2797360999, 1068828381, 1219638859,
3624741850, 2936675148, 906185462, 1090812512, 3747672003, 2825379669, 829329135, 1181335161,
3412177804, 3160834842, 628085408, 1382605366, 3423369109, 3138078467, 570562233, 1426400815,
3317316542, 2998733608, 733239954, 1555261956, 3268935591, 3050360625, 752459403, 1541320221,
2607071920, 3965973030, 1969922972, 40735498, 2617837225, 3943577151, 1913087877, 83908371,
2512341634, 3803740692, 2075208622, 213261112, 2463272603, 3855990285, 2094854071, 198958881,
2262029012, 4057260610, 1759359992, 534414190, 2176718541, 4139329115, 1873836001, 414664567,
2282248934, 4279200368, 1711684554, 285281116, 2405801727, 4167216745, 1634467795, 376229701,
2685067896, 3608007406, 1308918612, 956543938, 2808555105, 3495958263, 1231636301, 1047427035,
2932959818, 3654703836, 1088359270, 936918000, 2847714899, 3736837829, 1202900863, 817233897,
3183342108, 3401237130, 1404277552, 615818150, 3134207493, 3453421203, 1423857449, 601450431,
3009837614, 3294710456, 1567103746, 711928724, 3020668471, 3272380065, 1510334235, 755167117
];
crc32.Type = function () {
this.rem_ = 0xFFFFFFFF;
this.checksum = function () {
return ((this.rem_ ^ 0xFFFFFFFF) >>> 0);
};
this.processString = function (str) {
str = crc32.Utf8Encode(str);
for (var i = 0; i < str.length; i++) {
var byte_index = ((str.charCodeAt(i) ^ this.rem_) >>> 0) & 0xFF;
this.rem_ = ((this.rem_ >>> 8) ^ crc32.table[byte_index]) >>> 0;
}
};
return this;
};
return crc32;
})();

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,571 +0,0 @@
(function(nacl) {
'use strict';
// Ported in 2014 by Dmitry Chestnykh and Devi Mandiri.
// Public domain.
//
// Implementation derived from TweetNaCl version 20140427.
// See for details: http://tweetnacl.cr.yp.to/
// modified 2017 for some CN functions by luigi1111
var gf = function(init) {
var i, r = new Float64Array(16);
if (init) for (i = 0; i < init.length; i++) r[i] = init[i];
return r;
};
// Pluggable, initialized in high-level API below.
var randombytes = function(/* x, n */) { throw new Error('no PRNG'); };
var _0 = new Uint8Array(16);
var _9 = new Uint8Array(32); _9[0] = 9;
var gf0 = gf(),
gf1 = gf([1]),
_121665 = gf([0xdb41, 1]),
D = gf([0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070, 0xe898, 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203]),
D2 = gf([0xf159, 0x26b2, 0x9b94, 0xebd6, 0xb156, 0x8283, 0x149a, 0x00e0, 0xd130, 0xeef3, 0x80f2, 0x198e, 0xfce7, 0x56df, 0xd9dc, 0x2406]),
X = gf([0xd51a, 0x8f25, 0x2d60, 0xc956, 0xa7b2, 0x9525, 0xc760, 0x692c, 0xdc5c, 0xfdd6, 0xe231, 0xc0a4, 0x53fe, 0xcd6e, 0x36d3, 0x2169]),
Y = gf([0x6658, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666]),
I = gf([0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 0xe478, 0xad2f, 0x1806, 0x2f43, 0xd7a7, 0x3dfb, 0x0099, 0x2b4d, 0xdf0b, 0x4fc1, 0x2480, 0x2b83]);
function vn(x, xi, y, yi, n) {
var i,d = 0;
for (i = 0; i < n; i++) d |= x[xi+i]^y[yi+i];
return (1 & ((d - 1) >>> 8)) - 1;
}
function crypto_verify_16(x, xi, y, yi) {
return vn(x,xi,y,yi,16);
}
function crypto_verify_32(x, xi, y, yi) {
return vn(x,xi,y,yi,32);
}
function set25519(r, a) {
var i;
for (i = 0; i < 16; i++) r[i] = a[i]|0;
}
function car25519(o) {
var i, v, c = 1;
for (i = 0; i < 16; i++) {
v = o[i] + c + 65535;
c = Math.floor(v / 65536);
o[i] = v - c * 65536;
}
o[0] += c-1 + 37 * (c-1);
}
function sel25519(p, q, b) {
var t, c = ~(b-1);
for (var i = 0; i < 16; i++) {
t = c & (p[i] ^ q[i]);
p[i] ^= t;
q[i] ^= t;
}
}
function pack25519(o, n) {
var i, j, b;
var m = gf(), t = gf();
for (i = 0; i < 16; i++) t[i] = n[i];
car25519(t);
car25519(t);
car25519(t);
for (j = 0; j < 2; j++) {
m[0] = t[0] - 0xffed;
for (i = 1; i < 15; i++) {
m[i] = t[i] - 0xffff - ((m[i-1]>>16) & 1);
m[i-1] &= 0xffff;
}
m[15] = t[15] - 0x7fff - ((m[14]>>16) & 1);
b = (m[15]>>16) & 1;
m[14] &= 0xffff;
sel25519(t, m, 1-b);
}
for (i = 0; i < 16; i++) {
o[2*i] = t[i] & 0xff;
o[2*i+1] = t[i]>>8;
}
}
function neq25519(a, b) {
var c = new Uint8Array(32), d = new Uint8Array(32);
pack25519(c, a);
pack25519(d, b);
return crypto_verify_32(c, 0, d, 0);
}
function par25519(a) {
var d = new Uint8Array(32);
pack25519(d, a);
return d[0] & 1;
}
function unpack25519(o, n) {
var i;
for (i = 0; i < 16; i++) o[i] = n[2*i] + (n[2*i+1] << 8);
o[15] &= 0x7fff;
}
function A(o, a, b) {
for (var i = 0; i < 16; i++) o[i] = a[i] + b[i];
}
function Z(o, a, b) {
for (var i = 0; i < 16; i++) o[i] = a[i] - b[i];
}
function M(o, a, b) {
var v, c,
t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0, t5 = 0, t6 = 0, t7 = 0,
t8 = 0, t9 = 0, t10 = 0, t11 = 0, t12 = 0, t13 = 0, t14 = 0, t15 = 0,
t16 = 0, t17 = 0, t18 = 0, t19 = 0, t20 = 0, t21 = 0, t22 = 0, t23 = 0,
t24 = 0, t25 = 0, t26 = 0, t27 = 0, t28 = 0, t29 = 0, t30 = 0,
b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3], b4 = b[4], b5 = b[5],
b6 = b[6], b7 = b[7], b8 = b[8], b9 = b[9], b10 = b[10],
b11 = b[11], b12 = b[12], b13 = b[13], b14 = b[14], b15 = b[15];
v = a[0];
t0 += v * b0; t1 += v * b1; t2 += v * b2; t3 += v * b3;
t4 += v * b4; t5 += v * b5; t6 += v * b6; t7 += v * b7;
t8 += v * b8; t9 += v * b9; t10 += v * b10; t11 += v * b11;
t12 += v * b12; t13 += v * b13; t14 += v * b14; t15 += v * b15;
v = a[1];
t1 += v * b0; t2 += v * b1; t3 += v * b2; t4 += v * b3;
t5 += v * b4; t6 += v * b5; t7 += v * b6; t8 += v * b7;
t9 += v * b8; t10 += v * b9; t11 += v * b10; t12 += v * b11;
t13 += v * b12; t14 += v * b13; t15 += v * b14; t16 += v * b15;
v = a[2];
t2 += v * b0; t3 += v * b1; t4 += v * b2; t5 += v * b3;
t6 += v * b4; t7 += v * b5; t8 += v * b6; t9 += v * b7;
t10 += v * b8; t11 += v * b9; t12 += v * b10; t13 += v * b11;
t14 += v * b12; t15 += v * b13; t16 += v * b14; t17 += v * b15;
v = a[3];
t3 += v * b0; t4 += v * b1; t5 += v * b2; t6 += v * b3;
t7 += v * b4; t8 += v * b5; t9 += v * b6; t10 += v * b7;
t11 += v * b8; t12 += v * b9; t13 += v * b10; t14 += v * b11;
t15 += v * b12; t16 += v * b13; t17 += v * b14; t18 += v * b15;
v = a[4];
t4 += v * b0; t5 += v * b1; t6 += v * b2; t7 += v * b3;
t8 += v * b4; t9 += v * b5; t10 += v * b6; t11 += v * b7;
t12 += v * b8; t13 += v * b9; t14 += v * b10; t15 += v * b11;
t16 += v * b12; t17 += v * b13; t18 += v * b14; t19 += v * b15;
v = a[5];
t5 += v * b0; t6 += v * b1; t7 += v * b2; t8 += v * b3;
t9 += v * b4; t10 += v * b5; t11 += v * b6; t12 += v * b7;
t13 += v * b8; t14 += v * b9; t15 += v * b10; t16 += v * b11;
t17 += v * b12; t18 += v * b13; t19 += v * b14; t20 += v * b15;
v = a[6];
t6 += v * b0; t7 += v * b1; t8 += v * b2; t9 += v * b3;
t10 += v * b4; t11 += v * b5; t12 += v * b6; t13 += v * b7;
t14 += v * b8; t15 += v * b9; t16 += v * b10; t17 += v * b11;
t18 += v * b12; t19 += v * b13; t20 += v * b14; t21 += v * b15;
v = a[7];
t7 += v * b0; t8 += v * b1; t9 += v * b2; t10 += v * b3;
t11 += v * b4; t12 += v * b5; t13 += v * b6; t14 += v * b7;
t15 += v * b8; t16 += v * b9; t17 += v * b10; t18 += v * b11;
t19 += v * b12; t20 += v * b13; t21 += v * b14; t22 += v * b15;
v = a[8];
t8 += v * b0; t9 += v * b1; t10 += v * b2; t11 += v * b3;
t12 += v * b4; t13 += v * b5; t14 += v * b6; t15 += v * b7;
t16 += v * b8; t17 += v * b9; t18 += v * b10; t19 += v * b11;
t20 += v * b12; t21 += v * b13; t22 += v * b14; t23 += v * b15;
v = a[9];
t9 += v * b0; t10 += v * b1; t11 += v * b2; t12 += v * b3;
t13 += v * b4; t14 += v * b5; t15 += v * b6; t16 += v * b7;
t17 += v * b8; t18 += v * b9; t19 += v * b10; t20 += v * b11;
t21 += v * b12; t22 += v * b13; t23 += v * b14; t24 += v * b15;
v = a[10];
t10 += v * b0; t11 += v * b1; t12 += v * b2; t13 += v * b3;
t14 += v * b4; t15 += v * b5; t16 += v * b6; t17 += v * b7;
t18 += v * b8; t19 += v * b9; t20 += v * b10; t21 += v * b11;
t22 += v * b12; t23 += v * b13; t24 += v * b14; t25 += v * b15;
v = a[11];
t11 += v * b0; t12 += v * b1; t13 += v * b2; t14 += v * b3;
t15 += v * b4; t16 += v * b5; t17 += v * b6; t18 += v * b7;
t19 += v * b8; t20 += v * b9; t21 += v * b10; t22 += v * b11;
t23 += v * b12; t24 += v * b13; t25 += v * b14; t26 += v * b15;
v = a[12];
t12 += v * b0; t13 += v * b1; t14 += v * b2; t15 += v * b3;
t16 += v * b4; t17 += v * b5; t18 += v * b6; t19 += v * b7;
t20 += v * b8; t21 += v * b9; t22 += v * b10; t23 += v * b11;
t24 += v * b12; t25 += v * b13; t26 += v * b14; t27 += v * b15;
v = a[13];
t13 += v * b0; t14 += v * b1; t15 += v * b2; t16 += v * b3;
t17 += v * b4; t18 += v * b5; t19 += v * b6; t20 += v * b7;
t21 += v * b8; t22 += v * b9; t23 += v * b10; t24 += v * b11;
t25 += v * b12; t26 += v * b13; t27 += v * b14; t28 += v * b15;
v = a[14];
t14 += v * b0; t15 += v * b1; t16 += v * b2; t17 += v * b3;
t18 += v * b4; t19 += v * b5; t20 += v * b6; t21 += v * b7;
t22 += v * b8; t23 += v * b9; t24 += v * b10; t25 += v * b11;
t26 += v * b12; t27 += v * b13; t28 += v * b14; t29 += v * b15;
v = a[15];
t15 += v * b0; t16 += v * b1; t17 += v * b2; t18 += v * b3;
t19 += v * b4; t20 += v * b5; t21 += v * b6; t22 += v * b7;
t23 += v * b8; t24 += v * b9; t25 += v * b10; t26 += v * b11;
t27 += v * b12; t28 += v * b13; t29 += v * b14; t30 += v * b15;
t0 += 38 * t16; t1 += 38 * t17; t2 += 38 * t18; t3 += 38 * t19;
t4 += 38 * t20; t5 += 38 * t21; t6 += 38 * t22; t7 += 38 * t23;
t8 += 38 * t24; t9 += 38 * t25; t10 += 38 * t26; t11 += 38 * t27;
t12 += 38 * t28; t13 += 38 * t29; t14 += 38 * t30; // t15 left as is
// first car
c = 1;
v = t0 + c + 65535; c = Math.floor(v / 65536); t0 = v - c * 65536;
v = t1 + c + 65535; c = Math.floor(v / 65536); t1 = v - c * 65536;
v = t2 + c + 65535; c = Math.floor(v / 65536); t2 = v - c * 65536;
v = t3 + c + 65535; c = Math.floor(v / 65536); t3 = v - c * 65536;
v = t4 + c + 65535; c = Math.floor(v / 65536); t4 = v - c * 65536;
v = t5 + c + 65535; c = Math.floor(v / 65536); t5 = v - c * 65536;
v = t6 + c + 65535; c = Math.floor(v / 65536); t6 = v - c * 65536;
v = t7 + c + 65535; c = Math.floor(v / 65536); t7 = v - c * 65536;
v = t8 + c + 65535; c = Math.floor(v / 65536); t8 = v - c * 65536;
v = t9 + c + 65535; c = Math.floor(v / 65536); t9 = v - c * 65536;
v = t10 + c + 65535; c = Math.floor(v / 65536); t10 = v - c * 65536;
v = t11 + c + 65535; c = Math.floor(v / 65536); t11 = v - c * 65536;
v = t12 + c + 65535; c = Math.floor(v / 65536); t12 = v - c * 65536;
v = t13 + c + 65535; c = Math.floor(v / 65536); t13 = v - c * 65536;
v = t14 + c + 65535; c = Math.floor(v / 65536); t14 = v - c * 65536;
v = t15 + c + 65535; c = Math.floor(v / 65536); t15 = v - c * 65536;
t0 += c-1 + 37 * (c-1);
// second car
c = 1;
v = t0 + c + 65535; c = Math.floor(v / 65536); t0 = v - c * 65536;
v = t1 + c + 65535; c = Math.floor(v / 65536); t1 = v - c * 65536;
v = t2 + c + 65535; c = Math.floor(v / 65536); t2 = v - c * 65536;
v = t3 + c + 65535; c = Math.floor(v / 65536); t3 = v - c * 65536;
v = t4 + c + 65535; c = Math.floor(v / 65536); t4 = v - c * 65536;
v = t5 + c + 65535; c = Math.floor(v / 65536); t5 = v - c * 65536;
v = t6 + c + 65535; c = Math.floor(v / 65536); t6 = v - c * 65536;
v = t7 + c + 65535; c = Math.floor(v / 65536); t7 = v - c * 65536;
v = t8 + c + 65535; c = Math.floor(v / 65536); t8 = v - c * 65536;
v = t9 + c + 65535; c = Math.floor(v / 65536); t9 = v - c * 65536;
v = t10 + c + 65535; c = Math.floor(v / 65536); t10 = v - c * 65536;
v = t11 + c + 65535; c = Math.floor(v / 65536); t11 = v - c * 65536;
v = t12 + c + 65535; c = Math.floor(v / 65536); t12 = v - c * 65536;
v = t13 + c + 65535; c = Math.floor(v / 65536); t13 = v - c * 65536;
v = t14 + c + 65535; c = Math.floor(v / 65536); t14 = v - c * 65536;
v = t15 + c + 65535; c = Math.floor(v / 65536); t15 = v - c * 65536;
t0 += c-1 + 37 * (c-1);
o[ 0] = t0;
o[ 1] = t1;
o[ 2] = t2;
o[ 3] = t3;
o[ 4] = t4;
o[ 5] = t5;
o[ 6] = t6;
o[ 7] = t7;
o[ 8] = t8;
o[ 9] = t9;
o[10] = t10;
o[11] = t11;
o[12] = t12;
o[13] = t13;
o[14] = t14;
o[15] = t15;
}
function S(o, a) {
M(o, a, a);
}
function inv25519(o, i) {
var c = gf();
var a;
for (a = 0; a < 16; a++) c[a] = i[a];
for (a = 253; a >= 0; a--) {
S(c, c);
if(a !== 2 && a !== 4) M(c, c, i);
}
for (a = 0; a < 16; a++) o[a] = c[a];
}
function pow2523(o, i) {
var c = gf();
var a;
for (a = 0; a < 16; a++) c[a] = i[a];
for (a = 250; a >= 0; a--) {
S(c, c);
if(a !== 1) M(c, c, i);
}
for (a = 0; a < 16; a++) o[a] = c[a];
}
function add(p, q) {
var a = gf(), b = gf(), c = gf(),
d = gf(), e = gf(), f = gf(),
g = gf(), h = gf(), t = gf();
Z(a, p[1], p[0]);
Z(t, q[1], q[0]);
M(a, a, t);
A(b, p[0], p[1]);
A(t, q[0], q[1]);
M(b, b, t);
M(c, p[3], q[3]);
M(c, c, D2);
M(d, p[2], q[2]);
A(d, d, d);
Z(e, b, a);
Z(f, d, c);
A(g, d, c);
A(h, b, a);
M(p[0], e, f);
M(p[1], h, g);
M(p[2], g, f);
M(p[3], e, h);
}
function cswap(p, q, b) {
var i;
for (i = 0; i < 4; i++) {
sel25519(p[i], q[i], b);
}
}
function pack(r, p) {
var tx = gf(), ty = gf(), zi = gf();
inv25519(zi, p[2]);
M(tx, p[0], zi);
M(ty, p[1], zi);
pack25519(r, ty);
r[31] ^= par25519(tx) << 7;
}
function scalarmult(p, q, s) {
var b, i;
set25519(p[0], gf0);
set25519(p[1], gf1);
set25519(p[2], gf1);
set25519(p[3], gf0);
for (i = 255; i >= 0; --i) {
b = (s[(i/8)|0] >> (i&7)) & 1;
cswap(p, q, b);
add(q, p);
add(p, p);
cswap(p, q, b);
}
}
function scalarbase(p, s) {
var q = [gf(), gf(), gf(), gf()];
set25519(q[0], X);
set25519(q[1], Y);
set25519(q[2], gf1);
M(q[3], X, Y);
scalarmult(p, q, s);
}
//new functions for CN - scalar operations are handled externally
// this only handles curve operations, except for Hp()
//why do we negate points when unpacking them???
function ge_neg(pub) {
pub[31] ^= 0x80;
}
//res = s*G
function ge_scalarmult_base(s) {
var p = [gf(), gf(), gf(), gf()];
scalarbase(p, s);
var pk = new Uint8Array(32);
pack(pk, p);
return pk;
}
//res = s*P
function ge_scalarmult(P, s) {
var p = [gf(), gf(), gf(), gf()],
upk = [gf(), gf(), gf(), gf()],
res = new Uint8Array(32);
ge_neg(P);
if (unpackneg(upk, P) !== 0) throw "non-0 error on point decode";
scalarmult(p, upk, s);
pack(res, p);
return res;
}
//res = c*P + r*G
function ge_double_scalarmult_base_vartime(c, P, r) {
var uP = [gf(), gf(), gf(), gf()],
cP = [gf(), gf(), gf(), gf()],
rG = [gf(), gf(), gf(), gf()],
res = new Uint8Array(32);
ge_neg(P);
if (unpackneg(uP, P) !== 0) throw "non-0 error on point decode";
scalarmult(cP, uP, c);
scalarbase(rG, r);
add(rG, cP);
pack(res, rG);
return res;
}
//name changed to reflect not using precomp; res = r*Pb + c*I
function ge_double_scalarmult_postcomp_vartime(r, Pb, c, I) {
var uPb = [gf(), gf(), gf(), gf()],
uI = [gf(), gf(), gf(), gf()],
cI = [gf(), gf(), gf(), gf()],
rPb = [gf(), gf(), gf(), gf()],
res = new Uint8Array(32);
ge_neg(Pb);
if (unpackneg(uPb, Pb) !== 0) throw "non-0 error on point decode";
scalarmult(rPb, uPb, r);
ge_neg(I);
if (unpackneg(uI, I) !== 0) throw "non-0 error on point decode";
scalarmult(cI, uI, c);
add(rPb, cI);
pack(res, rPb);
return res;
}
//res = P + Q
function ge_add(P, Q) {
var uP = [gf(), gf(), gf(), gf()],
uQ = [gf(), gf(), gf(), gf()],
res = new Uint8Array(32);
ge_neg(P);
ge_neg(Q);
if (unpackneg(uP, P) !== 0) throw "non-0 error on point decode";
if (unpackneg(uQ, Q) !== 0) throw "non-0 error on point decode";
add(uP, uQ);
pack(res, uP);
return res;
}
var L = new Float64Array([0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10]);
function modL(r, x) {
var carry, i, j, k;
for (i = 63; i >= 32; --i) {
carry = 0;
for (j = i - 32, k = i - 12; j < k; ++j) {
x[j] += carry - 16 * x[i] * L[j - (i - 32)];
carry = (x[j] + 128) >> 8;
x[j] -= carry * 256;
}
x[j] += carry;
x[i] = 0;
}
carry = 0;
for (j = 0; j < 32; j++) {
x[j] += carry - (x[31] >> 4) * L[j];
carry = x[j] >> 8;
x[j] &= 255;
}
for (j = 0; j < 32; j++) x[j] -= carry * L[j];
for (i = 0; i < 32; i++) {
x[i+1] += x[i] >> 8;
r[i] = x[i] & 255;
}
}
function reduce(r) {
var x = new Float64Array(64), i;
for (i = 0; i < 64; i++) x[i] = r[i];
for (i = 0; i < 64; i++) r[i] = 0;
modL(r, x);
}
function unpackneg(r, p) {
var t = gf(), chk = gf(), num = gf(),
den = gf(), den2 = gf(), den4 = gf(),
den6 = gf();
set25519(r[2], gf1);
unpack25519(r[1], p);
S(num, r[1]);
M(den, num, D);
Z(num, num, r[2]);
A(den, r[2], den);
S(den2, den);
S(den4, den2);
M(den6, den4, den2);
M(t, den6, num);
M(t, t, den);
pow2523(t, t);
M(t, t, num);
M(t, t, den);
M(t, t, den);
M(r[0], t, den);
S(chk, r[0]);
M(chk, chk, den);
if (neq25519(chk, num)) M(r[0], r[0], I);
S(chk, r[0]);
M(chk, chk, den);
if (neq25519(chk, num)) return -1;
if (par25519(r[0]) === (p[31]>>7)) Z(r[0], gf0, r[0]);
M(r[3], r[0], r[1]);
return 0;
}
nacl.ll = {
ge_scalarmult_base: ge_scalarmult_base,
ge_scalarmult: ge_scalarmult,
ge_double_scalarmult_base_vartime: ge_double_scalarmult_base_vartime,
ge_add: ge_add,
ge_double_scalarmult_postcomp_vartime: ge_double_scalarmult_postcomp_vartime
};
/* High-level API */
function cleanup(arr) {
for (var i = 0; i < arr.length; i++) arr[i] = 0;
}
nacl.randomBytes = function(n) {
var b = new Uint8Array(n);
randombytes(b, n);
return b;
};
nacl.setPRNG = function(fn) {
randombytes = fn;
};
(function() {
// Initialize PRNG if environment provides CSPRNG.
// If not, methods calling randombytes will throw.
var crypto = typeof self !== 'undefined' ? (self.crypto || self.msCrypto) : null;
if (crypto && crypto.getRandomValues) {
// Browsers.
var QUOTA = 65536;
nacl.setPRNG(function(x, n) {
var i, v = new Uint8Array(n);
for (i = 0; i < n; i += QUOTA) {
crypto.getRandomValues(v.subarray(i, i + Math.min(n - i, QUOTA)));
}
for (i = 0; i < n; i++) x[i] = v[i];
cleanup(v);
});
} else if (typeof require !== 'undefined') {
// Node.js.
crypto = require('crypto');
if (crypto && crypto.randomBytes) {
nacl.setPRNG(function(x, n) {
var i, v = crypto.randomBytes(n);
for (i = 0; i < n; i++) x[i] = v[i];
cleanup(v);
});
}
}
})();
})(typeof module !== 'undefined' && module.exports ? module.exports : (self.nacl = self.nacl || {}));

View File

@ -1,473 +0,0 @@
/*
* js-sha3 v0.5.1
* https://github.com/emn178/js-sha3
*
* Copyright 2015, emn178@gmail.com
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/MIT
*/
;(function(root, undefined) {
'use strict';
var NODE_JS = typeof(module) != 'undefined';
if(NODE_JS) {
root = global;
if(root.JS_SHA3_TEST) {
root.navigator = { userAgent: 'Chrome'};
}
}
var HEX_CHARS = '0123456789abcdef'.split('');
var SHAKE_PADDING = [31, 7936, 2031616, 520093696];
var KECCAK_PADDING = [1, 256, 65536, 16777216];
var PADDING = [6, 1536, 393216, 100663296];
var SHIFT = [0, 8, 16, 24];
var RC = [1, 0, 32898, 0, 32906, 2147483648, 2147516416, 2147483648, 32907, 0, 2147483649,
0, 2147516545, 2147483648, 32777, 2147483648, 138, 0, 136, 0, 2147516425, 0,
2147483658, 0, 2147516555, 0, 139, 2147483648, 32905, 2147483648, 32771,
2147483648, 32770, 2147483648, 128, 2147483648, 32778, 0, 2147483658, 2147483648,
2147516545, 2147483648, 32896, 2147483648, 2147483649, 0, 2147516424, 2147483648];
var BITS = [224, 256, 384, 512];
var SHAKE_BITS = [128, 256];
var OUTPUT_TYPES = ['hex', 'buffer', 'array'];
var createOutputMethod = function(bits, padding, outputType) {
return function(message) {
return new Keccak(bits, padding, bits).update(message)[outputType]();
}
};
var createShakeOutputMethod = function(bits, padding, outputType) {
return function(message, outputBits) {
return new Keccak(bits, padding, outputBits).update(message)[outputType]();
}
};
var createMethod = function(bits, padding) {
var method = createOutputMethod(bits, padding, 'hex');
method.create = function() {
return new Keccak(bits, padding, bits);
};
method.update = function(message) {
return method.create().update(message);
};
for(var i = 0;i < OUTPUT_TYPES.length;++i) {
var type = OUTPUT_TYPES[i];
method[type] = createOutputMethod(bits, padding, type);
}
return method;
};
var createShakeMethod = function(bits, padding) {
var method = createShakeOutputMethod(bits, padding, 'hex');
method.create = function(outputBits) {
return new Keccak(bits, padding, outputBits);
};
method.update = function(message, outputBits) {
return method.create(outputBits).update(message);
};
for(var i = 0;i < OUTPUT_TYPES.length;++i) {
var type = OUTPUT_TYPES[i];
method[type] = createShakeOutputMethod(bits, padding, type);
}
return method;
};
var algorithms = [
{name: 'keccak', padding: KECCAK_PADDING, bits: BITS, createMethod: createMethod},
{name: 'sha3', padding: PADDING, bits: BITS, createMethod: createMethod},
{name: 'shake', padding: SHAKE_PADDING, bits: SHAKE_BITS, createMethod: createShakeMethod}
];
var methods = {};
for(var i = 0;i < algorithms.length;++i) {
var algorithm = algorithms[i];
var bits = algorithm.bits;
var createMethod = algorithm.createMethod;
for(var j = 0;j < bits.length;++j) {
var method = algorithm.createMethod(bits[j], algorithm.padding);
methods[algorithm.name +'_' + bits[j]] = method;
}
}
function Keccak(bits, padding, outputBits) {
this.blocks = [];
this.s = [];
this.padding = padding;
this.outputBits = outputBits;
this.reset = true;
this.block = 0;
this.start = 0;
this.blockCount = (1600 - (bits << 1)) >> 5;
this.byteCount = this.blockCount << 2;
this.outputBlocks = outputBits >> 5;
this.extraBytes = (outputBits & 31) >> 3;
for(var i = 0;i < 50;++i) {
this.s[i] = 0;
}
};
Keccak.prototype.update = function(message) {
var notString = typeof(message) != 'string';
if(notString && message.constructor == root.ArrayBuffer) {
message = new Uint8Array(message);
}
var length = message.length, blocks = this.blocks, byteCount = this.byteCount,
blockCount = this.blockCount, index = 0, s = this.s, i, code;
while(index < length) {
if(this.reset) {
this.reset = false;
blocks[0] = this.block;
for(i = 1;i < blockCount + 1;++i) {
blocks[i] = 0;
}
}
if(notString) {
for (i = this.start;index < length && i < byteCount; ++index) {
blocks[i >> 2] |= message[index] << SHIFT[i++ & 3];
}
} else {
for (i = this.start;index < length && i < byteCount; ++index) {
code = message.charCodeAt(index);
if (code < 0x80) {
blocks[i >> 2] |= code << SHIFT[i++ & 3];
} else if (code < 0x800) {
blocks[i >> 2] |= (0xc0 | (code >> 6)) << SHIFT[i++ & 3];
blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];
} else if (code < 0xd800 || code >= 0xe000) {
blocks[i >> 2] |= (0xe0 | (code >> 12)) << SHIFT[i++ & 3];
blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3];
blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];
} else {
code = 0x10000 + (((code & 0x3ff) << 10) | (message.charCodeAt(++index) & 0x3ff));
blocks[i >> 2] |= (0xf0 | (code >> 18)) << SHIFT[i++ & 3];
blocks[i >> 2] |= (0x80 | ((code >> 12) & 0x3f)) << SHIFT[i++ & 3];
blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3];
blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];
}
}
}
this.lastByteIndex = i;
if(i >= byteCount) {
this.start = i - byteCount;
this.block = blocks[blockCount];
for(i = 0;i < blockCount;++i) {
s[i] ^= blocks[i];
}
f(s);
this.reset = true;
} else {
this.start = i;
}
}
return this;
};
Keccak.prototype.finalize = function() {
var blocks = this.blocks, i = this.lastByteIndex, blockCount = this.blockCount, s = this.s;
blocks[i >> 2] |= this.padding[i & 3];
if(this.lastByteIndex == this.byteCount) {
blocks[0] = blocks[blockCount];
for(i = 1;i < blockCount + 1;++i) {
blocks[i] = 0;
}
}
blocks[blockCount - 1] |= 0x80000000;
for(i = 0;i < blockCount;++i) {
s[i] ^= blocks[i];
}
f(s);
};
Keccak.prototype.toString = Keccak.prototype.hex = function() {
this.finalize();
var blockCount = this.blockCount, s = this.s, outputBlocks = this.outputBlocks,
extraBytes = this.extraBytes, i = 0, j = 0;
var hex = '', block;
while(j < outputBlocks) {
for(i = 0;i < blockCount && j < outputBlocks;++i, ++j) {
block = s[i];
hex += HEX_CHARS[(block >> 4) & 0x0F] + HEX_CHARS[block & 0x0F] +
HEX_CHARS[(block >> 12) & 0x0F] + HEX_CHARS[(block >> 8) & 0x0F] +
HEX_CHARS[(block >> 20) & 0x0F] + HEX_CHARS[(block >> 16) & 0x0F] +
HEX_CHARS[(block >> 28) & 0x0F] + HEX_CHARS[(block >> 24) & 0x0F];
}
if(j % blockCount == 0) {
f(s);
}
}
if(extraBytes) {
block = s[i];
if(extraBytes > 0) {
hex += HEX_CHARS[(block >> 4) & 0x0F] + HEX_CHARS[block & 0x0F];
}
if(extraBytes > 1) {
hex += HEX_CHARS[(block >> 12) & 0x0F] + HEX_CHARS[(block >> 8) & 0x0F];
}
if(extraBytes > 2) {
hex += HEX_CHARS[(block >> 20) & 0x0F] + HEX_CHARS[(block >> 16) & 0x0F];
}
}
return hex;
};
Keccak.prototype.buffer = function() {
this.finalize();
var blockCount = this.blockCount, s = this.s, outputBlocks = this.outputBlocks,
extraBytes = this.extraBytes, i = 0, j = 0;
var bytes = this.outputBits >> 3;
var buffer;
if(extraBytes) {
buffer = new ArrayBuffer((outputBlocks + 1) << 2);
} else {
buffer = new ArrayBuffer(bytes);
}
var array = new Uint32Array(buffer);
while(j < outputBlocks) {
for(i = 0;i < blockCount && j < outputBlocks;++i, ++j) {
array[j] = s[i];
}
if(j % blockCount == 0) {
f(s);
}
}
if(extraBytes) {
array[i] = s[i];
buffer = buffer.slice(0, bytes);
}
return buffer;
};
Keccak.prototype.digest = Keccak.prototype.array = function() {
this.finalize();
var blockCount = this.blockCount, s = this.s, outputBlocks = this.outputBlocks,
extraBytes = this.extraBytes, i = 0, j = 0;
var array = [], offset, block;
while(j < outputBlocks) {
for(i = 0;i < blockCount && j < outputBlocks;++i, ++j) {
offset = j << 2;
block = s[i];
array[offset] = block & 0xFF;
array[offset + 1] = (block >> 8) & 0xFF;
array[offset + 2] = (block >> 16) & 0xFF;
array[offset + 3] = (block >> 24) & 0xFF;
}
if(j % blockCount == 0) {
f(s);
}
}
if(extraBytes) {
offset = j << 2;
block = s[i];
if(extraBytes > 0) {
array[offset] = block & 0xFF;
}
if(extraBytes > 1) {
array[offset + 1] = (block >> 8) & 0xFF;
}
if(extraBytes > 2) {
array[offset + 2] = (block >> 16) & 0xFF;
}
}
return array;
};
var f = function(s) {
var h, l, n, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9,
b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15, b16, b17,
b18, b19, b20, b21, b22, b23, b24, b25, b26, b27, b28, b29, b30, b31, b32, b33,
b34, b35, b36, b37, b38, b39, b40, b41, b42, b43, b44, b45, b46, b47, b48, b49;
for(n = 0; n < 48; n += 2) {
c0 = s[0] ^ s[10] ^ s[20] ^ s[30] ^ s[40];
c1 = s[1] ^ s[11] ^ s[21] ^ s[31] ^ s[41];
c2 = s[2] ^ s[12] ^ s[22] ^ s[32] ^ s[42];
c3 = s[3] ^ s[13] ^ s[23] ^ s[33] ^ s[43];
c4 = s[4] ^ s[14] ^ s[24] ^ s[34] ^ s[44];
c5 = s[5] ^ s[15] ^ s[25] ^ s[35] ^ s[45];
c6 = s[6] ^ s[16] ^ s[26] ^ s[36] ^ s[46];
c7 = s[7] ^ s[17] ^ s[27] ^ s[37] ^ s[47];
c8 = s[8] ^ s[18] ^ s[28] ^ s[38] ^ s[48];
c9 = s[9] ^ s[19] ^ s[29] ^ s[39] ^ s[49];
h = c8 ^ ((c2 << 1) | (c3 >>> 31));
l = c9 ^ ((c3 << 1) | (c2 >>> 31));
s[0] ^= h;
s[1] ^= l;
s[10] ^= h;
s[11] ^= l;
s[20] ^= h;
s[21] ^= l;
s[30] ^= h;
s[31] ^= l;
s[40] ^= h;
s[41] ^= l;
h = c0 ^ ((c4 << 1) | (c5 >>> 31));
l = c1 ^ ((c5 << 1) | (c4 >>> 31));
s[2] ^= h;
s[3] ^= l;
s[12] ^= h;
s[13] ^= l;
s[22] ^= h;
s[23] ^= l;
s[32] ^= h;
s[33] ^= l;
s[42] ^= h;
s[43] ^= l;
h = c2 ^ ((c6 << 1) | (c7 >>> 31));
l = c3 ^ ((c7 << 1) | (c6 >>> 31));
s[4] ^= h;
s[5] ^= l;
s[14] ^= h;
s[15] ^= l;
s[24] ^= h;
s[25] ^= l;
s[34] ^= h;
s[35] ^= l;
s[44] ^= h;
s[45] ^= l;
h = c4 ^ ((c8 << 1) | (c9 >>> 31));
l = c5 ^ ((c9 << 1) | (c8 >>> 31));
s[6] ^= h;
s[7] ^= l;
s[16] ^= h;
s[17] ^= l;
s[26] ^= h;
s[27] ^= l;
s[36] ^= h;
s[37] ^= l;
s[46] ^= h;
s[47] ^= l;
h = c6 ^ ((c0 << 1) | (c1 >>> 31));
l = c7 ^ ((c1 << 1) | (c0 >>> 31));
s[8] ^= h;
s[9] ^= l;
s[18] ^= h;
s[19] ^= l;
s[28] ^= h;
s[29] ^= l;
s[38] ^= h;
s[39] ^= l;
s[48] ^= h;
s[49] ^= l;
b0 = s[0];
b1 = s[1];
b32 = (s[11] << 4) | (s[10] >>> 28);
b33 = (s[10] << 4) | (s[11] >>> 28);
b14 = (s[20] << 3) | (s[21] >>> 29);
b15 = (s[21] << 3) | (s[20] >>> 29);
b46 = (s[31] << 9) | (s[30] >>> 23);
b47 = (s[30] << 9) | (s[31] >>> 23);
b28 = (s[40] << 18) | (s[41] >>> 14);
b29 = (s[41] << 18) | (s[40] >>> 14);
b20 = (s[2] << 1) | (s[3] >>> 31);
b21 = (s[3] << 1) | (s[2] >>> 31);
b2 = (s[13] << 12) | (s[12] >>> 20);
b3 = (s[12] << 12) | (s[13] >>> 20);
b34 = (s[22] << 10) | (s[23] >>> 22);
b35 = (s[23] << 10) | (s[22] >>> 22);
b16 = (s[33] << 13) | (s[32] >>> 19);
b17 = (s[32] << 13) | (s[33] >>> 19);
b48 = (s[42] << 2) | (s[43] >>> 30);
b49 = (s[43] << 2) | (s[42] >>> 30);
b40 = (s[5] << 30) | (s[4] >>> 2);
b41 = (s[4] << 30) | (s[5] >>> 2);
b22 = (s[14] << 6) | (s[15] >>> 26);
b23 = (s[15] << 6) | (s[14] >>> 26);
b4 = (s[25] << 11) | (s[24] >>> 21);
b5 = (s[24] << 11) | (s[25] >>> 21);
b36 = (s[34] << 15) | (s[35] >>> 17);
b37 = (s[35] << 15) | (s[34] >>> 17);
b18 = (s[45] << 29) | (s[44] >>> 3);
b19 = (s[44] << 29) | (s[45] >>> 3);
b10 = (s[6] << 28) | (s[7] >>> 4);
b11 = (s[7] << 28) | (s[6] >>> 4);
b42 = (s[17] << 23) | (s[16] >>> 9);
b43 = (s[16] << 23) | (s[17] >>> 9);
b24 = (s[26] << 25) | (s[27] >>> 7);
b25 = (s[27] << 25) | (s[26] >>> 7);
b6 = (s[36] << 21) | (s[37] >>> 11);
b7 = (s[37] << 21) | (s[36] >>> 11);
b38 = (s[47] << 24) | (s[46] >>> 8);
b39 = (s[46] << 24) | (s[47] >>> 8);
b30 = (s[8] << 27) | (s[9] >>> 5);
b31 = (s[9] << 27) | (s[8] >>> 5);
b12 = (s[18] << 20) | (s[19] >>> 12);
b13 = (s[19] << 20) | (s[18] >>> 12);
b44 = (s[29] << 7) | (s[28] >>> 25);
b45 = (s[28] << 7) | (s[29] >>> 25);
b26 = (s[38] << 8) | (s[39] >>> 24);
b27 = (s[39] << 8) | (s[38] >>> 24);
b8 = (s[48] << 14) | (s[49] >>> 18);
b9 = (s[49] << 14) | (s[48] >>> 18);
s[0] = b0 ^ (~b2 & b4);
s[1] = b1 ^ (~b3 & b5);
s[10] = b10 ^ (~b12 & b14);
s[11] = b11 ^ (~b13 & b15);
s[20] = b20 ^ (~b22 & b24);
s[21] = b21 ^ (~b23 & b25);
s[30] = b30 ^ (~b32 & b34);
s[31] = b31 ^ (~b33 & b35);
s[40] = b40 ^ (~b42 & b44);
s[41] = b41 ^ (~b43 & b45);
s[2] = b2 ^ (~b4 & b6);
s[3] = b3 ^ (~b5 & b7);
s[12] = b12 ^ (~b14 & b16);
s[13] = b13 ^ (~b15 & b17);
s[22] = b22 ^ (~b24 & b26);
s[23] = b23 ^ (~b25 & b27);
s[32] = b32 ^ (~b34 & b36);
s[33] = b33 ^ (~b35 & b37);
s[42] = b42 ^ (~b44 & b46);
s[43] = b43 ^ (~b45 & b47);
s[4] = b4 ^ (~b6 & b8);
s[5] = b5 ^ (~b7 & b9);
s[14] = b14 ^ (~b16 & b18);
s[15] = b15 ^ (~b17 & b19);
s[24] = b24 ^ (~b26 & b28);
s[25] = b25 ^ (~b27 & b29);
s[34] = b34 ^ (~b36 & b38);
s[35] = b35 ^ (~b37 & b39);
s[44] = b44 ^ (~b46 & b48);
s[45] = b45 ^ (~b47 & b49);
s[6] = b6 ^ (~b8 & b0);
s[7] = b7 ^ (~b9 & b1);
s[16] = b16 ^ (~b18 & b10);
s[17] = b17 ^ (~b19 & b11);
s[26] = b26 ^ (~b28 & b20);
s[27] = b27 ^ (~b29 & b21);
s[36] = b36 ^ (~b38 & b30);
s[37] = b37 ^ (~b39 & b31);
s[46] = b46 ^ (~b48 & b40);
s[47] = b47 ^ (~b49 & b41);
s[8] = b8 ^ (~b0 & b2);
s[9] = b9 ^ (~b1 & b3);
s[18] = b18 ^ (~b10 & b12);
s[19] = b19 ^ (~b11 & b13);
s[28] = b28 ^ (~b20 & b22);
s[29] = b29 ^ (~b21 & b23);
s[38] = b38 ^ (~b30 & b32);
s[39] = b39 ^ (~b31 & b33);
s[48] = b48 ^ (~b40 & b42);
s[49] = b49 ^ (~b41 & b43);
s[0] ^= RC[n];
s[1] ^= RC[n + 1];
}
}
if(!root.JS_SHA3_TEST && NODE_JS) {
module.exports = methods;
} else if(root) {
for(var key in methods) {
root[key] = methods[key];
}
}
}(this));

View File

@ -8,10 +8,9 @@
<tr>
<td>age [h:m:s]</td>
<td>transaction hash</td>
<td>fee/per_kB</td>
<td>fee/per_kB [&#181;&#x271]</td>
<!--<td>outputs</td>-->
<td>in/out/pID</td>
<td>ring size</td>
<td>in/out</td>
<td>tx size [kB]</td>
</tr>
{{#mempooltxs}}
@ -20,8 +19,7 @@
<td><a href="/tx/{{hash}}">{{hash}}</a></td>
<td>{{fee}}/{{payed_for_kB}}</td>
<!--<td>{{xmr_outputs}}</td>-->
<td>{{no_inputs}}/{{no_outputs}}/{{pID}}</td>
<td>{{mixin}}</td>
<td>{{no_inputs}}/{{no_outputs}}</td>
<td>{{txsize}}</td>
</tr>
{{/mempooltxs}}

View File

@ -69,7 +69,7 @@
</table>
<h3>
Sum XMR from matched outputs (i.e., incoming XMR):
Sum WOW from matched outputs (i.e., incoming WOW):
{{#found_our_outputs}}
{{sum_xmr}}
{{/found_our_outputs}}
@ -78,7 +78,7 @@
{{/found_our_outputs}}
</h3>
<h4>
<a href="{{shortcut_url}}" target="_blank">link to this page</a>
<a href="{{domain_url}}{{shortcut_url}}" target="_blank">link to this page</a>
</h4>
</div>
@ -142,7 +142,7 @@
</div>
<h3>
Sum XMR from matched and marked by * ring member's outputs: {{sum_mixin_xmr}}
Sum WOW from matched and marked by * ring member's outputs: {{sum_mixin_xmr}}
<br/>
<span style="font-size: 16px"> Possible spending is:
{{possible_spending}} (tx fee included)
@ -152,6 +152,12 @@
it is impossible to know whether this is your real spending. <br/>
So do not take this number seriously.
It is probably totally wrong anyway.</span>
<br/>
<span style="font-size: 14px">
Number of possible our mixins is {{no_all_possible_mixins}}
for {{all_possible_mixins_amount}} wow
(amount as uint64).
</span>
</h3>
</div>

View File

@ -10,7 +10,6 @@
{{#has_payment_id}}
<H5 style="margin:5px">Payment id: <span id="payment_id">{{payment_id}}</span></H5>
<H5 style="margin:5px">Payment id as ascii: {{payment_id_as_ascii}}</H5>
{{/has_payment_id}}
{{#has_payment_id8}}
@ -56,7 +55,7 @@
</table>
<h3>{{outputs_no}} output(s) for total of {{outputs_xmr_sum}} xmr</h3>
<h3>{{outputs_no}} output(s) for total of {{outputs_xmr_sum}} wow</h3>
<div class="center">
<table class="center">
<tr>
@ -82,32 +81,19 @@
<input type="radio" id="tab-1" name="tab-group-1" checked>
<label for="tab-1">Decode outputs</label>
<div class="content">
<h4 style="margin: 0px">Check which outputs belong to given Monero address/subaddress and viewkey</h4>
<h4 style="margin: 0px">Check which outputs belong to given Wownero address/subaddress and viewkey</h4>
<h5 style="margin: 0px">
For RingCT transactions, outputs' amounts are also decoded
<br/>
{{#enable_js}}
Note: address/subaddress and viewkey are NOT sent to the server, as the calculations are done on the client side
{{/enable_js}}
{{^enable_js}}
Note: address/subaddress and viewkey are sent to the server, as the calculations are done on the server side
{{/enable_js}}
Note: address/subaddress and viewkey are sent to the server, as the calculations are done on the server side
</h5>
<form action="/myoutputs" method="post" style="width:100%; margin-top:2px" class="style-1">
<input type="hidden" name="tx_hash" value="{{tx_hash}}"><br/>
<input type="text" name="xmr_address" size="110" placeholder="Monero address/subaddress"><br/>
<input type="text" name="xmr_address" size="110" placeholder="Wownero address/subaddress"><br/>
<input type="text" name="viewkey" size="110" placeholder="Private viewkey" style="margin-top:5px"><br/>
<input type="hidden" name="raw_tx_data" value="{{raw_tx_data}}">
<!--above raw_tx_data field only used when checking raw tx data through tx pusher-->
{{#enable_js}}
<!-- if have js, DONOT submit the form to server.
change submit button, to just a button -->
<button type="button" style="margin-top:5px" id="decode_btn" >Decode outputs</button>
{{/enable_js}}
{{^enable_js}}
<input type="submit" value="Decode outputs" style="margin-top:5px" >
{{/enable_js}}
<input type="submit" value="Decode outputs" style="margin-top:5px" >
</form>
</div>
</div>
@ -117,17 +103,12 @@
<label for="tab-2">Prove sending</label>
<div class="content">
<h4 style="margin: 0px">Prove to someone that you have sent them Monero in this transaction</h4>
<h4 style="margin: 0px">Prove to someone that you have sent them Wownero in this transaction</h4>
<h5 style="margin: 0px">
Tx private key can be obtained using <i>get_tx_key</i>
command in <i>monero-wallet-cli</i> command line tool
command in <i>wownero-wallet-cli</i> command line tool
<br/>
{{#enable_js}}
Note: address/subaddress and tx private key are NOT sent to the server, as the calculations are done on the client side
{{/enable_js}}
{{^enable_js}}
Note: address/subaddress and tx private key are sent to the server, as the calculations are done on the server side
{{/enable_js}}
Note: address/subaddress and tx private key are sent to the server, as the calculations are done on the server side
</h5>
<form action="/prove" method="post" style="width:100%;margin-top:2px" class="style-1">
<input type="hidden" name="txhash" value="{{tx_hash}}"><br/>
@ -135,16 +116,7 @@
<input type="hidden" name="raw_tx_data" value="{{raw_tx_data}}">
<!--above raw_tx_data field only used when checking raw tx data through tx pusher-->
<input type="text" name="xmraddress" size="120" placeholder="Recipient's monero address/subaddress" style="margin-top:5px"><br/>
{{#enable_js}}
<!-- if have js, DONOT submit the form to server.
change submit button, to just a button -->
<button type="button" style="margin-top:5px" id="prove_btn">Prove sending</button>
{{/enable_js}}
{{^enable_js}}
<input type="submit" value="Prove sending" style="margin-top:5px">
{{/enable_js}}
<input type="submit" value="Prove sending" style="margin-top:5px">
</form>
</div>
</div>
@ -152,235 +124,6 @@
</div>
{{/have_raw_tx}}
{{#enable_js}}
<!-- to disply results from deconding and proving txs using js -->
<div id="decode-prove-results" class="center" style="width: 80%; margin-top:10px;border-style: dotted">
</div>
<script>
// here we handle button presses from the above forms
// to decode and prove txs.
$(document).ready(function() {
// we need output pubplic keys, their indexes and amounts.
// all this is already avaliable on the html, but we can use
// musch framework to produce js array for this
var tx_json = {{#tx_json_raw}}{{/tx_json_raw}};
var tx_public_key = $("#tx_pub_key").text();
// when we process multi-ouput tx, it can have extra public keys
// due to sub-addresses
var add_tx_pub_keys = $("#add_tx_pub_keys").text().split(';').slice(0, -1);
//console.log("add_tx_pub_keys: ", add_tx_pub_keys);
var payment_id = $("#payment_id").text();
$("#decode_btn").click(function() {
var address = $("input[name=xmr_address]").val().trim();
var viewkey = $("input[name=viewkey]").val().trim();
if (!address || !viewkey) {
$("#decode-prove-results").html("<h4>Address or viewkey key not provided!</h4>");
return;
}
// not used when decoding, but used when proving.
// so we just use array here
multiple_tx_secret_keys = [];
try {
var address_decoded = decode_address(address);
decodeOutputs(tx_json, tx_public_key, viewkey,
address_decoded.spend, payment_id,
add_tx_pub_keys, multiple_tx_secret_keys, false);
} catch(err){
console.log(err);
$("#decode-prove-results").html('<h4>Error: ' + err + '</h4>' );
}
});
$("#prove_btn").click(function() {
var address = $("input[name=xmraddress]").val().trim();
var tx_prv_key = $("input[name=txprvkey]").val().trim();
if (!address || !tx_prv_key) {
$("#decode-prove-results").html("<h4>Address or tx private key not provided!</h4>");
return;
}
try {
// when using subaddress, there can be more than one tx_prv_key
var multiple_tx_prv_keys = parse_str_secret_key(tx_prv_key);
var address_decoded = decode_address(address);
decodeOutputs(tx_json, address_decoded.view, tx_prv_key,
address_decoded.spend, payment_id,
add_tx_pub_keys, multiple_tx_prv_keys, true);
} catch(err){
console.log(err);
$("#decode-prove-results").html('<h4>Error: ' + err + '</h4>' );
}
});
});
// based on C++ code by stoffu
function parse_str_secret_key(key_str) {
var multiple_tx_secret_keys = [];
var num_keys = Math.floor(key_str.length / 64);
if (num_keys * 64 != key_str.length)
throw "num_keys * 64 != key_str.length";
for (var i = 0; i < num_keys; i++)
{
multiple_tx_secret_keys.push(key_str.slice(64*i, 64*i + 64));
}
return multiple_tx_secret_keys;
}
function decodeOutputs(tx_json, pub_key, sec_key,
address_pub_key, payment_id,
add_tx_pub_keys, multiple_tx_prv_keys, tx_prove) {
//console.log(tx_json);
var is_rct = (tx_json.version === 2);
var rct_type = (is_rct ? tx_json.rct_signatures.type : -1);
var key_derivation = "";
if (tx_prove)
key_derivation = generate_key_derivation(pub_key, multiple_tx_prv_keys[0]);
else
key_derivation = generate_key_derivation(pub_key, sec_key);
var add_key_derivation = [];
if (add_tx_pub_keys) {
for (var i = 0; i < add_tx_pub_keys.length; i++)
{
if (!tx_prove)
add_key_derivation.push(generate_key_derivation(add_tx_pub_keys[i], sec_key));
else
add_key_derivation.push(generate_key_derivation(pub_key, multiple_tx_prv_keys[i+1]));
}
}
//console.log("add_key_derivation: ", add_key_derivation);
// go over each tx output, and check if it is ours or not
var decoding_results_str = '<h3>Output decoding results</h3>';
decoding_results_str += '<table class="center">';
decoding_results_str += '<tr>' +
'<td></td>' +
'<td>output public key</td>' +
'<td>amount</td>' +
'<td>output match?</td>' +
'</tr>';
var output_idx = 0;
var sum_outptus = 0;
tx_json.vout.forEach(function(output) {
var output_pub_key = output.target.key;
var amount = output.amount;
var pubkey_generated = derive_public_key(key_derivation, output_idx, address_pub_key);
var mine_output = (output_pub_key == pubkey_generated);
var with_additional = false;
var mine_output_str = "false";
if (!mine_output && add_tx_pub_keys.length == tx_json.vout.length) {
pubkey_generated = derive_public_key(add_key_derivation[output_idx],
output_idx, address_pub_key);
mine_output = (output_pub_key == pubkey_generated);
with_additional = true;
}
if (mine_output) {
mine_output_str = '<span style="color: #008009;font-weight: bold">true</span>';
if (is_rct && rct_type > 0 /* not coinbase*/) {
try {
//var ecdh = decodeRct(tx_json.rct_signatures, output_idx, key_derivation);
var ecdh = decodeRct(tx_json.rct_signatures, output_idx,
(with_additional ? add_key_derivation[output_idx] : key_derivation));
amount = parseInt(ecdh.amount);
} catch (err) {
decoding_results_str += "<span class='validNo'>RingCT amount for output " + i + " with pubkey: " + output_pub_key + "</span>" + "<br>"; //rct commitment != computed
throw "invalid rct amount";
}
}
sum_outptus += amount;
}
decoding_results_str += "<tr>"
+"<td>" + output_idx + "</td>"
+"<td>" + output_pub_key + "</td>"
+"<td>" + (amount / 1e12) + "</td>"
+"<td>" + mine_output_str + "</td>"
+"</tr>";
//console.log(output[1], pubkey_generated);
output_idx++;
});
decoding_results_str += "</table>";
decoding_results_str += "<h3>Sum XMR from matched outputs (i.e., incoming XMR): " + (sum_outptus / 1e12) + "</h3>"
// decrypt payment_id8 which results in using
// integrated address
if (payment_id.length == 16) {
if (pub_key) {
var decrypted_payment_id8
= decrypt_payment_id(payment_id, pub_key, sec_key);
console.log("decrypted_payment_id8: " + decrypted_payment_id8);
decoding_results_str += "<h5>Decrypted payment id: "
+ decrypted_payment_id8
+ " (value incorrect if you are not the recipient of the tx)</h5>"
}
}
$("#decode-prove-results").html(decoding_results_str);
}
</script>
{{/enable_js}}
{{#has_inputs}}
{{#enable_mixins_details}}
@ -397,14 +140,14 @@
{{/enable_mixins_details}}
{{^inputs_xmr_sum_not_zero}}
<h3>{{inputs_no}} input(s) for total of {{inputs_xmr_sum}} xmr</h3>
<h3>{{inputs_no}} input(s) for total of {{inputs_xmr_sum}} wow</h3>
{{/inputs_xmr_sum_not_zero}}
{{#inputs_xmr_sum_not_zero}}
{{^have_any_unknown_amount}}
<h3>{{inputs_no}} inputs(s) for total of {{inputs_xmr_sum}} xmr</h3>
<h3>{{inputs_no}} inputs(s) for total of {{inputs_xmr_sum}} wow</h3>
{{/have_any_unknown_amount}}
{{#have_any_unknown_amount}}
<h3>{{inputs_no}} inputs(s) for total of at least {{inputs_xmr_sum}} xmr</h3>
<h3>{{inputs_no}} inputs(s) for total of at least {{inputs_xmr_sum}} wow</h3>
{{/have_any_unknown_amount}}
{{/inputs_xmr_sum_not_zero}}
@ -531,7 +274,14 @@
{{^have_raw_tx}}
{{^with_ring_signatures}}
{{#show_more_details_link}}
<h5 style="margin-top:1px"><a href="/tx/{{tx_hash}}/1">More details</a></h5>
<h5 style="margin-top:1px">
<a href="/tx/{{tx_hash}}/1">More details</a>
{{#enable_as_hex}}
| <a href="/txhex/{{tx_hash}}">Tx as hex</a>
| <a href="/ringmembershex/{{tx_hash}}">Ring member outputs/mixins as hex</a>
| <a href="/ringmemberstxhex/{{tx_hash}}">Full ring member txs as hex</a>
{{/enable_as_hex}}
</h5>
{{/show_more_details_link}}
{{/with_ring_signatures}}
{{#with_ring_signatures}}
@ -549,18 +299,4 @@
{{/with_ring_signatures}}
{{/have_raw_tx}}
{{#show_cache_times}}
<div class="center">
{{#construction_time}}
<h6 style="margin-top: 1px;color:#949490">
Tx details construction time: {{construction_time}} s
{{#from_cache}}
<br/>Tx read from the tx cache
{{/from_cache}}
</h6>
{{/construction_time}}
</div>
{{/show_cache_times}}
</div>

View File

@ -0,0 +1,71 @@
<div>
<H4>Block hash (height): {{blk_hash}} ({{blk_height}})</H4>
<h4>
Eight RandomX and corresponding assembly x86 programs used
to calculate the PoW hash of the block.<br/>
The RandomX programs are executed on RandomX virtual machine.
</h4>
<h5>
Values of the integer and floating point registers
are also provided.
</h5>
{{#rx_codes}}
<h3> Program #{{rx_code_idx}}</h3>
<table class="center" style="width: 60%; margin-top:10px">
{{#first_program}}
<tr>
<td colspan="2">
Integer registers R:<br/><br/>
r0: 0x0000000000000000, r1: 0x0000000000000000, r2: 0x0000000000000000, r3: 0x0000000000000000<br/>
r4: 0x0000000000000000, r5: 0x0000000000000000, r6: 0x0000000000000000, r7: 0x0000000000000000<br/><br/>
Floating point registers F {lo, hi}:<br/><br/>
Initial values not accessible<br/><br/>
Floating point registers E {lo, hi}:<br/><br/>
Initial values not accessible<br/><br/>
Floating point registers A {lo, hi}:<br/><br/>
a0: {{a0}}, a1: {{a1}}<br/>
a2: {{a2}}, a3: {{a3}}<br/><br/>
{{/first_program}}
</td>
</tr>
<tr>
<td style="text-align: left;">RandomX code</td>
<td style="text-align: left;">ASM x86</td>
</tr>
<tr>
<td style="text-align: left;vertical-align: top;">
<pre>{{rx_code}}</pre>
</td>
<td style="text-align: left;vertical-align: top;">
<pre>{{rx_code_asm}}</pre>
</td>
</tr>
<tr>
<td colspan="2">
Integer registers R:<br/><br/>
r0: {{r0}}, r1: {{r1}}, r2: {{r2}}, r3: {{r3}}<br/>
r4: {{r4}}, r5: {{r5}}, r6: {{r6}}, r7: {{r7}}<br/><br/>
Floating point registers F {lo, hi}:<br/><br/>
f0: {{f0}}, f1: {{f1}}<br/>
f2: {{f2}}, f3: {{f3}}<br/><br/>
Floating point registers E {lo, hi}:<br/><br/>
e0: {{e0}}, e1: {{e1}}<br/>
e2: {{e2}}, e3: {{e3}}<br/><br/>
Floating point registers A {lo, hi}:<br/><br/>
a0: {{a0}}, a1: {{a1}}<br/>
a2: {{a2}}, a3: {{a3}}<br/><br/>
<br/>
</td>
</tr>
</table>
{{/rx_codes}}
</div>

View File

@ -9,12 +9,12 @@
<div class="center">
<form action="/checkandpush" method="post" style="width:100%; margin-top:15px" class="style-1">
Paste here either a hex string of raw transaction<br/>
(the <i>tx_blob</i> response in the wallet RPC, or the <i>raw_monero_tx</i>
(the <i>tx_blob</i> response in the wallet RPC, or the <i>raw_wownero_tx</i>
file saved by the wallet CLI with <i>--do-not-relay</i> option specified),<br/>
or base64 encoded, unsigned or signed transaction data<br/>
<br/>
(In Linux, can get the raw tx data: <i>cat raw_monero_tx | xclip -selection clipboard</i>)<br/>
(In Windows, can get the raw tx data: <i>certutil.exe -encode -f raw_monero_tx encoded.txt & type "encoded.txt" | clip</i>)<br/>
(In Linux, can get the raw tx data: <i>cat raw_wownero_tx | xclip -selection clipboard</i>)<br/>
(In Windows, can get the raw tx data: <i>certutil.exe -encode -f raw_wownero_tx encoded.txt & type "encoded.txt" | clip</i>)<br/>
<textarea name="rawtxdata" rows="20" cols="80"></textarea>
<br/>

View File

@ -1,4 +1,15 @@
<div class="center">
<h3 style="font-size: 12px; margin-top: 20px">
{{#refresh}}
<a href="/tx/{{tx_hash}}">Autorefresh is ON (10 s)</a>
{{/refresh}}
{{^refresh}}
<a href="/tx/{{tx_hash}}/autorefresh">Autorefresh is OFF</a>
{{/refresh}}
</h3>
</div>
<div>
{{#has_error}}

View File

@ -935,7 +935,9 @@ decode_ringct(rct::rctSig const& rv,
switch (rv.type)
{
case rct::RCTTypeSimple:
case rct::RCTTypeSimpleBulletproof:
case rct::RCTTypeBulletproof:
case rct::RCTTypeBulletproof2:
case rct::RCTTypeCLSAG:
amount = rct::decodeRctSimple(rv,
rct::sk2rct(scalar1),
i,
@ -943,7 +945,6 @@ decode_ringct(rct::rctSig const& rv,
hw::get_device("default"));
break;
case rct::RCTTypeFull:
case rct::RCTTypeFullBulletproof:
amount = rct::decodeRct(rv,
rct::sk2rct(scalar1),
i,
@ -1048,7 +1049,7 @@ decrypt(const std::string &ciphertext,
}
crypto::chacha_key key;
crypto::generate_chacha_key(&skey, sizeof(skey), key);
crypto::generate_chacha_key(&skey, sizeof(skey), key, 1);
const crypto::chacha_iv &iv = *(const crypto::chacha_iv*)&ciphertext[0];
@ -1075,7 +1076,7 @@ decrypt(const std::string &ciphertext,
}
crypto::chacha8(ciphertext.data() + sizeof(iv),
crypto::chacha20(ciphertext.data() + sizeof(iv),
ciphertext.size() - prefix_size,
key, iv, &plaintext[0]);
@ -1266,4 +1267,37 @@ pause_execution(uint64_t no_seconds, const string& text)
cout << endl;
}
string
tx_to_hex(transaction const& tx)
{
return epee::string_tools::buff_to_hex_nodelimer(t_serializable_object_to_blob(tx));
}
void get_metric_prefix(cryptonote::difficulty_type hr, double& hr_d, char& prefix)
{
if (hr < 1000)
{
prefix = 0;
return;
}
static const char metric_prefixes[4] = { 'k', 'M', 'G', 'T' };
for (size_t i = 0; i < sizeof(metric_prefixes); ++i)
{
if (hr < 1000000)
{
hr_d = hr.convert_to<double>() / 1000;
prefix = metric_prefixes[i];
return;
}
hr /= 1000;
}
prefix = 0;
}
cryptonote::difficulty_type
make_difficulty(uint64_t low, uint64_t high)
{
return (cryptonote::difficulty_type(high) << 64) + low;
}
}

View File

@ -8,7 +8,7 @@
#define PATH_SEPARARTOR '/'
#define XMR_AMOUNT(value) \
static_cast<double>(value) / 1e12
static_cast<double>(value) / 1e11
#define REMOVE_HASH_BRAKETS(a_hash) \
a_hash.substr(1, a_hash.size()-2)
@ -224,7 +224,7 @@ get_payment_id(const transaction& tx,
inline double
get_xmr(uint64_t core_amount)
{
return static_cast<double>(core_amount) / 1e12;
return static_cast<double>(core_amount) / 1e11;
}
array<size_t, 5>
@ -338,7 +338,7 @@ void chunks(Iterator begin,
*/
template <typename T>
inline string
remove_bad_chars(T&& in_str, std::regex const& rgx = std::regex ("[^a-zA-Z0-9]"))
remove_bad_chars(T&& in_str, std::regex const& rgx = std::regex ("[^a-zA-Z0-9+/=]"))
{
return std::regex_replace(std::forward<T>(in_str), rgx, "");
}
@ -370,6 +370,15 @@ calc_median(It it_begin, It it_end)
void
pause_execution(uint64_t no_seconds, const string& text = "now");
string
tx_to_hex(transaction const& tx);
void
get_metric_prefix(cryptonote::difficulty_type hr, double& hr_d, char& prefix);
cryptonote::difficulty_type
make_difficulty(uint64_t low, uint64_t high);
}
#endif //XMREG01_TOOLS_H
#endif //XMREG01_TOOLS_H