Compare commits

...

481 Commits

Author SHA1 Message Date
Riccardo Spagni
b97a2f72db Merge pull request #1445
95b9e85e rename cn_deserialize (Riccardo Spagni)
2016-12-13 19:14:00 +02:00
Riccardo Spagni
183d3657f3 Merge pull request #1446
b2adfa8c Bitmonero namespace renamed Monero. Bitmonero namespace alias added so that third party uses of the wallet api can transition. (Randi Joseph)
2016-12-13 19:13:09 +02:00
Randi Joseph
b2adfa8c51 Bitmonero namespace renamed Monero. Bitmonero namespace alias added so that third party uses of the wallet api can transition. 2016-12-13 10:21:38 -05:00
Riccardo Spagni
95b9e85e2d rename cn_deserialize 2016-12-13 16:39:43 +02:00
Riccardo Spagni
b1bdb4e529 Merge pull request #1437
655eafd1 bump version (Riccardo Spagni)
117194a3 update checkpoints (Riccardo Spagni)
39a9db9e update checkpoints (Riccardo Spagni)
2016-12-13 16:36:43 +02:00
Riccardo Spagni
2f2c6460ae Merge pull request #1442
dd144b14 blockchain: fix reorganizations past a hard fork boundary (moneromooo-monero)
2016-12-13 10:24:25 +02:00
Riccardo Spagni
c03da2b2dd Merge pull request #1441
0fb5dc87 monero-wallet-cli wording changes 'n' stuff (luigi1111)
2016-12-13 10:23:49 +02:00
Riccardo Spagni
c2a9229310 Merge pull request #1439
4299bdf6 Improve language of 'node ahead by' message (NanoAkron)
2016-12-13 10:23:22 +02:00
Riccardo Spagni
9d19e62fa2 Merge pull request #1438
9d906159 Tx verification failing is not an error (luigi1111)
2016-12-13 10:22:56 +02:00
moneromooo-monero
dd144b14bc blockchain: fix reorganizations past a hard fork boundary
After popping blocks from the old chain, the hard fork object's
notion of the current version was not in line with the new height,
causing the first blocks from the new chain to be rejected due
to a false expection of a newer version.
2016-12-13 02:13:23 +00:00
luigi1111
0fb5dc870d monero-wallet-cli wording changes 'n' stuff
Possibly other pedantry. Pedants are people too.
2016-12-12 19:53:28 -06:00
NanoAkron
4299bdf614 Improve language of 'node ahead by' message 2016-12-12 23:24:40 +00:00
luigi1111
9d906159c3 Tx verification failing is not an error
And rangeProofs are on outputs...
2016-12-12 17:01:20 -06:00
Riccardo Spagni
655eafd160 bump version 2016-12-13 00:29:29 +02:00
Riccardo Spagni
117194a397 update checkpoints 2016-12-13 00:26:25 +02:00
Riccardo Spagni
39a9db9eb1 update checkpoints 2016-12-13 00:24:48 +02:00
Riccardo Spagni
1a286061ff Merge pull request #1436
3b4539ee addressbook updates (Jaquee)
2016-12-12 23:46:47 +02:00
Jaquee
3b4539ee7e addressbook updates 2016-12-12 21:50:50 +01:00
Riccardo Spagni
5b7f1fc8e4 Merge pull request #1424
aeb13289 Update cryptonote_protocol_handler.inl (Gingeropolous)
2016-12-12 22:40:41 +02:00
Riccardo Spagni
aa7a926681 Merge pull request #1434
5df92877 GUI address book (Jaquee)
2016-12-12 22:39:38 +02:00
Riccardo Spagni
7e324b7ad7 Merge pull request #1433
66dc23c4 modded minimum and recommended monero versions (Gingeropolous)
2016-12-12 22:39:11 +02:00
Riccardo Spagni
84d3107600 Merge pull request #1431
81c6bb9a thread_group: fix build on older GCC (moneromooo-monero)
2016-12-12 22:38:27 +02:00
Riccardo Spagni
67844f826e Merge pull request #1425
c5c45ca6 wallet: bring forward use of the dynamic fee (moneromooo-monero)
2016-12-12 22:38:05 +02:00
Riccardo Spagni
7141d317df Merge pull request #1423
19585d49 mnemonics: fix misc STL containers leak (moneromooo-monero)
f6fcf0ef oaes_lib: fix a leak on OOM error path (moneromooo-monero)
2016-12-12 22:37:32 +02:00
Jaquee
5df92877c7 GUI address book 2016-12-12 00:43:02 +01:00
Gingeropolous
66dc23c458 modded minimum and recommended monero versions
modified all min and rec versions to v0.10.1 for v4 and v5 forks
2016-12-11 13:12:03 -05:00
moneromooo-monero
81c6bb9a40 thread_group: fix build on older GCC
vtnerd (original author) confirmed this is the Right Way.
2016-12-11 13:59:42 +00:00
moneromooo-monero
c5c45ca660 wallet: bring forward use of the dynamic fee
It was 14 days after v4, it is now one day after it.

luigi1111's suggestion
2016-12-10 15:39:26 +00:00
Gingeropolous
aeb13289bb Update cryptonote_protocol_handler.inl
Per discussion of #1359, the wording has changed to indicate that no assessment of the blocks validity is made.
2016-12-10 10:22:16 -05:00
moneromooo-monero
19585d4914 mnemonics: fix misc STL containers leak
found by coverity
2016-12-10 12:51:36 +00:00
moneromooo-monero
f6fcf0ef26 oaes_lib: fix a leak on OOM error path
found by coverity
2016-12-10 12:51:20 +00:00
Riccardo Spagni
2d0fbaf35b Merge pull request #1422
9b00d80f wallet2: pass by const ref where possible (moneromooo-monero)
2016-12-10 14:49:34 +02:00
Riccardo Spagni
930aceb242 Merge pull request #1419
f4a3ce15 Fix sending outputs from a tx with more than one pubkey (moneromooo-monero)
2016-12-10 14:48:56 +02:00
Riccardo Spagni
0f99423080 Merge pull request #1418
dfbb85b6 blockchain: fix setting non trovial alternate chain as invalid (moneromooo-monero)
2016-12-10 14:48:39 +02:00
Riccardo Spagni
99f725cbe2 Merge pull request #1408
b9c5f29d Revert forcing -fPIC for all ARMv8 builds (NanoAkron)
2016-12-10 14:48:00 +02:00
moneromooo-monero
9b00d80f85 wallet2: pass by const ref where possible
Reported by kenshi84
2016-12-10 11:43:44 +00:00
moneromooo-monero
f4a3ce15c1 Fix sending outputs from a tx with more than one pubkey
A bug in cold signing caused a spurious pubkey to be included
in transactions, so we need to ensure we use the correct one
when sending outputs from one of those.
2016-12-09 18:21:21 +00:00
NanoAkron
b9c5f29d1d Revert forcing -fPIC for all ARMv8 builds 2016-12-09 12:01:16 +00:00
moneromooo-monero
dfbb85b6fe blockchain: fix setting non trovial alternate chain as invalid
The wrong iterator was being used.
Also preincrement iterators to avoid possibly invalidating them,
I'm not sure this is necessary, but let's be safe.
2016-12-08 22:26:27 +00:00
Riccardo Spagni
12b59460c2 Merge pull request #1417
0b91d825 simplewallet: restore automatically setting trusted local daemon (moneromooo-monero)
2016-12-08 23:45:04 +02:00
Riccardo Spagni
8e1a8c6adc Merge pull request #1415
6c44f5c6 wallet: send 0 change to a random address where necessary with rct (moneromooo-monero)
2016-12-08 23:44:40 +02:00
Riccardo Spagni
e6b05ed95a Merge pull request #1414
3b005275 ringct: add sc_check calls in MLSAG_Ver for ss and cc (moneromooo-monero)
2f1732a7 ringct: guard against bad data exceptions in worker threads (moneromooo-monero)
2016-12-08 23:44:09 +02:00
Riccardo Spagni
22e16e88e3 Merge pull request #1413
648ea6be blockchain: bring the v4 fork height one block forward (luigi1111)
46a0dcc1 ringct: luigi1111's changes to fix and speedup Borromean sigs (luigi1111)
76958fc7 ringct: switch to Borromean signatures (Shen Noether)
2016-12-08 23:43:41 +02:00
Riccardo Spagni
f9503d2789 Merge pull request #1405
d1a75754 Remove infinite loop in refresh code (Jaquee)
2016-12-08 23:43:19 +02:00
Riccardo Spagni
9907fc689c Merge pull request #1387
18462aa0 Added confirmation before binding wallet-rpc to external IP (Lee Clagett)
2016-12-08 23:42:28 +02:00
moneromooo-monero
0b91d82574 simplewallet: restore automatically setting trusted local daemon 2016-12-08 20:01:24 +00:00
moneromooo-monero
3b00527500 ringct: add sc_check calls in MLSAG_Ver for ss and cc
luigi1111's recommendation
2016-12-07 22:41:21 +00:00
moneromooo-monero
2f1732a7e5 ringct: guard against bad data exceptions in worker threads
If purported pubkeys aren't actually valid pubkeys, exceptions
will fly. These will terminate if thrown in a worker thread.
Guard against this.
2016-12-07 22:09:43 +00:00
moneromooo-monero
6c44f5c6eb wallet: send 0 change to a random address where necessary with rct
If a rct transaction would cause no change to be generated, a zero
change output is added, and sent to a randomly generated address.
This ensures that no transaction will be sent with just one output,
which could cause the receiver to be able to determine which of the
inputs in the sent rings is the real one.
This is very rare, since it requires the sum of outputs to be equal
to the sum of outputs plus the fee, which is now a function of the
last few blocks.
2016-12-07 21:05:50 +00:00
luigi1111
648ea6bef1 blockchain: bring the v4 fork height one block forward
This will ensure the early 0.10 daemons will barf at the fork
height, and not a bit later, which could be confusing.
2016-12-06 21:59:08 +00:00
Lee Clagett
18462aa065 Added confirmation before binding wallet-rpc to external IP 2016-12-05 21:45:11 -05:00
Jaquee
d1a75754df Remove infinite loop in refresh code
This reverts commit fd181b03bb.
2016-12-05 13:02:45 +01:00
luigi1111
46a0dcc1d2 ringct: luigi1111's changes to fix and speedup Borromean sigs 2016-12-04 21:54:16 +00:00
Shen Noether
76958fc75a ringct: switch to Borromean signatures 2016-12-04 21:54:11 +00:00
Riccardo Spagni
45bb393577 Merge pull request #1403
60633cf6 Spelling in errors (taushet)
2016-12-04 22:30:15 +02:00
Riccardo Spagni
cc73d5000f Merge pull request #1402
bdd3fb85 Spelling in errors. (taushet)
2016-12-04 22:29:55 +02:00
Riccardo Spagni
b500a64524 Merge pull request #1399
73ac3b8e wallet2: avoid possible undefined behavior on empty string (moneromooo-monero)
2016-12-04 22:28:48 +02:00
Riccardo Spagni
f2ea2afb77 Merge pull request #1398
f4772bae Fix a few minor typos (Pierre Boyer)
2016-12-04 22:28:22 +02:00
Riccardo Spagni
8086379680 Merge pull request #1397
3f7d6fb5 Fix delayed exit when syncing (moneromooo-monero)
2016-12-04 22:27:41 +02:00
Riccardo Spagni
4a0be41dfe Merge pull request #1396
7c0dd5e4 net_node: drop connections from banned IPs after looping through connections (moneromooo-monero)
2016-12-04 22:26:12 +02:00
Riccardo Spagni
d59dc59744 Merge pull request #1395
59443bf9 ringct: fix MGs serialization to JSON (moneromooo-monero)
2016-12-04 22:25:24 +02:00
Riccardo Spagni
daf5dbebb0 Merge pull request #1393
0e18f465 db_lmdb: add info in an error message when we can't get an output (moneromooo-monero)
c96f9b02 db_lmdb: guard against going out of sync on unexpected db results (moneromooo-monero)
bef51e67 db_lmdb: minor pedantic tweaks (moneromooo-monero)
3465c4eb db_lmdb: set same packing format for output_data_t and pre_rct_output_data_t (moneromooo-monero)
2016-12-04 22:23:34 +02:00
Riccardo Spagni
416f7fbd5f Merge pull request #1392
204b1bff blockchain: use high bound block reward on error where appropriate (moneromooo-monero)
2016-12-04 22:23:03 +02:00
Riccardo Spagni
98150be7d8 Merge pull request #1389
4adde042 p2p: possibly fix crash in relay_blocks (moneromooo-monero)
2016-12-04 22:22:07 +02:00
Riccardo Spagni
977dd9b76c Merge pull request #1385
5783dd8c tests: add unit tests for uri parsing (moneromooo-monero)
82ba2108 wallet: add API and RPC to create/parse monero: URIs (moneromooo-monero)
d9001b43 epee: add functions to convert from URL format (ie, %XX values) (moneromooo-monero)
2016-12-04 22:19:06 +02:00
Riccardo Spagni
836c748366 Merge pull request #1388
fcd178ef wallet_api: add a few daemon related getters (moneromooo-monero)
2016-12-04 22:17:48 +02:00
Riccardo Spagni
2fd43e25ee Merge pull request #1386
8f6ec90c blockchain: reject invalid pubkeys from v4 (moneromooo-monero)
2016-12-04 22:15:36 +02:00
Riccardo Spagni
3c05aeda1b Merge pull request #1384
8b0e04cb monero.supp: add a suppression for noisy boost cond var signalling (moneromooo-monero)
c3527daf epee: signal cond var before unlocking (moneromooo-monero)
2016-12-04 22:14:01 +02:00
Riccardo Spagni
42d07e865f Merge pull request #1383
00592189 change 'invalid address format' loglevel (Jaquee)
2016-12-04 22:02:58 +02:00
Riccardo Spagni
3d533d1037 Merge pull request #1380
657a70e0 wallet: add a getter for the filename path (moneromooo-monero)
2016-12-04 22:02:40 +02:00
Riccardo Spagni
fe89782512 Merge pull request #1379
d6086f5b Improve daemon RPC version handling (moneromooo-monero)
2016-12-04 22:01:49 +02:00
Riccardo Spagni
35e5909a10 Merge pull request #1378
91ffb61c Added command_line::is_yes (Lee Clagett)
2016-12-04 22:01:07 +02:00
Riccardo Spagni
6e3a96bc4a Merge pull request #1365
1df0fc71 Fix formatting of RPi2 build instructions (NanoAkron)
2016-12-04 21:55:22 +02:00
taushet
60633cf674 Spelling in errors 2016-12-04 20:12:40 +01:00
taushet
bdd3fb85d6 Spelling in errors. 2016-12-04 20:10:43 +01:00
moneromooo-monero
73ac3b8e26 wallet2: avoid possible undefined behavior on empty string 2016-12-04 14:56:06 +00:00
Pierre Boyer
f4772bae81 Fix a few minor typos 2016-12-04 14:13:54 +01:00
moneromooo-monero
3f7d6fb57d Fix delayed exit when syncing 2016-12-04 12:27:45 +00:00
moneromooo-monero
7c0dd5e46c net_node: drop connections from banned IPs after looping through connections
This keeps the connections lock just for the time of looping
and adding connectoins to a list, and the dropping happens
after it. This should avoid lengthy delays waiting for the
connections lock.
2016-12-03 11:20:48 +00:00
moneromooo-monero
59443bf9df ringct: fix MGs serialization to JSON 2016-12-02 13:16:19 +00:00
moneromooo-monero
4adde0423b p2p: possibly fix crash in relay_blocks 2016-12-01 23:52:16 +00:00
moneromooo-monero
204b1bff62 blockchain: use high bound block reward on error where appropriate
If the block reward to use for the fee calculation can't be
calculated (should not happen in practice), use a high bound,
so we use a fee overestimate that will be accepted by the network.
2016-12-01 16:34:09 +00:00
moneromooo-monero
0e18f46522 db_lmdb: add info in an error message when we can't get an output
Will be useful to debug
2016-12-01 14:31:40 +00:00
moneromooo-monero
c96f9b0255 db_lmdb: guard against going out of sync on unexpected db results
m_num_outputs keeps track of the number of outputs, which should
be the same as the size of both the output_txs and output_amounts
databases. If one goes out of sync, we need to throw to abort
whatever it is we were doing.
2016-12-01 14:29:35 +00:00
moneromooo-monero
bef51e677e db_lmdb: minor pedantic tweaks
Add consts in a few places where it makes sense, avoid unnecessary
memory reallocation where we know the full size needed at the outset,
simplify and avoid memory copy.
2016-12-01 14:28:09 +00:00
moneromooo-monero
3465c4ebc7 db_lmdb: set same packing format for output_data_t and pre_rct_output_data_t
For safety, though it seems to have been the case already.

Also add a comment about the necessary layout identity.
2016-12-01 14:26:18 +00:00
moneromooo-monero
fcd178ef33 wallet_api: add a few daemon related getters
Blockchain height, version, Mining hash rate...
2016-11-29 10:54:38 +00:00
moneromooo-monero
8f6ec90c83 blockchain: reject invalid pubkeys from v4 2016-11-28 22:32:58 +00:00
moneromooo-monero
5783dd8c99 tests: add unit tests for uri parsing 2016-11-28 17:54:28 +00:00
moneromooo-monero
82ba2108e9 wallet: add API and RPC to create/parse monero: URIs 2016-11-28 17:54:22 +00:00
moneromooo-monero
d9001b43ac epee: add functions to convert from URL format (ie, %XX values) 2016-11-28 17:54:16 +00:00
moneromooo-monero
8b0e04cb12 monero.supp: add a suppression for noisy boost cond var signalling 2016-11-28 09:52:59 +00:00
moneromooo-monero
c3527dafd5 epee: signal cond var before unlocking
This is more canonical, and avoids some helgrind spam
2016-11-28 09:52:49 +00:00
Jaquee
0059218908 change 'invalid address format' loglevel 2016-11-27 14:44:19 +01:00
moneromooo-monero
657a70e004 wallet: add a getter for the filename path 2016-11-26 14:19:57 +00:00
moneromooo-monero
d6086f5b4e Improve daemon RPC version handling
Daemon RPC version is now composed of a major and minor number,
so that incompatible changes bump the major version, while
compatible changes can still bump the minor version without
causing clients to unnecessarily complain.
2016-11-26 12:56:44 +00:00
Lee Clagett
91ffb61c25 Added command_line::is_yes 2016-11-25 21:57:27 -05:00
Riccardo Spagni
c36cb54340 Merge pull request #1372
17b6bd6 Fix DNS failures in offline mode preventing daemon startup (moneromooo-monero)
2016-11-24 13:01:35 +02:00
Riccardo Spagni
4248d5131c Merge pull request #1371
8dadf02 Fixed undefined behavior in TestDB (Lee Clagett)
2016-11-24 13:01:05 +02:00
Riccardo Spagni
2497a2d547 Merge pull request #1369
6d76072 simplewallet: remove double confirmation when submitting signed tx (moneromooo-monero)
92dea04 wallet2: fix wrong change being recorded for cold signed txes (moneromooo-monero)
2016-11-24 13:00:32 +02:00
Riccardo Spagni
7f7d7cab5d Merge pull request #1368
f6660e1 Updated GPG key for Jaquee (Jaquee)
2016-11-24 13:00:10 +02:00
Riccardo Spagni
b1a5d4bd5d Merge pull request #1366
67e910a Instructions for debugging LMDB crashes taken from #1360 (NanoAkron)
2016-11-24 12:59:27 +02:00
Riccardo Spagni
ce8a2315cf Merge pull request #1364
f025198 Added task_region - a fork/join task implementation (Lee Clagett)
2016-11-24 12:58:09 +02:00
Riccardo Spagni
694efaaf28 Merge pull request #1362
ab7b56e tests: fix uninitialized data valgrind reports in levin tests (moneromooo-monero)
73e8a76 tests: fix uninitialized data valgrind reports in serialization tests (moneromooo-monero)
2016-11-24 12:57:45 +02:00
Riccardo Spagni
3fa1b6623a Merge pull request #1361
1d9e223 rpc: do not include output indices for pool txes (moneromooo-monero)
e227d6e rpc: bump version after RPC changes (moneromooo-monero)
2c0173c Add a get_outs (fully text based) version of get_outs.bin (moneromooo-monero)
e05907b rpc: add output indices to gettransactions (moneromooo-monero)
2016-11-24 12:57:00 +02:00
Riccardo Spagni
a26b27f66e Merge pull request #1358
7abfc54 wallet: fix exporting outputs and key images with txes with two pubkeys (moneromooo-monero)
2016-11-24 12:55:14 +02:00
Riccardo Spagni
25369df4d8 Merge pull request #1357
5fc36f9 wallet2_api: fix history leak on destruction (moneromooo-monero)
2016-11-24 12:54:25 +02:00
Riccardo Spagni
f801dc8567 Merge pull request #1356
69b188c wallet2_api: fix payment ids from integrated addresses being ignored (moneromooo-monero)
2016-11-24 12:53:59 +02:00
Riccardo Spagni
52175502de Merge pull request #1353
452aeca epee: blind attempt to fix exit hang on windows (moneromooo-monero)
2016-11-24 12:53:35 +02:00
Riccardo Spagni
570acdc686 Merge pull request #1352
d01f5c7 wallet2: fix illegal memory access removing newlines from password (moneromooo-monero)
2016-11-24 12:53:14 +02:00
Riccardo Spagni
2121f3b2f0 Merge pull request #1351
e6264a2 wallet2: fix decrypting a bit too much in authenticated mode (moneromooo-monero)
2016-11-24 12:52:54 +02:00
Riccardo Spagni
d094c45822 Merge pull request #1197
fd181b0 Clamp refresh from height to blockchain height. (Dion Ahmetaj)
2016-11-24 12:51:17 +02:00
moneromooo-monero
17b6bd6d35 Fix DNS failures in offline mode preventing daemon startup 2016-11-23 23:14:49 +00:00
Lee Clagett
8dadf02c4f Fixed undefined behavior in TestDB 2016-11-23 17:22:35 -05:00
moneromooo-monero
6d76072612 simplewallet: remove double confirmation when submitting signed tx 2016-11-23 20:45:03 +00:00
moneromooo-monero
92dea04929 wallet2: fix wrong change being recorded for cold signed txes 2016-11-23 20:27:22 +00:00
Lee Clagett
f025198f19 Added task_region - a fork/join task implementation 2016-11-23 14:41:25 -05:00
moneromooo-monero
1d9e223944 rpc: do not include output indices for pool txes
Those aren't yet in the blockchain, so will not be found
(and aren't yet known, since it depends on where exactly the
tx will be mined in the next block or blocks)
2016-11-23 18:56:54 +00:00
Jaquee
f6660e1851 Updated GPG key for Jaquee 2016-11-23 19:48:09 +01:00
moneromooo-monero
e227d6e7ac rpc: bump version after RPC changes 2016-11-22 20:01:20 +00:00
moneromooo-monero
2c0173c722 Add a get_outs (fully text based) version of get_outs.bin 2016-11-22 20:00:40 +00:00
moneromooo-monero
e05907b3e7 rpc: add output indices to gettransactions
Someone apparently needs that to make a wallet but never asked.
If you read that and that's not what you wanted, the bugtracker
is at https://github.com/monero-project/monero/issues
2016-11-22 20:00:23 +00:00
NanoAkron
1df0fc719e Fix formatting of RPi2 build instructions 2016-11-21 23:21:58 +00:00
NanoAkron
67e910a1a0 Instructions for debugging LMDB crashes taken from #1360 2016-11-21 23:00:20 +00:00
moneromooo-monero
ab7b56e0e2 tests: fix uninitialized data valgrind reports in levin tests 2016-11-20 17:51:17 +00:00
moneromooo-monero
73e8a76d86 tests: fix uninitialized data valgrind reports in serialization tests 2016-11-20 17:25:21 +00:00
moneromooo-monero
7abfc5474c wallet: fix exporting outputs and key images with txes with two pubkeys
This also needs to make sure to pick the correct one, in the case
where cold signing caused to tx keys to be included.
2016-11-19 09:36:40 +00:00
moneromooo-monero
5fc36f981c wallet2_api: fix history leak on destruction 2016-11-18 21:42:08 +00:00
moneromooo-monero
69b188c4b2 wallet2_api: fix payment ids from integrated addresses being ignored 2016-11-18 19:13:43 +00:00
Dion Ahmetaj
fd181b03bb Clamp refresh from height to blockchain height. 2016-11-18 13:40:55 -05:00
moneromooo-monero
452aeca5cd epee: blind attempt to fix exit hang on windows
Thanks to duckduckgo and the internet.

This might even compile.
2016-11-17 22:10:03 +00:00
moneromooo-monero
d01f5c7f1f wallet2: fix illegal memory access removing newlines from password 2016-11-17 20:43:58 +00:00
moneromooo-monero
e6264a2c35 wallet2: fix decrypting a bit too much in authenticated mode 2016-11-17 20:31:00 +00:00
Riccardo Spagni
dbf2ab56c5 Merge pull request #1346
4eb7347 wallet: return fee in transfer RPC (moneromooo-monero)
2016-11-17 16:40:37 +02:00
Riccardo Spagni
5df6f0be80 Merge pull request #1318
4fca34d Wallet2: calculate approximate blockchain height on offline creation (Jacob Brydolf)
2016-11-17 16:37:30 +02:00
Riccardo Spagni
2988e1be8c Merge pull request #1344
a0131c8 wallet: auto sync outputs and key images in cold signing files (moneromooo-monero)
f806611 wallet2: fill key image and pubkey maps when importing outputs (moneromooo-monero)
5fe363c wallet: cast indices to string in logs to be nice to CLANG (moneromooo-monero)
11ae187 wallet2: try all tx keys when scanning a new transaction (moneromooo-monero)
072d646 wallet2: fill in key image map when importing key images (moneromooo-monero)
23d80b1 core: remove any tx pubkey from extra before adding one (moneromooo-monero)
d72376d simplewallet: add a verbose flag to incoming_transfers (moneromooo-monero)
47413a5 simplewallet: spell out change when signing a transfer (moneromooo-monero)
14cb088 simplewallet: print public keys too on spendkey/viewkey commands (moneromooo-monero)
a99ab49 wallet: fix serialization of new m_key_image_known member (moneromooo-monero)
2016-11-17 16:36:12 +02:00
Riccardo Spagni
e2816fefc5 Merge pull request #1337
18772a3 tests: fix another fee test on 32 bit (moneromooo-monero)
2016-11-17 16:30:14 +02:00
Riccardo Spagni
b7b54b6cff Merge pull request #1336
bd4da18 simplewallet: include amount sent in transfer confirmation (moneromooo-monero)
2016-11-17 16:26:49 +02:00
Riccardo Spagni
9e3cedce87 Merge pull request #1335
d48f2e9 wallet: fix serialization of new m_key_image_known member (moneromooo-monero)
2016-11-17 16:26:04 +02:00
moneromooo-monero
4eb7347fdd wallet: return fee in transfer RPC 2016-11-16 18:56:45 +00:00
moneromooo-monero
a0131c8be3 wallet: auto sync outputs and key images in cold signing files
When passing around unsigned and signed transactions, outputs
and key images are passed along (outputs are passed along unsigned
transactions from the hot wallet to the cold wallet, key images
are passed along with signed transations from the cold wallet
to the hot wallet), to allow more user friendly syncing between
hot and cold wallets.
2016-11-16 09:22:24 +00:00
moneromooo-monero
f8066116dd wallet2: fill key image and pubkey maps when importing outputs 2016-11-16 09:22:18 +00:00
moneromooo-monero
5fe363cd22 wallet: cast indices to string in logs to be nice to CLANG 2016-11-16 09:22:13 +00:00
moneromooo-monero
11ae1873f8 wallet2: try all tx keys when scanning a new transaction
The vast majority of transactions will have just one tx pubkey,
but a bug with cold wallet signing caused two such keys to be
there, with the second one being the real one.
2016-11-16 09:22:05 +00:00
moneromooo-monero
072d646a45 wallet2: fill in key image map when importing key images 2016-11-15 21:20:08 +00:00
moneromooo-monero
23d80b15fd core: remove any tx pubkey from extra before adding one
This will happen when signing a transaction from a cold wallet,
and we don't want the placeholder the hot wallet put in it.
2016-11-15 21:20:02 +00:00
moneromooo-monero
d72376d467 simplewallet: add a verbose flag to incoming_transfers
Prints pubkey and key image as well
2016-11-13 18:20:46 +00:00
moneromooo-monero
47413a5626 simplewallet: spell out change when signing a transfer
Also catch change to multiple addresses, this is unexpected
2016-11-13 17:48:45 +00:00
moneromooo-monero
14cb088300 simplewallet: print public keys too on spendkey/viewkey commands 2016-11-13 17:24:53 +00:00
moneromooo-monero
a99ab49dd5 wallet: fix serialization of new m_key_image_known member 2016-11-13 16:38:29 +00:00
moneromooo-monero
18772a3ba9 tests: fix another fee test on 32 bit 2016-11-13 12:21:52 +00:00
moneromooo-monero
bd4da18525 simplewallet: include amount sent in transfer confirmation 2016-11-13 12:12:22 +00:00
moneromooo-monero
d48f2e9bc6 wallet: fix serialization of new m_key_image_known member 2016-11-13 12:02:29 +00:00
Riccardo Spagni
9363b2ac19 Merge pull request #1334
265e460 Fixed generate-from-json bug introduced in 358e068 (Lee Clagett)
2016-11-13 11:32:43 +02:00
Riccardo Spagni
56c4514486 Merge pull request #1331
e1dd15b Don't build monero-wallet-rpc when building the GUI (iDunk5400)
2016-11-13 11:32:24 +02:00
Lee Clagett
265e4605ec Fixed generate-from-json bug introduced in 358e068 2016-11-12 21:55:08 -05:00
Jacob Brydolf
4fca34ddb4 Wallet2: calculate approximate blockchain height on offline creation
Wallet API: add approximateBlockChainHeight()
2016-11-13 03:36:44 +01:00
iDunk5400
e1dd15b050 Don't build monero-wallet-rpc when building the GUI 2016-11-12 19:22:19 +01:00
Riccardo Spagni
eb6d66e4fc Merge pull request #1330
70d4915 wallet: add version dependency to the wallet target (moneromooo-monero)
2016-11-12 17:51:53 +02:00
Riccardo Spagni
41b2886795 Merge pull request #1329
cd929b8 levin: fix wrong value passed as return code to remote call (moneromooo-monero)
2016-11-12 17:51:25 +02:00
Riccardo Spagni
696fcba2a0 Merge pull request #1327
77e5bec added cmd to compile gtest (Gingeropolous)
2016-11-12 17:50:57 +02:00
Riccardo Spagni
fd4342097a Merge pull request #1325
2078cb6 tests: fix tests builds after fluffy blocks merge (moneromooo-monero)
2016-11-12 17:50:26 +02:00
Riccardo Spagni
300cb7b27b Merge pull request #1322
65528ae Always compile Position Independent Code on 64-bit ARMv8 systems (NanoAkron)
2016-11-12 17:49:31 +02:00
moneromooo-monero
70d4915980 wallet: add version dependency to the wallet target 2016-11-12 12:55:19 +00:00
moneromooo-monero
cd929b89b0 levin: fix wrong value passed as return code to remote call
When receiving an answer packet, the command code was passed
to the callback instead of the error code. This was hiding
the "command not found" failure from the peer, and in turn
causing the code to attempt to deserialize a non existent
reply string.
2016-11-12 10:12:23 +00:00
Gingeropolous
77e5bec0ab added cmd to compile gtest 2016-11-11 23:50:24 -05:00
NanoAkron
65528aef4e Always compile Position Independent Code on 64-bit ARMv8 systems 2016-11-12 00:26:49 +00:00
moneromooo-monero
2078cb6f2f tests: fix tests builds after fluffy blocks merge 2016-11-11 18:17:16 +00:00
Riccardo Spagni
6a2bb62827 Merge pull request #1316
358e068 Created monero-wallet-rpc, moving functionality from monero-wallet-cli (Lee Clagett)
2016-11-11 12:48:39 +02:00
Riccardo Spagni
524ff61ad5 Merge pull request #1321
0e418d2 rpc: bump RPC version (moneromooo-monero)
2016-11-11 12:38:01 +02:00
Riccardo Spagni
797fbbca2b Merge pull request #1319
c27c0fe tests: fix fee unit tests on 32 bit (moneromooo-monero)
2016-11-11 12:37:22 +02:00
Riccardo Spagni
a3cd7230f8 Merge pull request #1315
9150a16 Wallet API: use stored refresh height when rebuilding cache (Jacob Brydolf)
2016-11-11 12:35:47 +02:00
Riccardo Spagni
3fd13080b7 Merge pull request #1314
63772e4 wallet: fix corner case of no recent outputs available (moneromooo-monero)
2016-11-11 12:35:25 +02:00
Riccardo Spagni
0e0bf432a4 Merge pull request #1313
1669621 wallet2_api: support for sweeping all (moneromooo-monero)
2016-11-11 12:35:04 +02:00
Riccardo Spagni
5f568533aa Merge pull request #1263
d61bd81 add lightweight block propagation ("fluffy blocks") (Dion Ahmetaj)
2016-11-11 12:34:43 +02:00
moneromooo-monero
0e418d2a58 rpc: bump RPC version
I forgot to bump it previously when changing RPC, most notably
for the addition of the unlocked field in the histogram RPC.
This causes new wallets to not realize when they're talking to
an older daemon, and get confused trying to get outputs to use
as fake outs. This otherwise gratuitous bump ensures than old
daemons will be detected by wallets using this code.
2016-11-10 23:00:24 +00:00
Lee Clagett
358e068e87 Created monero-wallet-rpc, moving functionality from monero-wallet-cli 2016-11-10 16:39:27 -05:00
moneromooo-monero
c27c0feb3d tests: fix fee unit tests on 32 bit 2016-11-10 20:40:06 +00:00
moneromooo-monero
1669621937 wallet2_api: support for sweeping all 2016-11-09 19:32:37 +00:00
Dion Ahmetaj
d61bd8187e add lightweight block propagation ("fluffy blocks")
Added a new command to the P2P protocol definitions to allow querying for support flags.

Implemented handling of new support flags command in net_node. Changed for_each callback template to include support flags. Updated print_connections command to show peer support flags.

Added p2p constant for signaling fluffy block support.

Added get_pool_transaction function to cryptnote_core.

Added new commands to cryptonote protocol for relaying fluffy blocks.

Implemented handling of fluffy block command in cryptonote protocol.

Enabled fluffy block support in node initial configuration.

Implemented get_testnet function in cryptonote_core.

Made it so that fluffy blocks only run on testnet.
2016-11-09 14:24:27 -05:00
Jacob Brydolf
9150a16ed1 Wallet API: use stored refresh height when rebuilding cache 2016-11-09 18:46:03 +01:00
moneromooo-monero
63772e4048 wallet: fix corner case of no recent outputs available
Also clarify related logs
2016-11-09 14:01:54 +00:00
Riccardo Spagni
38727f7d2f Merge pull request #1312
acf908c thread_group: fix build with asserts enabled (moneromooo-monero)
2016-11-09 14:13:35 +02:00
Riccardo Spagni
7931cb19ef Merge pull request #1311
5c4cb96 cryptonote_protocol: drop connection when find_blockchain_supplement fails (moneromooo-monero)
2016-11-09 14:13:06 +02:00
Riccardo Spagni
dc5e0e45cd Merge pull request #1310
40a68e2 wallet2_api: add API for create_unmixable_sweep_transactions (moneromooo-monero)
2016-11-09 14:11:57 +02:00
Riccardo Spagni
56c594a8fe Merge pull request #1309
c441a61 wallet2_api: API to sign and verify a message (moneromooo-monero)
2016-11-09 14:10:39 +02:00
Riccardo Spagni
06ca304b06 Merge pull request #1307
4dcb74f wallet_api: PendingTransaction::txCount - number of split transactions (Ilya Kitaev)
2016-11-09 14:10:12 +02:00
Riccardo Spagni
144a7f090a Merge pull request #1305
c80f4d4 wallet: fix output collision detection for view wallets (moneromooo-monero)
2016-11-09 14:08:34 +02:00
moneromooo-monero
acf908c834 thread_group: fix build with asserts enabled
See https://github.com/monero-project/monero/pull/1291
2016-11-09 11:29:06 +00:00
moneromooo-monero
5c4cb96cfb cryptonote_protocol: drop connection when find_blockchain_supplement fails
This will be when we can't find common ground between the peer's
short chain history and our blockchain.

This fixes bad peers claiming a higher blockchain height from never
dropped, and keeping the node in synchronizing state forever, since
we will never get blocks from that peer.
2016-11-09 11:04:20 +00:00
moneromooo-monero
c441a61ef6 wallet2_api: API to sign and verify a message 2016-11-08 21:21:08 +00:00
Ilya Kitaev
4dcb74f97f wallet_api: PendingTransaction::txCount - number of split transactions 2016-11-09 00:13:18 +03:00
Riccardo Spagni
e8a55db29d Merge pull request #1308
0c530de Wallet API: Pause refresh while creating transaction (Jacob Brydolf)
2016-11-08 22:57:04 +02:00
Riccardo Spagni
18fdd8116e Merge pull request #1306
8aba0d4 wallet: encrypt outputs and key images files with the view key (moneromooo-monero)
2016-11-08 22:55:56 +02:00
Riccardo Spagni
7c7a6cf2f8 Merge pull request #1302
63fe6fd wallet2_api: allow connection to return "yes, but wrong version" (moneromooo-monero)
2016-11-08 22:53:13 +02:00
Riccardo Spagni
96e0138ebf Merge pull request #1301
35da3cb Wallet API: added getTxKey() (Jacob Brydolf)
2016-11-08 22:50:13 +02:00
Jacob Brydolf
35da3cb074 Wallet API: added getTxKey() 2016-11-08 21:48:26 +01:00
Riccardo Spagni
c57ce06a97 Merge pull request #1300
eb19492 wallet2_api: do not copy the whole pending tx when iterating (moneromooo-monero)
2016-11-08 22:48:04 +02:00
Riccardo Spagni
af2ceb29fa Merge pull request #1298
97288a5 wallet2_api: add API for tx notes (moneromooo-monero)
2016-11-08 22:45:54 +02:00
Riccardo Spagni
c05cecf036 Merge pull request #1297
af8a260 wallet_api: txkey checking functions for the GUI (moneromooo.monero)
2016-11-08 22:44:15 +02:00
Riccardo Spagni
3bd0456144 Merge pull request #1296
e59caf8 performance_tests: re-enable them... (moneromooo-monero)
2016-11-08 22:41:32 +02:00
Riccardo Spagni
dce47d52af Merge pull request #1291
64094e5 adding thread_group for managing async tasks (Lee Clagett)
2016-11-08 22:37:43 +02:00
Riccardo Spagni
6523694581 Merge pull request #1287
7edf76f CONTRIBUTING: add something about testing and bug reporting (moneromooo-monero)
2016-11-08 22:36:18 +02:00
Riccardo Spagni
4c44d896d3 Merge pull request #1285
a970a4e refresh speedup (luigi1111)
2016-11-08 22:34:26 +02:00
Riccardo Spagni
04003fe8e2 Merge pull request #1284
bc9b498 README: update coverity project number (anonimal)
9d9ab38 README: update armv8 link, add more coverage types (anonimal)
6f7f21f README: update build matrix (distro and ordering) (anonimal)
6711b98 README: add Freenode custom webchat link (anonimal)
b57d1e1 README: add build matrix like that in Kovri (anonimal)
38dc0bf README/Repo: remove Travis CI (anonimal)
2016-11-08 22:33:52 +02:00
Riccardo Spagni
0fa6cbef3f Merge pull request #1276
18f66f4 wallet: use the dynamic per kB fee (moneromooo-monero)
e6deb8a rpc: add a dynamic fee estimation RPC call (moneromooo-monero)
82dbba1 core: dynamic fee algorithm from ArticMine (moneromooo-monero)
2016-11-08 22:33:13 +02:00
moneromooo-monero
40a68e22fa wallet2_api: add API for create_unmixable_sweep_transactions 2016-11-08 20:03:07 +00:00
Jacob Brydolf
0c530de057 Wallet API: Pause refresh while creating transaction 2016-11-08 13:20:42 +01:00
moneromooo-monero
8aba0d4b4c wallet: encrypt outputs and key images files with the view key
This key is available to both cold and hot wallet.
Authenticated encryption will guard against interception and/or
modification of the file.
2016-11-07 20:01:05 +00:00
moneromooo-monero
c80f4d416d wallet: fix output collision detection for view wallets
View wallets do not have the spend secret key, and are thus
unable to derive key images for incoming outputs. Moreover,
a previous patch set key images to zero as a means to mark
an output as having an unknown key image, so they could be
filled in when importing key images at a later time. That
later patch caused spurious collisions. We now use public
keys to detect duplicate outputs. Public keys obtained from
the blockchain are checked to be identical to the ones
derived locally, so can't be spoofed.
2016-11-07 18:59:30 +00:00
moneromooo-monero
63fe6fd9ba wallet2_api: allow connection to return "yes, but wrong version" 2016-11-07 12:00:29 +00:00
anonimal
bc9b498598 README: update coverity project number 2016-11-06 18:21:08 +00:00
anonimal
9d9ab38fcd README: update armv8 link, add more coverage types
- Fixes armv8 build link
- Adds coverage matrix, coverity and license badges
2016-11-06 18:11:16 +00:00
moneromooo-monero
eb194925ec wallet2_api: do not copy the whole pending tx when iterating 2016-11-06 10:36:08 +00:00
moneromooo-monero
97288a5ce2 wallet2_api: add API for tx notes 2016-11-05 21:19:08 +00:00
moneromooo.monero
af8a2600aa wallet_api: txkey checking functions for the GUI 2016-11-05 15:24:05 +00:00
Riccardo Spagni
1372f255af Merge pull request #1295
b5d6faa wallet: fix bad amounts/fees again (moneromooo-monero)
2016-11-05 10:28:25 +02:00
anonimal
6f7f21f4e9 README: update build matrix (distro and ordering) 2016-11-05 01:17:08 +00:00
moneromooo-monero
e59caf87d3 performance_tests: re-enable them...
I think I'm the only one to review things here...
2016-11-04 11:11:45 +00:00
Lee Clagett
64094e5f4e adding thread_group for managing async tasks 2016-11-02 19:21:55 -04:00
moneromooo-monero
b5d6faada3 wallet: fix bad amounts/fees again
m_amount_out was sometimes getting initialized with the sum of
an transaction's outputs, and sometimes with the sum of outputs
that were not change. This caused confusion and bugs. We now
always set it to the sum of outputs. This reverts an earlier
fix for bad amounts as this used the other semantics. The wallet
data should be converted automatically in a percentage of cases
that I'm hesitant to estimate. In any case, restoring from seed
or keys or rebuilding the cache will get it right.
2016-11-02 23:11:30 +00:00
Riccardo Spagni
d51f1af75f Merge pull request #1272
48b57d8 monero.supp: valgrind suppressions file (moneromooo-monero)
ffd8c41 ringct: check the size of amount_keys is the same as destinations (moneromooo-monero)
836669d ringct: always shutdown the boost io service (moneromooo-monero)
2016-11-01 21:49:30 +02:00
luigi1111
a970a4e3cf refresh speedup
Compute derivation only once per tx, instead of once per output. Approx 33% faster while using 75% as much CPU on my machine. Note old functions in cryptonote_core (lookup_acc_outs and is_out_to_acc) are still used by tests.
2016-11-01 11:24:04 -05:00
Riccardo Spagni
b06c1abaa6 Merge pull request #1278
43ec2d0 Wallet API: added walletExists logic (Jacob Brydolf)
2016-11-01 15:29:44 +02:00
Riccardo Spagni
6f85b20d92 Merge pull request #1283
4869db7 adding static_assert to pod functions in string tools (Lee Clagett)
2016-11-01 15:13:10 +02:00
Riccardo Spagni
f189fe51ac Merge pull request #1282
f5ccfa4 core: fix removal of extra nonce using wrong type (moneromooo-monero)
3c2cad2 Revert "remove cn_deserialize" (moneromooo-monero)
2016-11-01 15:12:30 +02:00
Riccardo Spagni
d53bc2eddf Merge pull request #1281
bb560dd wallet: new import_outputs/export_outputs commands (moneromooo-monero)
2016-11-01 15:12:03 +02:00
Riccardo Spagni
95e0010fbb Merge pull request #1277
7e6d3cf wallet: set incoming outputs' key image to 0 on view wallets (moneromooo-monero)
1f9e6a4 wallet: print tx overview on submit_transfer too (moneromooo-monero)
2016-11-01 15:06:51 +02:00
Riccardo Spagni
77284c026f Merge pull request #1275
4bfb81a simplewallet: remove destinations with zero amount in sign_transfer (moneromooo-monero)
2016-11-01 15:03:08 +02:00
Riccardo Spagni
1e153c2fc6 Merge pull request #1273
f71b067 Changed to ..._HASHBITS everywhere for consistency (NanoAkron)
2016-11-01 15:01:02 +02:00
Riccardo Spagni
703999b21a Merge pull request #1260
092f7c5 utils: add anonimal's GPG key (anonimal)
2016-11-01 14:55:19 +02:00
moneromooo-monero
7edf76f92a CONTRIBUTING: add something about testing and bug reporting 2016-11-01 10:18:51 +00:00
anonimal
6711b982e7 README: add Freenode custom webchat link
Replaces irc:// link which is not always rendered
2016-10-31 21:00:50 +00:00
anonimal
b57d1e1efb README: add build matrix like that in Kovri 2016-10-31 20:55:57 +00:00
anonimal
38dc0bf497 README/Repo: remove Travis CI
We use Buildbot now: https://build.getmonero.org/
2016-10-31 20:41:29 +00:00
Lee Clagett
4869db702a adding static_assert to pod functions in string tools 2016-10-31 13:22:21 -04:00
moneromooo-monero
18f66f44ef wallet: use the dynamic per kB fee 2016-10-31 08:38:06 +00:00
moneromooo-monero
e6deb8abda rpc: add a dynamic fee estimation RPC call 2016-10-31 08:38:00 +00:00
moneromooo-monero
82dbba10d4 core: dynamic fee algorithm from ArticMine
The fee will vary based on the base reward and the current
block size limit:

fee = (R/R0) * (M0/M) * F0

R: base reward
R0: reference base reward (10 monero)
M: block size limit
M0: minimum block size limit (60000)
F0: 0.002 monero

Starts applying at v4
2016-10-31 08:37:08 +00:00
moneromooo-monero
f5ccfa4001 core: fix removal of extra nonce using wrong type 2016-10-30 20:44:45 +00:00
moneromooo-monero
3c2cad2d46 Revert "remove cn_deserialize"
This is useful (to me).

This reverts commit f968ccb9d3.
2016-10-30 20:34:48 +00:00
moneromooo-monero
bb560dd814 wallet: new import_outputs/export_outputs commands
The intended use is to export outputs from a hot wallet, which
can scan incoming transfers from the network, and import them
in the cold wallet, which can't. The cold wallet can then compute
key images for those outputs, which can then be exported with
export_key_images, etc.
2016-10-30 19:37:09 +00:00
Jacob Brydolf
43ec2d002a Wallet API: added walletExists logic 2016-10-30 15:34:50 +01:00
moneromooo-monero
7e6d3cf441 wallet: set incoming outputs' key image to 0 on view wallets
This allows rescan_spent to know the daemon response to those
is not valid.
2016-10-30 12:14:33 +00:00
moneromooo-monero
1f9e6a46d8 wallet: print tx overview on submit_transfer too
This is on the potentially compromised wallet, but still guards
against stupid mistakes.
2016-10-30 10:49:22 +00:00
moneromooo-monero
4bfb81a7f5 simplewallet: remove destinations with zero amount in sign_transfer
This will happen when sending to another address, after removing
the fee.
2016-10-30 09:15:04 +00:00
NanoAkron
f71b06770b Changed to ..._HASHBITS everywhere for consistency 2016-10-29 14:59:06 +01:00
moneromooo-monero
48b57d813c monero.supp: valgrind suppressions file
Seeded with a spurious problem when inspecting stack trace
2016-10-29 13:34:24 +01:00
moneromooo-monero
ffd8c41f36 ringct: check the size of amount_keys is the same as destinations 2016-10-29 13:33:48 +01:00
moneromooo-monero
836669d276 ringct: always shutdown the boost io service
Even if no worker threads were started, it needs shutting down
or it will cause an invalid access in the io service thread
2016-10-29 13:31:53 +01:00
Riccardo Spagni
83b0511731 Merge pull request #1270
fdef09f Wallet API: make sure path exists before searching for wallets (Jacob Brydolf)
2016-10-29 11:35:48 +02:00
Riccardo Spagni
1710a7dbc2 Merge pull request #1269
145d0b7 Add instructions to README.md for building on the Raspberry Pi 2 (NanoAkron)
2016-10-29 11:35:17 +02:00
Riccardo Spagni
726e8e7676 Merge pull request #1268
54c9400 Changed ARM6/7/8 to ARMv6/7/8 to be nice to peronero (NanoAkron)
2016-10-29 11:34:38 +02:00
Riccardo Spagni
2746cceeea Merge pull request #1267
d28db23 Unkonown -> unknown (NanoAkron)
2016-10-29 11:33:19 +02:00
Riccardo Spagni
3e43732455 Merge pull request #1264
a269f03 Report Boost library version during compilation (NanoAkron)
2016-10-29 11:32:26 +02:00
Riccardo Spagni
6b3b23cc30 Merge pull request #1262
56b07f7 tests: add performance test for keypair::generate (moneromooo-monero)
2016-10-29 11:31:16 +02:00
Riccardo Spagni
3365f770dd Merge pull request #1261
069d688 simplewallet: log transactions to submit in submit_transfer (moneromooo-monero)
31abac4 wallet: fix pre-rct cold wallet signing not splitting change (moneromooo-monero)
2016-10-29 11:30:21 +02:00
Riccardo Spagni
6a303b9a3a Merge pull request #1254
eb4ecd4 daemon: fix min/max tracking using the wrong size (moneromooo-monero)
2016-10-29 11:23:08 +02:00
Riccardo Spagni
971f3ae031 Merge pull request #1251
59f0d4b ringct: some more small optimizations (moneromooo-monero)
2016-10-29 11:22:27 +02:00
Riccardo Spagni
b9149d4d00 Merge pull request #1249
c93c1ad Added guzzi key (guzzi_jones)
2016-10-29 11:21:47 +02:00
Jacob Brydolf
fdef09f11c Wallet API: make sure path exists before searching for wallets 2016-10-28 22:29:33 +02:00
NanoAkron
145d0b78ef Add instructions to README.md for building on the Raspberry Pi 2 2016-10-28 16:02:25 +01:00
NanoAkron
54c9400fbe Changed ARM6/7/8 to ARMv6/7/8 to be nice to peronero 2016-10-27 23:22:07 +01:00
NanoAkron
d28db2368e Unkonown -> unknown 2016-10-27 23:07:37 +01:00
NanoAkron
a269f03e5d Report Boost library version during compilation 2016-10-27 21:38:29 +01:00
moneromooo-monero
56b07f7b89 tests: add performance test for keypair::generate 2016-10-26 22:10:05 +01:00
moneromooo-monero
069d688cf7 simplewallet: log transactions to submit in submit_transfer
Not as trustworthy as this is in the view wallet, the one
that's considered compromised.
2016-10-26 13:17:29 +01:00
moneromooo-monero
31abac4daf wallet: fix pre-rct cold wallet signing not splitting change
Re-creating the transaction on the cold wallet was not splitting
the change, causing the transaction to be rejected by the network.
This worked on testnet since amounts do not have to be split.

Also add selected_transfers, which can now be saved since they're
size_t rather than iterators. This allows the view wallet to
properly set the sent outputs as spent and update balance.

Bump transfer file version numbers to match.
2016-10-25 21:44:31 +01:00
anonimal
092f7c528d utils: add anonimal's GPG key 2016-10-25 18:53:30 +00:00
moneromooo-monero
eb4ecd442d daemon: fix min/max tracking using the wrong size
Reported by iDunk
2016-10-23 23:18:34 +01:00
Riccardo Spagni
18e406a0e6 Merge pull request #1253
3094670 daemon: even when switching branches, compile the damn thing ffs (moneromooo-monero)
2016-10-23 21:25:32 +02:00
moneromooo-monero
30946700a3 daemon: even when switching branches, compile the damn thing ffs 2016-10-23 20:21:00 +01:00
Riccardo Spagni
6fa35e3539 Merge pull request #1252
2f4f6c7 daemon: do not divide by 0 when the pool is empty (moneromooo-monero)
2016-10-23 21:08:47 +02:00
moneromooo-monero
2f4f6c7c26 daemon: do not divide by 0 when the pool is empty 2016-10-23 20:05:13 +01:00
Riccardo Spagni
6a2157b610 Merge pull request #1245
ff88252 simplewallet: factor locked_transfer, and fix a few rough edges (moneromooo-monero)
2016-10-23 19:27:09 +02:00
Riccardo Spagni
a0975e59ed Merge pull request #1250
839280d daemon: add a print_pool_stats daemon command (moneromooo-monero)
2016-10-23 19:25:33 +02:00
moneromooo-monero
ff8825210d simplewallet: factor locked_transfer, and fix a few rough edges
Factor locked_transfer into transfer_main, which brings various
improvements for free (multiple addresses, proper detection of
multiple payment ids, obeying the prompt settings).

Also fix a few things, such as using uint64_t instead of int
for block heights, actually checking whether getting blockchain
height succeeded, etc.
2016-10-23 18:21:30 +01:00
Riccardo Spagni
854abeb3bb Merge pull request #1247
10a79ea daemon: report transaction relay status in print_pool* commands (moneromooo-monero)
1e16366 core: notify the txpool when transactions are relayed (moneromooo-monero)
f3c374f tx_pool: set relayed flag on relay (moneromooo-monero)
2016-10-23 19:16:30 +02:00
Riccardo Spagni
4e98d2958c Merge pull request #1246
372f338 wallet: sanity check on selected transfer indices in signed ptx (moneromooo-monero)
2016-10-23 19:09:18 +02:00
Riccardo Spagni
31ceb830e5 Merge pull request #1239
12d8616 perf_timer: format string fix for 32 bits (moneromooo-monero)
2016-10-23 19:05:44 +02:00
Riccardo Spagni
13187379cc Merge pull request #1232
bfc1de7 CONTRIBUTING: somes notes about how to contribute (moneromooo-monero)
2016-10-23 19:04:37 +02:00
Riccardo Spagni
92095104fe Merge pull request #1230
06b642d wallet_api: add address validation functions (moneromooo-monero)
2016-10-23 19:04:01 +02:00
moneromooo-monero
839280d5fc daemon: add a print_pool_stats daemon command
Helps see what's going on now that Monero is getting used
2016-10-23 16:11:20 +01:00
moneromooo-monero
59f0d4b574 ringct: some more small optimizations 2016-10-23 16:10:17 +01:00
moneromooo-monero
10a79eae24 daemon: report transaction relay status in print_pool* commands 2016-10-23 00:32:55 +01:00
moneromooo-monero
1e163666f3 core: notify the txpool when transactions are relayed 2016-10-23 00:32:49 +01:00
guzzi_jones
c93c1ad0e5 Added guzzi key 2016-10-22 23:16:16 +00:00
Riccardo Spagni
4f6ea2eb6a Merge pull request #1229
b6b86ab wallet2_api: recognize full size payment ids as valid (moneromooo-monero)
2016-10-22 22:19:43 +02:00
Riccardo Spagni
b3d4505ae1 Merge pull request #1228
2bf65df wallet_api: do not override invalid payment id (moneromooo-monero)
2016-10-22 22:18:36 +02:00
Riccardo Spagni
09f62ed33e Merge pull request #1225
04da979 Always confirm transfers defaults to ON/YES (NanoAkron)
2016-10-22 22:16:39 +02:00
Riccardo Spagni
f800390ccc Merge pull request #1224
8231997 simplewallet: fix sweep_all misreporting sweeped amount for rct outputs (moneromooo-monero)
985f61a wallet: force 0 mixin transactions to use pre-rct txes (moneromooo-monero)
2016-10-22 22:15:50 +02:00
Riccardo Spagni
7c5431624e Merge pull request #1223
0950be9 wallet: speed up output selection, and fix bug with relatedness calculation (moneromooo-monero)
0eba133 wallet: fix mixup between mixin 2 and 4 before/after v5 (moneromooo-monero)
2016-10-22 22:15:16 +02:00
Riccardo Spagni
b9f31bbc10 Merge pull request #1222
5e10fb0 rpc: add blockchain cumulative difficulty to getinfo call (moneromooo-monero)
2016-10-22 22:14:35 +02:00
Riccardo Spagni
7426b5374f Merge pull request #1221
094f4c8 rpc: add missing top block hash to json getinfo call (moneromooo-monero)
2016-10-22 22:13:24 +02:00
Riccardo Spagni
9feb358e46 Merge pull request #1220
e76dcdd wallet: improve error messages when not enough money for transfer (moneromooo-monero)
2016-10-22 22:12:17 +02:00
Riccardo Spagni
e48ef1684c Merge pull request #1219
2d7083c wallet_api: fix wrong amount in tx history (moneromooo-monero)
b5f2001 simplewallet: fix wrong amount in show_transfers (moneromooo-monero)
2016-10-22 22:11:12 +02:00
Riccardo Spagni
2bb0bdc8b8 Merge pull request #1218
3429bfb ringct: thread verRct and verRctSimple (moneromooo-monero)
e06a4da ringct: remove unneeded type conversions (moneromooo-monero)
afc70df ringct: reserve space in vectors to avoid excessive reallocation (moneromooo-monero)
9ebf7b6 ringct: avoid unnecessary memcpy (moneromooo-monero)
1fe75c1 ringct: add a few consts where possible (moneromooo-monero)
ab002a1 ringct: pass vectors by const ref where possible (moneromooo-monero)
2016-10-22 22:10:01 +02:00
Riccardo Spagni
af2b1ec606 Merge pull request #1216
9c73128 Change default dust threshold to equal fee per kb (AwfulCrawler)
2016-10-22 22:08:31 +02:00
Riccardo Spagni
b53c9e5549 Merge pull request #1200
a3748f4 Rewrote add_wallet_create_if_needed for clearer flow and behaviour (NanoAkron)
2016-10-22 22:07:38 +02:00
moneromooo-monero
f3c374fe08 tx_pool: set relayed flag on relay 2016-10-22 20:46:19 +01:00
moneromooo-monero
372f338682 wallet: sanity check on selected transfer indices in signed ptx 2016-10-22 18:07:26 +01:00
moneromooo-monero
12d861694d perf_timer: format string fix for 32 bits 2016-10-20 18:43:33 +01:00
Riccardo Spagni
0b93dd39db Merge pull request #1237
4fd56a5 unit_tests: fix build after get_output_histogram signature change (moneromooo-monero)
2016-10-20 17:08:20 +02:00
moneromooo-monero
4fd56a52bc unit_tests: fix build after get_output_histogram signature change 2016-10-19 09:34:12 +01:00
Riccardo Spagni
d63fabdc62 Merge pull request #1215
a6bc110 patched parameter type bug that was causing failure on 32 bit (Dion Ahmetaj)
2016-10-18 12:22:22 +02:00
Riccardo Spagni
0a41b03fc7 Merge pull request #1082
88faec7 wallet: select part of the fake outs from recent outputs (moneromooo-monero)
2016-10-18 12:21:11 +02:00
moneromooo-monero
bfc1de7aa2 CONTRIBUTING: somes notes about how to contribute 2016-10-17 23:18:34 +01:00
moneromooo-monero
06b642dfe4 wallet_api: add address validation functions
The payment id from integrated addresses is also parsed
2016-10-16 16:52:45 +01:00
moneromooo-monero
b6b86ab347 wallet2_api: recognize full size payment ids as valid 2016-10-16 13:54:53 +01:00
moneromooo-monero
2bf65dfb8d wallet_api: do not override invalid payment id
Instead, return an empty string to mark the error
2016-10-16 13:17:29 +01:00
NanoAkron
a3748f40ea Rewrote add_wallet_create_if_needed for clearer flow and behaviour 2016-10-15 22:29:28 +01:00
NanoAkron
04da979f46 Always confirm transfers defaults to ON/YES 2016-10-15 20:38:07 +01:00
moneromooo-monero
8231997b66 simplewallet: fix sweep_all misreporting sweeped amount for rct outputs
RingCT outputs will be 0 in the vin, so we need to get the actual
amount from elsewhere.
2016-10-15 19:18:52 +01:00
moneromooo-monero
985f61a4ec wallet: force 0 mixin transactions to use pre-rct txes
rct transactions does not support 0 mixin, and those are
now typically dust sweep transactions, for which a lower
fee is a must.
2016-10-15 18:42:04 +01:00
moneromooo-monero
88faec75fe wallet: select part of the fake outs from recent outputs
25% of the outputs are selected from the last 5 days (if possible),
in order to avoid the common case of sending recently received
outputs again. 25% and 5 days are subject to review later, since
it's just a wallet level change.
2016-10-15 18:17:16 +01:00
moneromooo-monero
0950be9e34 wallet: speed up output selection, and fix bug with relatedness calculation 2016-10-15 16:32:08 +01:00
moneromooo-monero
0eba1335be wallet: fix mixup between mixin 2 and 4 before/after v5 2016-10-15 16:07:18 +01:00
moneromooo-monero
5e10fb042d rpc: add blockchain cumulative difficulty to getinfo call 2016-10-15 15:00:21 +01:00
moneromooo-monero
094f4c8cc6 rpc: add missing top block hash to json getinfo call 2016-10-15 14:35:29 +01:00
moneromooo-monero
e76dcdd810 wallet: improve error messages when not enough money for transfer 2016-10-15 14:31:40 +01:00
moneromooo-monero
2d7083ca56 wallet_api: fix wrong amount in tx history 2016-10-15 13:56:25 +01:00
moneromooo-monero
b5f20012d3 simplewallet: fix wrong amount in show_transfers 2016-10-15 13:56:09 +01:00
moneromooo-monero
3429bfb71d ringct: thread verRct and verRctSimple 2016-10-15 13:32:13 +01:00
moneromooo-monero
e06a4daf33 ringct: remove unneeded type conversions 2016-10-15 11:58:39 +01:00
moneromooo-monero
afc70df7ea ringct: reserve space in vectors to avoid excessive reallocation 2016-10-15 11:58:34 +01:00
moneromooo-monero
9ebf7b6dcf ringct: avoid unnecessary memcpy 2016-10-15 11:58:29 +01:00
moneromooo-monero
1fe75c1ea7 ringct: add a few consts where possible 2016-10-15 11:58:24 +01:00
moneromooo-monero
ab002a1d97 ringct: pass vectors by const ref where possible 2016-10-15 11:58:18 +01:00
Dion Ahmetaj
a6bc1103fd patched parameter type bug that was causing failure on 32 bit 2016-10-14 10:37:10 -04:00
AwfulCrawler
9c73128835 Change default dust threshold to equal fee per kb 2016-10-12 14:04:26 +13:00
Riccardo Spagni
34fcfcd7cc Merge pull request #1203
4038e86 Add performance timers for ringct tx verification (moneromooo-monero)
74dfdb0 perf_timer: new class and macros to make performance logs easier (moneromooo-monero)
2016-10-11 10:31:26 +02:00
Riccardo Spagni
3db0ebafe5 Merge pull request #1204
7db29d6 print_coinbase_tx_sum now breaks output into fee and emission components (Dion Ahmetaj)
dd6c443 changed params from start/end index to height/count (Dion Ahmetaj)
e95d3f3 attempted to remove whitespace spam (Dion Ahmetaj)
412da63 added print_coinbase_tx_sum option (Dion Ahmetaj)
2016-10-11 10:30:53 +02:00
Riccardo Spagni
9ea25cc866 Merge pull request #1205
eeb7ecf Hard fork info in the Readme (Gingeropolous)
2016-10-11 10:30:14 +02:00
Gingeropolous
eeb7ecfd81 Hard fork info in the Readme
With dashes in the dates and the markdown code aligned to make cows happy. :)
2016-10-10 23:22:13 -04:00
Dion Ahmetaj
7db29d6903 print_coinbase_tx_sum now breaks output into fee and emission components 2016-10-10 19:55:18 -04:00
Dion Ahmetaj
dd6c44327b changed params from start/end index to height/count 2016-10-10 17:19:36 -04:00
Dion Ahmetaj
e95d3f359b attempted to remove whitespace spam 2016-10-10 16:41:24 -04:00
moneromooo-monero
4038e86527 Add performance timers for ringct tx verification 2016-10-10 21:24:21 +01:00
moneromooo-monero
74dfdb0b30 perf_timer: new class and macros to make performance logs easier
Call PERF_TIMER(name), which is scoped.
2016-10-10 21:24:15 +01:00
Dion Ahmetaj
412da63622 added print_coinbase_tx_sum option 2016-10-10 15:45:51 -04:00
Riccardo Spagni
304c087dd0 Merge pull request #1201
a8cd656 Wallet API: added setRecoveringFromSeed(); (Jacob Brydolf)
2016-10-10 20:42:21 +02:00
Jacob Brydolf
a8cd65646c Wallet API: added setRecoveringFromSeed(); 2016-10-10 19:37:10 +02:00
Riccardo Spagni
0673db16ad Merge pull request #1195
697ce1d libwallet_api: reverted deleted curly brace (Ilya Kitaev)
bb9094f libwallet_api: fixes for transaction history (Ilya Kitaev)
62b3708 libwallet_api: do not signal on sent/received tx until wallet completely synchronized (Ilya Kitaev)
11fab41 libwallet_api: TransactionHistory: read/write syncchronization (Ilya Kitaev)
559f379 libwallet_api: test: adjusted mixin_count=4 as it's minumum allowed (Ilya Kitaev)
8b0cb8c libwallet_api: some renamings (Ilya Kitaev)
db3282c Initialize transaction history if empty (Ilya Kitaev)
85f5e73 libwallet_api: fixes for transaction history (Ilya Kitaev)
2016-10-09 14:34:59 +02:00
Riccardo Spagni
fe43461c2b Merge pull request #1194
3126ba7 ringct: use const refs as parameters where appropriate (moneromooo-monero)
d8eae67 tests: add performance test for ge_frombytes_vartime (moneromooo-monero)
3cb2436 core: remove some unused code (moneromooo-monero)
1eaa3e8 tests: add performance tests for rct signatures (moneromooo-monero)
2016-10-09 14:34:38 +02:00
Riccardo Spagni
8cd01bc378 Merge pull request #1192
36a89ab libwallet_api: Added option to restore from specific height (Jacob Brydolf)
2016-10-09 14:33:17 +02:00
Riccardo Spagni
0589209eb4 Merge pull request #1191
9f31e2d wallet: do not announce pool txes as money spent/received (yet) (moneromooo-monero)
2016-10-09 14:29:16 +02:00
moneromooo-monero
3126ba7425 ringct: use const refs as parameters where appropriate 2016-10-08 22:16:23 +01:00
moneromooo-monero
d8eae67ef2 tests: add performance test for ge_frombytes_vartime
At luigi1111's request
2016-10-08 19:35:47 +01:00
moneromooo-monero
3cb2436528 core: remove some unused code 2016-10-08 19:35:40 +01:00
moneromooo-monero
1eaa3e8040 tests: add performance tests for rct signatures 2016-10-08 19:35:34 +01:00
Jacob Brydolf
36a89ab435 libwallet_api: Added option to restore from specific height 2016-10-08 00:57:09 +02:00
Riccardo Spagni
9798bde11e Merge pull request #1182
2f51969 Add iDunk's GPG key (iDunk5400)
2016-10-07 21:01:53 +02:00
Riccardo Spagni
b9c8c0db06 Merge pull request #1121
4e6d708 wallet: better implementation of sweep_unmixable (moneromooo-monero)
2016-10-07 21:01:16 +02:00
moneromooo-monero
9f31e2d8c0 wallet: do not announce pool txes as money spent/received (yet) 2016-10-07 19:52:05 +01:00
Riccardo Spagni
ea95b22009 Merge pull request #1120
2a0ad8b simplewallet: add mixin and payment id to sweep_all help (moneromooo-monero)
2016-10-07 20:07:31 +02:00
Ilya Kitaev
697ce1d435 libwallet_api: reverted deleted curly brace 2016-10-07 00:43:45 +03:00
Ilya Kitaev
a4390dae07 resolved conflict with 'develop' of https://github.com/mbg033/monero 2016-10-07 00:36:36 +03:00
Ilya Kitaev
62b3708ea5 libwallet_api: do not signal on sent/received tx until wallet completely
synchronized
2016-10-07 00:29:13 +03:00
Ilya Kitaev
11fab41c36 libwallet_api: TransactionHistory: read/write syncchronization 2016-10-06 23:25:43 +03:00
Ilya Kitaev
559f379327 libwallet_api: test: adjusted mixin_count=4 as it's minumum allowed 2016-10-06 16:35:03 +03:00
Ilya Kitaev
8b0cb8caa4 libwallet_api: some renamings 2016-10-06 15:47:29 +03:00
Ilya Kitaev
db3282cdf0 Initialize transaction history if empty 2016-10-06 15:47:29 +03:00
Ilya Kitaev
85f5e73d9c libwallet_api: fixes for transaction history 2016-10-06 15:47:29 +03:00
Ilya Kitaev
bb9094f1fe libwallet_api: fixes for transaction history 2016-10-04 23:11:19 +03:00
iDunk5400
2f5196937b Add iDunk's GPG key 2016-10-04 21:54:06 +02:00
moneromooo-monero
4e6d70808d wallet: better implementation of sweep_unmixable
This was still using the old transaction creation algorithm,
coupled with a deterministic output selection scheme, which
made it ill suited to the job, since it'd loop indefinitely
in case the fee increased between the test tx and adding the
fee.
2016-10-04 17:44:56 +01:00
moneromooo-monero
2a0ad8b2fe simplewallet: add mixin and payment id to sweep_all help 2016-10-04 17:44:30 +01:00
Riccardo Spagni
80c5de9fa0 Merge pull request #1180
79bb5a6 Fix build after spelling corrections in core_rpc_server (Jacob Brydolf)
2016-10-04 15:01:50 +02:00
Jacob Brydolf
79bb5a670a Fix build after spelling corrections in core_rpc_server 2016-10-04 13:55:55 +02:00
Riccardo Spagni
ae987907c6 Merge pull request #1179
714ee99 Fix description for locked_transfer (Oyvind Kvanes)
71538f3 Rename to lockblocks and add max value (Oyvind Kvanes)
68ac060 Fix locked_transfer (Oyvind Kvanes)
7d020bd Add locked_transfer (Oyvind Kvanes)
d5f918a Revert transfer_main in simplewallet (Oyvind Kvanes)
3451963 Add motifications to test out locked_transfer (Oyvind Kvanes)
e5e6d88 Add more information to transaction in wallet (Oyvind Kvanes)
9b8a062 Make a small test change (Oyvind Kvanes)
2016-10-04 12:18:55 +02:00
Riccardo Spagni
a8e03344e5 Merge pull request #1177
3644aa9 blockchain: avoid using a reference to a temporary (moneromooo-monero)
2016-10-04 12:17:28 +02:00
Riccardo Spagni
bd43d8add2 Merge pull request #1175
b673830 Add NanoAkron's GPG key (NanoAkron)
2016-10-04 12:17:05 +02:00
Riccardo Spagni
07c5907c32 Merge pull request #1174
a4044df add Jaquees GPG key (Jacob Brydolf)
2016-10-04 12:16:38 +02:00
Riccardo Spagni
2723cd12e1 Merge pull request #1173
65ea836 wallet2_api: added Wallet::daemonBlockChainTargetHeight() libwallet_api: Wallet::blockChainTargetHeight (Jacob Brydolf)
2016-10-04 12:15:02 +02:00
Riccardo Spagni
e72b6a7ade Merge pull request #1165
e57379a p2p: drop any existing connection to a banned IP (moneromooo-monero)
2016-10-04 12:14:41 +02:00
Riccardo Spagni
ab60c0503c Merge pull request #1164
179b1f4 daemon: implement missing print_bc and matching RPC (moneromooo-monero)
2016-10-04 12:14:12 +02:00
Riccardo Spagni
bfdac4b5ff Merge pull request #1160
80b4da3 wallet: wallet option to confirm transfers with no payment id (moneromooo-monero)
2016-10-04 12:11:32 +02:00
Riccardo Spagni
4cb1348548 Merge pull request #1139
01ec195 Update CMakeLists.txt (codehalo)
446ebbc Update CMakeLists.txt (codehalo)
bd773e7 Update CMakeLists.txt (codehalo)
3627cea Cleanup. Dropped "bit" from bitmonero. (Randi Joseph)
2a51396 Dropped "bit" from bitmonero. (Randi Joseph)
78b13d6 Cleanup. Dropped "bit" from bitmonero. (Randi Joseph)
1e6aedb Cleanup. Dropped "bit" from bitmonero. (Randi Joseph)
9e54616 Dropped "bit" from bitmonero. (Randi Joseph)
2016-10-04 12:11:03 +02:00
Riccardo Spagni
d60826c0b9 Merge pull request #1133
cec090f Revert "Fix fake 'network synchronized, begin using' messages" (moneromooo-monero)
2016-10-04 12:08:33 +02:00
Riccardo Spagni
60e527f1c2 Merge pull request #1125
7b09e9f wallet: update min mixin for sweep_unmixable on v4 (moneromooo-monero)
2016-10-04 12:06:04 +02:00
Riccardo Spagni
895d20f901 Merge pull request #1123
0d036be blockchain: do not reject chain histories matching only genesis (moneromooo-monero)
2016-10-04 12:05:11 +02:00
Oyvind Kvanes
714ee99678 Fix description for locked_transfer 2016-10-04 11:46:44 +02:00
Riccardo Spagni
e34ef4de6c Merge pull request #1171
6390673 Removed all code related to fast_exit (NanoAkron)
2016-10-04 11:41:41 +02:00
Riccardo Spagni
fa1d5efb5a Merge pull request #1168
10be903 Brackets to prevent premature return (NanoAkron)
fb1785a Brackets to ensure doesn't function prematurely return (NanoAkron)
8ed0d72 Moved logging to target functions rather than caller (NanoAkron)
442bfd1 Added messages at log level 2 to reflect deactivation procedure (NanoAkron)
2016-10-04 11:41:13 +02:00
Riccardo Spagni
1be1e4a47d Merge pull request #1167
2e20ca9 Update README.md (lethos3)
2016-10-04 11:40:34 +02:00
Riccardo Spagni
0f3c865a98 Merge pull request #1163
1eae905 Small typo in README.i18n (Jkat)
2016-10-04 11:40:18 +02:00
Riccardo Spagni
36d80b4475 Merge pull request #1162
e5f8642 Update minimum mixin in transfer_original help text (TedTheFicus)
ea45d61 Update minimum mixin in transfer_original help text (TedTheFicus)
2016-10-04 11:38:35 +02:00
Riccardo Spagni
db90a16f03 Merge pull request #1152
8b20cbf libwallet_api: do not use fast-refresh on recovery (Ilya Kitaev)
10fe626 libwallet_api: fast-refresh in case of opening non-synced wallet (Ilya Kitaev)
0019e31 libwallet_api: fix unhandled exception on address check (Ilya Kitaev)
1f73f80 libwallet_api: fast-refresh for new wallet (Ilya Kitaev)
4789347 libwallet_api: test for create/init wallet on mainnet (Ilya Kitaev)
2016-10-04 11:37:18 +02:00
Riccardo Spagni
298a0723e8 Merge pull request #1149
25be1d3 Noticed two spellings of the word 'response' in the codebase, one 'responce' and the other 'response'. (NanoAkron)
2016-10-04 11:34:53 +02:00
Riccardo Spagni
8a67e3c95e Merge pull request #1145
8438fb4 Improving daemon startup log message (NanoAkron)
2016-10-04 11:29:46 +02:00
Riccardo Spagni
2ef81914b5 Merge pull request #1140
bba6af9 wallet: cold wallet transaction signing (moneromooo-monero)
9872dcb wallet: fix log confusion between bytes and kilobytes (moneromooo-monero)
d9b0bf9 cryptonote_core: make extra field removal more generic (moneromooo-monero)
98f19d4 serialization: add support for serializing std::pair and std::list (moneromooo-monero)
2016-10-04 11:27:38 +02:00
Riccardo Spagni
2f683291f4 Merge pull request #1159
baa3e80 tests: fix build after addition of cryptonote_core::get_block_sync_size (moneromooo-monero)
2016-10-04 11:26:45 +02:00
Oyvind Kvanes
71538f3240 Rename to lockblocks and add max value 2016-10-04 11:13:26 +02:00
NanoAkron
10be9036da Brackets to prevent premature return 2016-10-04 01:13:04 +01:00
NanoAkron
fb1785ab94 Brackets to ensure doesn't function prematurely return 2016-10-04 01:10:12 +01:00
moneromooo-monero
3644aa94f3 blockchain: avoid using a reference to a temporary 2016-10-03 23:20:50 +01:00
NanoAkron
b67383055a Add NanoAkron's GPG key 2016-10-03 22:28:05 +01:00
NanoAkron
8ed0d72b12 Moved logging to target functions rather than caller 2016-10-03 22:11:00 +01:00
Jacob Brydolf
65ea8364f8 wallet2_api: added Wallet::daemonBlockChainTargetHeight()
libwallet_api: Wallet::blockChainTargetHeight

Signed-off-by: Jacob Brydolf <jacob@brydolf.net>
2016-10-03 20:47:41 +02:00
Jacob Brydolf
a4044df923 add Jaquees GPG key
Signed-off-by: Jacob Brydolf <jacob@brydolf.net>
2016-10-03 20:42:21 +02:00
NanoAkron
6390673137 Removed all code related to fast_exit 2016-10-03 02:06:55 +01:00
NanoAkron
442bfd1600 Added messages at log level 2 to reflect deactivation procedure 2016-10-02 23:00:41 +01:00
lethos3
2e20ca9009 Update README.md
mnemonic wallets have 25 words.
2016-10-03 06:41:56 +09:00
moneromooo-monero
e57379a819 p2p: drop any existing connection to a banned IP 2016-10-02 19:23:35 +01:00
moneromooo-monero
179b1f43af daemon: implement missing print_bc and matching RPC 2016-10-02 10:21:21 +01:00
Jkat
1eae90512a Small typo in README.i18n 2016-10-01 23:52:41 -04:00
TedTheFicus
e5f8642f52 Update minimum mixin in transfer_original help text
Changed the wording from "from 0 to maximum available" to "from 2 to maximum available".

May I also suggest putting in a number rather than "maximum available" and also clarifying that mixin = 0 is still allowed if the user has unmixable outputs (dust), which he wants to "undust" using sweep_unmixable (comment from dEBRUYNE-1 ).
2016-10-01 12:59:55 -06:00
TedTheFicus
ea45d61f5d Update minimum mixin in transfer_original help text
Changed the wording from "from 0 to maximum available" to "from 2 to maximum available".

May I also suggest putting in a number rather than "maximum available" and also clarifying that mixin = 0 is still allowed if the user has unmixable outputs (dust), which he wants to "undust" using sweep_unmixable (comment from dEBRUYNE-1 ).
2016-10-01 12:55:54 -06:00
Ilya Kitaev
8b20cbfa7d libwallet_api: do not use fast-refresh on recovery 2016-10-01 21:04:49 +03:00
moneromooo-monero
80b4da3330 wallet: wallet option to confirm transfers with no payment id
set confirm-missing-payment-id 0|1

Defaults to true.
2016-10-01 17:03:53 +01:00
moneromooo-monero
baa3e80140 tests: fix build after addition of cryptonote_core::get_block_sync_size 2016-10-01 10:09:51 +01:00
Ilya Kitaev
10fe626e13 libwallet_api: fast-refresh in case of opening non-synced wallet 2016-09-30 22:42:15 +03:00
Ilya Kitaev
0019e3106b libwallet_api: fix unhandled exception on address check 2016-09-30 21:43:57 +03:00
Ilya Kitaev
1f73f80c94 libwallet_api: fast-refresh for new wallet 2016-09-30 02:11:28 +03:00
Riccardo Spagni
8f94fcf6a3 Merge pull request #1124
8b4e7c6 daemon: report status at 99.9% rather than 100% when not quite synced (moneromooo-monero)
2016-09-29 22:17:51 +02:00
Riccardo Spagni
63321bbbae Merge pull request #1127
1325842 This file is for rlwrap for monero 0.10 (zveda)
8d4674b This file is for rlwrap for monero 0.10 (zveda)
2016-09-29 22:16:52 +02:00
Riccardo Spagni
995dde4f95 Merge pull request #1128
d2e11f3 db_lmdb: do not error if dropping a non existent hard fork table (moneromooo-monero)
2016-09-29 22:16:15 +02:00
Riccardo Spagni
af831bed5c Merge pull request #1129
5e3e362 core: make the sync chunk block count overridable (moneromooo-monero)
2016-09-29 22:15:21 +02:00
Riccardo Spagni
f195a447cc Merge pull request #1136
2dacb19 wallet2: wallet2::get_daemon_blockchain_height() clean error message on success (Ilya Kitaev)
25e5efc libwallet_api: Wallet::setAutoRefreshInterval sanity check (Ilya Kitaev)
a668820 libwallet_api: explicitly return 0 in Wallet::daemonBlockChainHeight() on error (Ilya Kitaev)
aef92f2 libwallet_api: tests: fixed WalletCallbackReceived test (Ilya Kitaev)
15c0882 libwallet_api: tests: test fixed according implementation (Ilya Kitaev)
a7882da libwallet_api: tests: compilation errors fixed (Ilya Kitaev)
cda4cb9 formatting: 2-spaces indentation (Ilya Kitaev)
545a48f formatting: 2-spaces indentation (Ilya Kitaev)
3079c57 wallet2_api: milliseconds resolution for auto-refresh interval (Ilya Kitaev)
7b4a85b wallet2_api: added Wallet::daemonBlockChainHeight() (Ilya Kitaev)
9de3ec3 libwallet_api: Wallet::blockChainHeight, WalletListener::newBlock (Ilya Kitaev)
2016-09-29 22:13:49 +02:00
Riccardo Spagni
0b9888a4ee Merge pull request #1137
5360316 removed deprecated update-core (Adriaan Joubert)
2016-09-29 22:10:18 +02:00
Riccardo Spagni
1b23f1b224 Merge pull request #1141
7d7f684 add luigi1111's gpg key (luigi1111)
2016-09-29 22:06:56 +02:00
NanoAkron
25be1d3ed4 Noticed two spellings of the word 'response' in the codebase, one 'responce' and the other 'response'.
Fixed to the standard spelling 'response'. This may fix some functionality - some calls had mixed spellings.
2016-09-29 14:38:12 +01:00
Oyvind Kvanes
68ac0607da Fix locked_transfer 2016-09-28 16:44:43 +02:00
Oyvind Kvanes
7d020bde5e Add locked_transfer 2016-09-28 16:27:45 +02:00
Oyvind Kvanes
d5f918a0b1 Revert transfer_main in simplewallet 2016-09-28 15:20:37 +02:00
Oyvind Kvanes
3451963855 Add motifications to test out locked_transfer 2016-09-28 14:58:14 +02:00
Oyvind Kvanes
e5e6d88655 Add more information to transaction in wallet 2016-09-28 13:04:26 +02:00
Oyvind Kvanes
9b8a06203b Make a small test change 2016-09-28 11:01:20 +02:00
NanoAkron
8438fb4ae3 Improving daemon startup log message 2016-09-28 01:47:45 +01:00
Ilya Kitaev
4789347b27 libwallet_api: test for create/init wallet on mainnet 2016-09-28 01:36:49 +03:00
Ilya Kitaev
2dacb193d0 wallet2: wallet2::get_daemon_blockchain_height() clean error message on
success
2016-09-28 00:39:06 +03:00
Ilya Kitaev
25e5efc238 libwallet_api: Wallet::setAutoRefreshInterval sanity check 2016-09-28 00:35:10 +03:00
Ilya Kitaev
a6688200fb libwallet_api: explicitly return 0 in Wallet::daemonBlockChainHeight()
on error
2016-09-28 00:31:21 +03:00
Ilya Kitaev
aef92f27d9 libwallet_api: tests: fixed WalletCallbackReceived test 2016-09-28 00:02:35 +03:00
Ilya Kitaev
15c0882f4e libwallet_api: tests: test fixed according implementation 2016-09-27 23:47:50 +03:00
Ilya Kitaev
a7882da2f6 libwallet_api: tests: compilation errors fixed 2016-09-27 23:45:03 +03:00
moneromooo-monero
bba6af9064 wallet: cold wallet transaction signing
This change adds the ability to create a new unsigned transaction
from a watch only wallet, and save it to a file. This file can
then be moved to another computer/VM where a cold wallet may load
it, sign it, and save it. That cold wallet does not need to have
a blockchain nor daemon. The signed transaction file can then be
moved back to the watch only wallet, which can load it and send
it to the daemon.

Two new simplewallet commands to use it:
sign_transfer (on the cold wallet)
submit_transfer (on the watch only wallet)

The transfer command used on a watch only wallet now writes an
unsigned transaction set in a file called 'unsigned_monero_tx'
instead of submitting the tx to the daemon as a normal wallet does.
The signed tx file is called 'signed_monero_tx'.
2016-09-27 07:46:39 +01:00
codehalo
01ec1959c3 Update CMakeLists.txt 2016-09-27 02:11:23 -04:00
codehalo
446ebbcd7b Update CMakeLists.txt 2016-09-27 02:11:04 -04:00
codehalo
bd773e7805 Update CMakeLists.txt 2016-09-27 02:10:30 -04:00
luigi1111
7d7f684c9f add luigi1111's gpg key 2016-09-26 18:37:56 -05:00
moneromooo-monero
9872dcbbe3 wallet: fix log confusion between bytes and kilobytes 2016-09-26 23:12:43 +01:00
moneromooo-monero
d9b0bf9f35 cryptonote_core: make extra field removal more generic 2016-09-26 23:12:38 +01:00
moneromooo-monero
98f19d40aa serialization: add support for serializing std::pair and std::list 2016-09-26 23:12:28 +01:00
Randi Joseph
cfd71e6bde Cleanup. Dropped "bit" from bitmonero. 2016-09-26 17:47:57 -04:00
Randi Joseph
78b13d6dac Cleanup. Dropped "bit" from bitmonero. 2016-09-26 17:35:10 -04:00
Randi Joseph
1e6aedba8b Cleanup. Dropped "bit" from bitmonero. 2016-09-26 17:22:30 -04:00
Randi Joseph
9e54616924 Dropped "bit" from bitmonero. 2016-09-26 17:22:30 -04:00
Adriaan Joubert
53603163bd removed deprecated update-core
Functionality handled by pacman
2016-09-26 23:01:51 +02:00
Randi Joseph
3627cea34a Cleanup. Dropped "bit" from bitmonero. 2016-09-26 16:47:07 -04:00
Ilya Kitaev
cda4cb969a formatting: 2-spaces indentation 2016-09-26 23:46:07 +03:00
Ilya Kitaev
545a48f098 formatting: 2-spaces indentation 2016-09-26 23:29:53 +03:00
Ilya Kitaev
3079c5756b wallet2_api: milliseconds resolution for auto-refresh interval 2016-09-26 23:19:25 +03:00
Ilya Kitaev
7b4a85b309 wallet2_api: added Wallet::daemonBlockChainHeight() 2016-09-26 23:19:25 +03:00
Ilya Kitaev
9de3ec3e2a libwallet_api: Wallet::blockChainHeight, WalletListener::newBlock 2016-09-26 23:19:25 +03:00
Riccardo Spagni
e01a9ea507 Merge pull request #1117
fc855c1 Made error message consistent with other, more helpful, message (Will Skinner)
2016-09-26 17:34:26 +02:00
Riccardo Spagni
cf74a137f3 Merge pull request #1116
2e18e10 libwallet_api: simple documentation on testing environment (Ilya Kitaev)
69c9824 libwallet_api: tests: env variables for WALLETS_ROOT_DIR and TESTNET_DAEMON_ADDRESS (Ilya Kitaev)
1f8a70c libwallet_api: tests: changed testwallets path, uncommitted all tests (Ilya Kitaev)
d5d0856 wallet2_api: getter and setter for "refresh interval" (Ilya Kitaev)
cdb6c96 wallet2_api: fixed deadlock while closing wallet (Ilya Kitaev)
2016-09-26 17:34:06 +02:00
Riccardo Spagni
90f818b646 Merge pull request #1113
12427dd Fix minor typo in "need resize" message. (Myagui)
2016-09-26 17:33:08 +02:00
Riccardo Spagni
2025e8241c Merge pull request #1105
344e96c remove check for certain clang versions (Dan Miller)
b73bed2 Don't define stdc++ on FreeBSD (Dan Miller)
2016-09-26 17:32:14 +02:00
Riccardo Spagni
5a9fa3736b Merge pull request #1104
7f009bb Remove redundant "default" in set mixin help desc (J Ryan Littlefield)
2016-09-26 17:31:52 +02:00
Riccardo Spagni
179d89f111 Merge pull request #1103
b8fb9d1 Fix test for 'ARM_ID' as caught by @radfish in #1088 (NanoAkron)
2016-09-26 17:31:27 +02:00
Randi Joseph
2a5139644a Dropped "bit" from bitmonero. 2016-09-26 10:42:29 -04:00
moneromooo-monero
cec090fc8a Revert "Fix fake 'network synchronized, begin using' messages"
This reverts commit 78035d2b6c.

The patch doesn't work, and causes constant SYNCHRONIZED OK spam.
2016-09-25 19:08:35 +01:00
moneromooo-monero
5e3e362c85 core: make the sync chunk block count overridable 2016-09-24 17:00:19 +01:00
moneromooo-monero
d2e11f374a db_lmdb: do not error if dropping a non existent hard fork table 2016-09-24 16:15:50 +01:00
zveda
13258422ba This file is for rlwrap for monero 0.10 2016-09-25 00:45:01 +10:00
zveda
8d4674bd85 This file is for rlwrap for monero 0.10 2016-09-25 00:41:45 +10:00
moneromooo-monero
7b09e9ff77 wallet: update min mixin for sweep_unmixable on v4 2016-09-24 14:48:34 +01:00
moneromooo-monero
8b4e7c6c9c daemon: report status at 99.9% rather than 100% when not quite synced
Less confusing for users.
2016-09-24 11:45:19 +01:00
moneromooo-monero
0d036bec26 blockchain: do not reject chain histories matching only genesis
This is fine if our local chain is so small that it is entirely
contained within the last jump in the peer's short chain history.
2016-09-24 11:19:00 +01:00
Ilya Kitaev
2e18e10beb libwallet_api: simple documentation on testing environment 2016-09-23 23:35:57 +03:00
Will Skinner
fc855c1a21 Made error message consistent with other, more helpful, message 2016-09-22 21:06:39 -07:00
Ilya Kitaev
69c9824fc0 libwallet_api: tests: env variables for WALLETS_ROOT_DIR and
TESTNET_DAEMON_ADDRESS
2016-09-22 20:32:57 +03:00
Ilya Kitaev
1f8a70c03a libwallet_api: tests: changed testwallets path, uncommitted all tests 2016-09-22 19:07:12 +03:00
Myagui
12427dd8d3 Fix minor typo in "need resize" message.
Message observed while synchronizing a node from scratch.
"LMDB memory map needs resized"
Proposing a change to:
"LMDB memory map needs to be resized"
2016-09-21 20:40:07 +01:00
Dan Miller
344e96cc08 remove check for certain clang versions 2016-09-21 06:42:21 -07:00
Ilya Kitaev
d5d0856ce6 wallet2_api: getter and setter for "refresh interval" 2016-09-20 20:40:58 +03:00
Ilya Kitaev
cdb6c96f89 wallet2_api: fixed deadlock while closing wallet 2016-09-20 20:08:33 +03:00
Dan Miller
b73bed2992 Don't define stdc++ on FreeBSD 2016-09-19 16:19:54 -07:00
J Ryan Littlefield
7f009bb7e2 Remove redundant "default" in set mixin help desc 2016-09-19 16:09:31 -06:00
NanoAkron
b8fb9d1919 Fix test for 'ARM_ID' as caught by @radfish in #1088 2016-09-18 22:56:38 +01:00
149 changed files with 10536 additions and 2843 deletions

1
.gitignore vendored
View File

@@ -103,3 +103,4 @@ local.properties
.texlipse
.idea/
/testnet

View File

@@ -1,120 +0,0 @@
sudo: required
dist: trusty
language: cpp
matrix:
include:
#
# Coveralls.io
#
- os: linux
compiler: gcc
addons:
apt:
packages:
- build-essential
- cmake
- doxygen
- g++
- gcc
- clang
- graphviz
- libdb++-dev
- libdb-dev
- libgtest-dev
- libminiupnpc-dev
- libssl-dev
- libssl1.0.0
- libunbound-dev
- libunwind8-dev
sources:
- ubuntu-toolchain-r-test
before_install:
- sudo add-apt-repository -y ppa:kojoley/boost
- sudo apt-get -q update
- pip install --user cpp-coveralls
install:
- sudo apt-get -y install libboost-{chrono,program-options,date-time,thread,system,filesystem,regex,serialization}1.58{-dev,.0}
env:
# exclude long-running and failing tests (#895)
- ARGS=" -E 'coretests|libwallet_api_tests' "
script:
- make -j2 coverage
after_success:
- travis_wait coveralls -e external -e tests -e cmake -e contrib -e translations -e utils --gcov-options '\-lp' &> /dev/null
#
# Monero release-all (gcc)
#
- os: linux
compiler: gcc
addons:
apt:
packages:
- build-essential
- cmake
- doxygen
- g++
- gcc
- clang
- graphviz
- libdb++-dev
- libdb-dev
- libgtest-dev
- libminiupnpc-dev
- libssl-dev
- libssl1.0.0
- libunbound-dev
- libunwind8-dev
sources:
- ubuntu-toolchain-r-test
before_install:
- sudo add-apt-repository -y ppa:kojoley/boost
- sudo apt-get -q update
install:
- sudo apt-get -y install libboost-{chrono,program-options,date-time,thread,system,filesystem,regex,serialization}1.58{-dev,.0}
script:
- make -j2 && HAVE_DOT=YES doxygen Doxyfile
#
# Monero release-all (clang)
#
- os: linux
compiler: clang
addons:
apt:
packages:
- build-essential
- cmake
- doxygen
- clang
- graphviz
- libdb++-dev
- libdb-dev
- libgtest-dev
- libminiupnpc-dev
- libssl-dev
- libssl1.0.0
- libunbound-dev
- libunwind8-dev
sources:
- ubuntu-toolchain-r-test
before_install:
- sudo add-apt-repository -y ppa:kojoley/boost
- sudo apt-get -q update
install:
- sudo apt-get -y install libboost-{chrono,program-options,date-time,thread,system,filesystem,regex,serialization}1.58{-dev,.0}
script:
- make -j2 && HAVE_DOT=YES doxygen Doxyfile
notifications:
email: false
irc:
on_success: change
on_failure: change
channels:
- "chat.freenode.net#monero-bots"
nick: monero
template:
- "%{result} | %{repository}#%{build_number} (%{commit} : %{author}) | Build details : %{build_url}"

View File

@@ -65,10 +65,10 @@ else()
set(ARCH_ID "${ARCH}")
endif()
string(TOLOWER "${ARCH_ID}" ARM_ID)
string(SUBSTRING "${ARCH_ID}" 0 3 ARM_TEST)
string(SUBSTRING "${ARM_ID}" 0 3 ARM_TEST)
if (ARM_TEST STREQUAL "arm")
set(ARM 1)
string(SUBSTRING "${ARCH_ID}" 0 5 ARM_TEST)
string(SUBSTRING "${ARM_ID}" 0 5 ARM_TEST)
if (ARM_TEST STREQUAL "armv6")
set(ARM6 1)
endif()
@@ -77,7 +77,7 @@ if (ARM_TEST STREQUAL "arm")
endif()
endif()
if (ARCH_ID STREQUAL "aarch64")
if (ARM_ID STREQUAL "aarch64")
set(ARM 1)
set(ARM8 1)
endif()
@@ -182,10 +182,11 @@ option(STATIC "Link libraries statically" ${DEFAULT_STATIC})
# This is a CMake built-in switch that concerns internal libraries
if (NOT DEFINED BUILD_SHARED_LIBS AND NOT STATIC AND CMAKE_BUILD_TYPE_LOWER STREQUAL "debug")
set(BUILD_SHARED_LIBS ON CACHE STRING "Build internal libs as shared")
set(BUILD_SHARED_LIBS ON)
endif()
if (BUILD_SHARED_LIBS)
message(STATUS "Building internal libraries as shared")
message(STATUS "Building internal libraries with position independent code")
set(PIC_FLAG "-fPIC")
else()
message(STATUS "Building internal libraries as static")
@@ -378,9 +379,6 @@ else()
set(COVERAGE_FLAGS "-fprofile-arcs -ftest-coverage --coverage")
endif()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 -D_GNU_SOURCE ${MINGW_FLAG} ${STATIC_ASSERT_FLAG} ${WARNINGS} ${C_WARNINGS} ${ARCH_FLAG} ${COVERAGE_FLAGS} ${PIC_FLAG}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -D_GNU_SOURCE ${MINGW_FLAG} ${WARNINGS} ${CXX_WARNINGS} ${ARCH_FLAG} ${COVERAGE_FLAGS} ${PIC_FLAG}")
# With GCC 6.1.1 the compiled binary malfunctions due to aliasing. Until that
# is fixed in the code (Issue #847), force compiler to be conservative.
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-strict-aliasing")
@@ -408,8 +406,8 @@ else()
message(STATUS "AES support disabled")
endif()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 -D_GNU_SOURCE ${MINGW_FLAG} ${STATIC_ASSERT_FLAG} ${WARNINGS} ${C_WARNINGS} ${ARCH_FLAG} ${COVERAGE_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -D_GNU_SOURCE ${MINGW_FLAG} ${WARNINGS} ${CXX_WARNINGS} ${ARCH_FLAG} ${COVERAGE_FLAGS}")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 -D_GNU_SOURCE ${MINGW_FLAG} ${STATIC_ASSERT_FLAG} ${WARNINGS} ${C_WARNINGS} ${ARCH_FLAG} ${COVERAGE_FLAGS} ${PIC_FLAG}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -D_GNU_SOURCE ${MINGW_FLAG} ${STATIC_ASSERT_FLAG} ${WARNINGS} ${CXX_WARNINGS} ${ARCH_FLAG} ${COVERAGE_FLAGS} ${PIC_FLAG}")
# With GCC 6.1.1 the compiled binary malfunctions due to aliasing. Until that
# is fixed in the code (Issue #847), force compiler to be conservative.
@@ -512,11 +510,6 @@ else()
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
# There is a clang bug that does not allow to compile code that uses AES-NI intrinsics if -flto is enabled, so explicitly disable
set(USE_LTO false)
# explicitly define stdlib for older versions of clang
if(CMAKE_C_COMPILER_VERSION VERSION_LESS 3.7)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libstdc++")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -stdlib=libstdc++")
endif()
endif()
@@ -577,6 +570,8 @@ find_package(Boost 1.58 QUIET REQUIRED COMPONENTS system filesystem thread date_
set(CMAKE_FIND_LIBRARY_SUFFIXES ${OLD_LIB_SUFFIXES})
if(NOT Boost_FOUND)
die("Could not find Boost libraries, please make sure you have installed Boost or libboost-all-dev (1.58) or the equivalent")
elseif(Boost_FOUND)
message(STATUS "Found Boost Version: ${Boost_VERSION}")
endif()
include_directories(SYSTEM ${Boost_INCLUDE_DIRS})

36
CONTRIBUTING Normal file
View File

@@ -0,0 +1,36 @@
A good way to help is to test, and report bugs.
See http://www.chiark.greenend.org.uk/~sgtatham/bugs.html if you
want to help that way. Testing is invaluable in making a piece
of software solid and usable.
Patches are preferably to be sent via a github pull request. If that
can't be done, patches in "git format-patch" format can be sent
(eg, posted to fpaste.org with a long enough timeout and a link
posted to #monero-dev on irc.freenode.net).
Patches should be self contained. A good rule of thumb is to have
one patch per separate issue, feature, or logical change. Also, no
other changes, such as random whitespace changes or reindentation.
Following the code style of the particular chunk of code you're
modifying is encourgaged. Proper squashing should be done (eg, if
you're making a buggy patch, then a later patch to fix the bug,
both patches should be merged).
Commit messages should be sensible. That means a subject line that
describes the patch, with an optional longer body that gives details,
documentation, etc.
Comments are encouraged.
If modifying code for which Doxygen headers exist, that header must
be modified to match.
When submitting a pull request on github, make sure your branch is
rebased. No merge commits nor stray commits from other people in
your submitted branch, please. You may be asked to rebase if there
are conflicts (even trivially resolvable ones).
PGP signing commits is strongly encouraged. That should explain why
the previous paragraph is here.
Tests would be nice to have if you're adding functionality.

View File

@@ -32,7 +32,7 @@ DOXYFILE_ENCODING = UTF-8
# title of most generated pages and in a few other places.
# The default value is: My Project.
PROJECT_NAME = "Bitmonero"
PROJECT_NAME = "Monero"
# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
# could be handy for archiving the generated documentation or if some version

View File

@@ -62,11 +62,11 @@ coverage:
mkdir -p build/debug
cd build/debug && cmake -D BUILD_TESTS=ON -D CMAKE_BUILD_TYPE=Debug -D COVERAGE=ON ../.. && $(MAKE) && $(MAKE) test
release-static-arm6:
release-static-armv6:
mkdir -p build/release
cd build/release && cmake -D BUILD_TESTS=OFF -D ARCH="armv6zk" -D STATIC=ON -D BUILD_64=OFF -D CMAKE_BUILD_TYPE=release ../.. && $(MAKE)
release-static-arm7:
release-static-armv7:
mkdir -p build/release
cd build/release && cmake -D BUILD_TESTS=OFF -D ARCH="armv7-a" -D STATIC=ON -D BUILD_64=OFF -D CMAKE_BUILD_TYPE=release ../.. && $(MAKE)

View File

@@ -19,7 +19,7 @@ To edit translations for Spanish:
linguist translations/monero_es.ts
To build translations after modiying them:
To build translations after modifying them:
./utils/translations/build-translations.sh

129
README.md
View File

@@ -2,16 +2,36 @@
Copyright (c) 2014-2016, The Monero Project
[![Build Status](https://travis-ci.org/monero-project/monero.svg?branch=master)](https://travis-ci.org/monero-project/monero)
[![Coverage Status](https://coveralls.io/repos/github/monero-project/monero/badge.svg?branch=master)](https://coveralls.io/github/monero-project/monero?branch=master)
## Development Resources
- Web: [getmonero.org](https://getmonero.org)
- Forum: [forum.getmonero.org](https://forum.getmonero.org)
- Mail: [dev@getmonero.org](mailto:dev@getmonero.org)
- GitHub: [https://github.com/monero-project/monero](https://github.com/monero-project/monero)
- IRC: [#monero-dev on Freenode](irc://chat.freenode.net/#monero-dev)
- IRC: [#monero-dev on Freenode](http://webchat.freenode.net/?randomnick=1&channels=%23monero-dev&prompt=1&uio=d4)
## Build
| Operating System | Processor | Status |
| --------------------- | -------- |--------|
| Ubuntu 16.04 | i686 | [![Ubuntu 16.04 i686](https://build.getmonero.org/png?builder=monero-static-ubuntu-i686)](https://build.getmonero.org/builders/monero-static-ubuntu-i686)
| Ubuntu 16.04 | amd64 | [![Ubuntu 16.04 amd64](https://build.getmonero.org/png?builder=monero-static-ubuntu-amd64)](https://build.getmonero.org/builders/monero-static-ubuntu-amd64)
| Ubuntu 16.04 | armv7 | [![Ubuntu 16.04 armv7](https://build.getmonero.org/png?builder=monero-static-ubuntu-arm7)](https://build.getmonero.org/builders/monero-static-ubuntu-arm7)
| Debian Stable | armv8 | [![Debian armv8](https://build.getmonero.org/png?builder=monero-static-debian-armv8)](https://build.getmonero.org/builders/monero-static-debian-armv8)
| OSX 10.10 | amd64 | [![OSX 10.10 amd64](https://build.getmonero.org/png?builder=monero-static-osx-10.10)](https://build.getmonero.org/builders/monero-static-osx-10.10)
| OSX 10.11 | amd64 | [![OSX 10.11 amd64](https://build.getmonero.org/png?builder=monero-static-osx-10.11)](https://build.getmonero.org/builders/monero-static-osx-10.11)
| OSX 10.12 | amd64 | [![OSX 10.12 amd64](https://build.getmonero.org/png?builder=monero-static-osx-10.12)](https://build.getmonero.org/builders/monero-static-osx-10.12)
| FreeBSD 10.3 | amd64 | [![FreeBSD 10.3 amd64](https://build.getmonero.org/png?builder=monero-static-freebsd64)](https://build.getmonero.org/builders/monero-static-freebsd64)
| Windows (MSYS2/MinGW) | i686 | [![Windows (MSYS2/MinGW) i686](https://build.getmonero.org/png?builder=monero-static-win32)](https://build.getmonero.org/builders/monero-static-win32)
| Windows (MSYS2/MinGW) | amd64 | [![Windows (MSYS2/MinGW) amd64](https://build.getmonero.org/png?builder=monero-static-win64)](https://build.getmonero.org/builders/monero-static-win64)
## Coverage
| Type | Status |
|-----------|--------|
| Coverity | [![Coverity Status](https://scan.coverity.com/projects/9657/badge.svg)](https://scan.coverity.com/projects/9657/)
| Coveralls | [![Coveralls Status](https://coveralls.io/repos/github/monero-project/monero/badge.svg?branch=master)](https://coveralls.io/github/monero-project/monero?branch=master)
| License | [![License](https://img.shields.io/badge/license-BSD3-blue.svg)](https://opensource.org/licenses/BSD-3-Clause)
## Introduction
@@ -19,7 +39,7 @@ Monero is a private, secure, untraceable, decentralised digital currency. You ar
**Privacy:** Monero uses a cryptographically sound system to allow you to send and receive funds without your transactions being easily revealed on the blockchain (the ledger of transactions that everyone has). This ensures that your purchases, receipts, and all transfers remain absolutely private by default.
**Security:** Using the power of a distributed peer-to-peer consensus network, every transaction on the network is cryptographically secured. Individual wallets have a 24 word mnemonic seed that is only displayed once, and can be written down to backup the wallet. Wallet files are encrypted with a passphrase to ensure they are useless if stolen.
**Security:** Using the power of a distributed peer-to-peer consensus network, every transaction on the network is cryptographically secured. Individual wallets have a 25 word mnemonic seed that is only displayed once, and can be written down to backup the wallet. Wallet files are encrypted with a passphrase to ensure they are useless if stolen.
**Untraceability:** By taking advantage of ring signatures, a special property of a certain type of cryptography, Monero is able to ensure that transactions are not only untraceable, but have an optional measure of ambiguity that ensures that transactions cannot easily be tied back to an individual user or computer.
@@ -57,6 +77,20 @@ There are also several mining pools that kindly donate a portion of their fees,
See [LICENSE](LICENSE).
## Monero software updates and consensus protocol changes (hard forking)
Monero uses a hardforking mechanism to implement new features which requires that
users of Monero software run current versions and update their software on a
regular schedule. Here is the current schedule, versions, and compatability.
Dates are provided in the format YYYYMMDD.
| Date | Consensus version | Minimum Monero Version | Recommended Monero Version | Details |
| ----------------- | ----------------- | ---------------------- | -------------------------- | ------------------ |
| 2016-09-21 | v3 | v0.9.4 | v0.10.0 | Splits coinbase into denominations |
| 2017-01-05 | v4 | v0.10.1 | v0.10.1 | Allow normal and RingCT transactions |
| 2017-09-21 | v5 | v0.10.1 | v0.10.1 | Allow only RingCT transactions |
## Installing Monero from a Package
Packages are available for
@@ -111,7 +145,7 @@ library archives (`.a`).
| Graphviz | any | NO | `graphviz` | `graphviz` | YES | documentation |
[^] On Debian/Ubuntu `libgtest-dev` only includes sources and headers. You must
build the library binary manually.
build the library binary manually. This can be done with the following command ```sudo apt-get install libgtest-dev && cd /usr/src/gtest && sudo cmake . && sudo make && sudo mv libg* /usr/lib/ ```
### Build instructions
@@ -131,7 +165,11 @@ invokes cmake commands as needed.
this to be worthwhile, the machine should have one core and about 2GB of RAM
available per thread.
* The resulting executables can be found in `build/release/bin`.
* The resulting executables can be found in `build/release/bin`
* Add `PATH="$PATH:$HOME/monero/build/release/bin"` to `.profile`
* Run Monero with `monerod --detach`
* **Optional**: build and run the test suite to verify the binaries:
@@ -151,6 +189,50 @@ invokes cmake commands as needed.
HAVE_DOT=YES doxygen Doxyfile
#### On the Raspberry Pi
Tested on a Raspberry Pi 2 with a clean install of minimal Debian Jessie from https://www.raspberrypi.org/downloads/raspbian/
* `apt-get update && apt-get upgrade` to install all of the latest software
* Install the dependencies for Monero except libunwind and libboost-all-dev
* Increase the system swap size:
```
sudo /etc/init.d/dphys-swapfile stop
sudo nano /etc/dphys-swapfile
CONF_SWAPSIZE=1024
sudo /etc/init.d/dphys-swapfile start
```
* Install the latest version of boost (this may first require invoking `apt-get remove --purge libboost*` to remove a previous version if you're not using a clean install):
```
cd
wget https://sourceforge.net/projects/boost/files/boost/1.62.0/boost_1_62_0.tar.bz2
tar xvfo boost_1_62_0.tar.bz2
cd boost_1_62_0
./bootstrap.sh
sudo ./b2
```
* Wait ~8 hours
sudo ./bjam install
* Wait ~4 hours
* Change to the root of the source code directory and build:
cd monero
make release
* Wait ~4 hours
* The resulting executables can be found in `build/release/bin`
* Add `PATH="$PATH:$HOME/monero/build/release/bin"` to `.profile`
* Run Monero with `monerod --detach`
* You may wish to reduce the size of the swap file after the build has finished, and delete the boost directory from your home directory
#### On Windows:
@@ -164,11 +246,7 @@ application.
* Download and install the [MSYS2 installer](http://msys2.github.io), either the 64-bit or the 32-bit package, depending on your system.
* Open the MSYS shell via the `MSYS2 Shell` shortcut
* Update the core packages in your MSYS2 install:
update-core
* Exit the MSYS shell using Alt+F4, then restart MSYS and update packages using pacman:
* Update packages using pacman:
pacman -Syuu
@@ -232,9 +310,9 @@ By default, in either dynamically or statically linked builds, binaries target t
* ```make release-static-64``` builds binaries on Linux on x86_64 portable across POSIX systems on x86_64 processors
* ```make release-static-32``` builds binaries on Linux on x86_64 or i686 portable across POSIX systems on i686 processors
* ```make release-static-arm8``` builds binaries on Linux on armv8 portable across POSIX systems on armv8 processors
* ```make release-static-arm7``` builds binaries on Linux on armv7 portable across POSIX systems on armv7 processors
* ```make release-static-arm6``` builds binaries on Linux on armv7 or armv6 portable across POSIX systems on armv6 processors, such as the Raspberry Pi
* ```make release-static-armv8``` builds binaries on Linux portable across POSIX systems on armv8 processors
* ```make release-static-armv7``` builds binaries on Linux portable across POSIX systems on armv7 processors
* ```make release-static-armv6``` builds binaries on Linux portable across POSIX systems on armv6 processors
* ```make release-static-win64``` builds binaries on 64-bit Windows portable across 64-bit Windows systems
* ```make release-static-win32``` builds binaries on 64-bit or 32-bit Windows portable across 32-bit Windows systems
@@ -296,3 +374,24 @@ While monerod and monero-wallet-cli do not use readline directly, most of the fu
Note: rlwrap will save things like your seed and private keys, if you supply them on prompt. You may want to not use rlwrap when you use simplewallet to restore from seed, etc.
# Contributing
If you want to help out, see CONTRIBUTING for a set of guidelines.
# Debugging
This section contains general instructions for debugging failed installs or problems encountered with Monero. First ensure you are running the latest version built from the github repo.
## LMDB
Instructions for debugging suspected blockchain corruption as per @HYC
There is an `mdb_stat` command in the LMDB source that can print statistics about the database but it's not routinely built. This can be built with the following command:
`cd ~/monero/external/db_drivers/liblmdb && make`
The output of `mdb_stat -ea <path to blockchain dir>` will indicate inconsistencies in the blocks, block_heights and block_info table.
The output of `mdb_dump -s blocks <path to blockchain dir>` and `mdb_dump -s block_info <path to blockchain dir>` is useful for indicating whether blocks and block_info contain the same keys.
These records are dumped as hex data, where the first line is the key and the second line is the data.

View File

@@ -155,6 +155,20 @@ namespace epee
else if (0 < retval)
return true;
}
#else
while (m_run.load(std::memory_order_relaxed))
{
int retval = ::WaitForSingleObject(::GetStdHandle(STD_INPUT_HANDLE), 100);
switch (retval)
{
case WAIT_FAILED:
return false;
case WAIT_OBJECT_0:
return true;
default:
break;
}
}
#endif
return true;

View File

@@ -300,7 +300,6 @@ namespace net_utils
boost::thread::id m_main_thread_id;
critical_section m_threads_lock;
volatile uint32_t m_thread_index; // TODO change to std::atomic
void detach_threads();
t_connection_type m_connection_type;

View File

@@ -727,7 +727,7 @@ PRAGMA_WARNING_DISABLE_VS(4355)
m_address = address;
// Open the acceptor with the option to reuse the address (i.e. SO_REUSEADDR).
boost::asio::ip::tcp::resolver resolver(io_service_);
boost::asio::ip::tcp::resolver::query query(address, boost::lexical_cast<std::string>(port));
boost::asio::ip::tcp::resolver::query query(address, boost::lexical_cast<std::string>(port), boost::asio::ip::tcp::resolver::query::canonical_name);
boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve(query);
acceptor_.open(endpoint.protocol());
acceptor_.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
@@ -827,7 +827,7 @@ POP_WARNINGS
}
CRITICAL_REGION_END();
// Wait for all threads in the pool to exit.
if (wait) // && ! ::cryptonote::core::get_is_stopping()) // TODO fast_exit
if (wait)
{
_fact("JOINING all threads");
for (std::size_t i = 0; i < m_threads.size(); ++i) {
@@ -897,10 +897,6 @@ POP_WARNINGS
template<class t_protocol_handler>
void boosted_tcp_server<t_protocol_handler>::send_stop_signal()
{
if (::cryptonote::core::get_fast_exit() == true)
{
detach_threads();
}
m_stop_signal_sent = true;
TRY_ENTRY();
connections_mutex.lock();
@@ -974,7 +970,7 @@ POP_WARNINGS
//////////////////////////////////////////////////////////////////////////
boost::asio::ip::tcp::resolver resolver(io_service_);
boost::asio::ip::tcp::resolver::query query(boost::asio::ip::tcp::v4(), adr, port);
boost::asio::ip::tcp::resolver::query query(boost::asio::ip::tcp::v4(), adr, port, boost::asio::ip::tcp::resolver::query::canonical_name);
boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query);
boost::asio::ip::tcp::resolver::iterator end;
if(iterator == end)
@@ -1014,7 +1010,7 @@ POP_WARNINGS
boost::unique_lock<boost::mutex> lock(local_shared_context->connect_mut);
auto connect_callback = [](boost::system::error_code ec_, boost::shared_ptr<local_async_context> shared_context)
{
shared_context->connect_mut.lock(); shared_context->ec = ec_; shared_context->connect_mut.unlock(); shared_context->cond.notify_one();
shared_context->connect_mut.lock(); shared_context->ec = ec_; shared_context->cond.notify_one(); shared_context->connect_mut.unlock();
};
sock_.async_connect(remote_endpoint, boost::bind<void>(connect_callback, _1, local_shared_context));
@@ -1078,7 +1074,7 @@ POP_WARNINGS
//////////////////////////////////////////////////////////////////////////
boost::asio::ip::tcp::resolver resolver(io_service_);
boost::asio::ip::tcp::resolver::query query(boost::asio::ip::tcp::v4(), adr, port);
boost::asio::ip::tcp::resolver::query query(boost::asio::ip::tcp::v4(), adr, port, boost::asio::ip::tcp::resolver::query::canonical_name);
boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query);
boost::asio::ip::tcp::resolver::iterator end;
if(iterator == end)
@@ -1144,14 +1140,6 @@ POP_WARNINGS
return true;
CATCH_ENTRY_L0("boosted_tcp_server<t_protocol_handler>::connect_async", false);
}
//---------------------------------------------------------------------------------
template<class t_protocol_handler>
void boosted_tcp_server<t_protocol_handler>::detach_threads()
{
for (auto thread : m_threads)
thread->detach();
}
} // namespace
} // namespace

View File

@@ -156,6 +156,17 @@ using namespace std;
return csTmp;
}
static inline int get_index(const char *s, char c) { const char *ptr = (const char*)memchr(s, c, 16); return ptr ? ptr-s : -1; }
static inline
std::string hex_to_dec_2bytes(const char *s)
{
const char *hex = get_hex_vals();
int i0 = get_index(hex, toupper(s[0]));
int i1 = get_index(hex, toupper(s[1]));
if (i0 < 0 || i1 < 0)
return std::string("%") + std::string(1, s[0]) + std::string(1, s[1]);
return std::string(1, i0 * 16 | i1);
}
static inline std::string convert(char val)
{
@@ -180,6 +191,25 @@ using namespace std;
return result;
}
static inline std::string convert_from_url_format(const std::string& uri)
{
std::string result;
for(size_t i = 0; i!= uri.size(); i++)
{
if(uri[i] == '%' && i + 2 < uri.size())
{
result += hex_to_dec_2bytes(uri.c_str() + i + 1);
i += 2;
}
else
result += uri[i];
}
return result;
}
static inline std::string convert_to_url_format_force_all(const std::string& uri)
{

View File

@@ -373,7 +373,7 @@ public:
invoke_response_handlers_guard.unlock();
if(timer_cancelled)
response_handler->handle(m_current_head.m_command, buff_to_invoke, m_connection_context);
response_handler->handle(m_current_head.m_return_code, buff_to_invoke, m_connection_context);
}
else
{

View File

@@ -173,7 +173,7 @@ namespace net_utils
stop_handling = true;
return false;
default:
LOG_ERROR("Error in munin state machine! Unkonwon state=" << m_machine_state);
LOG_ERROR("Error in munin state machine! Unknown state=" << m_machine_state);
stop_handling = true;
m_machine_state = http_state_error;
return false;

View File

@@ -281,7 +281,7 @@ namespace epee
#define END_INVOKE_MAP2() \
LOG_ERROR("Unkonown command:" << command); \
LOG_ERROR("Unknown command:" << command); \
return LEVIN_ERROR_CONNECTION_HANDLER_NOT_DEFINED; \
}
}

View File

@@ -33,6 +33,7 @@
#include <locale>
#include <cstdlib>
#include <iomanip>
#include <type_traits>
//#include <strsafe.h>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_io.hpp>
@@ -171,6 +172,7 @@ namespace string_tools
template<class t_pod_type>
bool parse_tpod_from_hex_string(const std::string& str_hash, t_pod_type& t_pod)
{
static_assert(std::is_pod<t_pod_type>::value, "expected pod type");
std::string buf;
bool res = epee::string_tools::parse_hexstr_to_binbuff(str_hash, buf);
if (!res || buf.size() != sizeof(t_pod_type))
@@ -570,6 +572,7 @@ POP_WARNINGS
template<class t_pod_type>
std::string pod_to_hex(const t_pod_type& s)
{
static_assert(std::is_pod<t_pod_type>::value, "expected pod type");
std::string buff;
buff.assign(reinterpret_cast<const char*>(&s), sizeof(s));
return buff_to_hex_nodelimer(buff);
@@ -578,6 +581,7 @@ POP_WARNINGS
template<class t_pod_type>
bool hex_to_pod(const std::string& hex_str, t_pod_type& s)
{
static_assert(std::is_pod<t_pod_type>::value, "expected pod type");
std::string hex_str_tr = trim(hex_str);
if(sizeof(s)*2 != hex_str.size())
return false;

View File

@@ -0,0 +1,35 @@
ban
bans
diff
exit
flush_txpool
hard_fork_info
help
hide_hr
is_key_image_spent
limit
limit_down
limit_up
out_peers
output_histogram
print_bc
print_block
print_cn
print_height
print_pl
print_pool
print_pool_sh
print_pool_stats
print_status
print_tx
q
save
set_log
show_hr
start_mining
start_save_graph
status
stop_daemon
stop_mining
stop_save_graph
unban

View File

@@ -0,0 +1,33 @@
address
balance
bc_height
check_tx_key
export_key_images
get_tx_key
get_tx_note
help
import_key_images
incoming_transfers
integrated_address
payments
refresh
rescan_bc
rescan_spent
save
save_bc
save_watch_only
seed
set
set_tx_note
show_transfers
sign
spendkey
start_mining
status
stop_mining
sweep_all
sweep_unmixable
transfer
transfer_original
verify
viewkey

View File

@@ -0,0 +1,19 @@
{
libunwind causes spurious report
Memcheck:Param
msync(start)
...
obj:/usr/lib64/libunwind.so.*
...
fun:_ULx86_64_step
...
}
{
boost unlocks before signalling cond var
Helgrind:Misc
...
fun:pthread_cond_signal@*
fun:maybe_unlock_and_signal_one<boost::asio::detail::scoped_lock<boost::asio::detail::posix_mutex> >
...
}

View File

@@ -517,7 +517,7 @@ int main(int argc, char * * argv) {
fprintf(stderr, "unknown command line switch '%s'\n", argv[i]);
}
} else {
fprintf(stderr, "unkown command line argument '%s'\n", argv[i]);
fprintf(stderr, "unknown command line argument '%s'\n", argv[i]);
}
}

View File

@@ -34,13 +34,13 @@ if (WIN32 OR STATIC)
add_definitions(-DMINIUPNP_STATICLIB)
endif ()
function (bitmonero_private_headers group)
function (monero_private_headers group)
source_group("${group}\\Private"
FILES
${ARGN})
endfunction ()
function (bitmonero_install_headers subdir)
function (monero_install_headers subdir)
install(
FILES ${ARGN}
DESTINATION "include/${subdir}"
@@ -58,7 +58,7 @@ function (enable_stack_trace target)
endif()
endfunction()
function (bitmonero_add_executable name)
function (monero_add_executable name)
source_group("${name}"
FILES
${ARGN})
@@ -77,7 +77,7 @@ function (bitmonero_add_executable name)
enable_stack_trace("${name}")
endfunction ()
function (bitmonero_add_library name)
function (monero_add_library name)
source_group("${name}"
FILES
${ARGN})

View File

@@ -53,9 +53,9 @@ if (BERKELEY_DB)
)
endif()
bitmonero_private_headers(blockchain_db
monero_private_headers(blockchain_db
${crypto_private_headers})
bitmonero_add_library(blockchain_db
monero_add_library(blockchain_db
${blockchain_db_sources}
${blockchain_db_headers}
${blockchain_db_private_headers})

View File

@@ -1309,10 +1309,11 @@ public:
*
* @param amounts optional set of amounts to lookup
* @param unlocked whether to restrict count to unlocked outputs
* @param recent_cutoff timestamp to determine whether an output is recent
*
* @return a set of amount/instances
*/
virtual std::map<uint64_t, uint64_t> get_output_histogram(const std::vector<uint64_t> &amounts, bool unlocked) const = 0;
virtual std::map<uint64_t, std::tuple<uint64_t, uint64_t, uint64_t>> get_output_histogram(const std::vector<uint64_t> &amounts, bool unlocked, uint64_t recent_cutoff) const = 0;
/**
* @brief is BlockchainDB in read-only mode?

View File

@@ -51,12 +51,15 @@ using epee::string_tools::pod_to_hex;
namespace
{
#pragma pack(push, 1)
// This MUST be identical to output_data_t, without the extra rct data at the end
struct pre_rct_output_data_t
{
crypto::public_key pubkey; //!< the output's public key (for spend verification)
uint64_t unlock_time; //!< the output's unlock time (or height)
uint64_t height; //!< the height of the block which created the output
};
#pragma pack(pop)
template <typename T>
inline void throw0(const T &e)
@@ -877,12 +880,11 @@ void BlockchainLMDB::remove_tx_outputs(const uint64_t tx_id, const transaction&
throw0(DB_ERROR("tx has outputs, but no output indices found"));
}
bool is_miner_tx = tx.vin.size() == 1 && tx.vin[0].type() == typeid(txin_gen);
for (uint64_t i = tx.vout.size(); i > 0; --i)
bool is_pseudo_rct = tx.version >= 2 && tx.vin.size() == 1 && tx.vin[0].type() == typeid(txin_gen);
for (size_t i = tx.vout.size(); i-- > 0;)
{
const tx_out tx_output = tx.vout[i-1];
uint64_t amount = is_miner_tx && tx.version >= 2 ? 0 : tx_output.amount;
remove_output(amount, amount_output_indices[i-1]);
uint64_t amount = is_pseudo_rct ? 0 : tx.vout[i].amount;
remove_output(amount, amount_output_indices[i]);
}
}
@@ -903,12 +905,12 @@ void BlockchainLMDB::remove_output(const uint64_t amount, const uint64_t& out_in
else if (result)
throw0(DB_ERROR(lmdb_error("DB error attempting to get an output", result).c_str()));
outkey *ok = (outkey *)v.mv_data;
const pre_rct_outkey *ok = (const pre_rct_outkey *)v.mv_data;
MDB_val_set(otxk, ok->output_id);
result = mdb_cursor_get(m_cur_output_txs, (MDB_val *)&zerokval, &otxk, MDB_GET_BOTH);
if (result == MDB_NOTFOUND)
{
LOG_PRINT_L0("Unexpected: global output index not found in m_output_txs");
throw0(DB_ERROR("Unexpected: global output index not found in m_output_txs"));
}
else if (result)
{
@@ -1081,7 +1083,7 @@ void BlockchainLMDB::open(const std::string& filename, const int mdb_flags)
if (need_resize())
{
LOG_PRINT_L0("LMDB memory map needs resized, doing that now.");
LOG_PRINT_L0("LMDB memory map needs to be resized, doing that now.");
do_resize();
}
@@ -1132,7 +1134,7 @@ void BlockchainLMDB::open(const std::string& filename, const int mdb_flags)
if (!(mdb_flags & MDB_RDONLY))
{
result = mdb_drop(txn, m_hf_starting_heights, 1);
if (result)
if (result && result != MDB_NOTFOUND)
throw0(DB_ERROR(lmdb_error("Failed to drop m_hf_starting_heights: ", result).c_str()));
}
@@ -2041,9 +2043,10 @@ std::vector<uint64_t> BlockchainLMDB::get_tx_amount_output_indices(const uint64_
else if (result)
throw0(DB_ERROR(lmdb_error("DB error attempting to get data for tx_outputs[tx_index]", result).c_str()));
uint64_t* indices = (uint64_t*)v.mv_data;
const uint64_t* indices = (const uint64_t*)v.mv_data;
int num_outputs = v.mv_size / sizeof(uint64_t);
amount_output_indices.reserve(num_outputs);
for (int i = 0; i < num_outputs; ++i)
{
// LOG_PRINT_L0("amount output index[" << 2*i << "]" << ": " << paired_indices[2*i] << " global output index: " << paired_indices[2*i+1]);
@@ -2500,7 +2503,7 @@ uint64_t BlockchainLMDB::add_block(const block& blk, const size_t& block_size, c
// for batch mode, DB resize check is done at start of batch transaction
if (! m_batch_active && need_resize())
{
LOG_PRINT_L0("LMDB memory map needs resized, doing that now.");
LOG_PRINT_L0("LMDB memory map needs to be resized, doing that now.");
do_resize();
}
}
@@ -2597,7 +2600,7 @@ void BlockchainLMDB::get_output_key(const uint64_t &amount, const std::vector<ui
auto get_result = mdb_cursor_get(m_cur_output_amounts, &k, &v, MDB_GET_BOTH);
if (get_result == MDB_NOTFOUND)
throw1(OUTPUT_DNE("Attempting to get output pubkey by global index, but key does not exist"));
throw1(OUTPUT_DNE((std::string("Attempting to get output pubkey by global index (amount ") + boost::lexical_cast<std::string>(amount) + ", index " + boost::lexical_cast<std::string>(index) + ", count " + boost::lexical_cast<std::string>(get_num_outputs(amount)) + "), but key does not exist").c_str()));
else if (get_result)
throw0(DB_ERROR(lmdb_error("Error attempting to retrieve an output pubkey from the db", get_result).c_str()));
@@ -2644,7 +2647,7 @@ void BlockchainLMDB::get_output_tx_and_index(const uint64_t& amount, const std::
else if (get_result)
throw0(DB_ERROR(lmdb_error("Error attempting to retrieve an output from the db", get_result).c_str()));
outkey *okp = (outkey *)v.mv_data;
const outkey *okp = (const outkey *)v.mv_data;
tx_indices.push_back(okp->output_id);
}
@@ -2657,7 +2660,7 @@ void BlockchainLMDB::get_output_tx_and_index(const uint64_t& amount, const std::
LOG_PRINT_L3("db3: " << db3);
}
std::map<uint64_t, uint64_t> BlockchainLMDB::get_output_histogram(const std::vector<uint64_t> &amounts, bool unlocked) const
std::map<uint64_t, std::tuple<uint64_t, uint64_t, uint64_t>> BlockchainLMDB::get_output_histogram(const std::vector<uint64_t> &amounts, bool unlocked, uint64_t recent_cutoff) const
{
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
check_open();
@@ -2665,7 +2668,7 @@ std::map<uint64_t, uint64_t> BlockchainLMDB::get_output_histogram(const std::vec
TXN_PREFIX_RDONLY();
RCURSOR(output_amounts);
std::map<uint64_t, uint64_t> histogram;
std::map<uint64_t, std::tuple<uint64_t, uint64_t, uint64_t>> histogram;
MDB_val k;
MDB_val v;
@@ -2683,7 +2686,7 @@ std::map<uint64_t, uint64_t> BlockchainLMDB::get_output_histogram(const std::vec
mdb_size_t num_elems = 0;
mdb_cursor_count(m_cur_output_amounts, &num_elems);
uint64_t amount = *(const uint64_t*)k.mv_data;
histogram[amount] = num_elems;
histogram[amount] = std::make_tuple(num_elems, 0, 0);
}
}
else
@@ -2694,13 +2697,13 @@ std::map<uint64_t, uint64_t> BlockchainLMDB::get_output_histogram(const std::vec
int ret = mdb_cursor_get(m_cur_output_amounts, &k, &v, MDB_SET);
if (ret == MDB_NOTFOUND)
{
histogram[amount] = 0;
histogram[amount] = std::make_tuple(0, 0, 0);
}
else if (ret == MDB_SUCCESS)
{
mdb_size_t num_elems = 0;
mdb_cursor_count(m_cur_output_amounts, &num_elems);
histogram[amount] = num_elems;
histogram[amount] = std::make_tuple(num_elems, 0, 0);
}
else
{
@@ -2709,11 +2712,11 @@ std::map<uint64_t, uint64_t> BlockchainLMDB::get_output_histogram(const std::vec
}
}
if (unlocked) {
if (unlocked || recent_cutoff > 0) {
const uint64_t blockchain_height = height();
for (auto i: histogram) {
uint64_t amount = i.first;
uint64_t num_elems = i.second;
for (std::map<uint64_t, std::tuple<uint64_t, uint64_t, uint64_t>>::iterator i = histogram.begin(); i != histogram.end(); ++i) {
uint64_t amount = i->first;
uint64_t num_elems = std::get<0>(i->second);
while (num_elems > 0) {
const tx_out_index toi = get_output_tx_and_index(amount, num_elems - 1);
const uint64_t height = get_tx_block_height(toi.first);
@@ -2722,7 +2725,23 @@ std::map<uint64_t, uint64_t> BlockchainLMDB::get_output_histogram(const std::vec
--num_elems;
}
// modifying second does not invalidate the iterator
i.second = num_elems;
std::get<1>(i->second) = num_elems;
if (recent_cutoff > 0)
{
uint64_t recent = 0;
while (num_elems > 0) {
const tx_out_index toi = get_output_tx_and_index(amount, num_elems - 1);
const uint64_t height = get_tx_block_height(toi.first);
const uint64_t ts = get_block_timestamp(height);
if (ts < recent_cutoff)
break;
--num_elems;
++recent;
}
// modifying second does not invalidate the iterator
std::get<2>(i->second) = recent;
}
}
}

View File

@@ -265,10 +265,11 @@ public:
*
* @param amounts optional set of amounts to lookup
* @param unlocked whether to restrict count to unlocked outputs
* @param recent_cutoff timestamp to determine which outputs are recent
*
* @return a set of amount/instances
*/
std::map<uint64_t, uint64_t> get_output_histogram(const std::vector<uint64_t> &amounts, bool unlocked) const;
std::map<uint64_t, std::tuple<uint64_t, uint64_t, uint64_t>> get_output_histogram(const std::vector<uint64_t> &amounts, bool unlocked, uint64_t recent_cutoff) const;
private:
void do_resize(uint64_t size_increase=0);

View File

@@ -39,7 +39,7 @@ set(blockchain_import_private_headers
bootstrap_serialization.h
)
bitmonero_private_headers(blockchain_import
monero_private_headers(blockchain_import
${blockchain_import_private_headers})
set(blockchain_export_sources
@@ -54,11 +54,16 @@ set(blockchain_export_private_headers
bootstrap_serialization.h
)
bitmonero_private_headers(blockchain_export
monero_private_headers(blockchain_export
${blockchain_export_private_headers})
bitmonero_add_executable(blockchain_import
set(cn_deserialize_sources
cn_deserialize.cpp
)
monero_add_executable(blockchain_import
${blockchain_import_sources}
${blockchain_import_private_headers})
@@ -84,7 +89,7 @@ set_property(TARGET blockchain_import
PROPERTY
OUTPUT_NAME "monero-blockchain-import")
bitmonero_add_executable(blockchain_export
monero_add_executable(blockchain_export
${blockchain_export_sources}
${blockchain_export_private_headers})
@@ -104,3 +109,20 @@ add_dependencies(blockchain_export
set_property(TARGET blockchain_export
PROPERTY
OUTPUT_NAME "monero-blockchain-export")
monero_add_executable(cn_deserialize
${cn_deserialize_sources}
${cn_deserialize_private_headers})
target_link_libraries(cn_deserialize
LINK_PRIVATE
cryptonote_core
p2p
${CMAKE_THREAD_LIBS_INIT})
add_dependencies(cn_deserialize
version)
set_property(TARGET cn_deserialize
PROPERTY
OUTPUT_NAME "monero-utils-deserialize")

View File

@@ -0,0 +1,190 @@
// Copyright (c) 2014-2016, 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 "cryptonote_core/cryptonote_basic.h"
#include "cryptonote_core/tx_extra.h"
#include "cryptonote_core/blockchain.h"
#include "blockchain_utilities.h"
#include "common/command_line.h"
#include "version.h"
namespace po = boost::program_options;
using namespace epee; // log_space
using namespace cryptonote;
int main(int argc, char* argv[])
{
uint32_t log_level = 0;
std::string input;
tools::sanitize_locale();
boost::filesystem::path output_file_path;
po::options_description desc_cmd_only("Command line options");
po::options_description desc_cmd_sett("Command line options and settings options");
const command_line::arg_descriptor<std::string> arg_output_file = {"output-file", "Specify output file", "", true};
const command_line::arg_descriptor<uint32_t> arg_log_level = {"log-level", "", log_level};
const command_line::arg_descriptor<std::string> arg_input = {"input", "Specify input has a hexadecimal string", ""};
command_line::add_arg(desc_cmd_sett, arg_output_file);
command_line::add_arg(desc_cmd_sett, arg_log_level);
command_line::add_arg(desc_cmd_sett, arg_input);
command_line::add_arg(desc_cmd_only, command_line::arg_help);
po::options_description desc_options("Allowed options");
desc_options.add(desc_cmd_only).add(desc_cmd_sett);
po::variables_map vm;
bool r = command_line::handle_error_helper(desc_options, [&]()
{
po::store(po::parse_command_line(argc, argv, desc_options), vm);
po::notify(vm);
return true;
});
if (! r)
return 1;
if (command_line::get_arg(vm, command_line::arg_help))
{
std::cout << "Monero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
std::cout << desc_options << std::endl;
return 1;
}
log_level = command_line::get_arg(vm, arg_log_level);
input = command_line::get_arg(vm, arg_input);
if (input.empty())
{
std::cerr << "--input is mandatory" << std::endl;
return 1;
}
log_space::get_set_log_detalisation_level(true, log_level);
log_space::log_singletone::add_logger(LOGGER_CONSOLE, NULL, NULL);
std::string m_config_folder;
std::ostream *output;
std::ofstream *raw_data_file = NULL;
if (command_line::has_arg(vm, arg_output_file))
{
output_file_path = boost::filesystem::path(command_line::get_arg(vm, arg_output_file));
const boost::filesystem::path dir_path = output_file_path.parent_path();
if (!dir_path.empty())
{
if (boost::filesystem::exists(dir_path))
{
if (!boost::filesystem::is_directory(dir_path))
{
std::cerr << "output directory path is a file: " << dir_path << std::endl;
return 1;
}
}
else
{
if (!boost::filesystem::create_directory(dir_path))
{
std::cerr << "Failed to create directory " << dir_path << std::endl;
return 1;
}
}
}
raw_data_file = new std::ofstream();
raw_data_file->open(output_file_path.string(), std::ios_base::out | std::ios::trunc);
if (raw_data_file->fail())
return 1;
output = raw_data_file;
}
else
{
output_file_path = "";
output = &std::cout;
}
cryptonote::blobdata blob;
if (!epee::string_tools::parse_hexstr_to_binbuff(input, blob))
{
std::cerr << "Invalid hex input" << std::endl;
std::cerr << "Invalid hex input: " << input << std::endl;
return 1;
}
cryptonote::block block;
cryptonote::transaction tx;
std::vector<cryptonote::tx_extra_field> fields;
if (cryptonote::parse_and_validate_block_from_blob(blob, block))
{
std::cout << "Parsed block:" << std::endl;
std::cout << cryptonote::obj_to_json_str(block) << std::endl;
}
else if (cryptonote::parse_and_validate_tx_from_blob(blob, tx))
{
std::cout << "Parsed transaction:" << std::endl;
std::cout << cryptonote::obj_to_json_str(tx) << std::endl;
if (cryptonote::parse_tx_extra(tx.extra, fields))
{
std::cout << "tx_extra has " << fields.size() << " field(s)" << std::endl;
for (size_t n = 0; n < fields.size(); ++n)
{
std::cout << "field " << n << ": ";
if (typeid(cryptonote::tx_extra_padding) == fields[n].type()) std::cout << "extra padding: " << boost::get<cryptonote::tx_extra_padding>(fields[n]).size << " bytes";
else if (typeid(cryptonote::tx_extra_pub_key) == fields[n].type()) std::cout << "extra pub key: " << boost::get<cryptonote::tx_extra_pub_key>(fields[n]).pub_key;
else if (typeid(cryptonote::tx_extra_nonce) == fields[n].type()) std::cout << "extra nonce: " << epee::string_tools::buff_to_hex_nodelimer(boost::get<cryptonote::tx_extra_nonce>(fields[n]).nonce);
else if (typeid(cryptonote::tx_extra_merge_mining_tag) == fields[n].type()) std::cout << "extra merge mining tag: depth " << boost::get<cryptonote::tx_extra_merge_mining_tag>(fields[n]).depth << ", merkle root " << boost::get<cryptonote::tx_extra_merge_mining_tag>(fields[n]).merkle_root;
else if (typeid(cryptonote::tx_extra_mysterious_minergate) == fields[n].type()) std::cout << "extra minergate custom: " << epee::string_tools::buff_to_hex_nodelimer(boost::get<cryptonote::tx_extra_mysterious_minergate>(fields[n]).data);
else std::cout << "unknown";
std::cout << std::endl;
}
}
else
{
std::cout << "Failed to parse tx_extra" << std::endl;
}
}
else
{
std::cerr << "Not a recognized CN type" << std::endl;
return 1;
}
if (output->fail())
return 1;
output->flush();
if (raw_data_file)
delete raw_data_file;
return 0;
}

Binary file not shown.

View File

@@ -31,7 +31,10 @@ set(common_sources
command_line.cpp
dns_utils.cpp
util.cpp
i18n.cpp)
i18n.cpp
perf_timer.cpp
task_region.cpp
thread_group.cpp)
if (STACK_TRACE)
list(APPEND common_sources stack_trace.cpp)
@@ -53,11 +56,14 @@ set(common_private_headers
util.h
varint.h
i18n.h
stack_trace.h)
perf_timer.h
stack_trace.h
task_region.h
thread_group.h)
bitmonero_private_headers(common
monero_private_headers(common
${common_private_headers})
bitmonero_add_library(common
monero_add_library(common
${common_sources}
${common_headers}
${common_private_headers})
@@ -73,5 +79,5 @@ target_link_libraries(common
PRIVATE
${EXTRA_LIBRARIES})
#bitmonero_install_headers(common
#monero_install_headers(common
# ${common_headers})

View File

@@ -29,10 +29,22 @@
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
#include "command_line.h"
#include <boost/algorithm/string/compare.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include "common/i18n.h"
#include "cryptonote_config.h"
#include "string_tools.h"
namespace command_line
{
namespace
{
const char* tr(const char* str)
{
return i18n_translate(str, "command_line");
}
}
std::string input_line(const std::string& prompt)
{
std::cout << prompt;
@@ -44,6 +56,20 @@ namespace command_line
}
bool is_yes(const std::string& str)
{
if (str == "y" || str == "Y")
return true;
boost::algorithm::is_iequal ignore_case{};
if (boost::algorithm::equals("yes", str, ignore_case))
return true;
if (boost::algorithm::equals(command_line::tr("yes"), str, ignore_case))
return true;
return false;
}
const arg_descriptor<bool> arg_help = {"help", "Produce help message"};
const arg_descriptor<bool> arg_version = {"version", "Output version information"};
const arg_descriptor<std::string> arg_data_dir = {"data-dir", "Specify data directory"};
@@ -92,4 +118,9 @@ namespace command_line
, "Show time-stats when processing blocks/txs and disk synchronization."
, 0
};
const command_line::arg_descriptor<size_t> arg_block_sync_size = {
"block-sync-size"
, "How many blocks to sync at once during chain synchronization."
, BLOCKS_SYNCHRONIZING_DEFAULT_COUNT
};
}

View File

@@ -43,6 +43,9 @@ namespace command_line
std::string input_line(const std::string& prompt);
//! \return True if `str` is `is_iequal("y" || "yes" || `tr("yes"))`.
bool is_yes(const std::string& str);
template<typename T, bool required = false>
struct arg_descriptor;
@@ -216,4 +219,5 @@ namespace command_line
extern const arg_descriptor<uint64_t> arg_prep_blocks_threads;
extern const arg_descriptor<uint64_t> arg_db_auto_remove_logs;
extern const arg_descriptor<uint64_t> arg_show_time_stats;
extern const arg_descriptor<size_t> arg_block_sync_size;
}

47
src/common/perf_timer.cpp Normal file
View File

@@ -0,0 +1,47 @@
// Copyright (c) 2016, 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 "perf_timer.h"
namespace tools
{
int performance_timer_log_level = 2;
__thread std::vector<PerformanceTimer*> *performance_timers = NULL;
void set_performance_timer_log_level(int level)
{
if (level < LOG_LEVEL_MIN || level > LOG_LEVEL_MAX)
{
LOG_PRINT_L0("Wrong log level: " << level << ", using 2");
level = 2;
}
performance_timer_log_level = level;
}
}

92
src/common/perf_timer.h Normal file
View File

@@ -0,0 +1,92 @@
// Copyright (c) 2016, 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.
#pragma once
#include <string>
#include <stdio.h>
#include "misc_log_ex.h"
namespace tools
{
class PerformanceTimer;
extern int performance_timer_log_level;
extern __thread std::vector<PerformanceTimer*> *performance_timers;
class PerformanceTimer
{
public:
PerformanceTimer(const std::string &s, int l = LOG_LEVEL_2): name(s), level(l), started(false)
{
ticks = epee::misc_utils::get_tick_count();
if (!performance_timers)
{
LOG_PRINT("PERF ----------", level);
performance_timers = new std::vector<PerformanceTimer*>();
}
else
{
PerformanceTimer *pt = performance_timers->back();
if (!pt->started)
{
LOG_PRINT("PERF " << std::string((performance_timers->size()-1) * 2, ' ') << " " << pt->name, pt->level);
pt->started = true;
}
}
performance_timers->push_back(this);
}
~PerformanceTimer()
{
performance_timers->pop_back();
ticks = epee::misc_utils::get_tick_count() - ticks;
char s[12];
snprintf(s, sizeof(s), "%8llu ", (unsigned long long)ticks);
LOG_PRINT("PERF " << s << std::string(performance_timers->size() * 2, ' ') << " " << name, level);
if (performance_timers->empty())
{
delete performance_timers;
performance_timers = NULL;
}
}
private:
std::string name;
int level;
uint64_t ticks;
bool started;
};
void set_performance_timer_log_level(int level);
#define PERF_TIMER(name) tools::PerformanceTimer pt_##name(#name, tools::performance_timer_log_level)
#define PERF_TIMER_L(name, l) tools::PerformanceTimer pt_##name(#name, l)
}

View File

@@ -104,7 +104,7 @@ void log_stack_trace(const char *msg)
if (msg)
LOG_PRINT2(log, msg, LOG_LEVEL_0);
LOG_PRINT2(log, "Unwinded call stack:", LOG_LEVEL_0);
LOG_PRINT2(log, "Unwound call stack:", LOG_LEVEL_0);
if (unw_getcontext(&ctx) < 0) {
LOG_PRINT2(log, "Failed to create unwind context", LOG_LEVEL_0);
return;

View File

@@ -0,0 +1,94 @@
// Copyright (c) 2014-2016, 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 "common/task_region.h"
#include <boost/thread/locks.hpp>
#include <cassert>
/* `mark_completed` and `wait` can throw in the lock call, but its difficult to
recover from either. An exception in `wait` means the post condition of joining
all threads cannot be achieved, and an exception in `mark_completed` means
certain deadlock. `noexcept` qualifier will force a call to `std::terminate` if
locking throws an exception, which should only happen if a recursive lock
attempt is made (which is not possible since no external function is called
while holding the lock). */
namespace tools
{
void task_region_handle::state::mark_completed(id task_id) noexcept {
assert(task_id != 0 && (task_id & (task_id - 1)) == 0); // power of 2 check
if (pending.fetch_and(~task_id) == task_id) {
// synchronize with wait call, but do not need to hold
boost::unique_lock<boost::mutex>{sync_on_complete};
all_complete.notify_all();
}
}
void task_region_handle::state::abort() noexcept {
state* current = this;
while (current) {
current->ready = 0;
current = current->next.get();
}
}
void task_region_handle::state::wait() noexcept {
state* current = this;
while (current) {
{
boost::unique_lock<boost::mutex> lock{current->sync_on_complete};
current->all_complete.wait(lock, [current] { return current->pending == 0; });
}
current = current->next.get();
}
}
void task_region_handle::state::wait(thread_group& threads) noexcept {
state* current = this;
while (current) {
while (current->pending != 0) {
if (!threads.try_run_one()) {
current->wait();
return;
}
}
current = current->next.get();
}
}
void task_region_handle::create_state() {
st = std::make_shared<state>(std::move(st));
next_id = 1;
}
void task_region_handle::do_wait() noexcept {
assert(st);
const std::shared_ptr<state> temp = std::move(st);
temp->wait(threads);
}
}

223
src/common/task_region.h Normal file
View File

@@ -0,0 +1,223 @@
// Copyright (c) 2014-2016, 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.
#pragma once
#include <atomic>
#include <boost/thread/condition_variable.hpp>
#include <boost/thread/mutex.hpp>
#include <memory>
#include <type_traits>
#include <utility>
#include "common/thread_group.h"
namespace tools
{
/*! A model of the fork-join concept. `run(...)` "forks" (i.e. spawns new
tasks), and `~task_region_handle()` or `wait()` "joins" the spawned tasks.
`wait` will block until all tasks have completed, while `~task_region_handle()`
blocks until all tasks have completed or aborted.
Do _NOT_ give this object to separate thread of execution (which includes
`task_region_handle::run(...)`) because joining on a different thread is
undesireable (potential deadlock).
This class cannot be constructed directly, use the function
`task_region(...)` instead.
*/
class task_region_handle
{
struct state
{
using id = unsigned;
explicit state(std::shared_ptr<state> next_src) noexcept
: next(std::move(next_src))
, ready(0)
, pending(0)
, sync_on_complete()
, all_complete() {
}
state(const state&) = default;
state(state&&) = default;
~state() = default;
state& operator=(const state&) = default;
state& operator=(state&&) = default;
void track_id(id task_id) noexcept {
pending |= task_id;
ready |= task_id;
}
//! \return True only once whether a given id can execute
bool can_run(id task_id) noexcept {
return (ready.fetch_and(~task_id) & task_id);
}
//! Mark id as completed, and synchronize with waiting threads
void mark_completed(id task_id) noexcept;
//! Tell all unstarted functions in region to return immediately
void abort() noexcept;
//! Blocks until all functions in region have aborted or completed.
void wait() noexcept;
//! Same as `wait()`, except `this_thread` runs tasks while waiting.
void wait(thread_group& threads) noexcept;
private:
/* This implementation is a bit pessimistic, it ensures that all copies
of a wrapped task can only be executed once. `thread_group` should never
do this, but some variable needs to track whether an abort should be done
anyway... */
std::shared_ptr<state> next;
std::atomic<id> ready; //!< Tracks whether a task has been invoked
std::atomic<id> pending; //!< Tracks when a task has completed or aborted
boost::mutex sync_on_complete;
boost::condition_variable all_complete;
};
template<typename F>
struct wrapper
{
wrapper(state::id id_src, std::shared_ptr<state> st_src, F f_src)
: task_id(id_src), st(std::move(st_src)), f(std::move(f_src)) {
}
wrapper(const wrapper&) = default;
wrapper(wrapper&&) = default;
wrapper& operator=(const wrapper&) = default;
wrapper& operator=(wrapper&&) = default;
void operator()() {
if (st) {
if (st->can_run(task_id)) {
f();
}
st->mark_completed(task_id);
}
}
private:
const state::id task_id;
std::shared_ptr<state> st;
F f;
};
public:
friend struct task_region_;
task_region_handle() = delete;
task_region_handle(const task_region_handle&) = delete;
task_region_handle(task_region_handle&&) = delete;
//! Cancels unstarted pending tasks, and waits for them to respond.
~task_region_handle() noexcept {
if (st) {
st->abort();
st->wait(threads);
}
}
task_region_handle& operator=(const task_region_handle&) = delete;
task_region_handle& operator=(task_region_handle&&) = delete;
/*! If the group has no threads, `f` is immediately run before returning.
Otherwise, `f` is dispatched to the thread_group associated with `this`
region. If `f` is dispatched to another thread, and it throws, the process
will immediately terminate. See std::packaged_task for getting exceptions on
functions executed on other threads. */
template<typename F>
void run(F&& f) {
if (threads.count() == 0) {
f();
} else {
if (!st || next_id == 0) {
create_state();
}
const state::id this_id = next_id;
next_id <<= 1;
st->track_id(this_id);
threads.dispatch(wrapper<F>{this_id, st, std::move(f)});
}
}
//! Wait until all functions provided to `run` have completed.
void wait() noexcept {
if (st) {
do_wait();
}
}
private:
explicit task_region_handle(thread_group& threads_src)
: st(nullptr), threads(threads_src), next_id(0) {
}
void create_state();
void do_wait() noexcept;
std::shared_ptr<state> st;
thread_group& threads;
state::id next_id;
};
/*! Function for creating a `task_region_handle`, which automatically calls
`task_region_handle::wait()` before returning. If a `thread_group` is not
provided, one is created with an optimal number of threads. The callback `f`
must have the signature `void(task_region_handle&)`. */
struct task_region_ {
template<typename F>
void operator()(thread_group& threads, F&& f) const {
static_assert(
std::is_same<void, typename std::result_of<F(task_region_handle&)>::type>::value,
"f cannot have a return value"
);
task_region_handle region{threads};
f(region);
region.wait();
}
template<typename F>
void operator()(thread_group&& threads, F&& f) const {
(*this)(threads, std::forward<F>(f));
}
template<typename F>
void operator()(F&& f) const {
thread_group threads;
(*this)(threads, std::forward<F>(f));
}
};
constexpr const task_region_ task_region{};
}

150
src/common/thread_group.cpp Normal file
View File

@@ -0,0 +1,150 @@
// Copyright (c) 2014-2016, 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 "common/thread_group.h"
#include <boost/thread/locks.hpp>
#include <cassert>
#include <limits>
#include <stdexcept>
#include "common/util.h"
namespace tools
{
std::size_t thread_group::optimal() {
static_assert(
std::numeric_limits<unsigned>::max() <= std::numeric_limits<std::size_t>::max(),
"unexpected truncation"
);
const std::size_t hardware = get_max_concurrency();
return hardware ? (hardware - 1) : 0;
}
std::size_t thread_group::optimal_with_max(std::size_t count) {
return count ? std::min(count - 1, optimal()) : 0;
}
thread_group::thread_group(std::size_t count) : internal() {
if (count) {
internal.emplace(count);
}
}
thread_group::data::data(std::size_t count)
: threads()
, head{nullptr}
, last(std::addressof(head))
, mutex()
, has_work()
, stop(false) {
threads.reserve(count);
while (count--) {
threads.push_back(boost::thread(&thread_group::data::run, this));
}
}
thread_group::data::~data() noexcept {
{
const boost::unique_lock<boost::mutex> lock(mutex);
stop = true;
}
has_work.notify_all();
for (auto& worker : threads) {
try {
worker.join();
}
catch(...) {}
}
}
std::unique_ptr<thread_group::data::work> thread_group::data::get_next() noexcept {
std::unique_ptr<work> rc = std::move(head.ptr);
if (rc != nullptr) {
head.ptr = std::move(rc->next.ptr);
if (head.ptr == nullptr) {
last = std::addressof(head);
}
}
return rc;
}
bool thread_group::data::try_run_one() noexcept {
/* This function and `run()` can both throw when acquiring the lock, or in
dispatched function. It is tough to recover from either, particularly the
lock case. These functions are marked as noexcept so that if either call
throws, the entire process is terminated. Users of the `dispatch` call are
expected to make their functions noexcept, or use std::packaged_task to copy
exceptions so that the process will continue in all but the most pessimistic
cases (std::bad_alloc). This was the existing behavior;
`asio::io_service::run` propogates errors from dispatched calls, and uncaught
exceptions on threads result in process termination. */
std::unique_ptr<work> next = nullptr;
{
const boost::unique_lock<boost::mutex> lock(mutex);
next = get_next();
}
if (next) {
assert(next->f);
next->f();
return true;
}
return false;
}
void thread_group::data::run() noexcept {
// see `try_run_one()` source for additional information
while (true) {
std::unique_ptr<work> next = nullptr;
{
boost::unique_lock<boost::mutex> lock(mutex);
has_work.wait(lock, [this] { return head.ptr != nullptr || stop; });
if (stop) {
return;
}
next = get_next();
}
assert(next != nullptr);
assert(next->f);
next->f();
}
}
void thread_group::data::dispatch(std::function<void()> f) {
std::unique_ptr<work> latest(new work{std::move(f), node{nullptr}});
node* const latest_node = std::addressof(latest->next);
{
const boost::unique_lock<boost::mutex> lock(mutex);
assert(last != nullptr);
assert(last->ptr == nullptr);
last->ptr = std::move(latest);
last = latest_node;
}
has_work.notify_one();
}
}

143
src/common/thread_group.h Normal file
View File

@@ -0,0 +1,143 @@
// Copyright (c) 2014-2016, 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.
#pragma once
#include <boost/optional/optional.hpp>
#include <boost/thread/condition_variable.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/thread.hpp>
#include <cstddef>
#include <functional>
#include <thread>
#include <utility>
#include <vector>
namespace tools
{
//! Manages zero or more threads for work dispatching.
class thread_group
{
public:
//! \return `get_max_concurrency() ? get_max_concurrency() - 1 : 0`
static std::size_t optimal();
//! \return `count ? min(count - 1, optimal()) : 0`
static std::size_t optimal_with_max(std::size_t count);
//! Create an optimal number of threads.
explicit thread_group() : thread_group(optimal()) {}
//! Create exactly `count` threads.
explicit thread_group(std::size_t count);
thread_group(thread_group const&) = delete;
thread_group(thread_group&&) = delete;
//! Joins threads, but does not necessarily run all dispatched functions.
~thread_group() = default;
thread_group& operator=(thread_group const&) = delete;
thread_group& operator=(thread_group&&) = delete;
//! \return Number of threads owned by `this` group.
std::size_t count() const noexcept {
if (internal) {
return internal->count();
}
return 0;
}
//! \return True iff a function was available and executed (on `this_thread`).
bool try_run_one() noexcept {
if (internal) {
return internal->try_run_one();
}
return false;
}
/*! `f` is invoked immediately if `count() == 0`, otherwise execution of `f`
is queued for next available thread. If `f` is queued, any exception leaving
that function will result in process termination. Use std::packaged_task if
exceptions need to be handled. */
template<typename F>
void dispatch(F&& f) {
if (internal) {
internal->dispatch(std::forward<F>(f));
}
else {
f();
}
}
private:
class data {
public:
data(std::size_t count);
~data() noexcept;
std::size_t count() const noexcept {
return threads.size();
}
bool try_run_one() noexcept;
void dispatch(std::function<void()> f);
private:
struct work;
struct node {
std::unique_ptr<work> ptr;
};
struct work {
std::function<void()> f;
node next;
};
//! Requires lock on `mutex`.
std::unique_ptr<work> get_next() noexcept;
//! Blocks until destructor is invoked, only call from thread.
void run() noexcept;
private:
std::vector<boost::thread> threads;
node head;
node* last;
boost::condition_variable has_work;
boost::mutex mutex;
bool stop;
};
private:
// optionally construct elements, without separate heap allocation
boost::optional<data> internal;
};
}

View File

@@ -68,9 +68,9 @@ set(crypto_private_headers
skein.h
skein_port.h)
bitmonero_private_headers(crypto
monero_private_headers(crypto
${crypto_private_headers})
bitmonero_add_library(crypto
monero_add_library(crypto
${crypto_sources}
${crypto_headers}
${crypto_private_headers})

View File

@@ -236,6 +236,6 @@ namespace crypto {
}
}
CRYPTO_MAKE_COMPARABLE(public_key)
CRYPTO_MAKE_HASHABLE(public_key)
CRYPTO_MAKE_HASHABLE(key_image)
CRYPTO_MAKE_COMPARABLE(signature)

View File

@@ -639,7 +639,10 @@ static OAES_RET oaes_key_gen( OAES_CTX * ctx, size_t key_size )
_key->data = (uint8_t *) calloc( key_size, sizeof( uint8_t ));
if( NULL == _key->data )
{
free( _key );
return OAES_RET_MEM;
}
for( _i = 0; _i < key_size; _i++ )
#ifdef OAES_HAVE_ISAAC

View File

@@ -77,7 +77,7 @@ typedef struct /* 1024-bit Skein hash context stru
} Skein1024_Ctxt_t;
/* Skein APIs for (incremental) "straight hashing" */
#if SKEIN_256_NIST_MAX_HASH_BITS
#if SKEIN_256_NIST_MAX_HASHBITS
static int Skein_256_Init (Skein_256_Ctxt_t *ctx, size_t hashBitLen);
#endif
static int Skein_512_Init (Skein_512_Ctxt_t *ctx, size_t hashBitLen);
@@ -1941,7 +1941,7 @@ static HashReturn Final (hashState *state, BitSequence *hashval);
/* select the context size and init the context */
static HashReturn Init(hashState *state, int hashbitlen)
{
#if SKEIN_256_NIST_MAX_HASH_BITS
#if SKEIN_256_NIST_MAX_HASHBITS
if (hashbitlen <= SKEIN_256_NIST_MAX_HASHBITS)
{
Skein_Assert(hashbitlen > 0,BAD_HASHLEN);

View File

@@ -64,6 +64,8 @@
#define FEE_PER_KB_OLD ((uint64_t)10000000000) // pow(10, 10)
#define FEE_PER_KB ((uint64_t)2000000000) // 2 * pow(10, 9)
#define DYNAMIC_FEE_PER_KB_BASE_FEE ((uint64_t)2000000000) // 2 * pow(10,9)
#define DYNAMIC_FEE_PER_KB_BASE_BLOCK_REWARD ((uint64_t)10000000000000) // 10 * pow(10,12)
#define ORPHANED_BLOCKS_MAX_COUNT 100
@@ -111,6 +113,9 @@
#define P2P_IP_FAILS_BEFORE_BLOCK 10
#define P2P_IDLE_CONNECTION_KILL_INTERVAL (5*60) //5 minutes
#define P2P_SUPPORT_FLAG_FLUFFY_BLOCKS 0x01
#define P2P_SUPPORT_FLAGS P2P_SUPPORT_FLAG_FLUFFY_BLOCKS
#define ALLOW_DEBUG_COMMANDS
#define CRYPTONOTE_NAME "bitmonero"
@@ -122,12 +127,14 @@
#define THREAD_STACK_SIZE 5 * 1024 * 1024
#define HF_VERSION_DYNAMIC_FEE 4
// New constants are intended to go here
namespace config
{
uint64_t const DEFAULT_FEE_ATOMIC_XMR_PER_KB = 500; // Just a placeholder! Change me!
uint8_t const FEE_CALCULATION_MAX_RETRIES = 10;
uint64_t const DEFAULT_DUST_THRESHOLD = ((uint64_t)10000000000); // pow(10, 10)
uint64_t const DEFAULT_DUST_THRESHOLD = ((uint64_t)2000000000); // 2 * pow(10, 9)
uint64_t const BASE_REWARD_CLAMP_THRESHOLD = ((uint64_t)100000000); // pow(10, 8)
std::string const P2P_REMOTE_DEBUG_TRUSTED_PUB_KEY = "0000000000000000000000000000000000000000000000000000000000000000";

View File

@@ -66,9 +66,9 @@ else()
set(Blocks "")
endif()
bitmonero_private_headers(cryptonote_core
monero_private_headers(cryptonote_core
${crypto_private_headers})
bitmonero_add_library(cryptonote_core
monero_add_library(cryptonote_core
${cryptonote_core_sources}
${cryptonote_core_headers}
${cryptonote_core_private_headers})

View File

@@ -46,12 +46,14 @@
#include "misc_language.h"
#include "profile_tools.h"
#include "file_io_utils.h"
#include "common/int-util.h"
#include "common/boost_serialization_helper.h"
#include "warnings.h"
#include "crypto/hash.h"
#include "cryptonote_core/checkpoints.h"
#include "cryptonote_core/cryptonote_core.h"
#include "ringct/rctSigs.h"
#include "common/perf_timer.h"
#if defined(PER_BLOCK_CHECKPOINT)
#include "blocks/blocks.h"
#endif
@@ -71,6 +73,9 @@ extern "C" void slow_hash_free_state();
DISABLE_VS_WARNINGS(4267)
// used to overestimate the block reward when estimating a per kB to use
#define BLOCK_REWARD_OVERESTIMATE (10 * 1000000000000)
static const struct {
uint8_t version;
uint64_t height;
@@ -86,8 +91,8 @@ static const struct {
// version 3 starts from block 1141317, which is on or around the 24th of September, 2016. Fork time finalised on 2016-03-21.
{ 3, 1141317, 0, 1458558528 },
// version 4 starts from block 1220517, which is on or around the 5th of January, 2017. Fork time finalised on 2016-09-18.
{ 4, 1220517, 0, 1483574400 },
// version 4 starts from block 1220516, which is on or around the 5th of January, 2017. Fork time finalised on 2016-09-18.
{ 4, 1220516, 0, 1483574400 },
// version 5 starts from block 1406997, which is on or around the 20th of September, 2017. Fork time finalised on 2016-09-18.
{ 5, 1406997, 0, 1505865600 },
@@ -108,7 +113,7 @@ static const struct {
// versions 3-5 were passed in rapid succession from September 18th, 2016
{ 3, 800500, 0, 1472415034 },
{ 4, 801220, 0, 1472415035 },
{ 4, 801219, 0, 1472415035 },
{ 5, 802660, 0, 1472415036 },
};
static const uint64_t testnet_hard_fork_version_1_till = 624633;
@@ -116,7 +121,7 @@ static const uint64_t testnet_hard_fork_version_1_till = 624633;
//------------------------------------------------------------------
Blockchain::Blockchain(tx_memory_pool& tx_pool) :
m_db(), m_tx_pool(tx_pool), m_hardfork(NULL), m_timestamps_and_difficulties_height(0), m_current_block_cumul_sz_limit(0), m_is_in_checkpoint_zone(false),
m_is_blockchain_storing(false), m_enforce_dns_checkpoints(false), m_max_prepare_blocks_threads(4), m_db_blocks_per_sync(1), m_db_sync_mode(db_async), m_fast_sync(true), m_show_time_stats(false), m_sync_counter(0)
m_is_blockchain_storing(false), m_enforce_dns_checkpoints(false), m_max_prepare_blocks_threads(4), m_db_blocks_per_sync(1), m_db_sync_mode(db_async), m_fast_sync(true), m_show_time_stats(false), m_sync_counter(0), m_cancel(false)
{
LOG_PRINT_L3("Blockchain::" << __func__);
}
@@ -387,7 +392,7 @@ bool Blockchain::init(BlockchainDB* db, HardFork*& hf, const bool testnet)
//------------------------------------------------------------------
bool Blockchain::store_blockchain()
{
LOG_PRINT_YELLOW("Blockchain::" << __func__, LOG_LEVEL_3);
LOG_PRINT_L3("Blockchain::" << __func__);
// lock because the rpc_thread command handler also calls this
CRITICAL_REGION_LOCAL(m_db->m_synchronization_lock);
@@ -419,9 +424,10 @@ bool Blockchain::deinit()
{
LOG_PRINT_L3("Blockchain::" << __func__);
LOG_PRINT_L0("Closing IO Service.");
// stop async service
m_async_work_idle.reset();
LOG_PRINT_L1("Stopping blockchain read/write activity");
// stop async service
m_async_work_idle.reset();
m_async_pool.join_all();
m_async_service.stop();
@@ -436,14 +442,15 @@ bool Blockchain::deinit()
try
{
m_db->close();
LOG_PRINT_L1("Local blockchain read/write activity stopped successfully");
}
catch (const std::exception& e)
{
LOG_PRINT_L0(std::string("Error closing blockchain db: ") + e.what());
LOG_ERROR(std::string("Error closing blockchain db: ") + e.what());
}
catch (...)
{
LOG_PRINT_L0("There was an issue closing/storing the blockchain, shutting down now to prevent issues!");
LOG_ERROR("There was an issue closing/storing the blockchain, shutting down now to prevent issues!");
}
delete m_hardfork;
@@ -752,6 +759,9 @@ bool Blockchain::rollback_blockchain_switching(std::list<block>& original_chain,
pop_block_from_blockchain();
}
// make sure the hard fork object updates its current version
m_hardfork->reorganize_from_chain_height(rollback_height);
//return back original chain
for (auto& bl : original_chain)
{
@@ -825,12 +835,12 @@ bool Blockchain::switch_to_alternative_blockchain(std::list<blocks_ext_by_hash::
// looking into.
add_block_as_invalid(ch_ent->second, get_block_hash(ch_ent->second.bl));
LOG_PRINT_L1("The block was inserted as invalid while connecting new alternative chain, block_id: " << get_block_hash(ch_ent->second.bl));
m_alternative_chains.erase(ch_ent);
m_alternative_chains.erase(*alt_ch_iter++);
for(auto alt_ch_to_orph_iter = ++alt_ch_iter; alt_ch_to_orph_iter != alt_chain.end(); alt_ch_to_orph_iter++)
for(auto alt_ch_to_orph_iter = alt_ch_iter; alt_ch_to_orph_iter != alt_chain.end(); )
{
add_block_as_invalid((*alt_ch_iter)->second, (*alt_ch_iter)->first);
m_alternative_chains.erase(*alt_ch_to_orph_iter);
add_block_as_invalid((*alt_ch_to_orph_iter)->second, (*alt_ch_to_orph_iter)->first);
m_alternative_chains.erase(*alt_ch_to_orph_iter++);
}
return false;
}
@@ -1142,7 +1152,7 @@ bool Blockchain::create_block_template(block& b, const account_public_address& m
uint8_t hf_version = m_hardfork->get_current_version();
size_t max_outs = hf_version >= 4 ? 1 : 11;
bool r = construct_miner_tx(height, median_size, already_generated_coins, txs_size, fee, miner_address, b.miner_tx, ex_nonce, max_outs, hf_version);
CHECK_AND_ASSERT_MES(r, false, "Failed to construc miner tx, first chance");
CHECK_AND_ASSERT_MES(r, false, "Failed to construct miner tx, first chance");
size_t cumulative_size = txs_size + get_object_blobsize(b.miner_tx);
#if defined(DEBUG_CREATE_BLOCK_TEMPLATE)
LOG_PRINT_L1("Creating block template: miner tx size " << get_object_blobsize(b.miner_tx) <<
@@ -1152,7 +1162,7 @@ bool Blockchain::create_block_template(block& b, const account_public_address& m
{
r = construct_miner_tx(height, median_size, already_generated_coins, cumulative_size, fee, miner_address, b.miner_tx, ex_nonce, max_outs, hf_version);
CHECK_AND_ASSERT_MES(r, false, "Failed to construc miner tx, second chance");
CHECK_AND_ASSERT_MES(r, false, "Failed to construct miner tx, second chance");
size_t coinbase_blob_size = get_object_blobsize(b.miner_tx);
if (coinbase_blob_size > cumulative_size - txs_size)
{
@@ -1754,7 +1764,7 @@ bool Blockchain::get_random_rct_outs(const COMMAND_RPC_GET_RANDOM_RCT_OUTPUTS::r
return true;
}
//------------------------------------------------------------------
bool Blockchain::get_outs(const COMMAND_RPC_GET_OUTPUTS::request& req, COMMAND_RPC_GET_OUTPUTS::response& res) const
bool Blockchain::get_outs(const COMMAND_RPC_GET_OUTPUTS_BIN::request& req, COMMAND_RPC_GET_OUTPUTS_BIN::response& res) const
{
LOG_PRINT_L3("Blockchain::" << __func__);
CRITICAL_REGION_LOCAL(m_blockchain_lock);
@@ -1764,7 +1774,7 @@ bool Blockchain::get_outs(const COMMAND_RPC_GET_OUTPUTS::request& req, COMMAND_R
for (const auto &i: req.outputs)
{
// get tx_hash, tx_out_index from DB
const output_data_t &od = m_db->get_output_key(i.amount, i.index);
const output_data_t od = m_db->get_output_key(i.amount, i.index);
tx_out_index toi = m_db->get_output_tx_and_index(i.amount, i.index);
bool unlocked = is_tx_spendtime_unlocked(m_db->get_tx_unlock_time(toi.first));
@@ -1795,7 +1805,7 @@ bool Blockchain::find_blockchain_supplement(const std::list<crypto::hash>& qbloc
auto gen_hash = m_db->get_block_hash_from_height(0);
if(qblock_ids.back() != gen_hash)
{
LOG_PRINT_L1("Client sent wrong NOTIFY_REQUEST_CHAIN: genesis block missmatch: " << std::endl << "id: " << qblock_ids.back() << ", " << std::endl << "expected: " << gen_hash << "," << std::endl << " dropping connection");
LOG_PRINT_L1("Client sent wrong NOTIFY_REQUEST_CHAIN: genesis block mismatch: " << std::endl << "id: " << qblock_ids.back() << ", " << std::endl << "expected: " << gen_hash << "," << std::endl << " dropping connection");
m_db->block_txn_abort();
return false;
}
@@ -1828,14 +1838,6 @@ bool Blockchain::find_blockchain_supplement(const std::list<crypto::hash>& qbloc
return false;
}
// if split_height remains 0, we didn't have any but the genesis block in common
// which is only fine if the blocks just have the genesis block
if(split_height == 0 && qblock_ids.size() > 1)
{
LOG_ERROR("Ours and foreign blockchain have only genesis block in common... o.O");
return false;
}
//we start to put block ids INCLUDING last known id, just to make other side be sure
starter_offset = split_height;
return true;
@@ -2235,6 +2237,19 @@ bool Blockchain::check_tx_outputs(const transaction& tx, tx_verification_context
}
}
// from v4, forbid invalid pubkeys
if (m_hardfork->get_current_version() >= 4) {
for (const auto &o: tx.vout) {
if (o.target.type() == typeid(txout_to_key)) {
const txout_to_key& out_to_key = boost::get<txout_to_key>(o.target);
if (!crypto::check_key(out_to_key.key)) {
tvc.m_invalid_output = true;
return false;
}
}
}
}
return true;
}
//------------------------------------------------------------------
@@ -2251,6 +2266,7 @@ bool Blockchain::have_tx_keyimges_as_spent(const transaction &tx) const
}
bool Blockchain::expand_transaction_2(transaction &tx, const crypto::hash &tx_prefix_hash, const std::vector<std::vector<rct::ctkey>> &pubkeys)
{
PERF_TIMER(expand_transaction_2);
CHECK_AND_ASSERT_MES(tx.version == 2, false, "Transaction version is not 2");
rct::rctSig &rv = tx.rct_signatures;
@@ -2327,6 +2343,7 @@ bool Blockchain::expand_transaction_2(transaction &tx, const crypto::hash &tx_pr
// using threads, etc.)
bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc, uint64_t* pmax_used_block_height)
{
PERF_TIMER(check_tx_inputs);
LOG_PRINT_L3("Blockchain::" << __func__);
size_t sig_index = 0;
if(pmax_used_block_height)
@@ -2711,6 +2728,90 @@ void Blockchain::check_ring_signature(const crypto::hash &tx_prefix_hash, const
result = crypto::check_ring_signature(tx_prefix_hash, key_image, p_output_keys, sig.data()) ? 1 : 0;
}
//------------------------------------------------------------------
uint64_t Blockchain::get_dynamic_per_kb_fee(uint64_t block_reward, size_t median_block_size)
{
if (median_block_size < CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2)
median_block_size = CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2;
uint64_t unscaled_fee_per_kb = (DYNAMIC_FEE_PER_KB_BASE_FEE * CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 / median_block_size);
uint64_t hi, lo = mul128(unscaled_fee_per_kb, block_reward, &hi);
static_assert(DYNAMIC_FEE_PER_KB_BASE_BLOCK_REWARD % 1000000 == 0, "DYNAMIC_FEE_PER_KB_BASE_BLOCK_REWARD must be divisible by 1000000");
static_assert(DYNAMIC_FEE_PER_KB_BASE_BLOCK_REWARD / 1000000 <= std::numeric_limits<uint32_t>::max(), "DYNAMIC_FEE_PER_KB_BASE_BLOCK_REWARD is too large");
// divide in two steps, since the divisor must be 32 bits, but DYNAMIC_FEE_PER_KB_BASE_BLOCK_REWARD isn't
div128_32(hi, lo, DYNAMIC_FEE_PER_KB_BASE_BLOCK_REWARD / 1000000, &hi, &lo);
div128_32(hi, lo, 1000000, &hi, &lo);
assert(hi == 0);
return lo;
}
//------------------------------------------------------------------
bool Blockchain::check_fee(size_t blob_size, uint64_t fee) const
{
const uint8_t version = get_current_hard_fork_version();
uint64_t fee_per_kb;
if (version < HF_VERSION_DYNAMIC_FEE)
{
fee_per_kb = FEE_PER_KB;
}
else
{
uint64_t median = m_current_block_cumul_sz_limit / 2;
uint64_t already_generated_coins = m_db->height() ? m_db->get_block_already_generated_coins(m_db->height() - 1) : 0;
uint64_t base_reward;
if (!get_block_reward(median, 1, already_generated_coins, base_reward, version))
return false;
fee_per_kb = get_dynamic_per_kb_fee(base_reward, median);
}
LOG_PRINT_L2("Using " << print_money(fee) << "/kB fee");
uint64_t needed_fee = blob_size / 1024;
needed_fee += (blob_size % 1024) ? 1 : 0;
needed_fee *= fee_per_kb;
if (fee < needed_fee)
{
LOG_PRINT_L1("transaction fee is not enough: " << print_money(fee) << ", minimum fee: " << print_money(needed_fee));
return false;
}
return true;
}
//------------------------------------------------------------------
uint64_t Blockchain::get_dynamic_per_kb_fee_estimate(uint64_t grace_blocks) const
{
const uint8_t version = get_current_hard_fork_version();
if (version < HF_VERSION_DYNAMIC_FEE)
return FEE_PER_KB;
if (grace_blocks >= CRYPTONOTE_REWARD_BLOCKS_WINDOW)
grace_blocks = CRYPTONOTE_REWARD_BLOCKS_WINDOW - 1;
std::vector<size_t> sz;
get_last_n_blocks_sizes(sz, CRYPTONOTE_REWARD_BLOCKS_WINDOW - grace_blocks);
for (size_t i = 0; i < grace_blocks; ++i)
sz.push_back(CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2);
uint64_t median = epee::misc_utils::median(sz);
if(median <= CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2)
median = CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2;
uint64_t already_generated_coins = m_db->height() ? m_db->get_block_already_generated_coins(m_db->height() - 1) : 0;
uint64_t base_reward;
if (!get_block_reward(median, 1, already_generated_coins, base_reward, version))
{
LOG_PRINT_L1("Failed to determine block reward, using placeholder " << print_money(BLOCK_REWARD_OVERESTIMATE) << " as a high bound");
base_reward = BLOCK_REWARD_OVERESTIMATE;
}
uint64_t fee = get_dynamic_per_kb_fee(base_reward, median);
LOG_PRINT_L2("Estimating " << grace_blocks << "-block fee at " << print_money(fee) << "/kB");
return fee;
}
//------------------------------------------------------------------
// This function checks to see if a tx is unlocked. unlock_time is either
// a block index or a unix time.
@@ -3357,6 +3458,8 @@ void Blockchain::block_longhash_worker(const uint64_t height, const std::vector<
// the height of the block passed to it
for (const auto & block : blocks)
{
if (m_cancel)
return;
crypto::hash id = get_block_hash(block);
crypto::hash pow = get_block_longhash(block, height);
map.emplace(id, pow);
@@ -3532,6 +3635,9 @@ bool Blockchain::prepare_handle_incoming_blocks(const std::list<block_complete_e
thread_list.clear();
if (m_cancel)
return false;
for (const auto & map : maps)
{
m_blocks_longhash_table.insert(map.begin(), map.end());
@@ -3539,6 +3645,9 @@ bool Blockchain::prepare_handle_incoming_blocks(const std::list<block_complete_e
}
}
if (m_cancel)
return false;
if (blocks_exist)
{
LOG_PRINT_L0("Skipping prepare blocks. Blocks exist.");
@@ -3576,6 +3685,9 @@ bool Blockchain::prepare_handle_incoming_blocks(const std::list<block_complete_e
// generate sorted tables for all amounts and absolute offsets
for (const auto &entry : blocks_entry)
{
if (m_cancel)
return false;
for (const auto &tx_blob : entry.txs)
{
crypto::hash tx_hash = null_hash;
@@ -3684,6 +3796,9 @@ bool Blockchain::prepare_handle_incoming_blocks(const std::list<block_complete_e
// now generate a table for each tx_prefix and k_image hashes
for (const auto &entry : blocks_entry)
{
if (m_cancel)
return false;
for (const auto &tx_blob : entry.txs)
{
crypto::hash tx_hash = null_hash;
@@ -3760,9 +3875,14 @@ bool Blockchain::get_hard_fork_voting_info(uint8_t version, uint32_t &window, ui
return m_hardfork->get_voting_info(version, window, votes, threshold, earliest_height, voting);
}
std::map<uint64_t, uint64_t> Blockchain:: get_output_histogram(const std::vector<uint64_t> &amounts, bool unlocked) const
std::map<uint64_t, std::tuple<uint64_t, uint64_t, uint64_t>> Blockchain:: get_output_histogram(const std::vector<uint64_t> &amounts, bool unlocked, uint64_t recent_cutoff) const
{
return m_db->get_output_histogram(amounts, unlocked);
return m_db->get_output_histogram(amounts, unlocked, recent_cutoff);
}
void Blockchain::cancel()
{
m_cancel = true;
}
#if defined(PER_BLOCK_CHECKPOINT)

View File

@@ -452,7 +452,7 @@ namespace cryptonote
*
* @return true
*/
bool get_outs(const COMMAND_RPC_GET_OUTPUTS::request& req, COMMAND_RPC_GET_OUTPUTS::response& res) const;
bool get_outs(const COMMAND_RPC_GET_OUTPUTS_BIN::request& req, COMMAND_RPC_GET_OUTPUTS_BIN::response& res) const;
/**
* @brief gets random ringct outputs to mix with
@@ -512,6 +512,47 @@ namespace cryptonote
*/
bool check_tx_inputs(transaction& tx, uint64_t& pmax_used_block_height, crypto::hash& max_used_block_id, tx_verification_context &tvc, bool kept_by_block = false);
/**
* @brief get dynamic per kB fee for a given block size
*
* The dynamic fee is based on the block size in a past window, and
* the current block reward. It is expressed by kB.
*
* @param block_reward the current block reward
* @param median_block_size the median blob's size in the past window
*
* @return the per kB fee
*/
static uint64_t get_dynamic_per_kb_fee(uint64_t block_reward, size_t median_block_size);
/**
* @brief get dynamic per kB fee estimate for the next few blocks
*
* The dynamic fee is based on the block size in a past window, and
* the current block reward. It is expressed by kB. This function
* calculates an estimate for a dynamic fee which will be valid for
* the next grace_blocks
*
* @param grace_blocks number of blocks we want the fee to be valid for
*
* @return the per kB fee estimate
*/
uint64_t get_dynamic_per_kb_fee_estimate(uint64_t grace_blocks) const;
/**
* @brief validate a transaction's fee
*
* This function validates the fee is enough for the transaction.
* This is based on the size of the transaction blob, and, after a
* height threshold, on the average size of transaction in a past window
*
* @param blob_size the transaction blob's size
* @param fee the fee
*
* @return true if the fee is enough, false otherwise
*/
bool check_fee(size_t blob_size, uint64_t fee) const;
/**
* @brief check that a transaction's outputs conform to current standards
*
@@ -729,10 +770,11 @@ namespace cryptonote
*
* @param amounts optional set of amounts to lookup
* @param unlocked whether to restrict instances to unlocked ones
* @param recent_cutoff timestamp to consider outputs as recent
*
* @return a set of amount/instances
*/
std::map<uint64_t, uint64_t> get_output_histogram(const std::vector<uint64_t> &amounts, bool unlocked) const;
std::map<uint64_t, std::tuple<uint64_t, uint64_t, uint64_t>> get_output_histogram(const std::vector<uint64_t> &amounts, bool unlocked, uint64_t recent_cutoff) const;
/**
* @brief perform a check on all key images in the blockchain
@@ -801,6 +843,9 @@ namespace cryptonote
*/
void block_longhash_worker(const uint64_t height, const std::vector<block> &blocks,
std::unordered_map<crypto::hash, crypto::hash> &map) const;
void cancel();
private:
// TODO: evaluate whether or not each of these typedefs are left over from blockchain_storage
@@ -870,6 +915,8 @@ namespace cryptonote
bool m_testnet;
std::atomic<bool> m_cancel;
/**
* @brief collects the keys for all outputs being "spent" as an input
*

View File

@@ -186,6 +186,9 @@ namespace cryptonote
ADD_CHECKPOINT(913193, "5292d5d56f6ba4de33a58d9a34d263e2cb3c6fee0aed2286fd4ac7f36d53c85f");
ADD_CHECKPOINT(1000000, "a886ef5149902d8342475fee9bb296341b891ac67c4842f47a833f23c00ed721");
ADD_CHECKPOINT(1100000, "3fd720c5c8b3072fc1ccda922dec1ef25f9ed88a1e6ad4103d0fe00b180a5903");
ADD_CHECKPOINT(1150000, "1dd16f626d18e1e988490dfd06de5920e22629c972c58b4d8daddea0038627b2");
ADD_CHECKPOINT(1200000, "fa7d13a90850882060479d100141ff84286599ae39c3277c8ea784393f882d1f");
return true;
}

View File

@@ -199,7 +199,7 @@ namespace cryptonote {
uint64_t prefix;
if (!tools::base58::decode_addr(str, prefix, data))
{
LOG_PRINT_L1("Invalid address format");
LOG_PRINT_L2("Invalid address format");
return false;
}

View File

@@ -207,11 +207,11 @@ namespace boost
}
template <class Archive>
inline void serialize(Archive &a, rct::asnlSig &x, const boost::serialization::version_type ver)
inline void serialize(Archive &a, rct::boroSig &x, const boost::serialization::version_type ver)
{
a & x.L1;
a & x.s2;
a & x.s;
a & x.s0;
a & x.s1;
a & x.ee;
}
template <class Archive>

View File

@@ -123,7 +123,7 @@ namespace cryptonote
//-----------------------------------------------------------------------------------
void core::stop()
{
graceful_exit();
m_blockchain_storage.cancel();
}
//-----------------------------------------------------------------------------------
void core::init_options(boost::program_options::options_description& desc)
@@ -142,6 +142,7 @@ namespace cryptonote
command_line::add_arg(desc, command_line::arg_db_sync_mode);
command_line::add_arg(desc, command_line::arg_show_time_stats);
command_line::add_arg(desc, command_line::arg_db_auto_remove_logs);
command_line::add_arg(desc, command_line::arg_block_sync_size);
}
//-----------------------------------------------------------------------------------------------
bool core::handle_command_line(const boost::program_options::variables_map& vm)
@@ -227,14 +228,14 @@ namespace cryptonote
LOG_PRINT_L1("Locking " << lock_path.string());
if (!db_lock.try_lock())
{
LOG_PRINT_L0("Failed to lock " << lock_path.string());
LOG_ERROR("Failed to lock " << lock_path.string());
return false;
}
return true;
}
catch (const std::exception &e)
{
LOG_PRINT_L0("Error trying to lock " << lock_path.string() << ": " << e.what());
LOG_ERROR("Error trying to lock " << lock_path.string() << ": " << e.what());
return false;
}
}
@@ -243,6 +244,7 @@ namespace cryptonote
{
db_lock.unlock();
db_lock = boost::interprocess::file_lock();
LOG_PRINT_L1("Blockchain directory successfully unlocked");
return true;
}
//-----------------------------------------------------------------------------------------------
@@ -313,7 +315,7 @@ namespace cryptonote
}
else
{
LOG_ERROR("Attempted to use non-existant database type");
LOG_ERROR("Attempted to use non-existent database type");
return false;
}
@@ -386,7 +388,7 @@ namespace cryptonote
}
catch (const DB_ERROR& e)
{
LOG_PRINT_L0("Error opening database: " << e.what());
LOG_ERROR("Error opening database: " << e.what());
return false;
}
@@ -403,6 +405,10 @@ namespace cryptonote
m_blockchain_storage.set_show_time_stats(show_time_stats);
CHECK_AND_ASSERT_MES(r, false, "Failed to initialize blockchain storage");
block_sync_size = command_line::get_arg(vm, command_line::arg_block_sync_size);
if (block_sync_size == 0)
block_sync_size = BLOCKS_SYNCHRONIZING_DEFAULT_COUNT;
// load json & DNS checkpoints, and verify them
// with respect to what blocks we already have
CHECK_AND_ASSERT_MES(update_checkpoints(), false, "One or more checkpoints loaded from json or dns conflicted with existing checkpoints.");
@@ -428,23 +434,10 @@ namespace cryptonote
{
m_miner.stop();
m_mempool.deinit();
if (!m_fast_exit)
{
m_blockchain_storage.deinit();
}
m_blockchain_storage.deinit();
unlock_db_directory();
return true;
}
//-----------------------------------------------------------------------------------------------
void core::set_fast_exit()
{
m_fast_exit = true;
}
//-----------------------------------------------------------------------------------------------
bool core::get_fast_exit()
{
return m_fast_exit;
}
//-----------------------------------------------------------------------------------------------
void core::test_drop_download()
{
@@ -623,6 +616,34 @@ namespace cryptonote
return true;
}
//-----------------------------------------------------------------------------------------------
std::pair<uint64_t, uint64_t> core::get_coinbase_tx_sum(const uint64_t start_offset, const size_t count)
{
std::list<block> blocks;
std::list<transaction> txs;
std::list<crypto::hash> missed_txs;
uint64_t coinbase_amount = 0;
uint64_t emission_amount = 0;
uint64_t total_fee_amount = 0;
uint64_t tx_fee_amount = 0;
this->get_blocks(start_offset, count, blocks);
BOOST_FOREACH(auto& b, blocks)
{
coinbase_amount = get_outs_money_amount(b.miner_tx);
this->get_transactions(b.tx_hashes, txs, missed_txs);
BOOST_FOREACH(const auto& tx, txs)
{
tx_fee_amount += get_tx_fee(tx);
}
emission_amount += coinbase_amount - tx_fee_amount;
total_fee_amount += tx_fee_amount;
coinbase_amount = 0;
tx_fee_amount = 0;
}
return std::pair<uint64_t, uint64_t>(emission_amount, total_fee_amount);
}
//-----------------------------------------------------------------------------------------------
bool core::check_tx_inputs_keyimages_diff(const transaction& tx) const
{
std::unordered_set<crypto::key_image> ki;
@@ -688,6 +709,20 @@ namespace cryptonote
return true;
}
//-----------------------------------------------------------------------------------------------
void core::on_transaction_relayed(const cryptonote::blobdata& tx_blob)
{
std::list<std::pair<crypto::hash, cryptonote::transaction>> txs;
cryptonote::transaction tx;
crypto::hash tx_hash, tx_prefix_hash;
if (!parse_and_validate_tx_from_blob(tx_blob, tx, tx_hash, tx_prefix_hash))
{
LOG_ERROR("Failed to parse relayed transaction");
return;
}
txs.push_back(std::make_pair(tx_hash, std::move(tx)));
m_mempool.set_relayed(txs);
}
//-----------------------------------------------------------------------------------------------
bool core::get_block_template(block& b, const account_public_address& adr, difficulty_type& diffic, uint64_t& height, const blobdata& ex_nonce)
{
return m_blockchain_storage.create_block_template(b, adr, diffic, height, ex_nonce);
@@ -723,7 +758,7 @@ namespace cryptonote
return m_blockchain_storage.get_random_outs_for_amounts(req, res);
}
//-----------------------------------------------------------------------------------------------
bool core::get_outs(const COMMAND_RPC_GET_OUTPUTS::request& req, COMMAND_RPC_GET_OUTPUTS::response& res) const
bool core::get_outs(const COMMAND_RPC_GET_OUTPUTS_BIN::request& req, COMMAND_RPC_GET_OUTPUTS_BIN::response& res) const
{
return m_blockchain_storage.get_outs(req, res);
}
@@ -880,6 +915,11 @@ namespace cryptonote
m_mempool.get_transactions(txs);
return true;
}
//-----------------------------------------------------------------------------------------------
bool core::get_pool_transaction(const crypto::hash &id, transaction& tx) const
{
return m_mempool.get_transaction(id, tx);
}
//-----------------------------------------------------------------------------------------------
bool core::get_pool_transactions_and_spent_keys_info(std::vector<tx_info>& tx_infos, std::vector<spent_key_image_info>& key_image_infos) const
{
@@ -965,10 +1005,7 @@ namespace cryptonote
//-----------------------------------------------------------------------------------------------
void core::set_target_blockchain_height(uint64_t target_blockchain_height)
{
if (target_blockchain_height > m_target_blockchain_height)
{
m_target_blockchain_height = target_blockchain_height;
}
m_target_blockchain_height = target_blockchain_height;
}
//-----------------------------------------------------------------------------------------------
uint64_t core::get_target_blockchain_height() const
@@ -980,6 +1017,4 @@ namespace cryptonote
{
raise(SIGTERM);
}
std::atomic<bool> core::m_fast_exit(false);
}

View File

@@ -180,6 +180,11 @@ namespace cryptonote
*/
virtual bool get_block_template(block& b, const account_public_address& adr, difficulty_type& diffic, uint64_t& height, const blobdata& ex_nonce);
/**
* @brief called when a transaction is relayed
*/
virtual void on_transaction_relayed(const cryptonote::blobdata& tx);
/**
* @brief gets the miner instance
@@ -230,28 +235,10 @@ namespace cryptonote
*
* Uninitializes the miner instance, transaction pool, and Blockchain
*
* if m_fast_exit is set, the call to Blockchain::deinit() is not made.
*
* @return true
*/
bool deinit();
/**
* @brief sets fast exit flag
*
* @note see deinit()
*/
static void set_fast_exit();
/**
* @brief gets the current state of the fast exit flag
*
* @return the fast exit flag
*
* @note see deinit()
*/
static bool get_fast_exit();
/**
* @brief sets to drop blocks downloaded (for testing)
*/
@@ -392,6 +379,13 @@ namespace cryptonote
* @note see tx_memory_pool::get_transactions
*/
bool get_pool_transactions(std::list<transaction>& txs) const;
/**
* @copydoc tx_memory_pool::get_transaction
*
* @note see tx_memory_pool::get_transaction
*/
bool get_pool_transaction(const crypto::hash& id, transaction& tx) const;
/**
* @copydoc tx_memory_pool::get_pool_transactions_and_spent_keys_info
@@ -477,7 +471,7 @@ namespace cryptonote
*
* @note see Blockchain::get_outs
*/
bool get_outs(const COMMAND_RPC_GET_OUTPUTS::request& req, COMMAND_RPC_GET_OUTPUTS::response& res) const;
bool get_outs(const COMMAND_RPC_GET_OUTPUTS_BIN::request& req, COMMAND_RPC_GET_OUTPUTS_BIN::response& res) const;
/**
*
@@ -611,6 +605,27 @@ namespace cryptonote
*/
bool are_key_images_spent(const std::vector<crypto::key_image>& key_im, std::vector<bool> &spent) const;
/**
* @brief get the number of blocks to sync in one go
*
* @return the number of blocks to sync in one go
*/
size_t get_block_sync_size() const { return block_sync_size; }
/**
* @brief get the sum of coinbase tx amounts between blocks
*
* @return the number of blocks to sync in one go
*/
std::pair<uint64_t, uint64_t> get_coinbase_tx_sum(const uint64_t start_offset, const size_t count);
/**
* @brief get whether we're on testnet or not
*
* @return are we on testnet?
*/
bool get_testnet() const { return m_testnet; };
private:
/**
@@ -757,8 +772,6 @@ namespace cryptonote
*/
bool unlock_db_directory();
static std::atomic<bool> m_fast_exit; //!< whether or not to deinit Blockchain on exit
bool m_test_drop_download = true; //!< whether or not to drop incoming blocks (for testing)
uint64_t m_test_drop_download_height = 0; //!< height under which to drop incoming blocks, if doing so
@@ -798,6 +811,8 @@ namespace cryptonote
std::atomic_flag m_checkpoints_updating; //!< set if checkpoints are currently updating to avoid multiple threads attempting to update at once
boost::interprocess::file_lock db_lock; //!< a lock object for a file lock in the db directory
size_t block_sync_size;
};
}

View File

@@ -320,26 +320,26 @@ namespace cryptonote
return true;
}
//---------------------------------------------------------------
crypto::public_key get_tx_pub_key_from_extra(const std::vector<uint8_t>& tx_extra)
crypto::public_key get_tx_pub_key_from_extra(const std::vector<uint8_t>& tx_extra, size_t pk_index)
{
std::vector<tx_extra_field> tx_extra_fields;
parse_tx_extra(tx_extra, tx_extra_fields);
tx_extra_pub_key pub_key_field;
if(!find_tx_extra_field_by_type(tx_extra_fields, pub_key_field))
if(!find_tx_extra_field_by_type(tx_extra_fields, pub_key_field, pk_index))
return null_pkey;
return pub_key_field.pub_key;
}
//---------------------------------------------------------------
crypto::public_key get_tx_pub_key_from_extra(const transaction_prefix& tx_prefix)
crypto::public_key get_tx_pub_key_from_extra(const transaction_prefix& tx_prefix, size_t pk_index)
{
return get_tx_pub_key_from_extra(tx_prefix.extra);
return get_tx_pub_key_from_extra(tx_prefix.extra, pk_index);
}
//---------------------------------------------------------------
crypto::public_key get_tx_pub_key_from_extra(const transaction& tx)
crypto::public_key get_tx_pub_key_from_extra(const transaction& tx, size_t pk_index)
{
return get_tx_pub_key_from_extra(tx.extra);
return get_tx_pub_key_from_extra(tx.extra, pk_index);
}
//---------------------------------------------------------------
bool add_tx_pub_key_to_extra(transaction& tx, const crypto::public_key& tx_pub_key)
@@ -366,7 +366,7 @@ namespace cryptonote
return true;
}
//---------------------------------------------------------------
bool remove_extra_nonce_tx_extra(std::vector<uint8_t>& tx_extra)
bool remove_field_from_tx_extra(std::vector<uint8_t>& tx_extra, const std::type_info &type)
{
std::string extra_str(reinterpret_cast<const char*>(tx_extra.data()), tx_extra.size());
std::istringstream iss(extra_str);
@@ -380,7 +380,7 @@ namespace cryptonote
tx_extra_field field;
bool r = ::do_serialize(ar, field);
CHECK_AND_NO_ASSERT_MES_L1(r, false, "failed to deserialize extra field. extra = " << string_tools::buff_to_hex_nodelimer(std::string(reinterpret_cast<const char*>(tx_extra.data()), tx_extra.size())));
if (field.type() != typeid(tx_extra_nonce))
if (field.type() != type)
::do_serialize(newar, field);
std::ios_base::iostate state = iss.rdstate();
@@ -472,10 +472,7 @@ namespace cryptonote
bool construct_tx_and_get_tx_key(const account_keys& sender_account_keys, const std::vector<tx_source_entry>& sources, const std::vector<tx_destination_entry>& destinations, std::vector<uint8_t> extra, transaction& tx, uint64_t unlock_time, crypto::secret_key &tx_key, bool rct)
{
std::vector<rct::key> amount_keys;
tx.vin.clear();
tx.vout.clear();
tx.signatures.clear();
tx.rct_signatures.type = rct::RCTTypeNull;
tx.set_null();
amount_keys.clear();
tx.version = rct ? 2 : 1;
@@ -483,6 +480,7 @@ namespace cryptonote
tx.extra = extra;
keypair txkey = keypair::generate();
remove_field_from_tx_extra(tx.extra, typeid(tx_extra_pub_key));
add_tx_pub_key_to_extra(tx, txkey.pub);
tx_key = txkey.sec;
@@ -512,7 +510,7 @@ namespace cryptonote
std::string extra_nonce;
set_encrypted_payment_id_to_tx_extra_nonce(extra_nonce, payment_id);
remove_extra_nonce_tx_extra(tx.extra);
remove_field_from_tx_extra(tx.extra, typeid(tx_extra_nonce));
if (!add_extra_nonce_to_tx_extra(tx.extra, extra_nonce))
{
LOG_ERROR("Failed to add encrypted payment id to tx extra");
@@ -536,8 +534,10 @@ namespace cryptonote
uint64_t summary_inputs_money = 0;
//fill inputs
int idx = -1;
BOOST_FOREACH(const tx_source_entry& src_entr, sources)
{
++idx;
if(src_entr.real_output >= src_entr.outputs.size())
{
LOG_ERROR("real_output index (" << src_entr.real_output << ")bigger than output_keys.size()=" << src_entr.outputs.size());
@@ -555,9 +555,11 @@ namespace cryptonote
//check that derivated key is equal with real output key
if( !(in_ephemeral.pub == src_entr.outputs[src_entr.real_output].second.dest) )
{
LOG_ERROR("derived public key missmatch with output public key! "<< ENDL << "derived_key:"
LOG_ERROR("derived public key mismatch with output public key at index " << idx << ", real out " << src_entr.real_output << "! "<< ENDL << "derived_key:"
<< string_tools::pod_to_hex(in_ephemeral.pub) << ENDL << "real output_public_key:"
<< string_tools::pod_to_hex(src_entr.outputs[src_entr.real_output].second) );
LOG_ERROR("amount " << src_entr.amount << ", rct " << src_entr.rct);
LOG_ERROR("tx pubkey " << src_entr.real_out_tx_key << ", real_output_in_tx_index " << src_entr.real_output_in_tx_index);
return false;
}
@@ -615,6 +617,14 @@ namespace cryptonote
return false;
}
// check for watch only wallet
bool zero_secret_key = true;
for (size_t i = 0; i < sizeof(sender_account_keys.m_spend_secret_key); ++i)
zero_secret_key &= (sender_account_keys.m_spend_secret_key.data[i] == 0);
if (zero_secret_key)
{
LOG_PRINT_L1("Null secret key, skipping signatures");
}
if (tx.version == 1)
{
@@ -641,7 +651,8 @@ namespace cryptonote
tx.signatures.push_back(std::vector<crypto::signature>());
std::vector<crypto::signature>& sigs = tx.signatures.back();
sigs.resize(src_entr.outputs.size());
crypto::generate_ring_signature(tx_prefix_hash, boost::get<txin_to_key>(tx.vin[i]).k_image, keys_ptrs, in_contexts[i].in_ephemeral.sec, src_entr.real_output, sigs.data());
if (!zero_secret_key)
crypto::generate_ring_signature(tx_prefix_hash, boost::get<txin_to_key>(tx.vin[i]).k_image, keys_ptrs, in_contexts[i].in_ephemeral.sec, src_entr.real_output, sigs.data());
ss_ring_s << "signatures:" << ENDL;
std::for_each(sigs.begin(), sigs.end(), [&](const crypto::signature& s){ss_ring_s << s << ENDL;});
ss_ring_s << "prefix_hash:" << tx_prefix_hash << ENDL << "in_ephemeral_key: " << in_contexts[i].in_ephemeral.sec << ENDL << "real_output: " << src_entr.real_output;
@@ -652,10 +663,7 @@ namespace cryptonote
}
else
{
bool all_rct_inputs = true;
size_t n_total_outs = sources[0].outputs.size(); // only for non-simple rct
BOOST_FOREACH(const tx_source_entry& src_entr, sources)
all_rct_inputs &= !(src_entr.mask == rct::identity());
// the non-simple version is slightly smaller, but assumes all real inputs
// are on the same index, so can only be used if there just one ring.
@@ -873,6 +881,13 @@ namespace cryptonote
return pk == out_key.key;
}
//---------------------------------------------------------------
bool is_out_to_acc_precomp(const crypto::public_key& spend_public_key, const txout_to_key& out_key, const crypto::key_derivation& derivation, size_t output_index)
{
crypto::public_key pk;
derive_public_key(derivation, output_index, spend_public_key, pk);
return pk == out_key.key;
}
//---------------------------------------------------------------
bool lookup_acc_outs(const account_keys& acc, const transaction& tx, std::vector<size_t>& outs, uint64_t& money_transfered)
{
crypto::public_key tx_pub_key = get_tx_pub_key_from_extra(tx);

View File

@@ -62,6 +62,16 @@ namespace cryptonote
rct::key mask; //ringct amount mask
void push_output(uint64_t idx, const crypto::public_key &k, uint64_t amount) { outputs.push_back(std::make_pair(idx, rct::ctkey({rct::pk2rct(k), rct::zeroCommit(amount)}))); }
BEGIN_SERIALIZE_OBJECT()
FIELD(outputs)
VARINT_FIELD(real_output)
FIELD(real_out_tx_key)
VARINT_FIELD(real_output_in_tx_index)
VARINT_FIELD(amount)
FIELD(rct)
FIELD(mask)
END_SERIALIZE()
};
struct tx_destination_entry
@@ -71,6 +81,11 @@ namespace cryptonote
tx_destination_entry() : amount(0), addr(AUTO_VAL_INIT(addr)) { }
tx_destination_entry(uint64_t a, const account_public_address &ad) : amount(a), addr(ad) { }
BEGIN_SERIALIZE_OBJECT()
VARINT_FIELD(amount)
FIELD(addr)
END_SERIALIZE()
};
//---------------------------------------------------------------
@@ -78,9 +93,9 @@ namespace cryptonote
bool construct_tx_and_get_tx_key(const account_keys& sender_account_keys, const std::vector<tx_source_entry>& sources, const std::vector<tx_destination_entry>& destinations, std::vector<uint8_t> extra, transaction& tx, uint64_t unlock_time, crypto::secret_key &tx_key, bool rct = false);
template<typename T>
bool find_tx_extra_field_by_type(const std::vector<tx_extra_field>& tx_extra_fields, T& field)
bool find_tx_extra_field_by_type(const std::vector<tx_extra_field>& tx_extra_fields, T& field, size_t index = 0)
{
auto it = std::find_if(tx_extra_fields.begin(), tx_extra_fields.end(), [](const tx_extra_field& f) { return typeid(T) == f.type(); });
auto it = std::find_if(tx_extra_fields.begin(), tx_extra_fields.end(), [&index](const tx_extra_field& f) { return typeid(T) == f.type() && !index--; });
if(tx_extra_fields.end() == it)
return false;
@@ -89,17 +104,18 @@ namespace cryptonote
}
bool parse_tx_extra(const std::vector<uint8_t>& tx_extra, std::vector<tx_extra_field>& tx_extra_fields);
crypto::public_key get_tx_pub_key_from_extra(const std::vector<uint8_t>& tx_extra);
crypto::public_key get_tx_pub_key_from_extra(const transaction_prefix& tx);
crypto::public_key get_tx_pub_key_from_extra(const transaction& tx);
crypto::public_key get_tx_pub_key_from_extra(const std::vector<uint8_t>& tx_extra, size_t pk_index = 0);
crypto::public_key get_tx_pub_key_from_extra(const transaction_prefix& tx, size_t pk_index = 0);
crypto::public_key get_tx_pub_key_from_extra(const transaction& tx, size_t pk_index = 0);
bool add_tx_pub_key_to_extra(transaction& tx, const crypto::public_key& tx_pub_key);
bool add_extra_nonce_to_tx_extra(std::vector<uint8_t>& tx_extra, const blobdata& extra_nonce);
bool remove_extra_nonce_tx_extra(std::vector<uint8_t>& tx_extra);
bool remove_field_from_tx_extra(std::vector<uint8_t>& tx_extra, const std::type_info &type);
void set_payment_id_to_tx_extra_nonce(blobdata& extra_nonce, const crypto::hash& payment_id);
void set_encrypted_payment_id_to_tx_extra_nonce(blobdata& extra_nonce, const crypto::hash8& payment_id);
bool get_payment_id_from_tx_extra_nonce(const blobdata& extra_nonce, crypto::hash& payment_id);
bool get_encrypted_payment_id_from_tx_extra_nonce(const blobdata& extra_nonce, crypto::hash8& payment_id);
bool is_out_to_acc(const account_keys& acc, const txout_to_key& out_key, const crypto::public_key& tx_pub_key, size_t output_index);
bool is_out_to_acc_precomp(const crypto::public_key& spend_public_key, const txout_to_key& out_key, const crypto::key_derivation& derivation, size_t output_index);
bool lookup_acc_outs(const account_keys& acc, const transaction& tx, const crypto::public_key& tx_pub_key, std::vector<size_t>& outs, uint64_t& money_transfered);
bool lookup_acc_outs(const account_keys& acc, const transaction& tx, std::vector<size_t>& outs, uint64_t& money_transfered);
bool get_tx_fee(const transaction& tx, uint64_t & fee);

View File

@@ -278,8 +278,13 @@ namespace cryptonote
//-----------------------------------------------------------------------------------------------------
bool miner::stop()
{
LOG_PRINT_L1("Miner has received stop signal");
if (!is_mining())
{
LOG_PRINT_L1("Not mining - nothing to stop" );
return true;
}
send_stop_signal();
CRITICAL_REGION_LOCAL(m_threads_lock);

View File

@@ -42,6 +42,7 @@
#include "common/int-util.h"
#include "misc_language.h"
#include "warnings.h"
#include "common/perf_timer.h"
#include "crypto/hash.h"
DISABLE_VS_WARNINGS(4244 4345 4503) //'boost::foreach_detail_::or_' : decorated name length exceeded, name was truncated
@@ -78,6 +79,7 @@ namespace cryptonote
//---------------------------------------------------------------------------------
bool tx_memory_pool::add_tx(const transaction &tx, /*const crypto::hash& tx_prefix_hash,*/ const crypto::hash &id, size_t blob_size, tx_verification_context& tvc, bool kept_by_block, bool relayed, uint8_t version)
{
PERF_TIMER(add_tx);
if (tx.version == 0)
{
// v0 never accepted
@@ -131,12 +133,8 @@ namespace cryptonote
fee = tx.rct_signatures.txnFee;
}
uint64_t needed_fee = blob_size / 1024;
needed_fee += (blob_size % 1024) ? 1 : 0;
needed_fee *= FEE_PER_KB;
if (!kept_by_block && fee < needed_fee)
if (!kept_by_block && !m_blockchain.check_fee(blob_size, fee))
{
LOG_PRINT_L1("transaction fee is not enough: " << print_money(fee) << ", minimum fee: " << print_money(needed_fee));
tvc.m_verifivation_failed = true;
tvc.m_fee_too_low = true;
return false;
@@ -207,7 +205,7 @@ namespace cryptonote
{
//update transactions container
auto txd_p = m_transactions.insert(transactions_container::value_type(id, txd));
CHECK_AND_ASSERT_MES(txd_p.second, false, "intrnal error: transaction already exists at inserting in memorypool");
CHECK_AND_ASSERT_MES(txd_p.second, false, "internal error: transaction already exists at inserting in memorypool");
txd_p.first->second.blob_size = blob_size;
txd_p.first->second.kept_by_block = kept_by_block;
txd_p.first->second.fee = fee;
@@ -385,7 +383,10 @@ namespace cryptonote
{
auto i = m_transactions.find(it->first);
if (i != m_transactions.end())
{
i->second.relayed = true;
i->second.last_relayed_time = now;
}
}
}
//---------------------------------------------------------------------------------
@@ -420,6 +421,8 @@ namespace cryptonote
txi.last_failed_height = txd.last_failed_height;
txi.last_failed_id_hash = epee::string_tools::pod_to_hex(txd.last_failed_id);
txi.receive_time = txd.receive_time;
txi.relayed = txd.relayed;
txi.last_relayed_time = txd.last_relayed_time;
tx_infos.push_back(txi);
}
@@ -689,7 +692,7 @@ namespace cryptonote
bool res = tools::unserialize_obj_from_file(*this, state_file_path);
if(!res)
{
LOG_PRINT_L1("Failed to load memory pool from file " << state_file_path);
LOG_ERROR("Failed to load memory pool from file " << state_file_path);
m_transactions.clear();
m_txs_by_fee.clear();
@@ -710,12 +713,17 @@ namespace cryptonote
//TODO: investigate whether only ever returning true is correct
bool tx_memory_pool::deinit()
{
LOG_PRINT_L1("Received signal to deactivate memory pool store");
if (m_config_folder.empty())
{
LOG_PRINT_L1("Memory pool store already empty");
return true;
}
if (!tools::create_directories_if_necessary(m_config_folder))
{
LOG_PRINT_L1("Failed to create data directory: " << m_config_folder);
LOG_ERROR("Failed to create memory pool data directory: " << m_config_folder);
return false;
}
@@ -723,8 +731,14 @@ namespace cryptonote
bool res = tools::serialize_obj_to_file(*this, state_file_path);
if(!res)
{
LOG_PRINT_L1("Failed to serialize memory pool to file " << state_file_path);
LOG_ERROR("Failed to serialize memory pool to file " << state_file_path);
return false;
}
return true;
else
{
LOG_PRINT_L1("Memory pool store deactivated successfully");
return true;
}
}
}

View File

@@ -27,13 +27,13 @@
# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
cmake_minimum_required (VERSION 2.6)
project (bitmonero CXX)
project (monero CXX)
file(GLOB CRYPTONOTE_PROTOCOL *)
source_group(cryptonote_protocol FILES ${CRYPTONOTE_PROTOCOL})
#bitmonero_private_headers(cryptonote_protocol ${CRYPTONOTE_PROTOCOL})
bitmonero_add_library(cryptonote_protocol ${CRYPTONOTE_PROTOCOL})
#monero_private_headers(cryptonote_protocol ${CRYPTONOTE_PROTOCOL})
monero_add_library(cryptonote_protocol ${CRYPTONOTE_PROTOCOL})
target_link_libraries(cryptonote_protocol
PRIVATE
${EXTRA_LIBRARIES})

View File

@@ -69,6 +69,8 @@ namespace cryptonote
uint64_t avg_upload;
uint64_t current_upload;
uint32_t support_flags;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(incoming)
@@ -87,6 +89,7 @@ namespace cryptonote
KV_SERIALIZE(current_download)
KV_SERIALIZE(avg_upload)
KV_SERIALIZE(current_upload)
KV_SERIALIZE(support_flags)
END_KV_SERIALIZE_MAP()
};
@@ -223,5 +226,49 @@ namespace cryptonote
END_KV_SERIALIZE_MAP()
};
};
/************************************************************************/
/* */
/************************************************************************/
struct NOTIFY_NEW_FLUFFY_BLOCK
{
const static int ID = BC_COMMANDS_POOL_BASE + 8;
struct request
{
block_complete_entry b;
uint64_t current_blockchain_height;
uint32_t hop;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(b)
KV_SERIALIZE(current_blockchain_height)
KV_SERIALIZE(hop)
END_KV_SERIALIZE_MAP()
};
};
/************************************************************************/
/* */
/************************************************************************/
struct NOTIFY_REQUEST_FLUFFY_MISSING_TX
{
const static int ID = BC_COMMANDS_POOL_BASE + 9;
struct request
{
block_complete_entry b;
uint64_t current_blockchain_height;
std::vector<size_t> missing_tx_indices;
uint32_t hop;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(b)
KV_SERIALIZE_CONTAINER_POD_AS_BLOB(missing_tx_indices)
KV_SERIALIZE(hop)
KV_SERIALIZE(current_blockchain_height)
END_KV_SERIALIZE_MAP()
};
};
}

View File

@@ -91,6 +91,8 @@ namespace cryptonote
HANDLE_NOTIFY_T2(NOTIFY_RESPONSE_GET_OBJECTS, &cryptonote_protocol_handler::handle_response_get_objects)
HANDLE_NOTIFY_T2(NOTIFY_REQUEST_CHAIN, &cryptonote_protocol_handler::handle_request_chain)
HANDLE_NOTIFY_T2(NOTIFY_RESPONSE_CHAIN_ENTRY, &cryptonote_protocol_handler::handle_response_chain_entry)
HANDLE_NOTIFY_T2(NOTIFY_NEW_FLUFFY_BLOCK, &cryptonote_protocol_handler::handle_notify_new_fluffy_block)
HANDLE_NOTIFY_T2(NOTIFY_REQUEST_FLUFFY_MISSING_TX, &cryptonote_protocol_handler::handle_request_fluffy_missing_tx)
END_INVOKE_MAP2()
bool on_idle();
@@ -107,6 +109,7 @@ namespace cryptonote
bool is_synchronized(){return m_synchronized;}
void log_connections();
std::list<connection_info> get_connections();
void stop();
private:
//----------------- commands handlers ----------------------------------------------
int handle_notify_new_block(int command, NOTIFY_NEW_BLOCK::request& arg, cryptonote_connection_context& context);
@@ -115,8 +118,9 @@ namespace cryptonote
int handle_response_get_objects(int command, NOTIFY_RESPONSE_GET_OBJECTS::request& arg, cryptonote_connection_context& context);
int handle_request_chain(int command, NOTIFY_REQUEST_CHAIN::request& arg, cryptonote_connection_context& context);
int handle_response_chain_entry(int command, NOTIFY_RESPONSE_CHAIN_ENTRY::request& arg, cryptonote_connection_context& context);
int handle_notify_new_fluffy_block(int command, NOTIFY_NEW_FLUFFY_BLOCK::request& arg, cryptonote_connection_context& context);
int handle_request_fluffy_missing_tx(int command, NOTIFY_REQUEST_FLUFFY_MISSING_TX::request& arg, cryptonote_connection_context& context);
//----------------- i_bc_protocol_layout ---------------------------------------
virtual bool relay_block(NOTIFY_NEW_BLOCK::request& arg, cryptonote_connection_context& exclude_context);
virtual bool relay_transactions(NOTIFY_NEW_TRANSACTIONS::request& arg, cryptonote_connection_context& exclude_context);
@@ -132,29 +136,30 @@ namespace cryptonote
std::atomic<uint32_t> m_syncronized_connections_count;
std::atomic<bool> m_synchronized;
bool m_one_request = true;
std::atomic<bool> m_stopping;
// static std::ofstream m_logreq;
boost::mutex m_buffer_mutex;
double get_avg_block_size();
boost::circular_buffer<size_t> m_avg_buffer = boost::circular_buffer<size_t>(10);
template<class t_parametr>
bool post_notify(typename t_parametr::request& arg, cryptonote_connection_context& context)
template<class t_parameter>
bool post_notify(typename t_parameter::request& arg, cryptonote_connection_context& context)
{
LOG_PRINT_L2("[" << epee::net_utils::print_connection_context_short(context) << "] post " << typeid(t_parametr).name() << " -->");
LOG_PRINT_L2("[" << epee::net_utils::print_connection_context_short(context) << "] post " << typeid(t_parameter).name() << " -->");
std::string blob;
epee::serialization::store_t_to_binary(arg, blob);
//handler_response_blocks_now(blob.size()); // XXX
return m_p2p->invoke_notify_to_peer(t_parametr::ID, blob, context);
return m_p2p->invoke_notify_to_peer(t_parameter::ID, blob, context);
}
template<class t_parametr>
bool relay_post_notify(typename t_parametr::request& arg, cryptonote_connection_context& exlude_context)
template<class t_parameter>
bool relay_post_notify(typename t_parameter::request& arg, cryptonote_connection_context& exclude_context)
{
LOG_PRINT_L2("[" << epee::net_utils::print_connection_context_short(exlude_context) << "] post relay " << typeid(t_parametr).name() << " -->");
LOG_PRINT_L2("[" << epee::net_utils::print_connection_context_short(exclude_context) << "] post relay " << typeid(t_parameter).name() << " -->");
std::string arg_buff;
epee::serialization::store_t_to_binary(arg, arg_buff);
return m_p2p->relay_notify_to_all(t_parametr::ID, arg_buff, exlude_context);
return m_p2p->relay_notify_to_all(t_parameter::ID, arg_buff, exclude_context);
}
virtual std::ofstream& get_logreq() const ;

View File

@@ -37,6 +37,7 @@
#include <boost/interprocess/detail/atomic.hpp>
#include <list>
#include <unordered_map>
#include "cryptonote_core/cryptonote_format_utils.h"
#include "profile_tools.h"
@@ -59,7 +60,8 @@ namespace cryptonote
t_cryptonote_protocol_handler<t_core>::t_cryptonote_protocol_handler(t_core& rcore, nodetool::i_p2p_endpoint<connection_context>* p_net_layout):m_core(rcore),
m_p2p(p_net_layout),
m_syncronized_connections_count(0),
m_synchronized(false)
m_synchronized(false),
m_stopping(false)
{
if(!m_p2p)
@@ -75,8 +77,6 @@ namespace cryptonote
template<class t_core>
bool t_cryptonote_protocol_handler<t_core>::deinit()
{
return true;
}
//------------------------------------------------------------------------------------------------------------------------
@@ -126,6 +126,7 @@ namespace cryptonote
ss << std::setw(30) << std::left << "Remote Host"
<< std::setw(20) << "Peer id"
<< std::setw(20) << "Support Flags"
<< std::setw(30) << "Recv/Sent (inactive,sec)"
<< std::setw(25) << "State"
<< std::setw(20) << "Livetime(sec)"
@@ -136,7 +137,7 @@ namespace cryptonote
<< ENDL;
uint32_t ip;
m_p2p->for_each_connection([&](const connection_context& cntxt, nodetool::peerid_type peer_id)
m_p2p->for_each_connection([&](const connection_context& cntxt, nodetool::peerid_type peer_id, uint32_t support_flags)
{
bool local_ip = false;
ip = ntohl(cntxt.m_remote_ip);
@@ -147,6 +148,7 @@ namespace cryptonote
ss << std::setw(30) << std::left << std::string(cntxt.m_is_income ? " [INC]":"[OUT]") +
epee::string_tools::get_ip_string_from_int32(cntxt.m_remote_ip) + ":" + std::to_string(cntxt.m_remote_port)
<< std::setw(20) << std::hex << peer_id
<< std::setw(20) << std::hex << support_flags
<< std::setw(30) << std::to_string(cntxt.m_recv_cnt)+ "(" + std::to_string(time(NULL) - cntxt.m_last_recv) + ")" + "/" + std::to_string(cntxt.m_send_cnt) + "(" + std::to_string(time(NULL) - cntxt.m_last_send) + ")"
<< std::setw(25) << get_protocol_state_string(cntxt.m_state)
<< std::setw(20) << std::to_string(time(NULL) - cntxt.m_started)
@@ -186,7 +188,7 @@ namespace cryptonote
{
std::list<connection_info> connections;
m_p2p->for_each_connection([&](const connection_context& cntxt, nodetool::peerid_type peer_id)
m_p2p->for_each_connection([&](const connection_context& cntxt, nodetool::peerid_type peer_id, uint32_t support_flags)
{
connection_info cnx;
auto timestamp = time(NULL);
@@ -199,6 +201,8 @@ namespace cryptonote
std::stringstream peer_id_str;
peer_id_str << std::hex << peer_id;
peer_id_str >> cnx.peer_id;
cnx.support_flags = support_flags;
cnx.recv_count = cntxt.m_recv_cnt;
cnx.recv_idle_time = timestamp - cntxt.m_last_recv;
@@ -263,7 +267,7 @@ namespace cryptonote
if(context.m_state == cryptonote_connection_context::state_synchronizing)
return true;
if(m_core.have_block(hshd.top_id) && !(hshd.current_height < m_core.get_target_blockchain_height()))
if(m_core.have_block(hshd.top_id))
{
context.m_state = cryptonote_connection_context::state_normal;
if(is_inital)
@@ -280,8 +284,8 @@ namespace cryptonote
int64_t max_block_height = max(static_cast<int64_t>(hshd.current_height),static_cast<int64_t>(m_core.get_current_blockchain_height()));
int64_t last_block_v1 = 1009826;
int64_t diff_v2 = max_block_height > last_block_v1 ? min(abs(diff), max_block_height - last_block_v1) : 0;
LOG_PRINT_CCONTEXT_YELLOW("Sync data returned unknown top block: " << m_core.get_current_blockchain_height() << " -> " << hshd.current_height
<< " [" << std::abs(diff) << " blocks (" << ((abs(diff) - diff_v2) / (24 * 60 * 60 / DIFFICULTY_TARGET_V1)) + (diff_v2 / (24 * 60 * 60 / DIFFICULTY_TARGET_V2)) << " days) "
LOG_PRINT_CCONTEXT_YELLOW("Sync data returned a new top block candidate: " << m_core.get_current_blockchain_height() << " -> " << hshd.current_height
<< " [Your node is " << std::abs(diff) << " blocks (" << ((abs(diff) - diff_v2) / (24 * 60 * 60 / DIFFICULTY_TARGET_V1)) + (diff_v2 / (24 * 60 * 60 / DIFFICULTY_TARGET_V2)) << " days) "
<< (0 <= diff ? std::string("behind") : std::string("ahead"))
<< "] " << ENDL << "SYNCHRONIZATION started", (is_inital ? LOG_LEVEL_0:LOG_LEVEL_1));
LOG_PRINT_L1("Remote blockchain height: " << hshd.current_height << ", id: " << hshd.top_id);
@@ -363,6 +367,312 @@ namespace cryptonote
}
//------------------------------------------------------------------------------------------------------------------------
template<class t_core>
int t_cryptonote_protocol_handler<t_core>::handle_notify_new_fluffy_block(int command, NOTIFY_NEW_FLUFFY_BLOCK::request& arg, cryptonote_connection_context& context)
{
LOG_PRINT_CCONTEXT_L2("NOTIFY_NEW_FLUFFY_BLOCK (hop " << arg.hop << ")");
if(context.m_state != cryptonote_connection_context::state_normal)
return 1;
m_core.pause_mine();
block new_block;
transaction miner_tx;
if(parse_and_validate_block_from_blob(arg.b.block, new_block))
{
// This is a seccond notification, we must have asked for some missing tx
if(!context.m_requested_objects.empty())
{
// What we asked for != to what we received ..
if(context.m_requested_objects.size() != arg.b.txs.size())
{
LOG_ERROR_CCONTEXT
(
"NOTIFY_NEW_FLUFFY_BLOCK -> request/response mismatch, "
<< "block = " << epee::string_tools::pod_to_hex(get_blob_hash(arg.b.block))
<< ", requested = " << context.m_requested_objects.size()
<< ", received = " << new_block.tx_hashes.size()
<< ", dropping connection"
);
m_p2p->drop_connection(context);
m_core.resume_mine();
return 1;
}
}
std::list<blobdata> have_tx;
// Instead of requesting missing transactions by hash like BTC,
// we do it by index (thanks to a suggestion from moneromooo) because
// we're way cooler .. and also because they're smaller than hashes.
//
// Also, remember to pepper some whitespace changes around to bother
// moneromooo ... only because I <3 him.
std::vector<size_t> need_tx_indices;
transaction tx;
crypto::hash tx_hash;
BOOST_FOREACH(auto& tx_blob, arg.b.txs)
{
if(parse_and_validate_tx_from_blob(tx_blob, tx))
{
try
{
if(!get_transaction_hash(tx, tx_hash))
{
LOG_PRINT_CCONTEXT_L1
(
"NOTIFY_NEW_FLUFFY_BLOCK: get_transaction_hash failed"
<< ", dropping connection"
);
m_p2p->drop_connection(context);
m_core.resume_mine();
return 1;
}
}
catch(...)
{
LOG_PRINT_CCONTEXT_L1
(
"NOTIFY_NEW_FLUFFY_BLOCK: get_transaction_hash failed"
<< ", exception thrown"
<< ", dropping connection"
);
m_p2p->drop_connection(context);
m_core.resume_mine();
return 1;
}
// hijacking m_requested objects in connection context to patch up
// a possible DOS vector pointed out by @monero-moo where peers keep
// sending (0...n-1) transactions.
// If requested objects is not empty, then we must have asked for
// some missing transacionts, make sure that they're all there.
//
// Can I safely re-use this field? I think so, but someone check me!
if(!context.m_requested_objects.empty())
{
auto req_tx_it = context.m_requested_objects.find(tx_hash);
if(req_tx_it == context.m_requested_objects.end())
{
LOG_ERROR_CCONTEXT
(
"Peer sent wrong transaction (NOTIFY_NEW_FLUFFY_BLOCK): "
<< "transaction with id = " << tx_hash << " wasn't requested, "
<< "dropping connection"
);
m_p2p->drop_connection(context);
m_core.resume_mine();
return 1;
}
context.m_requested_objects.erase(req_tx_it);
}
// we might already have the tx that the peer
// sent in our pool, so don't verify again..
if(!m_core.get_pool_transaction(tx_hash, tx))
{
cryptonote::tx_verification_context tvc = AUTO_VAL_INIT(tvc);
if(!m_core.handle_incoming_tx(tx_blob, tvc, true, true) || tvc.m_verifivation_failed)
{
LOG_PRINT_CCONTEXT_L1("Block verification failed: transaction verification failed, dropping connection");
m_p2p->drop_connection(context);
m_core.resume_mine();
return 1;
}
//
// future todo:
// tx should only not be added to pool if verification failed, but
// maybe in the future could not be added for other reasons
// according to monero-moo so keep track of these separately ..
//
}
}
else
{
LOG_ERROR_CCONTEXT
(
"sent wrong tx: failed to parse and validate transaction: \r\n"
<< epee::string_tools::buff_to_hex_nodelimer(tx_blob)
<< "\r\n dropping connection"
);
m_p2p->drop_connection(context);
m_core.resume_mine();
return 1;
}
}
// The initial size equality check could have been fooled if the sender
// gave us the number of transactions we asked for, but not the right
// ones. This check make sure the transactions we asked for were the
// ones we received.
if(context.m_requested_objects.size())
{
LOG_PRINT_CCONTEXT_RED
(
"NOTIFY_NEW_FLUFFY_BLOCK: peer sent the number of transaction requested"
<< ", but not the actual transactions requested"
<< ", context.m_requested_objects.size() = " << context.m_requested_objects.size()
<< ", dropping connection", LOG_LEVEL_0
);
m_p2p->drop_connection(context);
m_core.resume_mine();
return 1;
}
size_t tx_idx = 0;
BOOST_FOREACH(auto& tx_hash, new_block.tx_hashes)
{
if(m_core.get_pool_transaction(tx_hash, tx))
{
have_tx.push_back(tx_to_blob(tx));
}
else
{
need_tx_indices.push_back(tx_idx);
}
++tx_idx;
}
if(!need_tx_indices.empty()) // drats, we don't have everything..
{
// request non-mempool txs
NOTIFY_REQUEST_FLUFFY_MISSING_TX::request missing_tx_req;
missing_tx_req.b = arg.b;
missing_tx_req.hop = arg.hop;
missing_tx_req.current_blockchain_height = arg.current_blockchain_height;
missing_tx_req.missing_tx_indices = std::move(need_tx_indices);
m_core.resume_mine();
post_notify<NOTIFY_REQUEST_FLUFFY_MISSING_TX>(missing_tx_req, context);
}
else // whoo-hoo we've got em all ..
{
block_complete_entry b;
b.block = arg.b.block;
b.txs = have_tx;
std::list<block_complete_entry> blocks;
blocks.push_back(b);
m_core.prepare_handle_incoming_blocks(blocks);
block_verification_context bvc = boost::value_initialized<block_verification_context>();
m_core.handle_incoming_block(arg.b.block, bvc); // got block from handle_notify_new_block
m_core.cleanup_handle_incoming_blocks(true);
m_core.resume_mine();
if( bvc.m_verifivation_failed )
{
LOG_PRINT_CCONTEXT_L0("Block verification failed, dropping connection");
m_p2p->drop_connection(context);
return 1;
}
if( bvc.m_added_to_main_chain )
{
++arg.hop;
//TODO: Add here announce protocol usage
NOTIFY_NEW_BLOCK::request reg_arg = AUTO_VAL_INIT(reg_arg);
reg_arg.hop = arg.hop;
reg_arg.current_blockchain_height = arg.current_blockchain_height;
reg_arg.b.block = b.block;
relay_block(reg_arg, context);
}
else if( bvc.m_marked_as_orphaned )
{
context.m_state = cryptonote_connection_context::state_synchronizing;
NOTIFY_REQUEST_CHAIN::request r = boost::value_initialized<NOTIFY_REQUEST_CHAIN::request>();
m_core.get_short_chain_history(r.block_ids);
LOG_PRINT_CCONTEXT_L2("-->>NOTIFY_REQUEST_CHAIN: m_block_ids.size()=" << r.block_ids.size() );
post_notify<NOTIFY_REQUEST_CHAIN>(r, context);
}
}
}
else
{
LOG_ERROR_CCONTEXT
(
"sent wrong block: failed to parse and validate block: \r\n"
<< epee::string_tools::buff_to_hex_nodelimer(arg.b.block)
<< "\r\n dropping connection"
);
m_core.resume_mine();
m_p2p->drop_connection(context);
return 1;
}
return 1;
}
//------------------------------------------------------------------------------------------------------------------------
template<class t_core>
int t_cryptonote_protocol_handler<t_core>::handle_request_fluffy_missing_tx(int command, NOTIFY_REQUEST_FLUFFY_MISSING_TX::request& arg, cryptonote_connection_context& context)
{
LOG_PRINT_CCONTEXT_L2("NOTIFY_REQUEST_FLUFFY_MISSING_TX");
std::list<block> local_blocks;
std::list<transaction> local_txs;
if(!m_core.get_blocks(arg.current_blockchain_height - 1, 1, local_blocks, local_txs))
{
LOG_ERROR_CCONTEXT
(
"Failed to handle request NOTIFY_REQUEST_FLUFFY_MISSING_TX"
<< ", get_blocks( start_offset = " << (arg.current_blockchain_height - 1) << " ) failed"
<< ", dropping connection"
);
m_p2p->drop_connection(context);
return 1;
}
NOTIFY_NEW_FLUFFY_BLOCK::request fluffy_response;
fluffy_response.b = arg.b;
fluffy_response.current_blockchain_height = m_core.get_current_blockchain_height();
fluffy_response.hop = arg.hop;
size_t local_txs_count = local_txs.size();
BOOST_FOREACH(auto& tx_idx, arg.missing_tx_indices)
{
if(tx_idx < local_txs_count)
{
fluffy_response.b.txs.push_back(t_serializable_object_to_blob( *(std::next(local_txs.begin(), tx_idx)) ));
}
else
{
LOG_ERROR_CCONTEXT
(
"Failed to handle request NOTIFY_REQUEST_FLUFFY_MISSING_TX"
<< ", request is asking for a tx whose index is out of bounds "
<< ", tx index = " << tx_idx << ", block_height = " << arg.current_blockchain_height
<< ", dropping connection"
);
m_p2p->drop_connection(context);
return 1;
}
}
LOG_PRINT_CCONTEXT_L2
(
"-->>NOTIFY_RESPONSE_FLUFFY_MISSING_TX: "
<< ", txs.size()=" << fluffy_response.b.txs.size()
<< ", rsp.current_blockchain_height=" << fluffy_response.current_blockchain_height
);
post_notify<NOTIFY_NEW_FLUFFY_BLOCK>(fluffy_response, context);
return 1;
}
//------------------------------------------------------------------------------------------------------------------------
template<class t_core>
int t_cryptonote_protocol_handler<t_core>::handle_notify_new_transactions(int command, NOTIFY_NEW_TRANSACTIONS::request& arg, cryptonote_connection_context& context)
{
LOG_PRINT_CCONTEXT_L2("NOTIFY_NEW_TRANSACTIONS");
@@ -484,6 +794,11 @@ namespace cryptonote
size_t count = 0;
BOOST_FOREACH(const block_complete_entry& block_entry, arg.blocks)
{
if (m_stopping)
{
return 1;
}
++count;
block b;
if(!parse_and_validate_block_from_blob(block_entry.block, b))
@@ -548,6 +863,12 @@ namespace cryptonote
m_core.prepare_handle_incoming_blocks(arg.blocks);
BOOST_FOREACH(const block_complete_entry& block_entry, arg.blocks)
{
if (m_stopping)
{
m_core.cleanup_handle_incoming_blocks();
return 1;
}
// process transactions
TIME_MEASURE_START(transactions_process_time);
BOOST_FOREACH(auto& tx_blob, block_entry.txs)
@@ -624,6 +945,7 @@ namespace cryptonote
if(!m_core.find_blockchain_supplement(arg.block_ids, r))
{
LOG_ERROR_CCONTEXT("Failed to handle NOTIFY_REQUEST_CHAIN.");
m_p2p->drop_connection(context);
return 1;
}
LOG_PRINT_CCONTEXT_L2("-->>NOTIFY_RESPONSE_CHAIN_ENTRY: m_start_height=" << r.start_height << ", m_total_height=" << r.total_height << ", m_block_ids.size()=" << r.m_block_ids.size());
@@ -650,9 +972,9 @@ namespace cryptonote
size_t count = 0;
auto it = context.m_needed_objects.begin();
size_t count_limit = BLOCKS_SYNCHRONIZING_DEFAULT_COUNT;
const size_t count_limit = m_core.get_block_sync_size();
_note_c("net/req-calc" , "Setting count_limit: " << count_limit);
while(it != context.m_needed_objects.end() && count < BLOCKS_SYNCHRONIZING_DEFAULT_COUNT)
while(it != context.m_needed_objects.end() && count < count_limit)
{
if( !(check_having_blocks && m_core.have_block(*it)))
{
@@ -776,12 +1098,51 @@ namespace cryptonote
template<class t_core>
bool t_cryptonote_protocol_handler<t_core>::relay_block(NOTIFY_NEW_BLOCK::request& arg, cryptonote_connection_context& exclude_context)
{
return relay_post_notify<NOTIFY_NEW_BLOCK>(arg, exclude_context);
NOTIFY_NEW_FLUFFY_BLOCK::request fluffy_arg = AUTO_VAL_INIT(fluffy_arg);
fluffy_arg.hop = arg.hop;
fluffy_arg.current_blockchain_height = arg.current_blockchain_height;
std::list<blobdata> fluffy_txs;
fluffy_arg.b = arg.b;
fluffy_arg.b.txs = fluffy_txs;
// pre-serialize them
std::string fullBlob, fluffyBlob;
epee::serialization::store_t_to_binary(arg, fullBlob);
epee::serialization::store_t_to_binary(fluffy_arg, fluffyBlob);
// sort peers between fluffy ones and others
std::list<boost::uuids::uuid> fullConnections, fluffyConnections;
m_p2p->for_each_connection([this, &arg, &fluffy_arg, &exclude_context, &fullConnections, &fluffyConnections](connection_context& context, nodetool::peerid_type peer_id, uint32_t support_flags)
{
if (peer_id && exclude_context.m_connection_id != context.m_connection_id)
{
if(m_core.get_testnet() && (support_flags & P2P_SUPPORT_FLAG_FLUFFY_BLOCKS))
{
LOG_PRINT_CCONTEXT_YELLOW("PEER SUPPORTS FLUFFY BLOCKS - RELAYING THIN/COMPACT WHATEVER BLOCK", LOG_LEVEL_1);
fluffyConnections.push_back(context.m_connection_id);
}
else
{
LOG_PRINT_CCONTEXT_YELLOW("PEER DOESN'T SUPPORT FLUFFY BLOCKS - RELAYING FULL BLOCK", LOG_LEVEL_1);
fullConnections.push_back(context.m_connection_id);
}
}
return true;
});
// send fluffy ones first, we want to encourage people to run that
m_p2p->relay_notify_to_list(NOTIFY_NEW_FLUFFY_BLOCK::ID, fluffyBlob, fluffyConnections);
m_p2p->relay_notify_to_list(NOTIFY_NEW_BLOCK::ID, fullBlob, fullConnections);
return 1;
}
//------------------------------------------------------------------------------------------------------------------------
template<class t_core>
bool t_cryptonote_protocol_handler<t_core>::relay_transactions(NOTIFY_NEW_TRANSACTIONS::request& arg, cryptonote_connection_context& exclude_context)
{
// no check for success, so tell core they're relayed unconditionally
for(auto tx_blob_it = arg.txs.begin(); tx_blob_it!=arg.txs.end(); ++tx_blob_it)
m_core.on_transaction_relayed(*tx_blob_it);
return relay_post_notify<NOTIFY_NEW_TRANSACTIONS>(arg, exclude_context);
}
@@ -797,5 +1158,11 @@ namespace cryptonote
(*logreq) << "log used" << std::endl;
return *logreq;
}
//------------------------------------------------------------------------------------------------------------------------
template<class t_core>
void t_cryptonote_protocol_handler<t_core>::stop()
{
m_stopping = true;
m_core.stop();
}
} // namespace

View File

@@ -74,9 +74,9 @@ set(daemon_private_headers
../p2p/p2p_protocol_defs.h
../p2p/stdafx.h)
bitmonero_private_headers(daemon
monero_private_headers(daemon
${daemon_private_headers})
bitmonero_add_executable(daemon
monero_add_executable(daemon
${daemon_sources}
${daemon_headers}
${daemon_private_headers}

View File

@@ -222,6 +222,13 @@ bool t_command_parser_executor::print_transaction_pool_short(const std::vector<s
return m_executor.print_transaction_pool_short();
}
bool t_command_parser_executor::print_transaction_pool_stats(const std::vector<std::string>& args)
{
if (!args.empty()) return false;
return m_executor.print_transaction_pool_stats();
}
bool t_command_parser_executor::start_mining(const std::vector<std::string>& args)
{
if(!args.size())
@@ -336,12 +343,6 @@ bool t_command_parser_executor::set_limit_down(const std::vector<std::string>& a
return m_executor.set_limit_down(limit);
}
bool t_command_parser_executor::fast_exit(const std::vector<std::string>& args)
{
if (!args.empty()) return false;
return m_executor.fast_exit();
}
bool t_command_parser_executor::out_peers(const std::vector<std::string>& args)
{
if (args.empty()) return false;
@@ -458,5 +459,27 @@ bool t_command_parser_executor::output_histogram(const std::vector<std::string>&
return m_executor.output_histogram(min_count, max_count);
}
bool t_command_parser_executor::print_coinbase_tx_sum(const std::vector<std::string>& args)
{
if(!args.size())
{
std::cout << "need block height parameter" << std::endl;
return false;
}
uint64_t height = 0;
uint64_t count = 0;
if(!epee::string_tools::get_xtype_from_string(height, args[0]))
{
std::cout << "wrong starter block height parameter" << std::endl;
return false;
}
if(args.size() >1 && !epee::string_tools::get_xtype_from_string(count, args[1]))
{
std::cout << "wrong count parameter" << std::endl;
return false;
}
return m_executor.print_coinbase_tx_sum(height, count);
}
} // namespace daemonize

View File

@@ -84,6 +84,8 @@ public:
bool print_transaction_pool_short(const std::vector<std::string>& args);
bool print_transaction_pool_stats(const std::vector<std::string>& args);
bool start_mining(const std::vector<std::string>& args);
bool stop_mining(const std::vector<std::string>& args);
@@ -98,8 +100,6 @@ public:
bool set_limit_down(const std::vector<std::string>& args);
bool fast_exit(const std::vector<std::string>& args);
bool out_peers(const std::vector<std::string>& args);
bool start_save_graph(const std::vector<std::string>& args);
@@ -117,6 +117,8 @@ public:
bool flush_txpool(const std::vector<std::string>& args);
bool output_histogram(const std::vector<std::string>& args);
bool print_coinbase_tx_sum(const std::vector<std::string>& args);
};
} // namespace daemonize

View File

@@ -110,6 +110,11 @@ t_command_server::t_command_server(
, std::bind(&t_command_parser_executor::print_transaction_pool_short, &m_parser, p::_1)
, "Print transaction pool (short format)"
);
m_command_lookup.set_handler(
"print_pool_stats"
, std::bind(&t_command_parser_executor::print_transaction_pool_stats, &m_parser, p::_1)
, "Print transaction pool statistics"
);
m_command_lookup.set_handler(
"show_hr"
, std::bind(&t_command_parser_executor::show_hash_rate, &m_parser, p::_1)
@@ -170,11 +175,6 @@ t_command_server::t_command_server(
, std::bind(&t_command_parser_executor::set_limit_down, &m_parser, p::_1)
, "limit <kB/s> - Set download limit"
);
m_command_lookup.set_handler(
"fast_exit"
, std::bind(&t_command_parser_executor::fast_exit, &m_parser, p::_1)
, "Exit"
);
m_command_lookup.set_handler(
"out_peers"
, std::bind(&t_command_parser_executor::out_peers, &m_parser, p::_1)
@@ -220,6 +220,11 @@ t_command_server::t_command_server(
, std::bind(&t_command_parser_executor::output_histogram, &m_parser, p::_1)
, "Print output histogram (amount, instances)"
);
m_command_lookup.set_handler(
"print_coinbase_tx_sum"
, std::bind(&t_command_parser_executor::print_coinbase_tx_sum, &m_parser, p::_1)
, "Print sum of coinbase transactions (start height, block count)"
);
}
bool t_command_server::process_command_str(const std::string& cmd)

View File

@@ -56,7 +56,7 @@ namespace daemonize
boost::program_options::variables_map const & vm
)
{
LOG_PRINT_L0("Monero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL);
LOG_PRINT_L0("Monero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ") Daemonised");
return t_daemon{vm};
}

View File

@@ -69,12 +69,13 @@ public:
~t_protocol()
{
LOG_PRINT_L0("Deinitializing cryptonote_protocol...");
LOG_PRINT_L0("Stopping cryptonote protocol...");
try {
m_protocol.deinit();
m_protocol.set_p2p_endpoint(nullptr);
LOG_PRINT_L0("Cryptonote protocol stopped successfully");
} catch (...) {
LOG_PRINT_L0("Failed to deinitialize protocol...");
LOG_ERROR("Failed to stop cryptonote protocol!");
}
}
};

View File

@@ -57,7 +57,7 @@ namespace {
tools::msg_writer() << boost::format("%-10s %-25s %-25s %s") % prefix % id_str % addr_str % elapsed;
}
void print_block_header(cryptonote::block_header_responce const & header)
void print_block_header(cryptonote::block_header_response const & header)
{
tools::success_msg_writer()
<< "timestamp: " << boost::lexical_cast<std::string>(header.timestamp) << std::endl
@@ -296,6 +296,16 @@ static std::string get_fork_extra_info(uint64_t t, uint64_t now, uint64_t block_
return "";
}
static float get_sync_percentage(const cryptonote::COMMAND_RPC_GET_INFO::response &ires)
{
uint64_t height = ires.height;
uint64_t target_height = ires.target_height ? ires.target_height < ires.height ? ires.height : ires.target_height : ires.height;
float pc = 100.0f * height / target_height;
if (height < target_height && pc > 99.9f)
return 99.9f; // to avoid 100% when not fully synced
return pc;
}
bool t_rpc_command_executor::show_status() {
cryptonote::COMMAND_RPC_GET_INFO::request ireq;
cryptonote::COMMAND_RPC_GET_INFO::response ires;
@@ -356,7 +366,7 @@ bool t_rpc_command_executor::show_status() {
tools::success_msg_writer() << boost::format("Height: %llu/%llu (%.1f%%) on %s, %s, net hash %s, v%u%s, %s, %u+%u connections")
% (unsigned long long)ires.height
% (unsigned long long)(ires.target_height >= ires.height ? ires.target_height : ires.height)
% (100.0f * ires.height / (ires.target_height ? ires.target_height < ires.height ? ires.height : ires.target_height : ires.height))
% get_sync_percentage(ires)
% (ires.testnet ? "testnet" : "mainnet")
% (mining_busy ? "syncing" : mres.active ? "mining at " + get_mining_speed(mres.speed) : "not mining")
% get_mining_speed(ires.difficulty / ires.target)
@@ -394,6 +404,7 @@ bool t_rpc_command_executor::print_connections() {
tools::msg_writer() << std::setw(30) << std::left << "Remote Host"
<< std::setw(20) << "Peer id"
<< std::setw(20) << "Support Flags"
<< std::setw(30) << "Recv/Sent (inactive,sec)"
<< std::setw(25) << "State"
<< std::setw(20) << "Livetime(sec)"
@@ -412,6 +423,7 @@ bool t_rpc_command_executor::print_connections() {
//<< std::setw(30) << std::left << in_out
<< std::setw(30) << std::left << address
<< std::setw(20) << info.peer_id
<< std::setw(20) << info.support_flags
<< std::setw(30) << std::to_string(info.recv_count) + "(" + std::to_string(info.recv_idle_time) + ")/" + std::to_string(info.send_count) + "(" + std::to_string(info.send_idle_time) + ")"
<< std::setw(25) << info.state
<< std::setw(20) << info.live_time
@@ -430,11 +442,6 @@ bool t_rpc_command_executor::print_connections() {
}
bool t_rpc_command_executor::print_blockchain_info(uint64_t start_block_index, uint64_t end_block_index) {
// this function appears to not exist in the json rpc api, and so is commented
// until such a time as it does.
/*
cryptonote::COMMAND_RPC_GET_BLOCK_HEADERS_RANGE::request req;
cryptonote::COMMAND_RPC_GET_BLOCK_HEADERS_RANGE::response res;
epee::json_rpc::error error_resp;
@@ -453,25 +460,26 @@ bool t_rpc_command_executor::print_blockchain_info(uint64_t start_block_index, u
}
else
{
if (!m_rpc_server->on_getblockheadersrange(req, res, error_resp) || res.status != CORE_RPC_STATUS_OK)
if (!m_rpc_server->on_get_block_headers_range(req, res, error_resp) || res.status != CORE_RPC_STATUS_OK)
{
tools::fail_msg_writer() << fail_message.c_str();
return true;
}
}
bool first = true;
for (auto & header : res.headers)
{
if (!first)
std::cout << std::endl;
std::cout
<< "major version: " << header.major_version << std::endl
<< "minor version: " << header.minor_version << std::endl
<< "major version: " << (unsigned)header.major_version << ", minor version: " << (unsigned)header.minor_version << std::endl
<< "height: " << header.height << ", timestamp: " << header.timestamp << ", difficulty: " << header.difficulty << std::endl
<< "block id: " << header.hash << std::endl
<< "previous block id: " << header.prev_hash << std::endl
<< "difficulty: " << header.difficulty << ", nonce " << header.nonce << std::endl;
<< "block id: " << header.hash << ", previous block id: " << header.prev_hash << std::endl
<< "difficulty: " << header.difficulty << ", nonce " << header.nonce << ", reward " << cryptonote::print_money(header.reward) << std::endl;
first = false;
}
*/
return true;
}
@@ -728,6 +736,7 @@ bool t_rpc_command_executor::print_transaction_pool_long() {
<< "blob_size: " << tx_info.blob_size << std::endl
<< "fee: " << cryptonote::print_money(tx_info.fee) << std::endl
<< "receive_time: " << tx_info.receive_time << " (" << get_human_time_ago(tx_info.receive_time, now) << ")" << std::endl
<< "relayed: " << [&](const cryptonote::tx_info &tx_info)->std::string { if (!tx_info.relayed) return "no"; return boost::lexical_cast<std::string>(tx_info.last_relayed_time) + " (" + get_human_time_ago(tx_info.last_relayed_time, now) + ")"; } (tx_info) << std::endl
<< "kept_by_block: " << (tx_info.kept_by_block ? 'T' : 'F') << std::endl
<< "max_used_block_height: " << tx_info.max_used_block_height << std::endl
<< "max_used_block_id: " << tx_info.max_used_block_id_hash << std::endl
@@ -807,6 +816,7 @@ bool t_rpc_command_executor::print_transaction_pool_short() {
<< "blob_size: " << tx_info.blob_size << std::endl
<< "fee: " << cryptonote::print_money(tx_info.fee) << std::endl
<< "receive_time: " << tx_info.receive_time << " (" << get_human_time_ago(tx_info.receive_time, now) << ")" << std::endl
<< "relayed: " << [&](const cryptonote::tx_info &tx_info)->std::string { if (!tx_info.relayed) return "no"; return boost::lexical_cast<std::string>(tx_info.last_relayed_time) + " (" + get_human_time_ago(tx_info.last_relayed_time, now) + ")"; } (tx_info) << std::endl
<< "kept_by_block: " << (tx_info.kept_by_block ? 'T' : 'F') << std::endl
<< "max_used_block_height: " << tx_info.max_used_block_height << std::endl
<< "max_used_block_id: " << tx_info.max_used_block_id_hash << std::endl
@@ -818,6 +828,62 @@ bool t_rpc_command_executor::print_transaction_pool_short() {
return true;
}
bool t_rpc_command_executor::print_transaction_pool_stats() {
cryptonote::COMMAND_RPC_GET_TRANSACTION_POOL::request req;
cryptonote::COMMAND_RPC_GET_TRANSACTION_POOL::response res;
std::string fail_message = "Problem fetching transaction pool";
if (m_is_rpc)
{
if (!m_rpc_client->rpc_request(req, res, "/get_transaction_pool", fail_message.c_str()))
{
return true;
}
}
else
{
if (!m_rpc_server->on_get_transaction_pool(req, res) || res.status != CORE_RPC_STATUS_OK)
{
tools::fail_msg_writer() << fail_message.c_str();
return true;
}
}
size_t n_transactions = res.transactions.size();
size_t bytes = 0, min_bytes = 0, max_bytes = 0;
size_t n_not_relayed = 0;
uint64_t fee = 0;
uint64_t oldest = 0;
size_t n_10m = 0;
size_t n_failing = 0;
const uint64_t now = time(NULL);
for (const auto &tx_info: res.transactions)
{
bytes += tx_info.blob_size;
if (min_bytes == 0 || tx_info.blob_size < min_bytes)
min_bytes = tx_info.blob_size;
if (tx_info.blob_size > max_bytes)
max_bytes = tx_info.blob_size;
if (!tx_info.relayed)
n_not_relayed++;
fee += tx_info.fee;
if (oldest == 0 || tx_info.receive_time < oldest)
oldest = tx_info.receive_time;
if (tx_info.receive_time < now - 600)
n_10m++;
if (tx_info.last_failed_height)
++n_failing;
}
size_t avg_bytes = n_transactions ? bytes / n_transactions : 0;
tools::msg_writer() << n_transactions << " tx(es), " << bytes << " bytes total (min " << min_bytes << ", max " << max_bytes << ", avg " << avg_bytes << ")" << std::endl
<< "fees " << cryptonote::print_money(fee) << " (avg " << cryptonote::print_money(n_transactions ? fee / n_transactions : 0) << " per tx)" << std::endl
<< n_not_relayed << " not relayed, " << n_failing << " failing, " << n_10m << " older than 10 minutes (oldest " << (oldest == 0 ? "-" : get_human_time_ago(oldest, now)) << ")" << std::endl;
return true;
}
bool t_rpc_command_executor::start_mining(cryptonote::account_public_address address, uint64_t num_threads, bool testnet) {
cryptonote::COMMAND_RPC_START_MINING::request req;
cryptonote::COMMAND_RPC_START_MINING::response res;
@@ -979,34 +1045,6 @@ bool t_rpc_command_executor::set_limit_down(int limit)
return true;
}
bool t_rpc_command_executor::fast_exit()
{
cryptonote::COMMAND_RPC_FAST_EXIT::request req;
cryptonote::COMMAND_RPC_FAST_EXIT::response res;
std::string fail_message = "Daemon did not stop";
if (m_is_rpc)
{
if (!m_rpc_client->rpc_request(req, res, "/fast_exit", fail_message.c_str()))
{
return true;
}
}
else
{
if (!m_rpc_server->on_fast_exit(req, res) || res.status != CORE_RPC_STATUS_OK)
{
tools::fail_msg_writer() << fail_message.c_str();
return true;
}
}
tools::success_msg_writer() << "Daemon stopped";
return true;
}
bool t_rpc_command_executor::out_peers(uint64_t limit)
{
cryptonote::COMMAND_RPC_OUT_PEERS::request req;
@@ -1265,6 +1303,8 @@ bool t_rpc_command_executor::output_histogram(uint64_t min_count, uint64_t max_c
req.min_count = min_count;
req.max_count = max_count;
req.unlocked = false;
req.recent_cutoff = 0;
if (m_is_rpc)
{
@@ -1283,14 +1323,49 @@ bool t_rpc_command_executor::output_histogram(uint64_t min_count, uint64_t max_c
}
std::sort(res.histogram.begin(), res.histogram.end(),
[](const cryptonote::COMMAND_RPC_GET_OUTPUT_HISTOGRAM::entry &e1, const cryptonote::COMMAND_RPC_GET_OUTPUT_HISTOGRAM::entry &e2)->bool { return e1.instances < e2.instances; });
[](const cryptonote::COMMAND_RPC_GET_OUTPUT_HISTOGRAM::entry &e1, const cryptonote::COMMAND_RPC_GET_OUTPUT_HISTOGRAM::entry &e2)->bool { return e1.total_instances < e2.total_instances; });
for (const auto &e: res.histogram)
{
tools::msg_writer() << e.instances << " " << cryptonote::print_money(e.amount);
tools::msg_writer() << e.total_instances << " " << cryptonote::print_money(e.amount);
}
return true;
}
bool t_rpc_command_executor::print_coinbase_tx_sum(uint64_t height, uint64_t count)
{
cryptonote::COMMAND_RPC_GET_COINBASE_TX_SUM::request req;
cryptonote::COMMAND_RPC_GET_COINBASE_TX_SUM::response res;
epee::json_rpc::error error_resp;
req.height = height;
req.count = count;
std::string fail_message = "Unsuccessful";
if (m_is_rpc)
{
if (!m_rpc_client->json_rpc_request(req, res, "get_coinbase_tx_sum", fail_message.c_str()))
{
return true;
}
}
else
{
if (!m_rpc_server->on_get_coinbase_tx_sum(req, res, error_resp))
{
tools::fail_msg_writer() << fail_message.c_str();
return true;
}
}
tools::msg_writer() << "Sum of coinbase transactions between block heights ["
<< height << ", " << (height + count) << ") is "
<< cryptonote::print_money(res.emission_amount + res.fee_amount) << " "
<< "consisting of " << cryptonote::print_money(res.emission_amount)
<< " in emissions, and " << cryptonote::print_money(res.fee_amount) << " in fees";
return true;
}
}// namespace daemonize

View File

@@ -96,6 +96,8 @@ public:
bool print_transaction_pool_short();
bool print_transaction_pool_stats();
bool start_mining(cryptonote::account_public_address address, uint64_t num_threads, bool testnet);
bool stop_mining();
@@ -116,8 +118,6 @@ public:
bool set_limit_down(int limit);
bool fast_exit();
bool out_peers(uint64_t limit);
bool start_save_graph();
@@ -135,6 +135,8 @@ public:
bool flush_txpool(const std::string &txid);
bool output_histogram(uint64_t min_count, uint64_t max_count);
bool print_coinbase_tx_sum(uint64_t height, uint64_t count);
};
} // namespace daemonize

View File

@@ -54,9 +54,9 @@ else()
)
endif()
bitmonero_private_headers(daemonizer
monero_private_headers(daemonizer
${daemonizer_private_headers})
bitmonero_add_library(daemonizer
monero_add_library(daemonizer
${daemonizer_sources}
${daemonizer_headers}
${daemonizer_private_headers})

View File

@@ -44,9 +44,9 @@ set(mnemonics_private_headers
singleton.h
spanish.h)
bitmonero_private_headers(mnemonics
monero_private_headers(mnemonics
${mnemonics_private_headers})
bitmonero_add_library(mnemonics
monero_add_library(mnemonics
${mnemonics_sources}
${mnemonics_headers}
${mnemonics_private_headers})

View File

@@ -106,6 +106,12 @@ namespace Language
trimmed_word_map = new std::unordered_map<std::string, uint32_t>;
unique_prefix_length = 4;
}
virtual ~Base()
{
delete word_list;
delete word_map;
delete trimmed_word_map;
}
/*!
* \brief Returns a pointer to the word list.
* \return A pointer to the word list.

View File

@@ -27,15 +27,15 @@
# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
cmake_minimum_required (VERSION 2.6)
project (bitmonero CXX)
project (monero CXX)
file(GLOB P2P *)
source_group(p2p FILES ${P2P})
#add_library(p2p ${P2P})
#bitmonero_private_headers(p2p ${P2P})
bitmonero_add_library(p2p ${P2P})
#monero_private_headers(p2p ${P2P})
monero_add_library(p2p ${P2P})
target_link_libraries(p2p
PUBLIC
${UPNP_LIBRARIES}

View File

@@ -63,6 +63,7 @@ namespace nodetool
struct p2p_connection_context_t: base_type //t_payload_net_handler::connection_context //public net_utils::connection_context_base
{
peerid_type peer_id;
uint32_t support_flags;
};
template<class t_payload_net_handler>
@@ -146,6 +147,7 @@ namespace nodetool
HANDLE_INVOKE_T2(COMMAND_REQUEST_NETWORK_STATE, &node_server::handle_get_network_state)
HANDLE_INVOKE_T2(COMMAND_REQUEST_PEER_ID, &node_server::handle_get_peer_id)
#endif
HANDLE_INVOKE_T2(COMMAND_REQUEST_SUPPORT_FLAGS, &node_server::handle_get_support_flags)
CHAIN_INVOKE_MAP_TO_OBJ_FORCE_CONTEXT(m_payload_handler, typename t_payload_net_handler::connection_context&)
END_INVOKE_MAP2()
@@ -158,6 +160,7 @@ namespace nodetool
int handle_get_network_state(int command, COMMAND_REQUEST_NETWORK_STATE::request& arg, COMMAND_REQUEST_NETWORK_STATE::response& rsp, p2p_connection_context& context);
int handle_get_peer_id(int command, COMMAND_REQUEST_PEER_ID::request& arg, COMMAND_REQUEST_PEER_ID::response& rsp, p2p_connection_context& context);
#endif
int handle_get_support_flags(int command, COMMAND_REQUEST_SUPPORT_FLAGS::request& arg, COMMAND_REQUEST_SUPPORT_FLAGS::response& rsp, p2p_connection_context& context);
bool init_config();
bool make_default_config();
bool store_config();
@@ -169,12 +172,13 @@ namespace nodetool
virtual void on_connection_close(p2p_connection_context& context);
virtual void callback(p2p_connection_context& context);
//----------------- i_p2p_endpoint -------------------------------------------------------------
virtual bool relay_notify_to_list(int command, const std::string& data_buff, const std::list<boost::uuids::uuid> &connections);
virtual bool relay_notify_to_all(int command, const std::string& data_buff, const epee::net_utils::connection_context_base& context);
virtual bool invoke_command_to_peer(int command, const std::string& req_buff, std::string& resp_buff, const epee::net_utils::connection_context_base& context);
virtual bool invoke_notify_to_peer(int command, const std::string& req_buff, const epee::net_utils::connection_context_base& context);
virtual bool drop_connection(const epee::net_utils::connection_context_base& context);
virtual void request_callback(const epee::net_utils::connection_context_base& context);
virtual void for_each_connection(std::function<bool(typename t_payload_net_handler::connection_context&, peerid_type)> f);
virtual void for_each_connection(std::function<bool(typename t_payload_net_handler::connection_context&, peerid_type, uint32_t)> f);
virtual bool add_ip_fail(uint32_t address);
//----------------- i_connection_filter --------------------------------------------------------
virtual bool is_remote_ip_allowed(uint32_t adress);
@@ -204,6 +208,7 @@ namespace nodetool
bool is_addr_connected(const net_address& peer);
template<class t_callback>
bool try_ping(basic_node_data& node_data, p2p_connection_context& context, t_callback cb);
bool try_get_support_flags(const p2p_connection_context& context, std::function<void(p2p_connection_context&, const uint32_t&)> f);
bool make_expected_connections_count(bool white_list, size_t expected_connections);
void cache_connect_fail_info(const net_address& addr);
bool is_addr_recently_failed(const net_address& addr);
@@ -240,10 +245,12 @@ namespace nodetool
{
network_config m_net_config;
uint64_t m_peer_id;
uint32_t m_support_flags;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(m_net_config)
KV_SERIALIZE(m_peer_id)
KV_SERIALIZE(m_support_flags)
END_KV_SERIALIZE_MAP()
};

View File

@@ -158,6 +158,7 @@ namespace nodetool
m_config.m_net_config.connection_timeout = P2P_DEFAULT_CONNECTION_TIMEOUT;
m_config.m_net_config.ping_connection_timeout = P2P_DEFAULT_PING_CONNECTION_TIMEOUT;
m_config.m_net_config.send_peerlist_sz = P2P_DEFAULT_PEERS_IN_HANDSHAKE;
m_config.m_support_flags = P2P_SUPPORT_FLAGS;
m_first_connection_maker_call = true;
CATCH_ENTRY_L0("node_server::init_config", false);
@@ -165,10 +166,10 @@ namespace nodetool
}
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
void node_server<t_payload_net_handler>::for_each_connection(std::function<bool(typename t_payload_net_handler::connection_context&, peerid_type)> f)
void node_server<t_payload_net_handler>::for_each_connection(std::function<bool(typename t_payload_net_handler::connection_context&, peerid_type, uint32_t)> f)
{
m_net_server.get_config_object().foreach_connection([&](p2p_connection_context& cntx){
return f(cntx, cntx.peer_id);
return f(cntx, cntx.peer_id, cntx.support_flags);
});
}
//-----------------------------------------------------------------------------------
@@ -200,6 +201,20 @@ namespace nodetool
{
CRITICAL_REGION_LOCAL(m_blocked_ips_lock);
m_blocked_ips[addr] = time(nullptr) + seconds;
// drop any connection to that IP
std::list<boost::uuids::uuid> conns;
m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt)
{
if (cntxt.m_remote_ip == addr)
{
conns.push_back(cntxt.m_connection_id);
}
return true;
});
for (const auto &c: conns)
m_net_server.get_config_object().close(c);
LOG_PRINT_CYAN("IP " << epee::string_tools::get_ip_string_from_int32(addr) << " blocked.", LOG_LEVEL_0);
return true;
}
@@ -326,7 +341,7 @@ namespace nodetool
io_service io_srv;
ip::tcp::resolver resolver(io_srv);
ip::tcp::resolver::query query(host, port);
ip::tcp::resolver::query query(host, port, boost::asio::ip::tcp::resolver::query::canonical_name);
boost::system::error_code ec;
ip::tcp::resolver::iterator i = resolver.resolve(query, ec);
CHECK_AND_ASSERT_MES_NO_RET(!ec, "Failed to resolve host name '" << host << "': " << ec.message() << ':' << ec.value());
@@ -528,7 +543,7 @@ namespace nodetool
} else if (result == 2) {
LOG_PRINT_L0("IGD was found but reported as not connected.");
} else if (result == 3) {
LOG_PRINT_L0("UPnP device was found but not recoginzed as IGD.");
LOG_PRINT_L0("UPnP device was found but not recognized as IGD.");
} else {
LOG_ERROR("UPNP_GetValidIGD returned an unknown result code.");
}
@@ -641,6 +656,7 @@ namespace nodetool
template<class t_payload_net_handler>
bool node_server<t_payload_net_handler>::send_stop_signal()
{
m_payload_handler.stop();
m_net_server.send_stop_signal();
LOG_PRINT_L0("[node] Stop signal sent");
return true;
@@ -718,6 +734,13 @@ namespace nodetool
LOG_PRINT_CC_L1(context_, "COMMAND_HANDSHAKE Failed");
m_net_server.get_config_object().close(context_.m_connection_id);
}
else
{
try_get_support_flags(context_, [](p2p_connection_context& flags_context, const uint32_t& support_flags)
{
flags_context.support_flags = support_flags;
});
}
return hsh_result;
}
@@ -1207,6 +1230,13 @@ namespace nodetool
return 1;
}
#endif
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
int node_server<t_payload_net_handler>::handle_get_support_flags(int command, COMMAND_REQUEST_SUPPORT_FLAGS::request& arg, COMMAND_REQUEST_SUPPORT_FLAGS::response& rsp, p2p_connection_context& context)
{
rsp.support_flags = m_config.m_support_flags;
return 1;
}
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
void node_server<t_payload_net_handler>::request_callback(const epee::net_utils::connection_context_base& context)
@@ -1215,6 +1245,16 @@ namespace nodetool
}
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
bool node_server<t_payload_net_handler>::relay_notify_to_list(int command, const std::string& data_buff, const std::list<boost::uuids::uuid> &connections)
{
BOOST_FOREACH(const auto& c_id, connections)
{
m_net_server.get_config_object().notify(command, data_buff, c_id);
}
return true;
}
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
bool node_server<t_payload_net_handler>::relay_notify_to_all(int command, const std::string& data_buff, const epee::net_utils::connection_context_base& context)
{
std::list<boost::uuids::uuid> connections;
@@ -1224,12 +1264,7 @@ namespace nodetool
connections.push_back(cntxt.m_connection_id);
return true;
});
BOOST_FOREACH(const auto& c_id, connections)
{
m_net_server.get_config_object().notify(command, data_buff, c_id);
}
return true;
return relay_notify_to_list(command, data_buff, connections);
}
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
@@ -1326,6 +1361,32 @@ namespace nodetool
}
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
bool node_server<t_payload_net_handler>::try_get_support_flags(const p2p_connection_context& context, std::function<void(p2p_connection_context&, const uint32_t&)> f)
{
COMMAND_REQUEST_SUPPORT_FLAGS::request support_flags_request;
bool r = epee::net_utils::async_invoke_remote_command2<typename COMMAND_REQUEST_SUPPORT_FLAGS::response>
(
context.m_connection_id,
COMMAND_REQUEST_SUPPORT_FLAGS::ID,
support_flags_request,
m_net_server.get_config_object(),
[=](int code, const typename COMMAND_REQUEST_SUPPORT_FLAGS::response& rsp, p2p_connection_context& context_)
{
if(code < 0)
{
LOG_PRINT_CC_RED(context_, "COMMAND_REQUEST_SUPPORT_FLAGS invoke failed. (" << code << ", " << epee::levin::get_err_descr(code) << ")", LOG_LEVEL_1);
return;
}
f(context_, rsp.support_flags);
},
P2P_DEFAULT_HANDSHAKE_INVOKE_TIMEOUT
);
return r;
}
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
int node_server<t_payload_net_handler>::handle_timed_sync(int command, typename COMMAND_TIMED_SYNC::request& arg, typename COMMAND_TIMED_SYNC::response& rsp, p2p_connection_context& context)
{
if(!m_payload_handler.process_payload_sync_data(arg.payload_data, context, false))
@@ -1382,7 +1443,7 @@ namespace nodetool
if(arg.node_data.peer_id != m_config.m_peer_id && arg.node_data.my_port)
{
peerid_type peer_id_l = arg.node_data.peer_id;
uint32_t port_l = arg.node_data.my_port;
uint32_t port_l = arg.node_data.my_port;
//try ping to be sure that we can add this peer to peer_list
try_ping(arg.node_data, context, [peer_id_l, port_l, context, this]()
{
@@ -1398,6 +1459,11 @@ namespace nodetool
LOG_PRINT_CCONTEXT_L2("PING SUCCESS " << epee::string_tools::get_ip_string_from_int32(context.m_remote_ip) << ":" << port_l);
});
}
try_get_support_flags(context, [](p2p_connection_context& flags_context, const uint32_t& support_flags)
{
flags_context.support_flags = support_flags;
});
//fill response
m_peerlist.get_peerlist_head(rsp.local_peerlist);
@@ -1419,10 +1485,10 @@ namespace nodetool
template<class t_payload_net_handler>
bool node_server<t_payload_net_handler>::log_peerlist()
{
std::list<peerlist_entry> pl_wite;
std::list<peerlist_entry> pl_white;
std::list<peerlist_entry> pl_gray;
m_peerlist.get_peerlist_full(pl_gray, pl_wite);
LOG_PRINT_L0(ENDL << "Peerlist white:" << ENDL << print_peerlist_to_string(pl_wite) << ENDL << "Peerlist gray:" << ENDL << print_peerlist_to_string(pl_gray) );
m_peerlist.get_peerlist_full(pl_gray, pl_white);
LOG_PRINT_L0(ENDL << "Peerlist white:" << ENDL << print_peerlist_to_string(pl_white) << ENDL << "Peerlist gray:" << ENDL << print_peerlist_to_string(pl_gray) );
return true;
}
//-----------------------------------------------------------------------------------

View File

@@ -43,13 +43,14 @@ namespace nodetool
template<class t_connection_context>
struct i_p2p_endpoint
{
virtual bool relay_notify_to_list(int command, const std::string& data_buff, const std::list<boost::uuids::uuid>& connections)=0;
virtual bool relay_notify_to_all(int command, const std::string& data_buff, const epee::net_utils::connection_context_base& context)=0;
virtual bool invoke_command_to_peer(int command, const std::string& req_buff, std::string& resp_buff, const epee::net_utils::connection_context_base& context)=0;
virtual bool invoke_notify_to_peer(int command, const std::string& req_buff, const epee::net_utils::connection_context_base& context)=0;
virtual bool drop_connection(const epee::net_utils::connection_context_base& context)=0;
virtual void request_callback(const epee::net_utils::connection_context_base& context)=0;
virtual uint64_t get_connections_count()=0;
virtual void for_each_connection(std::function<bool(t_connection_context&, peerid_type)> f)=0;
virtual void for_each_connection(std::function<bool(t_connection_context&, peerid_type, uint32_t)> f)=0;
virtual bool block_ip(uint32_t adress, time_t seconds = 0)=0;
virtual bool unblock_ip(uint32_t adress)=0;
virtual std::map<uint32_t, time_t> get_blocked_ips()=0;
@@ -59,6 +60,10 @@ namespace nodetool
template<class t_connection_context>
struct p2p_endpoint_stub: public i_p2p_endpoint<t_connection_context>
{
virtual bool relay_notify_to_list(int command, const std::string& data_buff, const std::list<boost::uuids::uuid>& connections)
{
return false;
}
virtual bool relay_notify_to_all(int command, const std::string& data_buff, const epee::net_utils::connection_context_base& context)
{
return false;
@@ -79,7 +84,7 @@ namespace nodetool
{
}
virtual void for_each_connection(std::function<bool(t_connection_context&,peerid_type)> f)
virtual void for_each_connection(std::function<bool(t_connection_context&,peerid_type,uint32_t)> f)
{
}

View File

@@ -332,6 +332,29 @@ namespace nodetool
};
};
/************************************************************************/
/* */
/************************************************************************/
struct COMMAND_REQUEST_SUPPORT_FLAGS
{
const static int ID = P2P_COMMANDS_POOL_BASE + 7;
struct request
{
BEGIN_KV_SERIALIZE_MAP()
END_KV_SERIALIZE_MAP()
};
struct response
{
uint32_t support_flags;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(support_flags)
END_KV_SERIALIZE_MAP()
};
};
#endif

View File

@@ -39,9 +39,9 @@ set(ringct_private_headers
rctSigs.h
rctTypes.h)
bitmonero_private_headers(ringct
monero_private_headers(ringct
${crypto_private_headers})
bitmonero_add_library(ringct
monero_add_library(ringct
${ringct_sources}
${ringct_headers}
${ringct_private_headers})

View File

@@ -37,50 +37,12 @@ namespace rct {
//Various key initialization functions
//Creates a zero scalar
void zero(key &zero) {
memset(&zero, 0, 32);
}
//Creates a zero scalar
key zero() {
static const key z = { {0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 } };
return z;
}
//Creates a zero elliptic curve point
void identity(key &Id) {
Id[0] = (unsigned char)(0x01);
memset(Id.bytes+1, 0, 31);
}
//Creates a zero elliptic curve point
key identity() {
key Id;
Id[0] = (unsigned char)(0x01);
memset(Id.bytes+1, 0, 31);
return Id;
}
//copies a scalar or point
void copy(key &AA, const key &A) {
memcpy(&AA, &A, 32);
}
//copies a scalar or point
key copy(const key &A) {
key AA;
memcpy(&AA, &A, 32);
return AA;
}
//initializes a key matrix;
//first parameter is rows,
//second is columns
keyM keyMInit(int rows, int cols) {
keyM keyMInit(size_t rows, size_t cols) {
keyM rv(cols);
int i = 0;
size_t i = 0;
for (i = 0 ; i < cols ; i++) {
rv[i] = keyV(rows);
}
@@ -107,11 +69,12 @@ namespace rct {
//Generates a vector of secret key
//Mainly used in testing
keyV skvGen(int rows ) {
keyV skvGen(size_t rows ) {
keyV rv(rows);
int i = 0;
size_t i = 0;
crypto::rand(rows * sizeof(key), (uint8_t*)&rv[0]);
for (i = 0 ; i < rows ; i++) {
skGen(rv[i]);
sc_reduce32(rv[i].bytes);
}
return rv;
}
@@ -155,7 +118,7 @@ namespace rct {
//generates a <secret , public> / Pedersen commitment but takes bH as input
tuple<ctkey, ctkey> ctskpkGen(key bH) {
tuple<ctkey, ctkey> ctskpkGen(const key &bH) {
ctkey sk, pk;
skpkGen(sk.dest, pk.dest);
skpkGen(sk.mask, pk.mask);
@@ -172,12 +135,12 @@ namespace rct {
return mask;
}
key commit(xmr_amount amount, key mask) {
mask = scalarmultBase(mask);
key commit(xmr_amount amount, const key &mask) {
key c = scalarmultBase(mask);
key am = d2h(amount);
key bH = scalarmultH(am);
addKeys(mask, mask, bH);
return mask;
addKeys(c, c, bH);
return c;
}
//generates a random uint long long (for testing)
@@ -304,7 +267,7 @@ namespace rct {
ge_p3_tobytes(AB.bytes, &A2);
}
//checks if A, B are equal as curve points
//checks if A, B are equal in terms of bytes (may say no if one is a non-reduced scalar)
//without doing curve operations
bool equalKeys(const key & a, const key & b) {
bool rv = true;
@@ -320,7 +283,7 @@ namespace rct {
//be careful these are also in crypto namespace
//cn_fast_hash for arbitrary multiples of 32 bytes
void cn_fast_hash(key &hash, const void * data, const std::size_t l) {
keccak((uint8_t *)data, l, hash.bytes, 32);
keccak((const uint8_t *)data, l, hash.bytes, 32);
}
void hash_to_scalar(key &hash, const void * data, const std::size_t l) {
@@ -330,7 +293,7 @@ namespace rct {
//cn_fast_hash for a 32 byte key
void cn_fast_hash(key & hash, const key & in) {
keccak((uint8_t *)in.bytes, 32, hash.bytes, 32);
keccak((const uint8_t *)in.bytes, 32, hash.bytes, 32);
}
void hash_to_scalar(key & hash, const key & in) {
@@ -341,7 +304,7 @@ namespace rct {
//cn_fast_hash for a 32 byte key
key cn_fast_hash(const key & in) {
key hash;
keccak((uint8_t *)in.bytes, 32, hash.bytes, 32);
keccak((const uint8_t *)in.bytes, 32, hash.bytes, 32);
return hash;
}
@@ -354,7 +317,7 @@ namespace rct {
//cn_fast_hash for a 128 byte unsigned char
key cn_fast_hash128(const void * in) {
key hash;
keccak((uint8_t *)in, 128, hash.bytes, 32);
keccak((const uint8_t *)in, 128, hash.bytes, 32);
return hash;
}
@@ -367,20 +330,13 @@ namespace rct {
//cn_fast_hash for multisig purpose
//This takes the outputs and commitments
//and hashes them into a 32 byte sized key
key cn_fast_hash(ctkeyV PC) {
key rv = identity();
std::size_t l = (std::size_t)PC.size();
size_t i = 0, j = 0;
vector<char> m(l * 64);
for (i = 0 ; i < l ; i++) {
memcpy(&m[i * 64], &PC[i].dest, 32);
memcpy(&m[i * 64 + 32], &PC[i].mask, 32);
}
cn_fast_hash(rv, &m[0], 64*l);
key cn_fast_hash(const ctkeyV &PC) {
key rv;
cn_fast_hash(rv, &PC[0], 64*PC.size());
return rv;
}
key hash_to_scalar(ctkeyV PC) {
key hash_to_scalar(const ctkeyV &PC) {
key rv = cn_fast_hash(PC);
sc_reduce32(rv.bytes);
return rv;
@@ -391,14 +347,8 @@ namespace rct {
//put them in the key vector and it concatenates them
//and then hashes them
key cn_fast_hash(const keyV &keys) {
size_t l = keys.size();
vector<unsigned char> m(l * 32);
size_t i;
for (i = 0 ; i < l ; i++) {
memcpy(&m[i * 32], keys[i].bytes, 32);
}
key rv;
cn_fast_hash(rv, &m[0], 32 * l);
cn_fast_hash(rv, &keys[0], keys.size() * sizeof(keys[0]));
//dp(rv);
return rv;
}
@@ -409,6 +359,19 @@ namespace rct {
return rv;
}
key cn_fast_hash(const key64 keys) {
key rv;
cn_fast_hash(rv, &keys[0], 64 * sizeof(keys[0]));
//dp(rv);
return rv;
}
key hash_to_scalar(const key64 keys) {
key rv = cn_fast_hash(keys);
sc_reduce32(rv.bytes);
return rv;
}
key hashToPointSimple(const key & hh) {
key pointk;
ge_p1p1 point2;

View File

@@ -64,19 +64,23 @@ namespace rct {
//Various key initialization functions
static const key Z = { {0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 } };
static const key I = { {0x01, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 , 0x00, 0x00, 0x00,0x00 } };
//Creates a zero scalar
key zero();
void zero(key &z);
inline key zero() { return Z; }
inline void zero(key &z) { memset(&z, 0, 32); }
//Creates a zero elliptic curve point
key identity();
void identity(key &Id);
inline key identity() { return I; }
inline void identity(key &Id) { memcpy(&Id, &I, 32); }
//copies a scalar or point
void copy(key &AA, const key &A);
key copy(const key & AA);
inline void copy(key &AA, const key &A) { memcpy(&AA, &A, 32); }
inline key copy(const key & A) { key AA; memcpy(&AA, &A, 32); return AA; }
//initializes a key matrix;
//first parameter is rows,
//second is columns
keyM keyMInit(int, int);
keyM keyMInit(size_t rows, size_t cols);
//Various key generation functions
@@ -85,7 +89,7 @@ namespace rct {
void skGen(key &);
//generates a vector of secret keys of size "int"
keyV skvGen(int );
keyV skvGen(size_t rows );
//generates a random curve point (for testing)
key pkGen();
@@ -97,9 +101,9 @@ namespace rct {
//generates C =aG + bH from b, a is random
void genC(key & C, const key & a, xmr_amount amount);
//this one is mainly for testing, can take arbitrary amounts..
tuple<ctkey, ctkey> ctskpkGen(key bH);
tuple<ctkey, ctkey> ctskpkGen(const key &bH);
// make a pedersen commitment with given key
key commit(xmr_amount amount, key mask);
key commit(xmr_amount amount, const key &mask);
// make a pedersen commitment with zero key
key zeroCommit(xmr_amount amount);
//generates a random uint long long
@@ -149,11 +153,14 @@ namespace rct {
//for mg sigs
key cn_fast_hash128(const void * in);
key hash_to_scalar128(const void * in);
key cn_fast_hash(ctkeyV PC);
key hash_to_scalar(ctkeyV PC);
key cn_fast_hash(const ctkeyV &PC);
key hash_to_scalar(const ctkeyV &PC);
//for mg sigs
key cn_fast_hash(const keyV &keys);
key hash_to_scalar(const keyV &keys);
//for ANSL
key cn_fast_hash(const key64 keys);
key hash_to_scalar(const key64 keys);
//returns hashToPoint as described in https://github.com/ShenNoether/ge_fromfe_writeup
key hashToPointSimple(const key &in);

View File

@@ -29,6 +29,10 @@
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "misc_log_ex.h"
#include "common/perf_timer.h"
#include "common/task_region.h"
#include "common/thread_group.h"
#include "common/util.h"
#include "rctSigs.h"
#include "cryptonote_core/cryptonote_format_utils.h"
@@ -36,94 +40,66 @@ using namespace crypto;
using namespace std;
namespace rct {
namespace {
struct verRangeWrapper_ {
void operator()(const key & C, const rangeSig & as, bool &result) const {
result = verRange(C, as);
}
};
constexpr const verRangeWrapper_ verRangeWrapper{};
struct verRctMGSimpleWrapper_ {
void operator()(const key &message, const mgSig &mg, const ctkeyV & pubs, const key & C, bool &result) const {
result = verRctMGSimple(message, mg, pubs, C);
}
};
constexpr const verRctMGSimpleWrapper_ verRctMGSimpleWrapper{};
}
//Schnorr Non-linkable
//Gen Gives a signature (L1, s1, s2) proving that the sender knows "x" such that xG = one of P1 or P2
//Ver Verifies that signer knows an "x" such that xG = one of P1 or P2
//These are called in the below ASNL sig generation
//Borromean (c.f. gmax/andytoshi's paper)
boroSig genBorromean(const key64 x, const key64 P1, const key64 P2, const bits indices) {
key64 L[2], alpha;
key c;
int naught = 0, prime = 0, ii = 0, jj=0;
boroSig bb;
for (ii = 0 ; ii < 64 ; ii++) {
naught = indices[ii]; prime = (indices[ii] + 1) % 2;
skGen(alpha[ii]);
scalarmultBase(L[naught][ii], alpha[ii]);
if (naught == 0) {
skGen(bb.s1[ii]);
c = hash_to_scalar(L[naught][ii]);
addKeys2(L[prime][ii], bb.s1[ii], c, P2[ii]);
}
}
bb.ee = hash_to_scalar(L[1]); //or L[1]..
key LL, cc;
for (jj = 0 ; jj < 64 ; jj++) {
if (!indices[jj]) {
sc_mulsub(bb.s0[jj].bytes, x[jj].bytes, bb.ee.bytes, alpha[jj].bytes);
} else {
skGen(bb.s0[jj]);
addKeys2(LL, bb.s0[jj], bb.ee, P1[jj]); //different L0
cc = hash_to_scalar(LL);
sc_mulsub(bb.s1[jj].bytes, x[jj].bytes, cc.bytes, alpha[jj].bytes);
}
}
return bb;
}
void GenSchnorrNonLinkable(key & L1, key & s1, key & s2, const key & x, const key & P1, const key & P2, int index) {
key c1, c2, L2;
key a = skGen();
if (index == 0) {
scalarmultBase(L1, a);
hash_to_scalar(c2, L1);
skGen(s2);
addKeys2(L2, s2, c2, P2);
hash_to_scalar(c1, L2);
//s1 = a - x * c1
sc_mulsub(s1.bytes, x.bytes, c1.bytes, a.bytes);
}
else if (index == 1) {
scalarmultBase(L2, a);
hash_to_scalar(c1, L2);
skGen(s1);
addKeys2(L1, s1, c1, P1);
hash_to_scalar(c2, L1);
sc_mulsub(s2.bytes, x.bytes, c2.bytes, a.bytes);
}
else {
throw std::runtime_error("GenSchnorrNonLinkable: invalid index (should be 0 or 1)");
//see above.
bool verifyBorromean(const boroSig &bb, const key64 P1, const key64 P2) {
key64 Lv1; key chash, LL;
int ii = 0;
for (ii = 0 ; ii < 64 ; ii++) {
addKeys2(LL, bb.s0[ii], bb.ee, P1[ii]);
chash = hash_to_scalar(LL);
addKeys2(Lv1[ii], bb.s1[ii], chash, P2[ii]);
}
key eeComputed = hash_to_scalar(Lv1); //hash function fine
return equalKeys(eeComputed, bb.ee);
}
//Schnorr Non-linkable
//Gen Gives a signature (L1, s1, s2) proving that the sender knows "x" such that xG = one of P1 or P2
//Ver Verifies that signer knows an "x" such that xG = one of P1 or P2
//These are called in the below ASNL sig generation
bool VerSchnorrNonLinkable(const key & P1, const key & P2, const key & L1, const key & s1, const key & s2) {
key c2, L2, c1, L1p;
hash_to_scalar(c2, L1);
addKeys2(L2, s2, c2, P2);
hash_to_scalar(c1, L2);
addKeys2(L1p, s1, c1, P1);
return equalKeys(L1, L1p);
}
//Aggregate Schnorr Non-linkable Ring Signature (ASNL)
// c.f. http://eprint.iacr.org/2015/1098 section 5.
// These are used in range proofs (alternatively Borromean could be used)
// Gen gives a signature which proves the signer knows, for each i,
// an x[i] such that x[i]G = one of P1[i] or P2[i]
// Ver Verifies the signer knows a key for one of P1[i], P2[i] at each i
asnlSig GenASNL(key64 x, key64 P1, key64 P2, bits indices) {
DP("Generating Aggregate Schnorr Non-linkable Ring Signature\n");
key64 s1;
int j = 0;
asnlSig rv;
rv.s = zero();
for (j = 0; j < ATOMS; j++) {
GenSchnorrNonLinkable(rv.L1[j], s1[j], rv.s2[j], x[j], P1[j], P2[j], (int)indices[j]);
sc_add(rv.s.bytes, rv.s.bytes, s1[j].bytes);
}
return rv;
}
//Aggregate Schnorr Non-linkable Ring Signature (ASNL)
// c.f. http://eprint.iacr.org/2015/1098 section 5.
// These are used in range proofs (alternatively Borromean could be used)
// Gen gives a signature which proves the signer knows, for each i,
// an x[i] such that x[i]G = one of P1[i] or P2[i]
// Ver Verifies the signer knows a key for one of P1[i], P2[i] at each i
bool VerASNL(const key64 P1, const key64 P2, const asnlSig &as) {
DP("Verifying Aggregate Schnorr Non-linkable Ring Signature\n");
key LHS = identity();
key RHS = scalarmultBase(as.s);
key c2, L2, c1;
int j = 0;
for (j = 0; j < ATOMS; j++) {
hash_to_scalar(c2, as.L1[j]);
addKeys2(L2, as.s2[j], c2, P2[j]);
addKeys(LHS, LHS, as.L1[j]);
hash_to_scalar(c1, L2);
addKeys(RHS, RHS, scalarmultKey(P1[j], c1));
}
key cc;
sc_sub(cc.bytes, LHS.bytes, RHS.bytes);
return sc_isnonzero(cc.bytes) == 0;
}
//Multilayered Spontaneous Anonymous Group Signatures (MLSAG signatures)
//These are aka MG signatutes in earlier drafts of the ring ct paper
// c.f. http://eprint.iacr.org/2015/1098 section 2.
@@ -150,7 +126,7 @@ namespace rct {
// Gen creates a signature which proves that for some column in the keymatrix "pk"
// the signer knows a secret key for each row in that column
// Ver verifies that the MG sig was created correctly
mgSig MLSAG_Gen(key message, const keyM & pk, const keyV & xx, const unsigned int index, size_t dsRows) {
mgSig MLSAG_Gen(const key &message, const keyM & pk, const keyV & xx, const unsigned int index, size_t dsRows) {
mgSig rv;
size_t cols = pk.size();
CHECK_AND_ASSERT_THROW_MES(cols >= 2, "Error! What is c if cols = 1!");
@@ -239,7 +215,7 @@ namespace rct {
// Gen creates a signature which proves that for some column in the keymatrix "pk"
// the signer knows a secret key for each row in that column
// Ver verifies that the MG sig was created correctly
bool MLSAG_Ver(key message, const keyM & pk, const mgSig & rv, size_t dsRows) {
bool MLSAG_Ver(const key &message, const keyM & pk, const mgSig & rv, size_t dsRows) {
size_t cols = pk.size();
CHECK_AND_ASSERT_MES(cols >= 2, false, "Error! What is c if cols = 1!");
@@ -255,6 +231,11 @@ namespace rct {
}
CHECK_AND_ASSERT_MES(dsRows <= rows, false, "Bad dsRows value");
for (size_t i = 0; i < rv.ss.size(); ++i)
for (size_t j = 0; j < rv.ss[i].size(); ++j)
CHECK_AND_ASSERT_MES(sc_check(rv.ss[i][j].bytes) == 0, false, "Bad ss slot");
CHECK_AND_ASSERT_MES(sc_check(rv.cc.bytes) == 0, false, "Bad cc");
size_t i = 0, j = 0, ii = 0;
key c, L, R, Hi;
key c_old = copy(rv.cc);
@@ -319,7 +300,7 @@ namespace rct {
sc_add(mask.bytes, mask.bytes, ai[i].bytes);
addKeys(C, C, sig.Ci[i]);
}
sig.asig = GenASNL(ai, sig.Ci, CiH, b);
sig.asig = genBorromean(ai, sig.Ci, CiH, b);
return sig;
}
@@ -331,6 +312,9 @@ namespace rct {
// mask is a such that C = aG + bH, and b = amount
//verRange verifies that \sum Ci = C and that each Ci is a commitment to 0 or 2^i
bool verRange(const key & C, const rangeSig & as) {
try
{
PERF_TIMER(verRange);
key64 CiH;
int i = 0;
key Ctmp = identity();
@@ -340,14 +324,18 @@ namespace rct {
}
if (!equalKeys(C, Ctmp))
return false;
if (!VerASNL(as.Ci, CiH, as.asig))
if (!verifyBorromean(as.asig, as.Ci, CiH))
return false;
return true;
}
// we can get deep throws from ge_frombytes_vartime if input isn't valid
catch (...) { return false; }
}
key get_pre_mlsag_hash(const rctSig &rv)
{
keyV hashes;
hashes.reserve(3);
hashes.push_back(rv.message);
crypto::hash h;
@@ -361,13 +349,14 @@ namespace rct {
hashes.push_back(hash2rct(h));
keyV kv;
kv.reserve((64*3+1) * rv.p.rangeSigs.size());
for (auto r: rv.p.rangeSigs)
{
for (size_t n = 0; n < 64; ++n)
kv.push_back(r.asig.L1[n]);
kv.push_back(r.asig.s0[n]);
for (size_t n = 0; n < 64; ++n)
kv.push_back(r.asig.s2[n]);
kv.push_back(r.asig.s);
kv.push_back(r.asig.s1[n]);
kv.push_back(r.asig.ee);
for (size_t n = 0; n < 64; ++n)
kv.push_back(r.Ci[n]);
}
@@ -467,6 +456,7 @@ namespace rct {
//Ver:
// verifies the above sig is created corretly
bool verRctMG(const mgSig &mg, const ctkeyM & pubs, const ctkeyV & outPk, key txnFeeKey, const key &message) {
PERF_TIMER(verRctMG);
//setup vars
size_t cols = pubs.size();
CHECK_AND_ASSERT_MES(cols >= 1, false, "Empty pubs");
@@ -505,6 +495,9 @@ namespace rct {
//This does a simplified version, assuming only post Rct
//inputs
bool verRctMGSimple(const key &message, const mgSig &mg, const ctkeyV & pubs, const key & C) {
try
{
PERF_TIMER(verRctMGSimple);
//setup vars
size_t rows = 1;
size_t cols = pubs.size();
@@ -519,8 +512,11 @@ namespace rct {
}
//DP(C);
return MLSAG_Ver(message, M, mg, rows);
}
catch (...) { return false; }
}
//These functions get keys from blockchain
//replace these when connecting blockchain
//getKeyFromBlockchain grabs a key from the blockchain at "reference_index" to mix with
@@ -583,6 +579,7 @@ namespace rct {
// Thus the amounts vector will be "one" longer than the destinations vectort
rctSig genRct(const key &message, const ctkeyV & inSk, const keyV & destinations, const vector<xmr_amount> & amounts, const ctkeyM &mixRing, const keyV &amount_keys, unsigned int index, ctkeyV &outSk) {
CHECK_AND_ASSERT_THROW_MES(amounts.size() == destinations.size() || amounts.size() == destinations.size() + 1, "Different number of amounts/destinations");
CHECK_AND_ASSERT_THROW_MES(amount_keys.size() == destinations.size(), "Different number of amount_keys/destinations");
CHECK_AND_ASSERT_THROW_MES(index < mixRing.size(), "Bad index into mixRing");
for (size_t n = 0; n < mixRing.size(); ++n) {
CHECK_AND_ASSERT_THROW_MES(mixRing[n].size() == inSk.size(), "Bad mixRing size");
@@ -644,6 +641,7 @@ namespace rct {
CHECK_AND_ASSERT_THROW_MES(inamounts.size() > 0, "Empty inamounts");
CHECK_AND_ASSERT_THROW_MES(inamounts.size() == inSk.size(), "Different number of inamounts/inSk");
CHECK_AND_ASSERT_THROW_MES(outamounts.size() == destinations.size(), "Different number of amounts/destinations");
CHECK_AND_ASSERT_THROW_MES(amount_keys.size() == destinations.size(), "Different number of amount_keys/destinations");
CHECK_AND_ASSERT_THROW_MES(index.size() == inSk.size(), "Different number of index/inSk");
CHECK_AND_ASSERT_THROW_MES(mixRing.size() == inSk.size(), "Different number of mixRing/inSk");
for (size_t n = 0; n < mixRing.size(); ++n) {
@@ -729,6 +727,7 @@ namespace rct {
// uses the attached ecdh info to find the amounts represented by each output commitment
// must know the destination private key to find the correct amount, else will return a random number
bool verRct(const rctSig & rv) {
PERF_TIMER(verRct);
CHECK_AND_ASSERT_MES(rv.type == RCTTypeFull, false, "verRct called on non-full rctSig");
CHECK_AND_ASSERT_MES(rv.outPk.size() == rv.p.rangeSigs.size(), false, "Mismatched sizes of outPk and rv.p.rangeSigs");
CHECK_AND_ASSERT_MES(rv.outPk.size() == rv.ecdhInfo.size(), false, "Mismatched sizes of outPk and rv.ecdhInfo");
@@ -737,24 +736,32 @@ namespace rct {
// some rct ops can throw
try
{
size_t i = 0;
bool tmp;
DP("range proofs verified?");
for (i = 0; i < rv.outPk.size(); i++) {
tmp = verRange(rv.outPk[i].mask, rv.p.rangeSigs[i]);
DP(tmp);
if (!tmp) {
LOG_ERROR("Range proof verification failed for input " << i);
return false;
}
std::deque<bool> results(rv.outPk.size(), false);
tools::thread_group threadpool(tools::thread_group::optimal_with_max(rv.outPk.size()));
tools::task_region(threadpool, [&] (tools::task_region_handle& region) {
DP("range proofs verified?");
for (size_t i = 0; i < rv.outPk.size(); i++) {
region.run([&, i] {
results[i] = verRange(rv.outPk[i].mask, rv.p.rangeSigs[i]);
});
}
});
for (size_t i = 0; i < rv.outPk.size(); ++i) {
if (!results[i]) {
LOG_PRINT_L1("Range proof verified failed for output " << i);
return false;
}
}
//compute txn fee
key txnFeeKey = scalarmultH(d2h(rv.txnFee));
bool mgVerd = verRctMG(rv.p.MGs[0], rv.mixRing, rv.outPk, txnFeeKey, get_pre_mlsag_hash(rv));
DP("mg sig verified?");
DP(mgVerd);
if (!mgVerd) {
LOG_ERROR("MG signature verification failed");
LOG_PRINT_L1("MG signature verification failed");
return false;
}
@@ -769,7 +776,9 @@ namespace rct {
//ver RingCT simple
//assumes only post-rct style inputs (at least for max anonymity)
bool verRctSimple(const rctSig & rv) {
size_t i = 0;
try
{
PERF_TIMER(verRctSimple);
CHECK_AND_ASSERT_MES(rv.type == RCTTypeSimple, false, "verRctSimple called on non simple rctSig");
CHECK_AND_ASSERT_MES(rv.outPk.size() == rv.p.rangeSigs.size(), false, "Mismatched sizes of outPk and rv.p.rangeSigs");
@@ -777,39 +786,71 @@ namespace rct {
CHECK_AND_ASSERT_MES(rv.pseudoOuts.size() == rv.p.MGs.size(), false, "Mismatched sizes of rv.pseudoOuts and rv.p.MGs");
CHECK_AND_ASSERT_MES(rv.pseudoOuts.size() == rv.mixRing.size(), false, "Mismatched sizes of rv.pseudoOuts and mixRing");
const size_t threads = std::max(rv.outPk.size(), rv.mixRing.size());
std::deque<bool> results(threads);
tools::thread_group threadpool(tools::thread_group::optimal_with_max(threads));
results.clear();
results.resize(rv.outPk.size());
tools::task_region(threadpool, [&] (tools::task_region_handle& region) {
for (size_t i = 0; i < rv.outPk.size(); i++) {
region.run([&, i] {
results[i] = verRange(rv.outPk[i].mask, rv.p.rangeSigs[i]);
});
}
});
for (size_t i = 0; i < results.size(); ++i) {
if (!results[i]) {
LOG_PRINT_L1("Range proof verified failed for output " << i);
return false;
}
}
key sumOutpks = identity();
for (i = 0; i < rv.outPk.size(); i++) {
if (!verRange(rv.outPk[i].mask, rv.p.rangeSigs[i])) {
LOG_ERROR("Range proof verified failed for input " << i);
return false;
}
for (size_t i = 0; i < rv.outPk.size(); i++) {
addKeys(sumOutpks, sumOutpks, rv.outPk[i].mask);
}
DP(sumOutpks);
key txnFeeKey = scalarmultH(d2h(rv.txnFee));
addKeys(sumOutpks, txnFeeKey, sumOutpks);
bool tmpb = false;
key message = get_pre_mlsag_hash(rv);
results.clear();
results.resize(rv.mixRing.size());
tools::task_region(threadpool, [&] (tools::task_region_handle& region) {
for (size_t i = 0 ; i < rv.mixRing.size() ; i++) {
region.run([&, i] {
results[i] = verRctMGSimple(message, rv.p.MGs[i], rv.mixRing[i], rv.pseudoOuts[i]);
});
}
});
for (size_t i = 0; i < results.size(); ++i) {
if (!results[i]) {
LOG_PRINT_L1("verRctMGSimple failed for input " << i);
return false;
}
}
key sumPseudoOuts = identity();
for (i = 0 ; i < rv.mixRing.size() ; i++) {
tmpb = verRctMGSimple(message, rv.p.MGs[i], rv.mixRing[i], rv.pseudoOuts[i]);
for (size_t i = 0 ; i < rv.mixRing.size() ; i++) {
addKeys(sumPseudoOuts, sumPseudoOuts, rv.pseudoOuts[i]);
DP(tmpb);
if (!tmpb) {
LOG_ERROR("verRctMGSimple failed for input " << i);
return false;
}
}
DP(sumPseudoOuts);
//check pseudoOuts vs Outs..
if (!equalKeys(sumPseudoOuts, sumOutpks)) {
LOG_ERROR("Sum check failed");
LOG_PRINT_L1("Sum check failed");
return false;
}
return true;
}
// we can get deep throws from ge_frombytes_vartime if input isn't valid
catch (...) { return false; }
}
//RingCT protocol

View File

@@ -66,21 +66,8 @@ using namespace crypto;
namespace rct {
//Schnorr Non-linkable
//Gen Gives a signature (L1, s1, s2) proving that the sender knows "x" such that xG = one of P1 or P2
//Ver Verifies that signer knows an "x" such that xG = one of P1 or P2
//These are called in the below ASNL sig generation
void GenSchnorrNonLinkable(key & L1, key & s1, key & s2, const key & x, const key & P1, const key & P2, int index);
bool VerSchnorrNonLinkable(const key & P1, const key & P2, const key & L1, const key & s1, const key & s2);
//Aggregate Schnorr Non-linkable Ring Signature (ASNL)
// c.f. http://eprint.iacr.org/2015/1098 section 5.
// These are used in range proofs (alternatively Borromean could be used)
// Gen gives a signature which proves the signer knows, for each i,
// an x[i] such that x[i]G = one of P1[i] or P2[i]
// Ver Verifies the signer knows a key for one of P1[i], P2[i] at each i
asnlSig GenASNL(key64 x, key64 P1, key64 P2, bits indices);
bool VerASNL(const key64 P1, const key64 P2, const asnlSig &as);
boroSig genBorromean(const key64 x, const key64 P1, const key64 P2, const bits indices);
bool verifyBorromean(const boroSig &bb, const key64 P1, const key64 P2);
//Multilayered Spontaneous Anonymous Group Signatures (MLSAG signatures)
//These are aka MG signatutes in earlier drafts of the ring ct paper
@@ -90,8 +77,8 @@ namespace rct {
// the signer knows a secret key for each row in that column
// Ver verifies that the MG sig was created correctly
keyV keyImageV(const keyV &xx);
mgSig MLSAG_Gen(key message, const keyM & pk, const keyV & xx, const unsigned int index, size_t dsRows);
bool MLSAG_Ver(key message, const keyM &pk, const mgSig &sig, size_t dsRows);
mgSig MLSAG_Gen(const key &message, const keyM & pk, const keyV & xx, const unsigned int index, size_t dsRows);
bool MLSAG_Ver(const key &message, const keyM &pk, const mgSig &sig, size_t dsRows);
//mgSig MLSAG_Gen_Old(const keyM & pk, const keyV & xx, const int index);
//proveRange and verRange

View File

@@ -125,12 +125,10 @@ namespace rct {
typedef unsigned int bits[ATOMS];
typedef key key64[64];
//just contains the necessary keys to represent asnlSigs
//c.f. http://eprint.iacr.org/2015/1098
struct asnlSig {
key64 L1;
key64 s2;
key s;
struct boroSig {
key64 s0;
key64 s1;
key ee;
};
//Container for precomp
@@ -151,14 +149,14 @@ namespace rct {
// FIELD(II) - not serialized, it can be reconstructed
END_SERIALIZE()
};
//contains the data for an asnl sig
//contains the data for an Borromean sig
// also contains the "Ci" values such that
// \sum Ci = C
// and the signature proves that each Ci is either
// a Pedersen commitment to 0 or to 2^i
//thus proving that C is in the range of [0, 2^64]
struct rangeSig {
asnlSig asig;
boroSig asig;
key64 Ci;
BEGIN_SERIALIZE_OBJECT()
@@ -281,6 +279,7 @@ namespace rct {
// we save the MGs contents directly, because we want it to save its
// arrays and matrices without the size prefixes, and the load can't
// know what size to expect if it's not in the data
ar.begin_object();
ar.tag("ss");
ar.begin_array();
PREPARE_CUSTOM_VECTOR_SERIALIZATION(mixin + 1, MGs[i].ss);
@@ -296,7 +295,7 @@ namespace rct {
for (size_t k = 0; k < mg_ss2_elements; ++k)
{
FIELDS(MGs[i].ss[j][k])
if (mg_ss2_elements - j > 1)
if (mg_ss2_elements - k > 1)
ar.delimit_array();
}
ar.end_array();
@@ -306,10 +305,13 @@ namespace rct {
}
ar.end_array();
ar.tag("cc");
FIELDS(MGs[i].cc)
// MGs[i].II not saved, it can be reconstructed
if (mg_elements - i > 1)
ar.delimit_array();
ar.end_object();
}
ar.end_array();
return true;
@@ -415,7 +417,7 @@ namespace rct {
// then the value in the first 8 bytes is returned
xmr_amount h2d(const key &test);
//32 byte key to int[64]
void h2b(bits amountb2, key & test);
void h2b(bits amountb2, const key & test);
//int[64] to 32 byte key
void b2h(key & amountdh, bits amountb2);
//int[64] to uint long long
@@ -448,7 +450,7 @@ inline std::ostream &operator <<(std::ostream &o, const rct::key &v) { return pr
BLOB_SERIALIZER(rct::key);
BLOB_SERIALIZER(rct::key64);
BLOB_SERIALIZER(rct::ctkey);
BLOB_SERIALIZER(rct::asnlSig);
BLOB_SERIALIZER(rct::boroSig);
VARIANT_TAG(debug_archive, rct::key, "rct::key");
VARIANT_TAG(debug_archive, rct::key64, "rct::key64");
@@ -460,7 +462,7 @@ VARIANT_TAG(debug_archive, rct::ctkeyM, "rct::ctkeyM");
VARIANT_TAG(debug_archive, rct::ecdhTuple, "rct::ecdhTuple");
VARIANT_TAG(debug_archive, rct::mgSig, "rct::mgSig");
VARIANT_TAG(debug_archive, rct::rangeSig, "rct::rangeSig");
VARIANT_TAG(debug_archive, rct::asnlSig, "rct::asnlSig");
VARIANT_TAG(debug_archive, rct::boroSig, "rct::boroSig");
VARIANT_TAG(debug_archive, rct::rctSig, "rct::rctSig");
VARIANT_TAG(binary_archive, rct::key, 0x90);
@@ -473,7 +475,7 @@ VARIANT_TAG(binary_archive, rct::ctkeyM, 0x96);
VARIANT_TAG(binary_archive, rct::ecdhTuple, 0x97);
VARIANT_TAG(binary_archive, rct::mgSig, 0x98);
VARIANT_TAG(binary_archive, rct::rangeSig, 0x99);
VARIANT_TAG(binary_archive, rct::asnlSig, 0x9a);
VARIANT_TAG(binary_archive, rct::boroSig, 0x9a);
VARIANT_TAG(binary_archive, rct::rctSig, 0x9b);
VARIANT_TAG(json_archive, rct::key, "rct_key");
@@ -486,7 +488,7 @@ VARIANT_TAG(json_archive, rct::ctkeyM, "rct_ctkeyM");
VARIANT_TAG(json_archive, rct::ecdhTuple, "rct_ecdhTuple");
VARIANT_TAG(json_archive, rct::mgSig, "rct_mgSig");
VARIANT_TAG(json_archive, rct::rangeSig, "rct_rangeSig");
VARIANT_TAG(json_archive, rct::asnlSig, "rct_asnlSig");
VARIANT_TAG(json_archive, rct::boroSig, "rct_boroSig");
VARIANT_TAG(json_archive, rct::rctSig, "rct_rctSig");
#endif /* RCTTYPES_H */

View File

@@ -36,9 +36,9 @@ set(rpc_private_headers
core_rpc_server_commands_defs.h
core_rpc_server_error_codes.h)
bitmonero_private_headers(rpc
monero_private_headers(rpc
${rpc_private_headers})
bitmonero_add_library(rpc
monero_add_library(rpc
${rpc_sources}
${rpc_headers}
${rpc_private_headers})

View File

@@ -142,6 +142,7 @@ namespace cryptonote
res.white_peerlist_size = m_p2p.get_peerlist_manager().get_white_peers_count();
res.grey_peerlist_size = m_p2p.get_peerlist_manager().get_gray_peers_count();
res.testnet = m_testnet;
res.cumulative_difficulty = m_core.get_blockchain_storage().get_db().get_block_cumulative_difficulty(res.height - 1);
res.status = CORE_RPC_STATUS_OK;
return true;
}
@@ -245,7 +246,7 @@ namespace cryptonote
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
bool core_rpc_server::on_get_outs(const COMMAND_RPC_GET_OUTPUTS::request& req, COMMAND_RPC_GET_OUTPUTS::response& res)
bool core_rpc_server::on_get_outs_bin(const COMMAND_RPC_GET_OUTPUTS_BIN::request& req, COMMAND_RPC_GET_OUTPUTS_BIN::response& res)
{
CHECK_CORE_BUSY();
res.status = "Failed";
@@ -268,6 +269,42 @@ namespace cryptonote
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
bool core_rpc_server::on_get_outs(const COMMAND_RPC_GET_OUTPUTS::request& req, COMMAND_RPC_GET_OUTPUTS::response& res)
{
CHECK_CORE_BUSY();
res.status = "Failed";
if (m_restricted)
{
if (req.outputs.size() > MAX_RESTRICTED_GLOBAL_FAKE_OUTS_COUNT)
{
res.status = "Too many outs requested";
return true;
}
}
cryptonote::COMMAND_RPC_GET_OUTPUTS_BIN::request req_bin;
req_bin.outputs = req.outputs;
cryptonote::COMMAND_RPC_GET_OUTPUTS_BIN::response res_bin;
if(!m_core.get_outs(req_bin, res_bin))
{
return true;
}
// convert to text
for (const auto &i: res_bin.outs)
{
res.outs.push_back(cryptonote::COMMAND_RPC_GET_OUTPUTS::outkey());
cryptonote::COMMAND_RPC_GET_OUTPUTS::outkey &outkey = res.outs.back();
outkey.key = epee::string_tools::pod_to_hex(i.key);
outkey.mask = epee::string_tools::pod_to_hex(i.mask);
outkey.unlocked = i.unlocked;
}
res.status = CORE_RPC_STATUS_OK;
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
bool core_rpc_server::on_get_random_rct_outs(const COMMAND_RPC_GET_RANDOM_RCT_OUTPUTS::request& req, COMMAND_RPC_GET_RANDOM_RCT_OUTPUTS::response& res)
{
CHECK_CORE_BUSY();
@@ -387,6 +424,17 @@ namespace cryptonote
res.txs_as_hex.push_back(e.as_hex);
if (req.decode_as_json)
res.txs_as_json.push_back(e.as_json);
// output indices too if not in pool
if (pool_tx_hashes.find(tx_hash) == pool_tx_hashes.end())
{
bool r = m_core.get_tx_outputs_gindexs(tx_hash, e.output_indices);
if (!r)
{
res.status = "Failed";
return false;
}
}
}
BOOST_FOREACH(const auto& miss_tx, missed_txs)
@@ -830,19 +878,19 @@ namespace cryptonote
return reward;
}
//------------------------------------------------------------------------------------------------------------------------------
bool core_rpc_server::fill_block_header_responce(const block& blk, bool orphan_status, uint64_t height, const crypto::hash& hash, block_header_responce& responce)
bool core_rpc_server::fill_block_header_response(const block& blk, bool orphan_status, uint64_t height, const crypto::hash& hash, block_header_response& response)
{
responce.major_version = blk.major_version;
responce.minor_version = blk.minor_version;
responce.timestamp = blk.timestamp;
responce.prev_hash = string_tools::pod_to_hex(blk.prev_id);
responce.nonce = blk.nonce;
responce.orphan_status = orphan_status;
responce.height = height;
responce.depth = m_core.get_current_blockchain_height() - height - 1;
responce.hash = string_tools::pod_to_hex(hash);
responce.difficulty = m_core.get_blockchain_storage().block_difficulty(height);
responce.reward = get_block_reward(blk);
response.major_version = blk.major_version;
response.minor_version = blk.minor_version;
response.timestamp = blk.timestamp;
response.prev_hash = string_tools::pod_to_hex(blk.prev_id);
response.nonce = blk.nonce;
response.orphan_status = orphan_status;
response.height = height;
response.depth = m_core.get_current_blockchain_height() - height - 1;
response.hash = string_tools::pod_to_hex(hash);
response.difficulty = m_core.get_blockchain_storage().block_difficulty(height);
response.reward = get_block_reward(blk);
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
@@ -871,8 +919,8 @@ namespace cryptonote
error_resp.message = "Internal error: can't get last block.";
return false;
}
bool responce_filled = fill_block_header_responce(last_block, false, last_block_height, last_block_hash, res.block_header);
if (!responce_filled)
bool response_filled = fill_block_header_response(last_block, false, last_block_height, last_block_hash, res.block_header);
if (!response_filled)
{
error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
error_resp.message = "Internal error: can't produce valid response.";
@@ -912,8 +960,8 @@ namespace cryptonote
return false;
}
uint64_t block_height = boost::get<txin_gen>(blk.miner_tx.vin.front()).height;
bool responce_filled = fill_block_header_responce(blk, false, block_height, block_hash, res.block_header);
if (!responce_filled)
bool response_filled = fill_block_header_response(blk, false, block_height, block_hash, res.block_header);
if (!response_filled)
{
error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
error_resp.message = "Internal error: can't produce valid response.";
@@ -923,6 +971,57 @@ namespace cryptonote
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
bool core_rpc_server::on_get_block_headers_range(const COMMAND_RPC_GET_BLOCK_HEADERS_RANGE::request& req, COMMAND_RPC_GET_BLOCK_HEADERS_RANGE::response& res, epee::json_rpc::error& error_resp){
if(!check_core_busy())
{
error_resp.code = CORE_RPC_ERROR_CODE_CORE_BUSY;
error_resp.message = "Core is busy.";
return false;
}
const uint64_t bc_height = m_core.get_current_blockchain_height();
if (req.start_height >= bc_height || req.end_height >= bc_height || req.start_height > req.end_height)
{
error_resp.code = CORE_RPC_ERROR_CODE_TOO_BIG_HEIGHT;
error_resp.message = "Invalid start/end heights.";
return false;
}
for (uint64_t h = req.start_height; h <= req.end_height; ++h)
{
crypto::hash block_hash = m_core.get_block_id_by_height(h);
block blk;
bool have_block = m_core.get_block_by_hash(block_hash, blk);
if (!have_block)
{
error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
error_resp.message = "Internal error: can't get block by height. Height = " + boost::lexical_cast<std::string>(h) + ". Hash = " + epee::string_tools::pod_to_hex(block_hash) + '.';
return false;
}
if (blk.miner_tx.vin.front().type() != typeid(txin_gen))
{
error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
error_resp.message = "Internal error: coinbase transaction in the block has the wrong type";
return false;
}
uint64_t block_height = boost::get<txin_gen>(blk.miner_tx.vin.front()).height;
if (block_height != h)
{
error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
error_resp.message = "Internal error: coinbase transaction in the block has the wrong height";
return false;
}
res.headers.push_back(block_header_response());
bool responce_filled = fill_block_header_response(blk, false, block_height, block_hash, res.headers.back());
if (!responce_filled)
{
error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
error_resp.message = "Internal error: can't produce valid response.";
return false;
}
}
res.status = CORE_RPC_STATUS_OK;
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
bool core_rpc_server::on_get_block_header_by_height(const COMMAND_RPC_GET_BLOCK_HEADER_BY_HEIGHT::request& req, COMMAND_RPC_GET_BLOCK_HEADER_BY_HEIGHT::response& res, epee::json_rpc::error& error_resp){
if(!check_core_busy())
{
@@ -945,8 +1044,8 @@ namespace cryptonote
error_resp.message = "Internal error: can't get block by height. Height = " + std::to_string(req.height) + '.';
return false;
}
bool responce_filled = fill_block_header_responce(blk, false, req.height, block_hash, res.block_header);
if (!responce_filled)
bool response_filled = fill_block_header_response(blk, false, req.height, block_hash, res.block_header);
if (!response_filled)
{
error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
error_resp.message = "Internal error: can't produce valid response.";
@@ -999,8 +1098,8 @@ namespace cryptonote
return false;
}
uint64_t block_height = boost::get<txin_gen>(blk.miner_tx.vin.front()).height;
bool responce_filled = fill_block_header_responce(blk, false, block_height, block_hash, res.block_header);
if (!responce_filled)
bool response_filled = fill_block_header_response(blk, false, block_height, block_hash, res.block_header);
if (!response_filled)
{
error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
error_resp.message = "Internal error: can't produce valid response.";
@@ -1041,7 +1140,14 @@ namespace cryptonote
return false;
}
res.height = m_core.get_current_blockchain_height();
crypto::hash top_hash;
if (!m_core.get_blockchain_top(res.height, top_hash))
{
res.status = "Failed";
return false;
}
++res.height; // turn top block height into blockchain height
res.top_block_hash = string_tools::pod_to_hex(top_hash);
res.target_height = m_core.get_target_blockchain_height();
res.difficulty = m_core.get_blockchain_storage().get_difficulty_for_next_block();
res.target = m_core.get_blockchain_storage().get_current_hard_fork_version() < 2 ? DIFFICULTY_TARGET_V1 : DIFFICULTY_TARGET_V2;
@@ -1054,6 +1160,7 @@ namespace cryptonote
res.white_peerlist_size = m_p2p.get_peerlist_manager().get_white_peers_count();
res.grey_peerlist_size = m_p2p.get_peerlist_manager().get_gray_peers_count();
res.testnet = m_testnet;
res.cumulative_difficulty = m_core.get_blockchain_storage().get_db().get_block_cumulative_difficulty(res.height - 1);
res.status = CORE_RPC_STATUS_OK;
return true;
}
@@ -1185,10 +1292,10 @@ namespace cryptonote
return false;
}
std::map<uint64_t, uint64_t> histogram;
std::map<uint64_t, std::tuple<uint64_t, uint64_t, uint64_t>> histogram;
try
{
histogram = m_core.get_blockchain_storage().get_output_histogram(req.amounts, req.unlocked);
histogram = m_core.get_blockchain_storage().get_output_histogram(req.amounts, req.unlocked, req.recent_cutoff);
}
catch (const std::exception &e)
{
@@ -1200,8 +1307,8 @@ namespace cryptonote
res.histogram.reserve(histogram.size());
for (const auto &i: histogram)
{
if (i.second >= req.min_count && (i.second <= req.max_count || req.max_count == 0))
res.histogram.push_back(COMMAND_RPC_GET_OUTPUT_HISTOGRAM::entry(i.first, i.second));
if (std::get<0>(i.second) >= req.min_count && (std::get<0>(i.second) <= req.max_count || req.max_count == 0))
res.histogram.push_back(COMMAND_RPC_GET_OUTPUT_HISTOGRAM::entry(i.first, std::get<0>(i.second), std::get<1>(i.second), std::get<2>(i.second)));
}
res.status = CORE_RPC_STATUS_OK;
@@ -1215,12 +1322,19 @@ namespace cryptonote
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
bool core_rpc_server::on_fast_exit(const COMMAND_RPC_FAST_EXIT::request& req, COMMAND_RPC_FAST_EXIT::response& res)
bool core_rpc_server::on_get_coinbase_tx_sum(const COMMAND_RPC_GET_COINBASE_TX_SUM::request& req, COMMAND_RPC_GET_COINBASE_TX_SUM::response& res, epee::json_rpc::error& error_resp)
{
cryptonote::core::set_fast_exit();
m_p2p.deinit();
m_core.deinit();
return true;
std::pair<uint64_t, uint64_t> amounts = m_core.get_coinbase_tx_sum(req.height, req.count);
res.emission_amount = amounts.first;
res.fee_amount = amounts.second;
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
bool core_rpc_server::on_get_per_kb_fee_estimate(const COMMAND_RPC_GET_PER_KB_FEE_ESTIMATE::request& req, COMMAND_RPC_GET_PER_KB_FEE_ESTIMATE::response& res, epee::json_rpc::error& error_resp)
{
res.fee = m_core.get_blockchain_storage().get_dynamic_per_kb_fee_estimate(req.grace_blocks);
res.status = CORE_RPC_STATUS_OK;
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
bool core_rpc_server::on_out_peers(const COMMAND_RPC_OUT_PEERS::request& req, COMMAND_RPC_OUT_PEERS::response& res)

View File

@@ -79,7 +79,7 @@ namespace cryptonote
MAP_URI_AUTO_BIN2("/gethashes.bin", on_get_hashes, COMMAND_RPC_GET_HASHES_FAST)
MAP_URI_AUTO_BIN2("/get_o_indexes.bin", on_get_indexes, COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES)
MAP_URI_AUTO_BIN2("/getrandom_outs.bin", on_get_random_outs, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS)
MAP_URI_AUTO_BIN2("/get_outs.bin", on_get_outs, COMMAND_RPC_GET_OUTPUTS)
MAP_URI_AUTO_BIN2("/get_outs.bin", on_get_outs_bin, COMMAND_RPC_GET_OUTPUTS_BIN)
MAP_URI_AUTO_BIN2("/getrandom_rctouts.bin", on_get_random_rct_outs, COMMAND_RPC_GET_RANDOM_RCT_OUTPUTS)
MAP_URI_AUTO_JON2("/gettransactions", on_get_transactions, COMMAND_RPC_GET_TRANSACTIONS)
MAP_URI_AUTO_JON2("/is_key_image_spent", on_is_key_image_spent, COMMAND_RPC_IS_KEY_IMAGE_SPENT)
@@ -94,10 +94,10 @@ namespace cryptonote
MAP_URI_AUTO_JON2("/get_transaction_pool", on_get_transaction_pool, COMMAND_RPC_GET_TRANSACTION_POOL)
MAP_URI_AUTO_JON2_IF("/stop_daemon", on_stop_daemon, COMMAND_RPC_STOP_DAEMON, !m_restricted)
MAP_URI_AUTO_JON2("/getinfo", on_get_info, COMMAND_RPC_GET_INFO)
MAP_URI_AUTO_JON2_IF("/fast_exit", on_fast_exit, COMMAND_RPC_FAST_EXIT, !m_restricted)
MAP_URI_AUTO_JON2_IF("/out_peers", on_out_peers, COMMAND_RPC_OUT_PEERS, !m_restricted)
MAP_URI_AUTO_JON2_IF("/start_save_graph", on_start_save_graph, COMMAND_RPC_START_SAVE_GRAPH, !m_restricted)
MAP_URI_AUTO_JON2_IF("/stop_save_graph", on_stop_save_graph, COMMAND_RPC_STOP_SAVE_GRAPH, !m_restricted)
MAP_URI_AUTO_JON2("/get_outs", on_get_outs, COMMAND_RPC_GET_OUTPUTS)
BEGIN_JSON_RPC_MAP("/json_rpc")
MAP_JON_RPC("getblockcount", on_getblockcount, COMMAND_RPC_GETBLOCKCOUNT)
MAP_JON_RPC_WE("on_getblockhash", on_getblockhash, COMMAND_RPC_GETBLOCKHASH)
@@ -106,6 +106,7 @@ namespace cryptonote
MAP_JON_RPC_WE("getlastblockheader", on_get_last_block_header, COMMAND_RPC_GET_LAST_BLOCK_HEADER)
MAP_JON_RPC_WE("getblockheaderbyhash", on_get_block_header_by_hash, COMMAND_RPC_GET_BLOCK_HEADER_BY_HASH)
MAP_JON_RPC_WE("getblockheaderbyheight", on_get_block_header_by_height, COMMAND_RPC_GET_BLOCK_HEADER_BY_HEIGHT)
MAP_JON_RPC_WE("getblockheadersrange", on_get_block_headers_range, COMMAND_RPC_GET_BLOCK_HEADERS_RANGE)
MAP_JON_RPC_WE("getblock", on_get_block, COMMAND_RPC_GET_BLOCK)
MAP_JON_RPC_WE_IF("get_connections", on_get_connections, COMMAND_RPC_GET_CONNECTIONS, !m_restricted)
MAP_JON_RPC_WE("get_info", on_get_info_json, COMMAND_RPC_GET_INFO)
@@ -115,6 +116,8 @@ namespace cryptonote
MAP_JON_RPC_WE_IF("flush_txpool", on_flush_txpool, COMMAND_RPC_FLUSH_TRANSACTION_POOL, !m_restricted)
MAP_JON_RPC_WE("get_output_histogram", on_get_output_histogram, COMMAND_RPC_GET_OUTPUT_HISTOGRAM)
MAP_JON_RPC_WE("get_version", on_get_version, COMMAND_RPC_GET_VERSION)
MAP_JON_RPC_WE("get_coinbase_tx_sum", on_get_coinbase_tx_sum, COMMAND_RPC_GET_COINBASE_TX_SUM)
MAP_JON_RPC_WE("get_fee_estimate", on_get_per_kb_fee_estimate, COMMAND_RPC_GET_PER_KB_FEE_ESTIMATE)
END_JSON_RPC_MAP()
END_URI_MAP2()
@@ -129,6 +132,7 @@ namespace cryptonote
bool on_stop_mining(const COMMAND_RPC_STOP_MINING::request& req, COMMAND_RPC_STOP_MINING::response& res);
bool on_mining_status(const COMMAND_RPC_MINING_STATUS::request& req, COMMAND_RPC_MINING_STATUS::response& res);
bool on_get_random_outs(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response& res);
bool on_get_outs_bin(const COMMAND_RPC_GET_OUTPUTS_BIN::request& req, COMMAND_RPC_GET_OUTPUTS_BIN::response& res);
bool on_get_outs(const COMMAND_RPC_GET_OUTPUTS::request& req, COMMAND_RPC_GET_OUTPUTS::response& res);
bool on_get_random_rct_outs(const COMMAND_RPC_GET_RANDOM_RCT_OUTPUTS::request& req, COMMAND_RPC_GET_RANDOM_RCT_OUTPUTS::response& res);
bool on_get_info(const COMMAND_RPC_GET_INFO::request& req, COMMAND_RPC_GET_INFO::response& res);
@@ -138,7 +142,6 @@ namespace cryptonote
bool on_set_log_level(const COMMAND_RPC_SET_LOG_LEVEL::request& req, COMMAND_RPC_SET_LOG_LEVEL::response& res);
bool on_get_transaction_pool(const COMMAND_RPC_GET_TRANSACTION_POOL::request& req, COMMAND_RPC_GET_TRANSACTION_POOL::response& res);
bool on_stop_daemon(const COMMAND_RPC_STOP_DAEMON::request& req, COMMAND_RPC_STOP_DAEMON::response& res);
bool on_fast_exit(const COMMAND_RPC_FAST_EXIT::request& req, COMMAND_RPC_FAST_EXIT::response& res);
bool on_out_peers(const COMMAND_RPC_OUT_PEERS::request& req, COMMAND_RPC_OUT_PEERS::response& res);
bool on_start_save_graph(const COMMAND_RPC_START_SAVE_GRAPH::request& req, COMMAND_RPC_START_SAVE_GRAPH::response& res);
bool on_stop_save_graph(const COMMAND_RPC_STOP_SAVE_GRAPH::request& req, COMMAND_RPC_STOP_SAVE_GRAPH::response& res);
@@ -151,6 +154,7 @@ namespace cryptonote
bool on_get_last_block_header(const COMMAND_RPC_GET_LAST_BLOCK_HEADER::request& req, COMMAND_RPC_GET_LAST_BLOCK_HEADER::response& res, epee::json_rpc::error& error_resp);
bool on_get_block_header_by_hash(const COMMAND_RPC_GET_BLOCK_HEADER_BY_HASH::request& req, COMMAND_RPC_GET_BLOCK_HEADER_BY_HASH::response& res, epee::json_rpc::error& error_resp);
bool on_get_block_header_by_height(const COMMAND_RPC_GET_BLOCK_HEADER_BY_HEIGHT::request& req, COMMAND_RPC_GET_BLOCK_HEADER_BY_HEIGHT::response& res, epee::json_rpc::error& error_resp);
bool on_get_block_headers_range(const COMMAND_RPC_GET_BLOCK_HEADERS_RANGE::request& req, COMMAND_RPC_GET_BLOCK_HEADERS_RANGE::response& res, epee::json_rpc::error& error_resp);
bool on_get_block(const COMMAND_RPC_GET_BLOCK::request& req, COMMAND_RPC_GET_BLOCK::response& res, epee::json_rpc::error& error_resp);
bool on_get_connections(const COMMAND_RPC_GET_CONNECTIONS::request& req, COMMAND_RPC_GET_CONNECTIONS::response& res, epee::json_rpc::error& error_resp);
bool on_get_info_json(const COMMAND_RPC_GET_INFO::request& req, COMMAND_RPC_GET_INFO::response& res, epee::json_rpc::error& error_resp);
@@ -160,6 +164,8 @@ namespace cryptonote
bool on_flush_txpool(const COMMAND_RPC_FLUSH_TRANSACTION_POOL::request& req, COMMAND_RPC_FLUSH_TRANSACTION_POOL::response& res, epee::json_rpc::error& error_resp);
bool on_get_output_histogram(const COMMAND_RPC_GET_OUTPUT_HISTOGRAM::request& req, COMMAND_RPC_GET_OUTPUT_HISTOGRAM::response& res, epee::json_rpc::error& error_resp);
bool on_get_version(const COMMAND_RPC_GET_VERSION::request& req, COMMAND_RPC_GET_VERSION::response& res, epee::json_rpc::error& error_resp);
bool on_get_coinbase_tx_sum(const COMMAND_RPC_GET_COINBASE_TX_SUM::request& req, COMMAND_RPC_GET_COINBASE_TX_SUM::response& res, epee::json_rpc::error& error_resp);
bool on_get_per_kb_fee_estimate(const COMMAND_RPC_GET_PER_KB_FEE_ESTIMATE::request& req, COMMAND_RPC_GET_PER_KB_FEE_ESTIMATE::response& res, epee::json_rpc::error& error_resp);
//-----------------------
private:
@@ -172,7 +178,7 @@ private:
//utils
uint64_t get_block_reward(const block& blk);
bool fill_block_header_responce(const block& blk, bool orphan_status, uint64_t height, const crypto::hash& hash, block_header_responce& responce);
bool fill_block_header_response(const block& blk, bool orphan_status, uint64_t height, const crypto::hash& hash, block_header_response& response);
core& m_core;
nodetool::node_server<cryptonote::t_cryptonote_protocol_handler<cryptonote::core> >& m_p2p;

View File

@@ -41,7 +41,16 @@ namespace cryptonote
#define CORE_RPC_STATUS_BUSY "BUSY"
#define CORE_RPC_STATUS_NOT_MINING "NOT MINING"
#define CORE_RPC_VERSION 3
// When making *any* change here, bump minor
// If the change is incompatible, then bump major and set minor to 0
// This ensures CORE_RPC_VERSION always increases, that every change
// has its own version, and that clients can just test major to see
// whether they can talk to a given daemon without having to know in
// advance which version they will stop working with
// Don't go over 32767 for any of these
#define CORE_RPC_VERSION_MAJOR 1
#define CORE_RPC_VERSION_MINOR 0
#define CORE_RPC_VERSION (((CORE_RPC_VERSION_MAJOR)<<16)|(CORE_RPC_VERSION_MINOR))
struct COMMAND_RPC_GET_HEIGHT
{
@@ -162,6 +171,7 @@ namespace cryptonote
std::string as_json;
bool in_pool;
uint64_t block_height;
std::vector<uint64_t> output_indices;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(tx_hash)
@@ -169,6 +179,7 @@ namespace cryptonote
KV_SERIALIZE(as_json)
KV_SERIALIZE(in_pool)
KV_SERIALIZE(block_height)
KV_SERIALIZE(output_indices)
END_KV_SERIALIZE_MAP()
};
@@ -291,22 +302,22 @@ namespace cryptonote
};
};
//-----------------------------------------------
struct COMMAND_RPC_GET_OUTPUTS
struct get_outputs_out
{
struct out
{
uint64_t amount;
uint64_t index;
uint64_t amount;
uint64_t index;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(amount)
KV_SERIALIZE(index)
END_KV_SERIALIZE_MAP()
};
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(amount)
KV_SERIALIZE(index)
END_KV_SERIALIZE_MAP()
};
struct COMMAND_RPC_GET_OUTPUTS_BIN
{
struct request
{
std::vector<out> outputs;
std::vector<get_outputs_out> outputs;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(outputs)
@@ -337,6 +348,42 @@ namespace cryptonote
END_KV_SERIALIZE_MAP()
};
};
//-----------------------------------------------
struct COMMAND_RPC_GET_OUTPUTS
{
struct request
{
std::vector<get_outputs_out> outputs;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(outputs)
END_KV_SERIALIZE_MAP()
};
struct outkey
{
std::string key;
std::string mask;
bool unlocked;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(key)
KV_SERIALIZE(mask)
KV_SERIALIZE(unlocked)
END_KV_SERIALIZE_MAP()
};
struct response
{
std::vector<outkey> outs;
std::string status;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(outs)
KV_SERIALIZE(status)
END_KV_SERIALIZE_MAP()
};
};
struct COMMAND_RPC_GET_RANDOM_RCT_OUTPUTS
{
@@ -464,6 +511,7 @@ namespace cryptonote
uint64_t grey_peerlist_size;
bool testnet;
std::string top_block_hash;
uint64_t cumulative_difficulty;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(status)
@@ -480,6 +528,7 @@ namespace cryptonote
KV_SERIALIZE(grey_peerlist_size)
KV_SERIALIZE(testnet)
KV_SERIALIZE(top_block_hash)
KV_SERIALIZE(cumulative_difficulty)
END_KV_SERIALIZE_MAP()
};
};
@@ -631,7 +680,7 @@ namespace cryptonote
};
};
struct block_header_responce
struct block_header_response
{
uint8_t major_version;
uint8_t minor_version;
@@ -671,7 +720,7 @@ namespace cryptonote
struct response
{
std::string status;
block_header_responce block_header;
block_header_response block_header;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(block_header)
@@ -695,7 +744,7 @@ namespace cryptonote
struct response
{
std::string status;
block_header_responce block_header;
block_header_response block_header;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(block_header)
@@ -719,7 +768,7 @@ namespace cryptonote
struct response
{
std::string status;
block_header_responce block_header;
block_header_response block_header;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(block_header)
@@ -745,7 +794,7 @@ namespace cryptonote
struct response
{
std::string status;
block_header_responce block_header;
block_header_response block_header;
std::vector<std::string> tx_hashes;
std::string blob;
std::string json;
@@ -855,6 +904,8 @@ namespace cryptonote
uint64_t last_failed_height;
std::string last_failed_id_hash;
uint64_t receive_time;
bool relayed;
uint64_t last_relayed_time;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(id_hash)
@@ -867,6 +918,8 @@ namespace cryptonote
KV_SERIALIZE(last_failed_height)
KV_SERIALIZE(last_failed_id_hash)
KV_SERIALIZE(receive_time)
KV_SERIALIZE(relayed)
KV_SERIALIZE(last_failed_id_hash)
END_KV_SERIALIZE_MAP()
};
@@ -940,7 +993,7 @@ namespace cryptonote
struct response
{
std::string status;
std::vector<block_header_responce> headers;
std::vector<block_header_response> headers;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(status)
@@ -1172,26 +1225,33 @@ namespace cryptonote
uint64_t min_count;
uint64_t max_count;
bool unlocked;
uint64_t recent_cutoff;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(amounts);
KV_SERIALIZE(min_count);
KV_SERIALIZE(max_count);
KV_SERIALIZE(unlocked);
KV_SERIALIZE(recent_cutoff);
END_KV_SERIALIZE_MAP()
};
struct entry
{
uint64_t amount;
uint64_t instances;
uint64_t total_instances;
uint64_t unlocked_instances;
uint64_t recent_instances;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(amount);
KV_SERIALIZE(instances);
KV_SERIALIZE(total_instances);
KV_SERIALIZE(unlocked_instances);
KV_SERIALIZE(recent_instances);
END_KV_SERIALIZE_MAP()
entry(uint64_t amount, uint64_t instances): amount(amount), instances(instances) {}
entry(uint64_t amount, uint64_t total_instances, uint64_t unlocked_instances, uint64_t recent_instances):
amount(amount), total_instances(total_instances), unlocked_instances(unlocked_instances), recent_instances(recent_instances) {}
entry() {}
};
@@ -1226,5 +1286,54 @@ namespace cryptonote
END_KV_SERIALIZE_MAP()
};
};
}
struct COMMAND_RPC_GET_COINBASE_TX_SUM
{
struct request
{
uint64_t height;
uint64_t count;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(height);
KV_SERIALIZE(count);
END_KV_SERIALIZE_MAP()
};
struct response
{
std::string status;
uint64_t emission_amount;
uint64_t fee_amount;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(status)
KV_SERIALIZE(emission_amount)
KV_SERIALIZE(fee_amount)
END_KV_SERIALIZE_MAP()
};
};
struct COMMAND_RPC_GET_PER_KB_FEE_ESTIMATE
{
struct request
{
uint64_t grace_blocks;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(grace_blocks)
END_KV_SERIALIZE_MAP()
};
struct response
{
std::string status;
uint64_t fee;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(status)
KV_SERIALIZE(fee)
END_KV_SERIALIZE_MAP()
};
};
}

100
src/serialization/list.h Normal file
View File

@@ -0,0 +1,100 @@
// Copyright (c) 2014-2015, 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.
//
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
#pragma once
#include "serialization.h"
namespace serialization
{
namespace detail
{
template <typename Archive, class T>
bool serialize_list_element(Archive& ar, T& e)
{
return ::do_serialize(ar, e);
}
template <typename Archive>
bool serialize_list_element(Archive& ar, uint64_t& e)
{
ar.serialize_varint(e);
return true;
}
}
}
template <template <bool> class Archive, class T>
bool do_serialize(Archive<false> &ar, std::list<T> &l)
{
size_t cnt;
ar.begin_array(cnt);
if (!ar.stream().good())
return false;
l.clear();
// very basic sanity check
if (ar.remaining_bytes() < cnt) {
ar.stream().setstate(std::ios::failbit);
return false;
}
for (size_t i = 0; i < cnt; i++) {
if (i > 0)
ar.delimit_array();
l.push_back(T());
T &t = l.back();
if (!::serialization::detail::serialize_list_element(ar, t))
return false;
if (!ar.stream().good())
return false;
}
ar.end_array();
return true;
}
template <template <bool> class Archive, class T>
bool do_serialize(Archive<true> &ar, std::list<T> &l)
{
size_t cnt = l.size();
ar.begin_array(cnt);
for (typename std::list<T>::iterator i = l.begin(); i != l.end(); ++i) {
if (!ar.stream().good())
return false;
if (i != l.begin())
ar.delimit_array();
if(!::serialization::detail::serialize_list_element(ar, *i))
return false;
if (!ar.stream().good())
return false;
}
ar.end_array();
return true;
}

96
src/serialization/pair.h Normal file
View File

@@ -0,0 +1,96 @@
// Copyright (c) 2014-2015, 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.
//
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
#pragma once
#include <memory>
#include "serialization.h"
namespace serialization
{
namespace detail
{
template <typename Archive, class T>
bool serialize_pair_element(Archive& ar, T& e)
{
return ::do_serialize(ar, e);
}
template <typename Archive>
bool serialize_pair_element(Archive& ar, uint64_t& e)
{
ar.serialize_varint(e);
return true;
}
}
}
template <template <bool> class Archive, class F, class S>
inline bool do_serialize(Archive<false>& ar, std::pair<F,S>& p)
{
size_t cnt;
ar.begin_array(cnt);
if (!ar.stream().good())
return false;
if (cnt != 2)
return false;
if (!::serialization::detail::serialize_pair_element(ar, p.first))
return false;
if (!ar.stream().good())
return false;
ar.delimit_array();
if (!::serialization::detail::serialize_pair_element(ar, p.second))
return false;
if (!ar.stream().good())
return false;
ar.end_array();
return true;
}
template <template <bool> class Archive, class F, class S>
inline bool do_serialize(Archive<true>& ar, std::pair<F,S>& p)
{
ar.begin_array(2);
if (!ar.stream().good())
return false;
if(!::serialization::detail::serialize_pair_element(ar, p.first))
return false;
if (!ar.stream().good())
return false;
ar.delimit_array();
if(!::serialization::detail::serialize_pair_element(ar, p.second))
return false;
if (!ar.stream().good())
return false;
ar.end_array();
return true;
}

View File

@@ -41,6 +41,7 @@
#pragma once
#include <vector>
#include <list>
#include <string>
#include <boost/type_traits/is_integral.hpp>
#include <boost/type_traits/integral_constant.hpp>
@@ -59,6 +60,16 @@ struct is_blob_type { typedef boost::false_type type; };
template <class T>
struct has_free_serializer { typedef boost::true_type type; };
/*! \struct is_pair_type
*
* \brief a descriptor for dispatching serialize
*/
template <class T>
struct is_pair_type { typedef boost::false_type type; };
template<typename F, typename S>
struct is_pair_type<std::pair<F,S>> { typedef boost::true_type type; };
/*! \struct serializer
*
* \brief ... wouldn't a class be better?
@@ -75,20 +86,26 @@ struct has_free_serializer { typedef boost::true_type type; };
template <class Archive, class T>
struct serializer{
static bool serialize(Archive &ar, T &v) {
return serialize(ar, v, typename boost::is_integral<T>::type(), typename is_blob_type<T>::type());
return serialize(ar, v, typename boost::is_integral<T>::type(), typename is_blob_type<T>::type(), typename is_pair_type<T>::type());
}
static bool serialize(Archive &ar, T &v, boost::false_type, boost::true_type) {
template<typename A>
static bool serialize(Archive &ar, T &v, boost::false_type, boost::true_type, A a) {
ar.serialize_blob(&v, sizeof(v));
return true;
}
static bool serialize(Archive &ar, T &v, boost::true_type, boost::false_type) {
template<typename A>
static bool serialize(Archive &ar, T &v, boost::true_type, boost::false_type, A a) {
ar.serialize_int(v);
return true;
}
static bool serialize(Archive &ar, T &v, boost::false_type, boost::false_type) {
static bool serialize(Archive &ar, T &v, boost::false_type, boost::false_type, boost::false_type) {
//serialize_custom(ar, v, typename has_free_serializer<T>::type());
return v.do_serialize(ar);
}
static bool serialize(Archive &ar, T &v, boost::false_type, boost::false_type, boost::true_type) {
//serialize_custom(ar, v, typename has_free_serializer<T>::type());
return do_serialize(ar, v);
}
static void serialize_custom(Archive &ar, T &v, boost::true_type) {
}
};
@@ -328,3 +345,5 @@ namespace serialization {
#include "string.h"
#include "vector.h"
#include "list.h"
#include "pair.h"

View File

@@ -27,18 +27,16 @@
# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
set(simplewallet_sources
simplewallet.cpp
password_container.cpp)
simplewallet.cpp)
set(simplewallet_headers)
set(simplewallet_private_headers
simplewallet.h
password_container.h)
simplewallet.h)
bitmonero_private_headers(simplewallet
monero_private_headers(simplewallet
${simplewallet_private_headers})
bitmonero_add_executable(simplewallet
monero_add_executable(simplewallet
${simplewallet_sources}
${simplewallet_headers}
${simplewallet_private_headers})

File diff suppressed because it is too large Load Diff

View File

@@ -37,13 +37,14 @@
#include <memory>
#include <boost/optional/optional.hpp>
#include <boost/program_options/variables_map.hpp>
#include "cryptonote_core/account.h"
#include "cryptonote_core/cryptonote_basic_impl.h"
#include "wallet/wallet2.h"
#include "console_handler.h"
#include "password_container.h"
#include "wallet/password_container.h"
#include "crypto/crypto.h" // for definition of crypto::secret_key
/*!
@@ -58,7 +59,6 @@ namespace cryptonote
class simple_wallet : public tools::i_wallet2_callback
{
public:
static bool get_password(const boost::program_options::variables_map& vm, bool allow_entry, tools::password_container &pwd_container);
static const char *tr(const char *str) { return i18n_translate(str, "cryptonote::simple_wallet"); }
public:
@@ -70,7 +70,6 @@ namespace cryptonote
bool run();
void stop();
void interrupt();
bool generate_from_json(const boost::program_options::variables_map& vm, std::string &wallet_file, std::string &password);
//wallet *create_wallet();
bool process_command(const std::vector<std::string> &args);
@@ -82,13 +81,11 @@ namespace cryptonote
void wallet_idle_thread();
bool new_wallet(const std::string &wallet_file, const std::string& password, const crypto::secret_key& recovery_key,
bool recover, bool two_random, bool testnet, const std::string &old_language);
bool new_wallet(const std::string &wallet_file, const std::string& password, const cryptonote::account_public_address& address,
const crypto::secret_key& spendkey, const crypto::secret_key& viewkey, bool testnet);
bool new_wallet(const std::string &wallet_file, const std::string& password, const cryptonote::account_public_address& address,
const crypto::secret_key& viewkey, bool testnet);
bool open_wallet(const std::string &wallet_file, const std::string& password, bool testnet);
bool new_wallet(const boost::program_options::variables_map& vm, const crypto::secret_key& recovery_key,
bool recover, bool two_random, const std::string &old_language);
bool new_wallet(const boost::program_options::variables_map& vm, const cryptonote::account_public_address& address,
const boost::optional<crypto::secret_key>& spendkey, const crypto::secret_key& viewkey);
bool open_wallet(const boost::program_options::variables_map& vm);
bool close_wallet();
bool viewkey(const std::vector<std::string> &args = std::vector<std::string>());
@@ -110,6 +107,7 @@ namespace cryptonote
bool set_default_mixin(const std::vector<std::string> &args = std::vector<std::string>());
bool set_auto_refresh(const std::vector<std::string> &args = std::vector<std::string>());
bool set_refresh_type(const std::vector<std::string> &args = std::vector<std::string>());
bool set_confirm_missing_payment_id(const std::vector<std::string> &args = std::vector<std::string>());
bool help(const std::vector<std::string> &args = std::vector<std::string>());
bool start_mining(const std::vector<std::string> &args);
bool stop_mining(const std::vector<std::string> &args);
@@ -123,8 +121,11 @@ namespace cryptonote
bool transfer_main(int transfer_type, const std::vector<std::string> &args);
bool transfer(const std::vector<std::string> &args);
bool transfer_new(const std::vector<std::string> &args);
bool locked_transfer(const std::vector<std::string> &args);
bool sweep_all(const std::vector<std::string> &args);
bool sweep_unmixable(const std::vector<std::string> &args);
bool sign_transfer(const std::vector<std::string> &args);
bool submit_transfer(const std::vector<std::string> &args);
std::vector<std::vector<cryptonote::tx_destination_entry>> split_amounts(
std::vector<cryptonote::tx_destination_entry> dsts, size_t num_splits
);
@@ -148,10 +149,15 @@ namespace cryptonote
bool verify(const std::vector<std::string> &args);
bool export_key_images(const std::vector<std::string> &args);
bool import_key_images(const std::vector<std::string> &args);
bool export_outputs(const std::vector<std::string> &args);
bool import_outputs(const std::vector<std::string> &args);
uint64_t get_daemon_blockchain_height(std::string& err);
bool try_connect_to_daemon(bool silent = false);
bool ask_wallet_create_if_needed();
bool accept_loaded_tx(const std::function<size_t()> get_num_txes, const std::function<const tools::wallet2::tx_construction_data&(size_t)> &get_tx, const std::string &extra_message = std::string());
bool accept_loaded_tx(const tools::wallet2::unsigned_tx_set &txs);
bool accept_loaded_tx(const tools::wallet2::signed_tx_set &txs);
bool get_address_from_str(const std::string &str, cryptonote::account_public_address &address, bool &has_payment_id, crypto::hash8 &payment_id);
/*!
@@ -247,10 +253,6 @@ namespace cryptonote
bool m_restoring; // are we restoring, by whatever method?
uint64_t m_restore_height; // optional
std::string m_daemon_address;
std::string m_daemon_host;
int m_daemon_port;
epee::console_handlers_binder m_cmd_binder;
std::unique_ptr<tools::wallet2> m_wallet;

View File

@@ -1,4 +1,4 @@
#define MONERO_VERSION_TAG "@VERSIONTAG@"
#define MONERO_VERSION "0.10.0.0"
#define MONERO_VERSION "0.10.1.0"
#define MONERO_RELEASE_NAME "Wolfram Warptangent"
#define MONERO_VERSION_FULL MONERO_VERSION "-" MONERO_VERSION_TAG

View File

@@ -31,21 +31,26 @@
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(wallet_sources
password_container.cpp
wallet2.cpp
wallet_args.cpp
wallet_rpc_server.cpp
api/wallet.cpp
api/wallet_manager.cpp
api/transaction_info.cpp
api/transaction_history.cpp
api/pending_transaction.cpp
api/utils.cpp)
api/utils.cpp
api/address_book.cpp)
set(wallet_api_headers
wallet2_api.h)
set(wallet_private_headers
password_container.h
wallet2.h
wallet_args.h
wallet_errors.h
wallet_rpc_server.h
wallet_rpc_server_commands_defs.h
@@ -55,11 +60,12 @@ set(wallet_private_headers
api/transaction_info.h
api/transaction_history.h
api/pending_transaction.h
api/common_defines.h)
api/common_defines.h
api/address_book.h)
bitmonero_private_headers(wallet
monero_private_headers(wallet
${wallet_private_headers})
bitmonero_add_library(wallet
monero_add_library(wallet
${wallet_sources}
${wallet_api_headers}
${wallet_private_headers})
@@ -76,6 +82,44 @@ target_link_libraries(wallet
${Boost_REGEX_LIBRARY}
PRIVATE
${EXTRA_LIBRARIES})
add_dependencies(wallet version)
if (NOT BUILD_GUI_DEPS)
set(wallet_rpc_sources
wallet_rpc_server.cpp)
set(wallet_rpc_headers)
set(wallet_rpc_private_headers
wallet_rpc_server.h)
monero_private_headers(wallet_rpc_server
${wallet_rpc_private_headers})
monero_add_executable(wallet_rpc_server
${wallet_rpc_sources}
${wallet_rpc_headers}
${wallet_rpc_private_headers})
target_link_libraries(wallet_rpc_server
PRIVATE
wallet
rpc
cryptonote_core
crypto
common
${Boost_CHRONO_LIBRARY}
${Boost_PROGRAM_OPTIONS_LIBRARY}
${Boost_FILESYSTEM_LIBRARY}
${Boost_THREAD_LIBRARY}
${CMAKE_THREAD_LIBS_INIT}
${EXTRA_LIBRARIES})
add_dependencies(wallet_rpc_server version)
set_property(TARGET wallet_rpc_server
PROPERTY
OUTPUT_NAME "monero-wallet-rpc")
install(TARGETS wallet_rpc_server DESTINATION bin)
endif()
# build and install libwallet_merged only if we building for GUI
if (BUILD_GUI_DEPS)

View File

@@ -0,0 +1,131 @@
// Copyright (c) 2014-2016, 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.
//
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
#include "address_book.h"
#include "wallet.h"
#include "crypto/hash.h"
#include "wallet/wallet2.h"
#include <vector>
namespace Monero {
AddressBook::~AddressBook() {}
AddressBookImpl::AddressBookImpl(WalletImpl *wallet)
: m_wallet(wallet) {}
bool AddressBookImpl::addRow(const std::string &dst_addr , const std::string &payment_id, const std::string &description)
{
LOG_PRINT_L2("Adding row");
clearStatus();
cryptonote::account_public_address addr;
bool has_payment_id;
crypto::hash8 payment_id_short;
if(!cryptonote::get_account_integrated_address_from_str(addr, has_payment_id, payment_id_short, m_wallet->m_wallet->testnet(), dst_addr)) {
m_errorString = "Invalid destination address";
m_errorCode = Invalid_Address;
return false;
}
crypto::hash pid32 = cryptonote::null_hash;
bool long_pid = (payment_id.empty())? false : tools::wallet2::parse_long_payment_id(payment_id, pid32);
if(!payment_id.empty() && !long_pid) {
m_errorString = "Invalid payment ID";
m_errorCode = Invalid_Payment_Id;
return false;
}
bool r = m_wallet->m_wallet->add_address_book_row(addr,pid32,description);
if (r)
refresh();
else
m_errorCode = General_Error;
return r;
}
void AddressBookImpl::refresh()
{
LOG_PRINT_L2("Refreshing addressbook");
clearRows();
// Fetch from Wallet2 and create vector of AddressBookRow objects
std::vector<tools::wallet2::address_book_row> rows = m_wallet->m_wallet->get_address_book();
for (size_t i = 0; i < rows.size(); ++i) {
tools::wallet2::address_book_row * row = &rows.at(i);
std::string payment_id = (row->m_payment_id == cryptonote::null_hash)? "" : epee::string_tools::pod_to_hex(row->m_payment_id);
std::string address = cryptonote::get_account_address_as_str(m_wallet->m_wallet->testnet(),row->m_address);
AddressBookRow * abr = new AddressBookRow(i, address, payment_id, row->m_description);
m_rows.push_back(abr);
}
}
bool AddressBookImpl::deleteRow(int rowId)
{
LOG_PRINT_L2("Deleting address book row " << rowId);
bool r = m_wallet->m_wallet->delete_address_book_row(rowId);
if (r)
refresh();
return r;
}
void AddressBookImpl::clearRows() {
for (auto r : m_rows) {
delete r;
}
m_rows.clear();
}
void AddressBookImpl::clearStatus(){
m_errorString = "";
m_errorCode = 0;
}
std::vector<AddressBookRow*> AddressBookImpl::getAll() const
{
return m_rows;
}
AddressBookImpl::~AddressBookImpl()
{
clearRows();
}
} // namespace
namespace Bitmonero = Monero;

View File

@@ -0,0 +1,69 @@
// Copyright (c) 2014-2016, 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.
//
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
#include "wallet/wallet2_api.h"
#include "wallet/wallet2.h"
namespace Monero {
class AddressBookRow;
class WalletImpl;
class AddressBookImpl : public AddressBook
{
public:
AddressBookImpl(WalletImpl * wallet);
~AddressBookImpl();
// Fetches addresses from Wallet2
void refresh();
std::vector<AddressBookRow*> getAll() const;
bool addRow(const std::string &dst_addr , const std::string &payment_id, const std::string &description);
bool deleteRow(int rowId);
// Error codes. See AddressBook:ErrorCode enum in wallet2_api.h
std::string errorString() const {return m_errorString;}
int errorCode() const {return m_errorCode;}
private:
void clearRows();
void clearStatus();
private:
WalletImpl *m_wallet;
std::vector<AddressBookRow*> m_rows;
std::string m_errorString;
int m_errorCode;
};
}
namespace Bitmonero = Monero;

View File

@@ -43,7 +43,7 @@
using namespace std;
namespace Bitmonero {
namespace Monero {
PendingTransaction::~PendingTransaction() {}
@@ -69,11 +69,19 @@ string PendingTransactionImpl::errorString() const
return m_errorString;
}
std::vector<std::string> PendingTransactionImpl::txid() const
{
std::vector<std::string> txid;
for (const auto &pt: m_pending_tx)
txid.push_back(epee::string_tools::pod_to_hex(cryptonote::get_transaction_hash(pt.tx)));
return txid;
}
bool PendingTransactionImpl::commit()
{
LOG_PRINT_L0("m_pending_tx size: " << m_pending_tx.size());
assert(m_pending_tx.size() == 1);
LOG_PRINT_L3("m_pending_tx size: " << m_pending_tx.size());
try {
while (!m_pending_tx.empty()) {
auto & ptx = m_pending_tx.back();
@@ -128,11 +136,18 @@ uint64_t PendingTransactionImpl::dust() const
uint64_t PendingTransactionImpl::fee() const
{
uint64_t result = 0;
for (const auto ptx : m_pending_tx) {
for (const auto &ptx : m_pending_tx) {
result += ptx.fee;
}
return result;
}
uint64_t PendingTransactionImpl::txCount() const
{
return m_pending_tx.size();
}
}
namespace Bitmonero = Monero;

View File

@@ -35,7 +35,7 @@
#include <vector>
namespace Bitmonero {
namespace Monero {
class WalletImpl;
class PendingTransactionImpl : public PendingTransaction
@@ -49,6 +49,8 @@ public:
uint64_t amount() const;
uint64_t dust() const;
uint64_t fee() const;
std::vector<std::string> txid() const;
uint64_t txCount() const;
// TODO: continue with interface;
private:
@@ -62,3 +64,5 @@ private:
}
namespace Bitmonero = Monero;

View File

@@ -42,7 +42,7 @@
using namespace epee;
namespace Bitmonero {
namespace Monero {
TransactionHistory::~TransactionHistory() {}
@@ -55,26 +55,50 @@ TransactionHistoryImpl::TransactionHistoryImpl(WalletImpl *wallet)
TransactionHistoryImpl::~TransactionHistoryImpl()
{
for (auto t : m_history)
delete t;
}
int TransactionHistoryImpl::count() const
{
return m_history.size();
boost::shared_lock<boost::shared_mutex> lock(m_historyMutex);
int result = m_history.size();
return result;
}
TransactionInfo *TransactionHistoryImpl::transaction(int index) const
{
boost::shared_lock<boost::shared_mutex> lock(m_historyMutex);
// sanity check
if (index < 0)
return nullptr;
unsigned index_ = static_cast<unsigned>(index);
return index_ < m_history.size() ? m_history[index_] : nullptr;
}
TransactionInfo *TransactionHistoryImpl::transaction(const std::string &id) const
{
return nullptr;
boost::shared_lock<boost::shared_mutex> lock(m_historyMutex);
auto itr = std::find_if(m_history.begin(), m_history.end(),
[&](const TransactionInfo * ti) {
return ti->hash() == id;
});
return itr != m_history.end() ? *itr : nullptr;
}
std::vector<TransactionInfo *> TransactionHistoryImpl::getAll() const
{
boost::shared_lock<boost::shared_mutex> lock(m_historyMutex);
return m_history;
}
void TransactionHistoryImpl::refresh()
{
// multithreaded access:
// boost::lock_guard<boost::mutex> guarg(m_historyMutex);
// for "write" access, locking exclusively
boost::unique_lock<boost::shared_mutex> lock(m_historyMutex);
// TODO: configurable values;
uint64_t min_height = 0;
uint64_t max_height = (uint64_t)-1;
@@ -84,8 +108,6 @@ void TransactionHistoryImpl::refresh()
delete t;
m_history.clear();
// transactions are stored in wallet2:
// - confirmed_transfer_details - out transfers
// - unconfirmed_transfer_details - pending out transfers
@@ -109,7 +131,7 @@ void TransactionHistoryImpl::refresh()
ti->m_hash = string_tools::pod_to_hex(pd.m_tx_hash);
ti->m_blockheight = pd.m_block_height;
// TODO:
// ti->m_timestamp = pd.m_timestamp;
ti->m_timestamp = pd.m_timestamp;
m_history.push_back(ti);
/* output.insert(std::make_pair(pd.m_block_height, std::make_pair(true, (boost::format("%20.20s %s %s %s")
@@ -135,8 +157,8 @@ void TransactionHistoryImpl::refresh()
const crypto::hash &hash = i->first;
const tools::wallet2::confirmed_transfer_details &pd = i->second;
uint64_t fee = pd.m_amount_in - pd.m_amount_out;
uint64_t change = pd.m_change == (uint64_t)-1 ? 0 : pd.m_change; // change may not be known
uint64_t fee = pd.m_amount_in - pd.m_amount_out;
std::string payment_id = string_tools::pod_to_hex(i->second.m_payment_id);
@@ -151,6 +173,7 @@ void TransactionHistoryImpl::refresh()
ti->m_direction = TransactionInfo::Direction_Out;
ti->m_hash = string_tools::pod_to_hex(hash);
ti->m_blockheight = pd.m_block_height;
ti->m_timestamp = pd.m_timestamp;
// single output transaction might contain multiple transfers
for (const auto &d: pd.m_dests) {
@@ -180,14 +203,11 @@ void TransactionHistoryImpl::refresh()
ti->m_failed = is_failed;
ti->m_pending = true;
ti->m_hash = string_tools::pod_to_hex(hash);
ti->m_timestamp = pd.m_timestamp;
m_history.push_back(ti);
}
}
TransactionInfo *TransactionHistoryImpl::transaction(int index) const
{
return nullptr;
}
} // namespace
}
namespace Bitmonero = Monero;

View File

@@ -29,8 +29,9 @@
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
#include "wallet/wallet2_api.h"
#include <boost/thread/shared_mutex.hpp>
namespace Bitmonero {
namespace Monero {
class TransactionInfo;
class WalletImpl;
@@ -51,7 +52,10 @@ private:
// TransactionHistory is responsible of memory management
std::vector<TransactionInfo*> m_history;
WalletImpl *m_wallet;
mutable boost::shared_mutex m_historyMutex;
};
}
namespace Bitmonero = Monero;

View File

@@ -33,7 +33,7 @@
using namespace std;
namespace Bitmonero {
namespace Monero {
TransactionInfo::~TransactionInfo() {}
@@ -110,3 +110,5 @@ const std::vector<TransactionInfo::Transfer> &TransactionInfoImpl::transfers() c
}
} // namespace
namespace Bitmonero = Monero;

Some files were not shown because too many files have changed in this diff Show More