1
mirror of https://github.com/m2049r/xmrwallet synced 2025-09-03 08:23:04 +02:00

Compare commits

...

170 Commits

Author SHA1 Message Date
m2049r
2c3e73b540 bump version v1.11.7 2019-05-22 08:30:11 +02:00
m2049r
830d9dadb9 paste receiver address (#592) 2019-05-20 17:17:46 +02:00
m2049r
331d88ebba use daemon height for new wallets if available (#591) 2019-05-20 17:17:27 +02:00
m2049r
7cc2f6fafb bump version v1.11.6 2019-05-19 21:34:26 +02:00
m2049r
9a3ee0eda8 fix update of account balances (#590) 2019-05-19 20:27:35 +02:00
m2049r
6e898939a3 show account balances (#589)
and refactor displayAmount
2019-05-19 17:33:19 +02:00
m2049r
40ae39d647 update studio 2019-05-19 10:28:18 +02:00
jindouyunz
ca81e652e5 Update strings.xml_Chinese (#575)
* Update strings.xml

updated on 4/22/2019 version 2, Jindouyunz.

* Update string.xml_Chinese 2019-5-12

Hi, I made several pieces of modification based on lafudoci's review, thanks.

* Update string.xml-zh-rCN 2019-5-13

removed all lines with "translatable=false", and currency array
2019-05-18 08:40:31 +02:00
jindouyunz
796048be4e Update about.xml (#574)
updated on 4/21/2019, Jindouyunz.
2019-05-18 08:39:49 +02:00
jindouyunz
441bf995c8 Update help.xml_Chinese (#573)
* Update help.xml

updated on 4/21/2019, version 2, Jindouyunz

* Update help.xml 2019-5-11

Hi, I add changes on line 200, based on lafudoci's review, thanks.
2019-05-18 08:39:28 +02:00
m2049r
e8860ab8eb focus on password if no fingerprint (#587) 2019-05-12 00:17:21 +02:00
m2049r
525b38ff53 remove save button for notes (#586) 2019-05-12 00:17:07 +02:00
m2049r
ba79bf87aa Update rpc checks (#585)
* check rpc version

* update protocol version check
2019-05-11 21:15:35 +02:00
m2049r
3fe6571e7d update restore heights for 4 & 5.2019 (#583) 2019-05-11 11:41:16 +02:00
erciccione
364e6a8137 update values-it/strings.xml (Italian translation) (#580) 2019-05-11 11:40:20 +02:00
vp11
cb69ce99d6 update pt-BR translation (#581)
* update pt-BR translation

* missing block
2019-05-11 11:40:01 +02:00
m2049r
1f976872fc increase sanity check size limit (#576) 2019-04-23 20:52:43 +02:00
kic0
27f266b6f7 PT-PT translations updated (#569) 2019-04-20 11:03:57 +02:00
m2049r
168928d54a Update studio (#572)
* gradle 5.1

* remove ref to @id/ibBookmark
2019-04-19 15:51:25 +02:00
Leza89
b3f61072aa V1.11.4 - german translations (#556)
* Corrections on the translation without translating

* Added missing commas, hyphens
* replaced diverging terminology with Monero GUI (i.e. Remote Node → Drittanbieter-Node, Saldo → Guthaben, Daemon/Dienst → Hintergrunddienst)
* grammatical adjustments
* unifying the gender of certain words (i.e. "die" Wallet)

* Translations - Draft for peer review

* Corrections according to rodolfo912's review

en-dash as a symbol vs. unicode ;#8211; is yet to be resolved

* Reverting case of "Wallet" from "die" to "das"

As requested by m2049r the article of "Wallet" was reverted back from "die Wallet" to "das Wallet" and corrected in places where it was inconsistent before.
2019-04-19 14:57:49 +02:00
Jack Rogers Lewis
ccb64aded0 SK update help.xml (#568) 2019-04-19 14:49:25 +02:00
Jack Rogers Lewis
e98fa089f2 update new strings (#567)
podadresa = subadresa
2019-04-19 14:48:47 +02:00
Scott Anecito
884878b7a7 Update Japanese localization, fix English typo (#564) 2019-04-19 14:43:56 +02:00
v1docq47
4e23f0ef3a Update for Russian translation #444 (#558)
* Update for Russian translation #444

* fix

added translation of missing lines (help.xml / strings.xml)
2019-03-19 20:12:37 +01:00
0140454
6ea4e3d998 Update zh-rTW translation (#557)
* Update zh-rTW translation

* Update translation for "Using a payment link"
2019-03-19 20:12:16 +01:00
m2049r
971c90f35b Merge pull request #559 from m2049r/feature_enable_ledger
Feature enable ledger
2019-03-19 20:06:17 +01:00
m2049r
f0523c403c bump version 2019-03-19 19:34:04 +01:00
m2049r
966ed23b87 enable ledger again 2019-03-19 19:32:38 +01:00
m2049r
95f2ca74a6 clean code (#555) 2019-03-10 22:00:57 +01:00
m2049r
81d94478f2 update wallet api (#554) 2019-03-10 21:49:57 +01:00
el00ruobuob
16ff779ebc New strings & help update to FR (#552) 2019-03-09 21:58:10 +01:00
m2049r
6b7bb164f4 v1.11.3 (#550) 2019-03-09 00:07:37 +01:00
m2049r
da1d4ea1bf convert ledger seed dialog (#549) 2019-03-09 00:02:58 +01:00
m2049r
d5a967f690 upgrade gradle version (#548) 2019-03-06 16:46:52 +01:00
m2049r
de8de02f9f disable ledger support (#547) 2019-03-05 23:35:11 +01:00
m2049r
06456e33e4 v1.11.1 (#546)
for use with b087cbf995
2019-03-05 21:59:19 +01:00
m2049r
d97b36aa44 v1.11 (#545) 2019-03-02 12:26:36 +01:00
m2049r
8fa06e5b37 2019-03 restore height (#544) 2019-03-02 09:44:40 +01:00
m2049r
8d95de828b prevent screenshots on dialogs (#543) 2019-03-02 09:31:06 +01:00
m2049r
93a7be0452 update slow_hash signature (#542) 2019-03-02 09:07:27 +01:00
m2049r
25c8ec1229 fix reading rest (#541) 2019-02-28 22:07:22 +01:00
m2049r
0bf0444dce seed is a password (#540) 2019-02-28 18:43:32 +01:00
m2049r
b74f9c6bd7 upgrade monero core (#539) 2019-02-28 18:33:16 +01:00
m2049r
f843bb1685 share: multiple send & save only when fired (#537) 2019-02-25 21:55:57 +01:00
m2049r
7d9d49c29e landscape mode on tablets (#535) 2019-02-18 19:05:45 +01:00
m2049r
4ca9328949 bump version (#534) 2019-02-17 20:23:00 +01:00
m2049r
08b5a87f19 get rid of keystore exception on first call (#533) 2019-02-14 23:45:01 +01:00
m2049r
445d8acc38 open on monero: & bitcoin: uri (#532) 2019-02-14 23:34:38 +01:00
m2049r
9385ac8c31 update gradle version 2019-02-11 18:50:43 +01:00
Keksoj
4c7ebd8402 translated 'help', 'strings' and 'about' to esperanto (#531) 2019-02-11 07:41:50 +01:00
m2049r
67f3c5f948 bump version 2019-02-04 19:41:28 +01:00
m2049r
cd67a7e2bf 2019-02 height 2019-02-04 19:41:28 +01:00
0140454
fa5fe313ea Update zh-rTW translation (#529) 2019-02-03 07:54:41 +01:00
jaro Lee
ed4957a3cc sk strings update (#523) 2019-01-29 22:33:09 +01:00
jaro Lee
3e0eeebd51 sk help.xml update (#527)
sk-translation - help_send update
2019-01-29 22:32:40 +01:00
m2049r
0d213a1eb4 hide sweep amount in street mode (#526) 2019-01-28 01:16:00 +01:00
m2049r
39d048fd5e Feature bitpay (#525)
* support bitcoin payment protocol (BIP70/72)

* prep translations
2019-01-27 21:32:06 +01:00
m2049r
1a5d2d0399 Update Android Studio v3.3 (#522)
* Update Android Studio v3.3

* also update circleci script to accept licenses
2019-01-21 17:38:59 +01:00
m2049r
028057a672 bump version (#519) 2019-01-14 12:52:28 +01:00
TheFuzzStone
909ff8ca5e Ukranian translation for Monerujo (#517)
* Ukranian translation

* Update for Russian language (fixed small typos)
2019-01-12 19:56:59 +01:00
m2049r
ffd61e4495 remove getErrorString method (#516) 2019-01-11 19:24:33 +01:00
m2049r
003dee382e Merge pull request #515 from m2049r/fix_license
SwipeableRecyclerView license
2019-01-11 19:23:56 +01:00
m2049r
be0498c67d SwipeableRecyclerView license 2019-01-11 19:23:25 +01:00
m2049r
06227a4a83 Merge pull request #514 from m2049r/feature_dismissTx
Allow swipe-to-dismiss transactions in street mode
2019-01-10 19:33:26 +01:00
m2049r
4409087bd0 update dependencies 2019-01-10 19:31:34 +01:00
m2049r
965e52d8a5 allow to dismiss tx in streetmode 2019-01-10 19:31:15 +01:00
m2049r
beba0f497b Fix bech32 (#513)
* fix bech32 recognition

* bump version
2019-01-09 20:54:14 +01:00
m2049r
9d1827ff0d show current node (#511)
& bump version
2019-01-08 22:13:25 +01:00
m2049r
c04b192753 keep node once found (#510) 2019-01-06 10:57:25 +01:00
m2049r
888b5edaec height for jan19 (#509) 2019-01-06 09:56:00 +01:00
netrik182
5ee5a81926 updated pt-BR translation help and node strings (#491)
* updated pt-BR translation for #440

* update help.xml after review

* update strings.xml after review

* update help.xml after further peer review
2019-01-05 13:42:49 +01:00
m2049r
c4e361a873 allow bech32 segwit btc addresses (#508) 2019-01-05 13:42:22 +01:00
m2049r
dba6cb057e add restore height for december (#502) 2018-12-23 08:29:21 +01:00
m2049r
9e1167c5b9 read unsigned types & read payload_data (top_version...) (#501) 2018-12-23 08:12:50 +01:00
Hans
12546a1ade [Estonian] Some additional translations (#497) 2018-12-23 07:48:20 +01:00
BlackLotus64
e9313bc235 ES Translation of strings and help v2 (#490) 2018-12-08 18:26:20 +01:00
m2049r
7e9bf84640 tweaks to barcode/tag reading (#494)
- deal with empty payment_id
- use btc message as description
- BarcodeData is final
2018-12-02 10:23:07 +01:00
m2049r
94f87a5193 bump version 2018-11-28 22:03:24 +01:00
Lafudoci
8a8fc5ec9e Node-o-matiC translation in zh-tw (#488) 2018-11-28 19:47:29 +01:00
joshuamarques
036d4ebf6c Japanese translation added (#481) 2018-11-28 07:52:16 +01:00
m2049r
c6d4de8599 bump version 2018-11-26 23:39:01 +01:00
m2049r
2ef7f8571c adjust & tweak tx details layout (#489) 2018-11-26 23:08:32 +01:00
m2049r
d2612a26e5 show my tx (sub)address (#487) 2018-11-26 12:05:40 +01:00
m2049r
7e14572756 (optional) disable crazypass generation (#486)
* (optional) disable crazypass generation

* update FAQ about disabling crazypass
2018-11-26 12:05:25 +01:00
hrumag
6f840dcacf [IT-Translation] help.xml / strings.xml - First Issue (#480)
* [IT-Translation] help.xml / strings.xml

* [IT-Translation] Fixes from @erciccione and @serhack
2018-11-26 12:05:03 +01:00
m2049r
36b389cd0f USE_FINGERPRINT & bump version 2018-11-24 23:39:35 +01:00
m2049r
ed2b95ea37 Fix android9 permissions (#484)
* FOREGROUND_SERVICE for Android 9

* USE_BIOMETRIC for Android 9
2018-11-24 23:03:20 +01:00
m2049r
8d41d1d03e Stagenet build config (#483)
* combine gitignores

* stagenet build config
2018-11-24 22:28:33 +01:00
m2049r
e2e9da3437 bump version 2018-11-24 13:08:38 +01:00
m2049r
7cd07d1988 resurrect 'backup successful' message (#482) 2018-11-24 13:00:31 +01:00
Lafudoci
f5ae0525e3 Street mode translation in zh-tw (#465)
* Street mode translation in zh-tw

* Change street mode translation and minor fix

* Replace private mode translation to low profile mode
2018-11-24 11:32:12 +01:00
jaro Lee
b32ed8caf2 values-sk update (#479)
* Ledger and NFC support added
* minor typo fixes
* removed string  <string name="menu_language">
2018-11-24 11:29:48 +01:00
el00ruobuob
e0c2bfc4c4 French Nodes (#477) 2018-11-24 11:21:39 +01:00
m2049r
2986dfeaa7 nodes help (#476) 2018-11-20 21:10:25 +01:00
m2049r
acb7398dca Merge pull request #475 from m2049r/feature_nodes
- Feature node-o-matic
- allow fingerprint return from streetmode
2018-11-20 21:05:32 +01:00
m2049r
c8322f5a83 fingerprint return from streetmode 2018-11-20 20:06:56 +01:00
m2049r
973472e0ef Node-o-matiC 2018-11-20 19:20:51 +01:00
m2049r
2dad55e498 revert avoiding NPE 2018-11-13 22:51:43 +01:00
m2049r
8e82bd4cc8 fix typo (#472) 2018-11-13 22:35:01 +01:00
m2049r
38a825d580 avoid possible NPE (#471) 2018-11-13 22:32:31 +01:00
m2049r
be04185481 fix disappearing progressbar during sync (#470) 2018-11-13 21:58:32 +01:00
m2049r
5bfb920979 Direct Streetmode & credentials for disabling it (#469)
- Add wallet menu item to enter streetmode directly
- Add credentials check to leave streetmode (someone-snatches-your-phone-scenario)
- Recheck credentials for showing secrets after entering streetmode
2018-11-13 19:08:51 +01:00
m2049r
29583fa40d fix crash when no ledger connected (#463) 2018-11-05 18:47:11 +01:00
el00ruobuob
dc86f0469e Update FR for street mode (#464)
+ corrections after review
2018-11-05 18:28:34 +01:00
hrumag
9e48f2bdcb [i18n-IT] Aligned translation of new features (#461)
* [i18n-IT] Aligned translation of new features

* [i18n-IT] Translation change "menu_info"

Dettagli => Mostra i segreti!
2018-11-05 18:26:25 +01:00
Hans
b71c260323 Update to Estonian translations (#462) 2018-11-04 23:12:39 +01:00
m2049r
46dbc0659b vital fixes to translations (#460) 2018-11-03 17:24:11 +01:00
m2049r
85622b3958 bump version 2018-11-03 17:17:02 +01:00
m2049r
5a63481c09 correct static jni methods (#459) 2018-11-03 16:59:16 +01:00
m2049r
1cb558d78e streetmode hides all balances & previous transactions (#458) 2018-11-03 16:45:34 +01:00
Hans
942c80e38b Estonian translations (#447)
* Create about.xml

* Create help.xml

* Create strings.xml
2018-11-03 16:11:25 +01:00
m2049r
24ec848f0f 2018-11-01 height 2018-11-03 11:06:49 +01:00
m2049r
0d1b1da5f3 remove v9 notice (#457) 2018-11-03 09:45:39 +01:00
jaro Lee
0840d2f350 Update strings.xml (#445)
new strings translated , few old strings tuned
2018-10-31 12:25:01 +01:00
hrumag
c7d933ea9d [strings_it.xml] Correct some translations (#450)
"subaddress" => "sottoindirizzo"
"balance => "saldo"
Fix '/n' with '\n'
2018-10-31 12:24:42 +01:00
vp1111
c9b1800309 Translation to Brazilian Portuguese (pt-rBR). (#455)
* Translation to Brazilian Portuguese (pt-rBR).

* adopted some of shigutso's suggestions

* adopted some of netrik's suggestions
2018-10-31 12:24:12 +01:00
m2049r
e7b0b5999e remove help for ringsize & priority (#448) 2018-10-18 09:10:21 +02:00
m2049r
47e1871693 update buildToolsVersion 2018-10-17 22:23:43 +02:00
m2049r
900eab70c8 update gradle 2018-10-16 22:27:01 +02:00
m2049r
b11357f379 bump version 2018-10-13 10:05:52 +02:00
m2049r
eba0156a6d info/warn about v9 upgrade (#442) 2018-10-13 10:05:17 +02:00
m2049r
bf64d8bd89 add 2018-10-01 height (#441) 2018-10-13 10:04:30 +02:00
m2049r
2d74281b31 bump version 2018-10-12 23:05:14 +02:00
m2049r
668cefb357 explicit check pw (#439)
also, revert device type query changes
2018-10-12 23:03:53 +02:00
0140454
1f5061df38 Update zh-rTW translation for node version warning (#437) 2018-10-11 17:41:59 +02:00
m2049r
51445f5941 Fix build (#435) 2018-10-10 21:12:18 +02:00
m2049r
8c01ec36e8 deal with illegal values for device type (#434) 2018-10-10 21:11:59 +02:00
m2049r
3cf84c599d ignore build directories 2018-10-10 08:01:56 +02:00
m2049r
ead8564688 bump version 2018-10-09 19:38:06 +02:00
m2049r
b71b3badd8 remove settings & fix prio to default (#433) 2018-10-09 19:33:29 +02:00
ProkhorZ
5ad46e2f54 Add node version warning (#432)
for monero v0.13 upgrade.
2018-10-09 07:59:49 +02:00
m2049r
9d6895b60f adding missing resources 2018-10-08 23:10:25 +02:00
m2049r
a8755ee0da correct error message 2018-10-08 22:50:40 +02:00
m2049r
f186bc9d4f core wallet api 0.13 2018-10-08 22:50:16 +02:00
ProkhorZ
9cb961a368 Translate missing strings (#429)
As requested in #411
2018-10-08 22:34:00 +02:00
m2049r
aa78541b6f fix build 2018-10-08 20:58:26 +02:00
v1docq47
eba6a78004 Update for Russian translation #370 (#422)
* Update for Russian translation
- strings.xml
- help.xml
2018-10-08 19:44:56 +02:00
m2049r
8587eab41c whitespace & cleanup 2018-10-08 19:02:00 +02:00
m2049r
4271c743c7 update wallet balance on refresh 2018-10-08 19:02:00 +02:00
m2049r
5b60987692 remove beta flavor 2018-10-08 19:02:00 +02:00
m2049r
e1bd04c945 tweaks & new version 2018-10-08 19:02:00 +02:00
m2049r
ef29db62c4 change error message 2018-10-08 19:02:00 +02:00
m2049r
82ce12e27c increase mixin to 10 as per protocol v8 2018-10-08 19:02:00 +02:00
m2049r
4211687981 rework build process 2018-10-08 19:02:00 +02:00
m2049r
d398416a3d translation prep 2018-10-08 19:02:00 +02:00
m2049r
1844d84be8 whitespace 2018-10-08 19:02:00 +02:00
m2049r
5101b7da5e flavor alpha,beta 2018-10-08 19:02:00 +02:00
m2049r
3e90f2e22e new Ledger interface 2018-10-08 19:02:00 +02:00
m2049r
f01a8eac5d bump version 2018-10-08 19:02:00 +02:00
m2049r
0c13338dc0 link with libsodium 2018-10-08 19:02:00 +02:00
m2049r
78d6fef3e4 getDeviceType 2018-10-08 19:02:00 +02:00
m2049r
cbddcdc92d new api & queryWalletDevice 2018-10-08 19:02:00 +02:00
jaro Lee
4289aaac77 Update strings.xml (#428)
Minor translation misssteps. Bringing to context.
Regarding `send_settings_title` - NASTAVENIA string is too long (wrapping the text in a button). Changed to `Možnosti`  (options in english)
2018-10-08 19:00:55 +02:00
m2049r
fd15da9c84 cleaned old/irrelevant stuff 2018-10-08 18:59:36 +02:00
m2049r
c3357087d5 add missing strings 2018-10-08 13:35:10 +02:00
m2049r
47e0bc86fd fixed positional formatting 2018-10-08 13:35:10 +02:00
Wobole
dbd45ea4f5 Update german translation (#425) 2018-10-08 13:02:06 +02:00
ProkhorZ
90c3e6ef8b Add Dutch translation in values-nl (#411) 2018-10-08 13:00:17 +02:00
m2049r
bc6a816462 upgrade AndroidStudio 2018-09-25 22:39:07 +02:00
m2049r
274a1a25f1 correct cstdio files to patch 2018-09-25 21:27:05 +02:00
m2049r
9e3a2b102e correct sed syntax 2018-09-25 20:53:58 +02:00
Johan Lindqvist
647ae9a565 Patch 1 (#414)
* Added Swedish translations

* Fixed spelling error
2018-09-23 08:38:20 +02:00
m2049r
2bbd20855f deal correctly with escaped strings (#419) 2018-09-22 11:20:31 +02:00
erciccione
b8fc5f910a add 'ErCiccione' to the credits (#417) 2018-09-21 18:26:22 +02:00
erciccione
01700cf780 update values-it/strings.xml (#413) 2018-09-21 14:39:05 +02:00
Lafudoci
2fa6286b0e Update zh-rTW translation for OpenAlias (#415) 2018-09-21 14:37:24 +02:00
jar'o Lee
0ac1680e75 Update strings.xml (#416)
new strings translated , minor fix of weird-sounding old translation (restore height)
2018-09-21 14:37:06 +02:00
el00ruobuob
bd9a98e0d8 French translation OpenAlias & Language menu (#412) 2018-09-21 14:36:47 +02:00
jenniferberger
8a5121e792 enhance build description (#271)
Writing a script to build the artifacts in a reproducible environment
- PATH for openssl build was not set
- branch for m2049r/monero.git was not set
2018-09-21 09:52:07 +02:00
m2049r
5e6d3f3032 refresh qr code when notes changed (#410) 2018-09-18 21:25:46 +02:00
233 changed files with 17703 additions and 3555 deletions

View File

@@ -3,11 +3,13 @@ jobs:
build:
working_directory: ~/code
docker:
- image: bitriseio/android-ndk
- image: circleci/android:api-28-ndk
environment:
JVM_OPTS: -Xmx3200m
steps:
- checkout
- run: yes | sdkmanager --licenses || exit 0
- run: yes | sdkmanager --update || exit 0
- restore_cache:
key: jars-{{ checksum "build.gradle" }}-{{ checksum "app/build.gradle" }}
- run:

7
.gitignore vendored
View File

@@ -6,4 +6,11 @@
/captures
.externalNativeBuild
.DS_Store
/app/build
/app/release
/app/alpha
/app/prod
/app/alphaMainnet
/app/prodMainnet
/app/alphaStagenet
/app/prodStagenet

3
.idea/.gitignore generated vendored
View File

@@ -1,3 +0,0 @@
workspace.xml
markdown-*
misc.xml

1
.idea/.name generated
View File

@@ -1 +0,0 @@
xmrwallet

22
.idea/compiler.xml generated
View File

@@ -1,22 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<resourceExtensions />
<wildcardResourcePatterns>
<entry name="!?*.java" />
<entry name="!?*.form" />
<entry name="!?*.class" />
<entry name="!?*.groovy" />
<entry name="!?*.scala" />
<entry name="!?*.flex" />
<entry name="!?*.kt" />
<entry name="!?*.clj" />
<entry name="!?*.aj" />
</wildcardResourcePatterns>
<annotationProcessing>
<profile default="true" name="Default" enabled="false">
<processorPath useClasspath="true" />
</profile>
</annotationProcessing>
</component>
</project>

View File

@@ -1,3 +0,0 @@
<component name="CopyrightManager">
<settings default="" />
</component>

18
.idea/gradle.xml generated
View File

@@ -1,18 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" />
</set>
</option>
<option name="resolveModulePerSourceSet" value="false" />
</GradleProjectSettings>
</option>
</component>
</project>

9
.idea/modules.xml generated
View File

@@ -1,9 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" />
<module fileurl="file://$PROJECT_DIR$/xmrwallet.iml" filepath="$PROJECT_DIR$/xmrwallet.iml" />
</modules>
</component>
</project>

View File

@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RunConfigurationProducerService">
<option name="ignoredProducers">
<set>
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
</set>
</option>
</component>
</project>

6
.idea/vcs.xml generated
View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

View File

@@ -22,12 +22,8 @@ Help us translate Monerujo! You can find instructions [On Taiga](https://taiga.g
You may lose all your Moneroj if you use this App. Be cautious when spending on the mainnet.
### Random Notes
- Based off monero v0.11.1.0
- currently only android32 (runs on 64-bit as well)
- works on the testnet & mainnet
- sync is slow due to 32-bit architecture
- works on the mainnet & stagenet
- use your own daemon - it's easy
- screen stays on until first sync is complete
- Monerujo means "Monero Wallet" according to https://www.reddit.com/r/Monero/comments/3exy7t/esperanto_corner/
### TODO
@@ -43,13 +39,8 @@ of the "real" testnet. After creating a new wallet, make a **new** one by recov
The official monero client shows the same behaviour.
### HOW TO BUILD
No need to build. Binaries are included:
- openssl-1.0.2l
- monero-v0.12
- boost_1_58_0
If you want to build them yourself (recommended) check out [the instructions](doc/BUILDING-external-libs.md)
See [the instructions](doc/BUILDING-external-libs.md)
Then, fire up Android Studio and build the APK.

3
app/.gitignore vendored
View File

@@ -1,3 +0,0 @@
.externalNativeBuild
build
app.iml

View File

@@ -7,13 +7,21 @@ add_library( monerujo
set(EXTERNAL_LIBS_DIR ${CMAKE_SOURCE_DIR}/../external-libs)
############
# libsodium
############
add_library(sodium STATIC IMPORTED)
set_target_properties(sodium PROPERTIES IMPORTED_LOCATION
${EXTERNAL_LIBS_DIR}/libsodium/lib/${ANDROID_ABI}/libsodium.a)
############
# OpenSSL
############
add_library(crypto STATIC IMPORTED)
set_target_properties(crypto PROPERTIES IMPORTED_LOCATION
${EXTERNAL_LIBS_DIR}/openssl/lib/${ANDROID_ABI}/libcrypto.a)
${EXTERNAL_LIBS_DIR}/openssl/lib/${ANDROID_ABI}/libcrypto.a)
add_library(ssl STATIC IMPORTED)
set_target_properties(ssl PROPERTIES IMPORTED_LOCATION
@@ -184,5 +192,7 @@ target_link_libraries( monerujo
ssl
crypto
sodium
${log-lib}
)

View File

@@ -1,14 +1,15 @@
apply plugin: 'com.android.application'
android {
compileSdkVersion 27
buildToolsVersion '28.0.2'
compileSdkVersion 28
buildToolsVersion '28.0.3'
defaultConfig {
applicationId "com.m2049r.xmrwallet"
minSdkVersion 21
targetSdkVersion 27
versionCode 122
versionName "1.7.2 'OpenAlias'"
targetSdkVersion 28
versionCode 177
versionName "1.11.7 'Chernushka'"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
@@ -18,6 +19,26 @@ android {
}
}
flavorDimensions 'type', 'net'
productFlavors {
mainnet {
dimension 'net'
}
stagenet {
dimension 'net'
applicationIdSuffix '.stage'
versionNameSuffix ' (stage)'
}
alpha {
dimension 'type'
applicationIdSuffix '.alpha'
versionNameSuffix ' (alpha)'
}
prod {
dimension 'type'
}
}
buildTypes {
release {
minifyEnabled false
@@ -27,6 +48,7 @@ android {
applicationIdSuffix ".debug"
}
}
externalNativeBuild {
cmake {
path "CMakeLists.txt"
@@ -61,9 +83,13 @@ android {
output ->
def abiName = output.getFilter(com.android.build.OutputFile.ABI)
output.versionCodeOverride = abiCodes.get(abiName, 0) + 10 * variant.versionCode
//def flavor = output.getFilter(flavor)
if (abiName == null) abiName = "universal"
def v = "${variant.versionName}".replaceFirst(" .*\$", "").replace(".", "x")
def v = "${variant.versionName}".replaceFirst(" '.*' ?", "")
.replace(".", "x")
.replace("(", "-")
.replace(")", "")
outputFileName = "$rootProject.ext.apkName-" + v + "_" + abiName + ".apk"
}
}
@@ -75,9 +101,11 @@ dependencies {
implementation "com.android.support:support-v4:$rootProject.ext.supportVersion"
implementation "com.android.support:recyclerview-v7:$rootProject.ext.supportVersion"
implementation "com.android.support:cardview-v7:$rootProject.ext.supportVersion"
implementation "com.android.support:swiperefreshlayout:$rootProject.ext.supportVersion"
implementation 'me.dm7.barcodescanner:zxing:1.9.8'
implementation "com.squareup.okhttp3:okhttp:$rootProject.ext.okHttpVersion"
implementation "com.burgstaller:okhttp-digest:1.18"
implementation "com.jakewharton.timber:timber:$rootProject.ext.timberVersion"
implementation 'com.nulab-inc:zxcvbn:1.2.3'
@@ -85,10 +113,16 @@ dependencies {
implementation 'dnsjava:dnsjava:2.1.8'
implementation 'org.jitsi:dnssecjava:1.1.3'
implementation 'org.slf4j:slf4j-nop:1.7.25'
implementation 'com.github.brnunes:swipeablerecyclerview:1.0.2'
// https://mvnrepository.com/artifact/com.github.aelstad/keccakj
implementation 'com.github.aelstad:keccakj:1.1.0'
testImplementation "junit:junit:$rootProject.ext.junitVersion"
testImplementation "org.mockito:mockito-all:$rootProject.ext.mockitoVersion"
testImplementation "com.squareup.okhttp3:mockwebserver:$rootProject.ext.okHttpVersion"
testImplementation 'org.json:json:20140107'
testImplementation 'net.jodah:concurrentunit:0.4.2'
testImplementation 'org.json:json:20180813'
testImplementation 'net.jodah:concurrentunit:0.4.4'
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 244 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

View File

@@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name" translatable="false">monerujo - Debug</string>
</resources>

View File

@@ -7,8 +7,10 @@
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
<uses-permission android:name="android.permission.NFC" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<application
android:name=".XmrWalletApplication"
@@ -16,21 +18,22 @@
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/MyMaterialTheme">
android:theme="@style/MyMaterialTheme"
android:usesCleartextTraffic="true">
<activity
android:name=".WalletActivity"
android:configChanges="orientation|keyboardHidden"
android:label="@string/wallet_activity_name"
android:launchMode="singleTask"
android:screenOrientation="portrait" />
android:screenOrientation="behind" />
<activity
android:name=".LoginActivity"
android:configChanges="orientation|keyboardHidden"
android:label="@string/app_name"
android:launchMode="singleTop"
android:screenOrientation="portrait">
android:screenOrientation="locked">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
@@ -39,15 +42,41 @@
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
</intent-filter>
<intent-filter android:label="@string/app_name">
<action android:name="android.intent.action.VIEW" />
<data android:scheme="monero" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
</intent-filter>
<intent-filter android:label="@string/app_name">
<action android:name="android.intent.action.VIEW" />
<data android:scheme="bitcoin" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
</intent-filter>
<meta-data
android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
android:resource="@xml/usb_device_filter" />
</activity>
<service
android:name=".service.WalletService"
android:description="@string/service_description"
android:exported="false"
android:label="Monero Wallet Service" />
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/filepaths" />
</provider>
</application>
</manifest>

View File

@@ -43,6 +43,9 @@ Copyright (c) 2014 Dushyanth Maguluru
<h3>AndroidLicensesPage (https://github.com/adamsp/AndroidLicensesPage)</h3>
Copyright (c) 2013 Adam Speakman
<h3>SwipeableRecyclerView (https://github.com/brnunes/SwipeableRecyclerView)</h3>
Copyright (c) 2015 Bruno R. Nunes
<h3>Apache License, Version 2.0, January 2004</h3>
http://www.apache.org/licenses/<br/>
<br/>

View File

@@ -0,0 +1,88 @@
// Copyright (c) 2017-2018, 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.
//
#if defined(HAVE_MONERUJO)
#ifdef __cplusplus
extern "C"
{
#endif
/**
* @brief LedgerFind - find Ledger Device and return it's name
* @param buffer - buffer for name of found device
* @param len - length of buffer
* @return 0 - success
* -1 - no device connected / found
* -2 - JVM not found
*/
int LedgerFind(char *buffer, size_t len);
/**
* @brief LedgerExchange - exchange data with Ledger Device
* @param command - buffer for data to send
* @param cmd_len - length of send to send
* @param response - buffer for received data
* @param max_resp_len - size of receive buffer
*
* @return length of received data in response or -1 if error
*/
int LedgerExchange(unsigned char *command, unsigned int cmd_len, unsigned char *response, unsigned int max_resp_len);
#ifdef __cplusplus
}
#endif
#include "device_io.hpp"
#pragma once
namespace hw {
namespace io {
class device_io_monerujo: device_io {
public:
device_io_monerujo() {};
~device_io_monerujo() {};
void init() {};
void release() {};
void connect(void *params) {};
void disconnect() {};
bool connected() const {return true;}; // monerujo is always connected before it gets here
// returns number of bytes read or -1 on error
int exchange(unsigned char *command, unsigned int cmd_len, unsigned char *response, unsigned int max_resp_len) {
return LedgerExchange(command, cmd_len, response, max_resp_len);
}
};
};
};
#endif //#if defined(HAVE_MONERUJO)

File diff suppressed because it is too large Load Diff

View File

@@ -60,14 +60,14 @@ enum {
HASH_DATA_AREA = 136
};
void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int prehashed);
void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int prehashed, uint64_t height);
inline void slow_hash(const void *data, const size_t length, char *hash) {
cn_slow_hash(data, length, hash, 0 /* variant */, 0/*prehashed*/);
cn_slow_hash(data, length, hash, 0 /*variant*/, 0 /*prehashed*/, 0 /*height*/);
}
inline void slow_hash_broken(const void *data, char *hash, int variant) {
cn_slow_hash(data, 200 /*sizeof(union hash_state)*/, hash, variant, 1 /*prehashed*/);
cn_slow_hash(data, 200 /*sizeof(union hash_state)*/, hash, variant, 1 /*prehashed*/, 0 /*height*/);
}
#ifdef __cplusplus

View File

@@ -1,46 +0,0 @@
/**
* Copyright (c) 2018 m2049r
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef XMRWALLET_LEDGER_H
#define XMRWALLET_LEDGER_H
#ifdef __cplusplus
extern "C"
{
#endif
#define SCARD_S_SUCCESS ((LONG)0x00000000) /**< No error was encountered. */
#define SCARD_E_INSUFFICIENT_BUFFER ((LONG)0x80100008) /**< The data buffer to receive returned data is too small for the returned data. */
#define SCARD_E_NO_READERS_AVAILABLE ((LONG)0x8010002E) /**< Cannot find a smart card reader. */
typedef long LONG;
typedef unsigned long DWORD;
typedef DWORD *LPDWORD;
typedef unsigned char BYTE;
typedef BYTE *LPBYTE;
typedef const BYTE *LPCBYTE;
typedef char CHAR;
typedef CHAR *LPSTR;
int LedgerFind(char *buffer, size_t len);
LONG LedgerExchange(LPCBYTE pbSendBuffer, DWORD cbSendLength, LPBYTE pbRecvBuffer, LPDWORD pcbRecvLength);
#ifdef __cplusplus
}
#endif
#endif //XMRWALLET_LEDGER_H

View File

@@ -23,9 +23,9 @@ package com.btchip.comm;
import com.btchip.BTChipException;
public interface BTChipTransport {
public byte[] exchange(byte[] command);
byte[] exchange(byte[] command);
public void close();
void close();
public void setDebug(boolean debugFlag);
void setDebug(boolean debugFlag);
}

View File

@@ -0,0 +1,145 @@
/*
* Copyright (c) 2018 m2049r
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.m2049r.levin.data;
import com.m2049r.levin.util.HexHelper;
import com.m2049r.levin.util.LevinReader;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
public class Bucket {
// constants copied from monero p2p & epee
public final static int P2P_COMMANDS_POOL_BASE = 1000;
public final static int COMMAND_HANDSHAKE_ID = P2P_COMMANDS_POOL_BASE + 1;
public final static int COMMAND_TIMED_SYNC_ID = P2P_COMMANDS_POOL_BASE + 2;
public final static int COMMAND_PING_ID = P2P_COMMANDS_POOL_BASE + 3;
public final static int COMMAND_REQUEST_STAT_INFO_ID = P2P_COMMANDS_POOL_BASE + 4;
public final static int COMMAND_REQUEST_NETWORK_STATE_ID = P2P_COMMANDS_POOL_BASE + 5;
public final static int COMMAND_REQUEST_PEER_ID_ID = P2P_COMMANDS_POOL_BASE + 6;
public final static int COMMAND_REQUEST_SUPPORT_FLAGS_ID = P2P_COMMANDS_POOL_BASE + 7;
public final static long LEVIN_SIGNATURE = 0x0101010101012101L; // Bender's nightmare
public final static long LEVIN_DEFAULT_MAX_PACKET_SIZE = 100000000; // 100MB by default
public final static int LEVIN_PACKET_REQUEST = 0x00000001;
public final static int LEVIN_PACKET_RESPONSE = 0x00000002;
public final static int LEVIN_PROTOCOL_VER_0 = 0;
public final static int LEVIN_PROTOCOL_VER_1 = 1;
public final static int LEVIN_OK = 0;
public final static int LEVIN_ERROR_CONNECTION = -1;
public final static int LEVIN_ERROR_CONNECTION_NOT_FOUND = -2;
public final static int LEVIN_ERROR_CONNECTION_DESTROYED = -3;
public final static int LEVIN_ERROR_CONNECTION_TIMEDOUT = -4;
public final static int LEVIN_ERROR_CONNECTION_NO_DUPLEX_PROTOCOL = -5;
public final static int LEVIN_ERROR_CONNECTION_HANDLER_NOT_DEFINED = -6;
public final static int LEVIN_ERROR_FORMAT = -7;
public final static int P2P_SUPPORT_FLAG_FLUFFY_BLOCKS = 0x01;
public final static int P2P_SUPPORT_FLAGS = P2P_SUPPORT_FLAG_FLUFFY_BLOCKS;
final private long signature;
final private long cb;
final public boolean haveToReturnData;
final public int command;
final public int returnCode;
final private int flags;
final private int protcolVersion;
final byte[] payload;
final public Section payloadSection;
// create a request
public Bucket(int command, byte[] payload) throws IOException {
this.signature = LEVIN_SIGNATURE;
this.cb = payload.length;
this.haveToReturnData = true;
this.command = command;
this.returnCode = 0;
this.flags = LEVIN_PACKET_REQUEST;
this.protcolVersion = LEVIN_PROTOCOL_VER_1;
this.payload = payload;
payloadSection = LevinReader.readPayload(payload);
}
// create a response
public Bucket(int command, byte[] payload, int rc) throws IOException {
this.signature = LEVIN_SIGNATURE;
this.cb = payload.length;
this.haveToReturnData = false;
this.command = command;
this.returnCode = rc;
this.flags = LEVIN_PACKET_RESPONSE;
this.protcolVersion = LEVIN_PROTOCOL_VER_1;
this.payload = payload;
payloadSection = LevinReader.readPayload(payload);
}
public Bucket(DataInput in) throws IOException {
signature = in.readLong();
cb = in.readLong();
haveToReturnData = in.readBoolean();
command = in.readInt();
returnCode = in.readInt();
flags = in.readInt();
protcolVersion = in.readInt();
if (signature == Bucket.LEVIN_SIGNATURE) {
if (cb > Integer.MAX_VALUE)
throw new IllegalArgumentException();
payload = new byte[(int) cb];
in.readFully(payload);
} else
throw new IllegalStateException();
payloadSection = LevinReader.readPayload(payload);
}
public Section getPayloadSection() {
return payloadSection;
}
public void send(DataOutput out) throws IOException {
out.writeLong(signature);
out.writeLong(cb);
out.writeBoolean(haveToReturnData);
out.writeInt(command);
out.writeInt(returnCode);
out.writeInt(flags);
out.writeInt(protcolVersion);
out.write(payload);
}
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("sig: ").append(signature).append("\n");
sb.append("cb: ").append(cb).append("\n");
sb.append("call: ").append(haveToReturnData).append("\n");
sb.append("cmd: ").append(command).append("\n");
sb.append("rc: ").append(returnCode).append("\n");
sb.append("flags:").append(flags).append("\n");
sb.append("proto:").append(protcolVersion).append("\n");
sb.append(HexHelper.bytesToHex(payload)).append("\n");
sb.append(payloadSection.toString());
return sb.toString();
}
}

View File

@@ -0,0 +1,125 @@
/*
* Copyright (c) 2018 m2049r
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.m2049r.levin.data;
import com.m2049r.levin.util.HexHelper;
import com.m2049r.levin.util.LevinReader;
import com.m2049r.levin.util.LevinWriter;
import com.m2049r.levin.util.LittleEndianDataOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataOutput;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class Section {
// constants copied from monero p2p & epee
static final public int PORTABLE_STORAGE_SIGNATUREA = 0x01011101;
static final public int PORTABLE_STORAGE_SIGNATUREB = 0x01020101;
static final public byte PORTABLE_STORAGE_FORMAT_VER = 1;
static final public byte PORTABLE_RAW_SIZE_MARK_MASK = 0x03;
static final public byte PORTABLE_RAW_SIZE_MARK_BYTE = 0;
static final public byte PORTABLE_RAW_SIZE_MARK_WORD = 1;
static final public byte PORTABLE_RAW_SIZE_MARK_DWORD = 2;
static final public byte PORTABLE_RAW_SIZE_MARK_INT64 = 3;
static final long MAX_STRING_LEN_POSSIBLE = 2000000000; // do not let string be so big
// data types
static final public byte SERIALIZE_TYPE_INT64 = 1;
static final public byte SERIALIZE_TYPE_INT32 = 2;
static final public byte SERIALIZE_TYPE_INT16 = 3;
static final public byte SERIALIZE_TYPE_INT8 = 4;
static final public byte SERIALIZE_TYPE_UINT64 = 5;
static final public byte SERIALIZE_TYPE_UINT32 = 6;
static final public byte SERIALIZE_TYPE_UINT16 = 7;
static final public byte SERIALIZE_TYPE_UINT8 = 8;
static final public byte SERIALIZE_TYPE_DUOBLE = 9;
static final public byte SERIALIZE_TYPE_STRING = 10;
static final public byte SERIALIZE_TYPE_BOOL = 11;
static final public byte SERIALIZE_TYPE_OBJECT = 12;
static final public byte SERIALIZE_TYPE_ARRAY = 13;
static final public byte SERIALIZE_FLAG_ARRAY = (byte) 0x80;
private final Map<String, Object> entries = new HashMap<String, Object>();
public void add(String key, Object entry) {
entries.put(key, entry);
}
public int size() {
return entries.size();
}
public Set<Map.Entry<String, Object>> entrySet() {
return entries.entrySet();
}
public Object get(String key) {
return entries.get(key);
}
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append("\n");
for (Map.Entry<String, Object> entry : entries.entrySet()) {
sb.append(entry.getKey()).append("=");
final Object value = entry.getValue();
if (value instanceof List) {
@SuppressWarnings("unchecked") final List<Object> list = (List<Object>) value;
for (Object listEntry : list) {
sb.append(listEntry.toString()).append("\n");
}
} else if (value instanceof String) {
sb.append("(").append(value).append(")\n");
} else if (value instanceof byte[]) {
sb.append(HexHelper.bytesToHex((byte[]) value)).append("\n");
} else {
sb.append(value.toString()).append("\n");
}
}
return sb.toString();
}
static public Section fromByteArray(byte[] buffer) {
try {
return LevinReader.readPayload(buffer);
} catch (IOException ex) {
throw new IllegalStateException();
}
}
public byte[] asByteArray() {
try {
ByteArrayOutputStream bas = new ByteArrayOutputStream();
DataOutput out = new LittleEndianDataOutputStream(bas);
LevinWriter writer = new LevinWriter(out);
writer.writePayload(this);
return bas.toByteArray();
} catch (IOException ex) {
throw new IllegalStateException();
}
}
}

View File

@@ -0,0 +1,196 @@
/*
* Copyright (c) 2018 m2049r
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.m2049r.levin.scanner;
import com.m2049r.xmrwallet.data.NodeInfo;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import timber.log.Timber;
public class Dispatcher implements PeerRetriever.OnGetPeers {
static final public int NUM_THREADS = 50;
static final public int MAX_PEERS = 1000;
static final public long MAX_TIME = 30000000000L; //30 seconds
private int peerCount = 0;
final private Set<NodeInfo> knownNodes = new HashSet<>(); // set of nodes to test
final private Set<NodeInfo> rpcNodes = new HashSet<>(); // set of RPC nodes we like
final private ExecutorService exeService = Executors.newFixedThreadPool(NUM_THREADS);
public interface Listener {
void onGet(NodeInfo nodeInfo);
}
private Listener listener;
public Dispatcher(Listener listener) {
this.listener = listener;
}
public Set<NodeInfo> getRpcNodes() {
return rpcNodes;
}
public int getPeerCount() {
return peerCount;
}
public boolean getMorePeers() {
return peerCount < MAX_PEERS;
}
public void awaitTermination(int nodesToFind) {
try {
final long t = System.nanoTime();
while (!jobs.isEmpty()) {
try {
Timber.d("Remaining jobs %d", jobs.size());
final PeerRetriever retrievedPeer = jobs.poll().get();
if (retrievedPeer.isGood() && getMorePeers())
retrievePeers(retrievedPeer);
final NodeInfo nodeInfo = retrievedPeer.getNodeInfo();
Timber.d("Retrieved %s", nodeInfo);
if ((nodeInfo.isValid() || nodeInfo.isFavourite())) {
nodeInfo.setName();
rpcNodes.add(nodeInfo);
Timber.d("RPC: %s", nodeInfo);
// the following is not totally correct but it works (otherwise we need to
// load much more before filtering - but we don't have time
if (listener != null) listener.onGet(nodeInfo);
if (rpcNodes.size() >= nodesToFind) {
Timber.d("are we done here?");
filterRpcNodes();
if (rpcNodes.size() >= nodesToFind) {
Timber.d("we're done here");
break;
}
}
}
if (System.nanoTime() - t > MAX_TIME) break; // watchdog
} catch (ExecutionException ex) {
Timber.d(ex); // tell us about it and continue
}
}
} catch (InterruptedException ex) {
Timber.d(ex);
} finally {
Timber.d("Shutting down!");
exeService.shutdownNow();
try {
exeService.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
} catch (InterruptedException ex) {
Timber.d(ex);
}
}
filterRpcNodes();
}
static final public int HEIGHT_WINDOW = 1;
private boolean testHeight(long height, long consensus) {
return (height >= (consensus - HEIGHT_WINDOW))
&& (height <= (consensus + HEIGHT_WINDOW));
}
private long calcConsensusHeight() {
Timber.d("Calc Consensus height from %d nodes", rpcNodes.size());
final Map<Long, Integer> nodeHeights = new TreeMap<Long, Integer>();
for (NodeInfo info : rpcNodes) {
if (!info.isValid()) continue;
Integer h = nodeHeights.get(info.getHeight());
if (h == null)
h = 0;
nodeHeights.put(info.getHeight(), h + 1);
}
long consensusHeight = 0;
long consensusCount = 0;
for (Map.Entry<Long, Integer> entry : nodeHeights.entrySet()) {
final long entryHeight = entry.getKey();
int count = 0;
for (long i = entryHeight - HEIGHT_WINDOW; i <= entryHeight + HEIGHT_WINDOW; i++) {
Integer v = nodeHeights.get(i);
if (v == null)
v = 0;
count += v;
}
if (count >= consensusCount) {
consensusCount = count;
consensusHeight = entryHeight;
}
Timber.d("%d - %d/%d", entryHeight, count, entry.getValue());
}
return consensusHeight;
}
private void filterRpcNodes() {
long consensus = calcConsensusHeight();
Timber.d("Consensus Height = %d for %d nodes", consensus, rpcNodes.size());
for (Iterator<NodeInfo> iter = rpcNodes.iterator(); iter.hasNext(); ) {
NodeInfo info = iter.next();
// don't remove favourites
if (!info.isFavourite()) {
if (!testHeight(info.getHeight(), consensus)) {
iter.remove();
Timber.d("Removed %s", info);
}
}
}
}
// TODO: does this NEED to be a ConcurrentLinkedDeque?
private ConcurrentLinkedDeque<Future<PeerRetriever>> jobs = new ConcurrentLinkedDeque<>();
private void retrievePeer(NodeInfo nodeInfo) {
if (knownNodes.add(nodeInfo)) {
Timber.d("\t%d:%s", knownNodes.size(), nodeInfo);
jobs.add(exeService.submit(new PeerRetriever(nodeInfo, this)));
peerCount++; // jobs.size() does not perform well
}
}
private void retrievePeers(PeerRetriever peer) {
for (LevinPeer levinPeer : peer.getPeers()) {
if (getMorePeers())
retrievePeer(new NodeInfo(levinPeer));
else
break;
}
}
public void seedPeers(Collection<NodeInfo> seedNodes) {
for (NodeInfo node : seedNodes) {
node.clear();
if (node.isFavourite()) {
rpcNodes.add(node);
if (listener != null) listener.onGet(node);
}
retrievePeer(node);
}
}
}

View File

@@ -0,0 +1,23 @@
package com.m2049r.levin.scanner;
import java.net.InetAddress;
import java.net.InetSocketAddress;
public class LevinPeer {
final public InetSocketAddress socketAddress;
final public int version;
final public long height;
final public String top;
public InetSocketAddress getSocketAddress() {
return socketAddress;
}
LevinPeer(InetAddress address, int port, int version, long height, String top) {
this.socketAddress = new InetSocketAddress(address, port);
this.version = version;
this.height = height;
this.top = top;
}
}

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