zold 0.29.27 → 0.29.28

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/.github/CODE_OF_CONDUCT.md +76 -0
  3. data/.github/CONTRIBUTING.md +11 -0
  4. data/.github/ISSUE_TEMPLATE/bug_report.md +38 -0
  5. data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
  6. data/.rubocop.yml +6 -2
  7. data/README.md +107 -6
  8. data/fixtures/merge/legacy_negatives_stay/copies/0123456789abcdef/scores.zc +1 -1
  9. data/fixtures/merge/negative_overwriting/0123456789abcdef.z +6 -0
  10. data/fixtures/merge/negative_overwriting/146b852f2d9ad984.z +6 -0
  11. data/fixtures/merge/negative_overwriting/assert.rb +25 -0
  12. data/fixtures/merge/negative_overwriting/copies/0123456789abcdef/1.zc +6 -0
  13. data/fixtures/merge/negative_overwriting/copies/0123456789abcdef/scores.zc +1 -0
  14. data/fixtures/merge/negative_overwriting/opts +2 -0
  15. data/lib/zold/commands/fetch.rb +1 -1
  16. data/lib/zold/commands/merge.rb +6 -6
  17. data/lib/zold/commands/node.rb +4 -0
  18. data/lib/zold/commands/pay.rb +1 -0
  19. data/lib/zold/commands/push.rb +5 -1
  20. data/lib/zold/commands/remote.rb +7 -3
  21. data/lib/zold/commands/routines/reconcile.rb +7 -2
  22. data/lib/zold/commands/routines/reconnect.rb +20 -5
  23. data/lib/zold/commands/routines/retire.rb +48 -0
  24. data/lib/zold/gem.rb +1 -1
  25. data/lib/zold/node/farm.rb +1 -1
  26. data/lib/zold/node/farmers.rb +1 -1
  27. data/lib/zold/node/front.rb +1 -0
  28. data/lib/zold/patch.rb +10 -2
  29. data/lib/zold/remotes.rb +10 -4
  30. data/lib/zold/version.rb +1 -1
  31. data/test/commands/routines/test_reconnect.rb +2 -1
  32. data/test/commands/routines/test_retire.rb +40 -0
  33. data/test/commands/test_node.rb +1 -1
  34. data/test/commands/test_pay.rb +2 -1
  35. data/test/node/test_front.rb +1 -0
  36. data/zold.gemspec +13 -13
  37. metadata +42 -29
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 295768d109f5ff2f7362a0f7b30f4aeb2d8fc67c58816556472c8d9da2909677
4
- data.tar.gz: '086008d6b389610f95e9a7a681c8e7401df0b6db97186c948037afb60c55bde6'
3
+ metadata.gz: 8fc5f47657b08c4e98a026b0b71def6da39a322e3f24666614a4f35d7f4580aa
4
+ data.tar.gz: da6bac2fdec7446e025e96ba6df2ada4a41122152eabf1f3748a0c80628d4fec
5
5
  SHA512:
6
- metadata.gz: 165a28b79bc5da4e965190c4ce6c912acef541fcbee0cacbe6af6b0fc3be89d10467fc75375e41f18a223be414e5d6970637e7d3c7bb52475ce38f0488db012c
7
- data.tar.gz: b86173d3d67c9013526df001165af3dab752bc2fe46d5c519cabd0a7114472d2619337f31f7762195a7ff24b95588abb7d563f186a6b7547e8f19e4d80c92a10
6
+ metadata.gz: c5c081dd571630428327bc2ae02ff0a47bab44e4d288f6ca6bfe9852cad9dd1c5300183f8c00b26de7e167af62281dcb3fc1c38691e1f656e02a3405d54fac44
7
+ data.tar.gz: 787d7d4d98ff67a4b26297ed3e1a3ec7dd5993e012585f2ac4755e5c69543cfb70f328497801cedb100576b3f1d70fb6ef13e71564c88d766ecb54659662d63d
@@ -0,0 +1,76 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as
6
+ contributors and maintainers pledge to making participation in our project and
7
+ our community a harassment-free experience for everyone, regardless of age, body
8
+ size, disability, ethnicity, sex characteristics, gender identity and expression,
9
+ level of experience, education, socio-economic status, nationality, personal
10
+ appearance, race, religion, or sexual identity and orientation.
11
+
12
+ ## Our Standards
13
+
14
+ Examples of behavior that contributes to creating a positive environment
15
+ include:
16
+
17
+ * Using welcoming and inclusive language
18
+ * Being respectful of differing viewpoints and experiences
19
+ * Gracefully accepting constructive criticism
20
+ * Focusing on what is best for the community
21
+ * Showing empathy towards other community members
22
+
23
+ Examples of unacceptable behavior by participants include:
24
+
25
+ * The use of sexualized language or imagery and unwelcome sexual attention or
26
+ advances
27
+ * Trolling, insulting/derogatory comments, and personal or political attacks
28
+ * Public or private harassment
29
+ * Publishing others' private information, such as a physical or electronic
30
+ address, without explicit permission
31
+ * Other conduct which could reasonably be considered inappropriate in a
32
+ professional setting
33
+
34
+ ## Our Responsibilities
35
+
36
+ Project maintainers are responsible for clarifying the standards of acceptable
37
+ behavior and are expected to take appropriate and fair corrective action in
38
+ response to any instances of unacceptable behavior.
39
+
40
+ Project maintainers have the right and responsibility to remove, edit, or
41
+ reject comments, commits, code, wiki edits, issues, and other contributions
42
+ that are not aligned to this Code of Conduct, or to ban temporarily or
43
+ permanently any contributor for other behaviors that they deem inappropriate,
44
+ threatening, offensive, or harmful.
45
+
46
+ ## Scope
47
+
48
+ This Code of Conduct applies both within project spaces and in public spaces
49
+ when an individual is representing the project or its community. Examples of
50
+ representing a project or community include using an official project e-mail
51
+ address, posting via an official social media account, or acting as an appointed
52
+ representative at an online or offline event. Representation of a project may be
53
+ further defined and clarified by project maintainers.
54
+
55
+ ## Enforcement
56
+
57
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
+ reported by contacting the project team at github@zold.io. All
59
+ complaints will be reviewed and investigated and will result in a response that
60
+ is deemed necessary and appropriate to the circumstances. The project team is
61
+ obligated to maintain confidentiality with regard to the reporter of an incident.
62
+ Further details of specific enforcement policies may be posted separately.
63
+
64
+ Project maintainers who do not follow or enforce the Code of Conduct in good
65
+ faith may face temporary or permanent repercussions as determined by other
66
+ members of the project's leadership.
67
+
68
+ ## Attribution
69
+
70
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
+ available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
72
+
73
+ [homepage]: https://www.contributor-covenant.org
74
+
75
+ For answers to common questions about this code of conduct, see
76
+ https://www.contributor-covenant.org/faq
@@ -0,0 +1,11 @@
1
+ Just send a pull request and call it a day.
2
+
3
+ Don't forget to run this, beforehand:
4
+
5
+ ```
6
+ bundle exec rake
7
+ ```
8
+
9
+ Only if the build is green, you send us your pull request.
10
+
11
+ Thanks!
@@ -0,0 +1,38 @@
1
+ ---
2
+ name: Bug report
3
+ about: Create a report to help us improve
4
+ title: ''
5
+ labels: ''
6
+ assignees: ''
7
+
8
+ ---
9
+
10
+ **Describe the bug**
11
+ A clear and concise description of what the bug is.
12
+
13
+ **To Reproduce**
14
+ Steps to reproduce the behavior:
15
+ 1. Go to '...'
16
+ 2. Click on '....'
17
+ 3. Scroll down to '....'
18
+ 4. See error
19
+
20
+ **Expected behavior**
21
+ A clear and concise description of what you expected to happen.
22
+
23
+ **Screenshots**
24
+ If applicable, add screenshots to help explain your problem.
25
+
26
+ **Desktop (please complete the following information):**
27
+ - OS: [e.g. iOS]
28
+ - Browser [e.g. chrome, safari]
29
+ - Version [e.g. 22]
30
+
31
+ **Smartphone (please complete the following information):**
32
+ - Device: [e.g. iPhone6]
33
+ - OS: [e.g. iOS8.1]
34
+ - Browser [e.g. stock browser, safari]
35
+ - Version [e.g. 22]
36
+
37
+ **Additional context**
38
+ Add any other context about the problem here.
@@ -0,0 +1,20 @@
1
+ ---
2
+ name: Feature request
3
+ about: Suggest an idea for this project
4
+ title: ''
5
+ labels: ''
6
+ assignees: ''
7
+
8
+ ---
9
+
10
+ **Is your feature request related to a problem? Please describe.**
11
+ A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12
+
13
+ **Describe the solution you'd like**
14
+ A clear and concise description of what you want to happen.
15
+
16
+ **Describe alternatives you've considered**
17
+ A clear and concise description of any alternative solutions or features you've considered.
18
+
19
+ **Additional context**
20
+ Add any other context or screenshots about the feature request here.
@@ -5,12 +5,16 @@ AllCops:
5
5
  DisplayCopNames: true
6
6
  TargetRubyVersion: 2.5
7
7
 
8
+ Lint/ToJSON:
9
+ Enabled: false
10
+ Layout/AlignArguments:
11
+ Enabled: false
8
12
  Style/ClassAndModuleChildren:
9
13
  Enabled: false
10
14
  Layout/EmptyLineAfterGuardClause:
11
15
  Enabled: false
12
16
  Metrics/CyclomaticComplexity:
13
- Max: 30
17
+ Max: 33
14
18
  Metrics/MethodLength:
15
19
  Enabled: false
16
20
  Layout/MultilineMethodCallIndentation:
@@ -30,7 +34,7 @@ Metrics/ParameterLists:
30
34
  Layout/AlignParameters:
31
35
  Enabled: false
32
36
  Metrics/PerceivedComplexity:
33
- Max: 34
37
+ Max: 36
34
38
  Metrics/LineLength:
35
39
  Max: 120
36
40
  Style/MultilineBlockChain:
data/README.md CHANGED
@@ -15,20 +15,39 @@
15
15
 
16
16
  [![Yard Docs](http://img.shields.io/badge/yard-docs-blue.svg)](http://rubydoc.info/github/zold-io/zold/master/frames)
17
17
  [![Maintainability](https://api.codeclimate.com/v1/badges/2861728929db934eb376/maintainability)](https://codeclimate.com/github/zold-io/zold/maintainability)
18
+ [![Hits-of-Code](https://hitsofcode.com/github/zold-io/zold)](https://hitsofcode.com/github/zold-io/zold)
18
19
 
19
- **NOTICE**: It's an experiment and a very early draft! Please, feel free to
20
- submit your ideas and/or pull requests.
20
+ To understand what Zold cryptocurrency is about you may want
21
+ to watch [this video](https://youtu.be/5A9uBwMow0M) first. Then, you may
22
+ want to read [this blog](https://blog.zold.io/2018/07/08/mission.html) post.
23
+ Then, you have to read the [Green Paper](https://papers.zold.io/green-paper.pdf)
24
+ (just four pages). In a nutshell, Zold is a cryptocurrency with the following
25
+ features:
21
26
 
22
- Here is the [White Paper](https://papers.zold.io/wp.pdf).
27
+ * No Blockchain
28
+ * No General Ledger
29
+ * Very fast, because de-centralized
30
+ * 100 times cheaper than Bitcoin
31
+ * Proof-of-work
32
+ * Unique consensus protocol
33
+ * Pre-mined with total capacity of 2 billion ZLD
34
+ * Anonymous
35
+ * Written in Ruby
36
+
37
+ More details you can find in the [White Paper](https://papers.zold.io/wp.pdf).
38
+
39
+ You can also find us at the [Bitcointalk](https://bitcointalk.org/index.php?topic=5095078) forum.
23
40
 
24
41
  Join our [Telegram group](https://t.me/zold_io) to discuss it all live.
25
42
 
26
43
  The license is [MIT](https://github.com/zold-io/zold/blob/master/LICENSE.txt).
27
44
 
28
- The web wallet is here: [wts.zold.io](https://wts.zold.io).
29
-
30
45
  ## How to Use
31
46
 
47
+ You can try the web wallet [here](https://wts.zold.io), but the best way
48
+ to use Zold is through the command line tool, which has all the features
49
+ and should remind you Git, if you are a programmer.
50
+
32
51
  First, install [Ruby 2.3+](https://www.ruby-lang.org/en/documentation/installation/),
33
52
  [Rubygems](https://rubygems.org/pages/download), and
34
53
  the [gem](https://rubygems.org/gems/zold).
@@ -190,7 +209,7 @@ Yes, you can run many nodes with the same wallet ID.
190
209
  Yes, you can use `--threads` command line argument for your node
191
210
  and the number of threads will be as big as you wish.
192
211
 
193
- ## JSON Details
212
+ ## Front-end JSON Details
194
213
 
195
214
  When you open up the front web page of your node, you will see a JSON document
196
215
  with a lot of technical details. Here is the explanation of the majority of them:
@@ -271,6 +290,88 @@ To be continued...
271
290
 
272
291
  `hours_alive` is the time in hours your server is alive without a reboot.
273
292
 
293
+ ## HTTP RESTful API
294
+
295
+ Well, maybe it's not purely RESTful, but each node has a simple
296
+ set of HTTP entry points, which you can use to retrieve information
297
+ about wallets, node status, log details, and some other things. Here
298
+ is a more or less complete list of them:
299
+
300
+ * `GET /`: returns the JSON explained above
301
+
302
+ * `GET /score`: returns the text presentation of the current Score
303
+
304
+ * `GET /version`: returns the version of the software
305
+
306
+ * `GET /protocol`: returns the protocol ID
307
+
308
+ * `GET /wallet/ID`: returns the JSON with wallet details
309
+
310
+ * `GET /wallet/ID/balance`: returns wallet balance in zents (text/plain)
311
+
312
+ * `GET /wallet/ID/key`: returns wallet public RSA key
313
+
314
+ * `GET /wallet/ID/mtime`: returns ISO-8601 time of wallet file modification
315
+
316
+ * `GET /wallet/ID/size`: returns the size of the wallet file in bytes
317
+
318
+ * `GET /wallet/ID/age`: returns the age of the wallet, in seconds
319
+
320
+ * `GET /wallet/ID/txns`: returns the amount of transactions in the wallet
321
+
322
+ * `GET /wallet/ID/debt`: returns the tax debt of the wallet in zents
323
+
324
+ * `GET /wallet/ID/digest`: returns SHA-256 digest of the wallet file
325
+
326
+ * `GET /wallet/ID/mnemo`: returns the mnemo short string of the wallet
327
+
328
+ * `GET /wallet/ID/txns.json`: returns the full list of transactions in the wallet in JSON document
329
+
330
+ * `GET /wallet/ID.txt`: returns the text presentation of the wallet
331
+
332
+ * `GET /wallet/ID.html`: returns the HTML presentation of the wallet
333
+
334
+ * `GET /wallet/ID.bin`: returns the entire wallet file
335
+
336
+ * `GET /wallet/ID/copies`: returns the list of copies of the wallet
337
+
338
+ * `GET /wallet/ID/copy/NAME`: returns the entire content of a single copy of the wallet
339
+
340
+ * `PUT /wallet/ID`: accepts a new content of the wallet, in order to
341
+ modify the one stored on the server (PUSH operation)
342
+
343
+ * `GET /wallets`: returns the list of all wallets maintained by the node,
344
+ in plain text, separated by EOL
345
+
346
+ * `GET /remotes`: returns the list of remote nodes in JSON
347
+
348
+ * `GET /ledger`: returns the list of recently visible transactions
349
+
350
+ * `GET /ledger.json`: returns the list of recently visible transactions, in JSON
351
+
352
+ There are a few other entry points, which exist most for debugging purposes,
353
+ they may not be supported by alternative implementations of the node software:
354
+
355
+ * `GET /pid`: returns the process ID of the software
356
+
357
+ * `GET /trace`: returns the entire log of the node
358
+
359
+ * `GET /farm`: returns the statistics of the Farm
360
+
361
+ * `GET /metronome`: returns the statistics of the Metronome
362
+
363
+ * `GET /threads`: returns the statistics of all Ruby threads
364
+
365
+ * `GET /ps`: returns the statistics of all currently running Unix processes
366
+
367
+ * `GET /queue`: returns the statistics of the node queue
368
+
369
+ * `GET /journal`: returns the journal, in HTML
370
+
371
+ * `GET /journal/item?id=ID`: returns the content of a single journal entry
372
+
373
+ There could be other entry points, not documented here.
374
+
274
375
  ## SDK
275
376
 
276
377
  Here is how you use Zold SDK from your Ruby app. First, you should
@@ -1 +1 @@
1
- 1,0.0.0.0,4096,10,NOW,M
1
+ 1,0.0.0.0,4096,10,NOW,
@@ -0,0 +1,6 @@
1
+ test
2
+ 2
3
+ 0123456789abcdef
4
+ MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnppnkzrCreiKaHF09XKS6bO+2274+wSGo+F8KHvVrNbqear/e09r9PB/P6bFdLoMh4Xc7p/7+NSEZLeu2Eg/dBkQLEb8M/zgkT4gBDGyETW/zusYHIznX/lgf0f8qleIQIIB/3Y7QpDztkamWYTKWlnmlrcQvCVB0uRRPm4ZMcMJouKR9n7E2DpL9eolKyOwr/JY08iJOuK3HuW6tRdvE+0x7I+wDprM65OH/PoArlfO5qnIGbeXwsEGRXt0w6a/ubPpeadFjPXotE7cT1SA4YSD1tWTIVm1ZWppOE967XoDIum6tzt5KfzDNRfs9GbCfO0BL235HxbO8I9rTlVLTKcNAiEe0CWolY9HR5pMaosOgZ6PB54InJEZJs4L2b10c+IlVUX1RSnwfFYg0vy5oqrYyqt7gnipl/06YW4PKIYc7TljogsEHf9Cz/kpEKzqDtsH2LrmjMNsbWiousvNHM+MPgcuMg8ZnwLKwDy9NWdI4XLTpg6hVRJNH9erZdfAO5tg/3ub3JLeJbyNo4Bd5f/Bnr5YN/9ahZ87kSpI7v0Qk94dR4hDPjstEcghyZ9RVUoN52+h1g83cd3cIqksJd0kifMCoBmObD013RSPQqNwr9GGU2JaJEm25Vq35dy2DHAkOQpUZVT8GNg9IM4qUDV0yagTN3bZyvuLWIgufb0CAwEAAQ==
5
+
6
+ 0001;2018-01-01T01:01:01Z;ffffffe000000000;qJkKMWUC;146b852f2d9ad984;test;j9ozyBTjJ90TK1u3o4m6ueLWspbXCgEWhLYNQ8B9EonQ9bIsl19DbdsPwyY5M3o8dSefDOwsA9OE48x9ncyh3n/BSYKSUHzSrU1RmVLR2+hveEzwGKPZleUzurDbKZA06MuuP46KDv3uhJ9OjX6szVwBqHorxoJ0zyqRtRdjKop7gqTVbyIIGOM5fu4lx3KhdWJLzD0sN75rdCmuF2yw/V2D+AdkB+84C+rTjp4x9bUr5zIinQtAYn8AJbdpk/3CLHWR/RhqFdUmQrQlgLile016bfkKg8l2S7HufrKdGNVThuoOrpTKZV+prctV2f8/2XANrHoVrtT5y3aENXfvlvYMQYqJsOl8wvLtQEts4pwtQBOdKUC4i82aZW/3lkQr9T8JPoyIthmm8AoOAx6RU0ccDckarDYAg1t5nYA/wK+fBDFkwIwUoI6zkvmwpUCI6/Wf9smF69H+FQNi8OrH0MaO0nzh7zFxgpFKaJAGumEvGPtA7rY3zYZ0P4lK9QnIa887p8WgA7YCN9/WieY71DINfMjVRwC7kxCa7LqNtOlXyp2pMJzWGWGbZH/SF6HpeIMbq7J0yUrdyLz8OwgLk5Wzuv/mht+mvhbI54mZixs4MawAXs9kTPmqGIRpMFvqLmD6GtKEltKuHGnAs4QSFjMmWbGG0WS98TztzFMpLG0=
@@ -0,0 +1,6 @@
1
+ test
2
+ 2
3
+ 146b852f2d9ad984
4
+ MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAyevqT0h4CcDkA4jeC+u0ITqULIyKD4HlUTyoOl8QK6BqDZ5oc4jCIGHgVfwdRVhKdUukWb7AUIVPVf76qepNZLwQ8UGtEwk+nCfq0/4u4zlCr78ZMmpIbdme5a6rXjiB3TE8UVgTPROx5EecazKXcvgmqfl7o98QBkqSKVqvIHzED5wADQzxjmGMmLWP8aTs0/6v4NG7wXJnMEJ0QYf845HMjpiXlNgldU1M1gTCM/8RJJaGjbEOax8HWj4n7LnqPHL5wtSe0CI6BzQsm9lEHUyywMW+SleCc5yponz5ZPzVkMYIzvO36BqykeZ0AXJyE5JfMoljJXG5bJX4tMhvIDVlZDlDh07vd11x3qJEtKB0c/hYcUmrUMAr0jZXBjv+MVq3WMVMClrMDyc1LMmrGh7Jp4hyugYRmrRAiTiZvmd2MaVB16sU91aiDHo90MefQ+RTwGO0YDNDzW1jW0qEYlfXZQGALWDWnyP1h1qzu4SaWrp4Chnt5OmwV67gxUw/VKQekTaiN7/ApeB5wXakrZiuIITi39865qqkkjDWVrRneqF0YDZz1S7eOIZ3OJvCi5OMU1nTTxaycVofolVmfGZlWROS9ENj2gVk9RQLX9xBXC1Vk4C/U7bIPDhk+nMHaDriuTNlmRPwMa6Flj1A9cLDUFPu7F0rDv3iqJkKMWUCAwEAAQ==
5
+
6
+ 0001;2019-05-14T14:34:56Z;0000001000000000;v4NG7wXJ;0123456789abcdef;test;
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2018-2019 Zerocracy, Inc.
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the 'Software'), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in all
13
+ # copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ # SOFTWARE.
22
+
23
+ require_relative 'asserts'
24
+ wallet = Zold::Wallet.new('0123456789abcdef.z')
25
+ assert_equal(Zold::Amount.new(zld: -16.0), wallet.balance)
@@ -0,0 +1,6 @@
1
+ test
2
+ 1
3
+ 0123456789abcdef
4
+ MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnppnkzrCreiKaHF09XKS6bO+2274+wSGo+F8KHvVrNbqear/e09r9PB/P6bFdLoMh4Xc7p/7+NSEZLeu2Eg/dBkQLEb8M/zgkT4gBDGyETW/zusYHIznX/lgf0f8qleIQIIB/3Y7QpDztkamWYTKWlnmlrcQvCVB0uRRPm4ZMcMJouKR9n7E2DpL9eolKyOwr/JY08iJOuK3HuW6tRdvE+0x7I+wDprM65OH/PoArlfO5qnIGbeXwsEGRXt0w6a/ubPpeadFjPXotE7cT1SA4YSD1tWTIVm1ZWppOE967XoDIum6tzt5KfzDNRfs9GbCfO0BL235HxbO8I9rTlVLTKcNAiEe0CWolY9HR5pMaosOgZ6PB54InJEZJs4L2b10c+IlVUX1RSnwfFYg0vy5oqrYyqt7gnipl/06YW4PKIYc7TljogsEHf9Cz/kpEKzqDtsH2LrmjMNsbWiousvNHM+MPgcuMg8ZnwLKwDy9NWdI4XLTpg6hVRJNH9erZdfAO5tg/3ub3JLeJbyNo4Bd5f/Bnr5YN/9ahZ87kSpI7v0Qk94dR4hDPjstEcghyZ9RVUoN52+h1g83cd3cIqksJd0kifMCoBmObD013RSPQqNwr9GGU2JaJEm25Vq35dy2DHAkOQpUZVT8GNg9IM4qUDV0yagTN3bZyvuLWIgufb0CAwEAAQ==
5
+
6
+ 0001;2019-05-14T14:34:56Z;fffffff000000000;v4NG7wXJ;146b852f2d9ad984;test;NSOdJUTYidOne3T0VranU9H8Lb4weJQ1KYhMu7MfFTIiUWXc56O4c/cRIikjQ+EFsneFtYBEHs0TH2oevndGyrHcHkBkmsMRWD0ujYFD27oWEuOX828dYM/vjn7q1ggb9XTJN3kEKnrP8zbfVzJotsh2I9ctNByGoy33ecGfYtv7pFfcUItjd6SbYmGGOCt/Jf4/I5p+pgW2xGjG75jRMQ1Gh40aWGHfOxi38HyUqSr9pcymerbUaEKpFrk8+CJ3LbCUN9Ve2WYIwIZd9POpN2PH+aF+syzEv2Yj7LDTfkLQHLzIJJqtCJvSXeqKgVKQLmtkjgHDX6aTyb8w7+NJ2Mkjq6mREny8qbJnwLi+d7Pl+fFCArP3kFBULKQDzqe7sA8+xew6Dq8kVZWoBtuPFusMhBu7rq573waOcj6ZiW7tKww0abTGe96KUNssMhyF4alHvXQ0b7orK6l2DOBV/JDlgP5mEu2mOJ8Y81peCMNa1m8Y+AgrGijrm5aqk0JHjGH2hVRrHPZcyyO+msoLe7vP5umpf4DuMBMPgGZQc5Sqpc8wuSgD+XaiSVKv1Nr/gQYp2oZbGXnGl47reCvy1lJr2kBzLIWIPdrZIGh7iVy/DFcvw+t7wvoOm1fEfVfDgl04yHwNOiUOLKNlfGFliWJoCJ+sJv5DztHpDEKLBv4=
@@ -0,0 +1,2 @@
1
+ --verbose
2
+ --allow-negative-balance
@@ -138,7 +138,7 @@ run 'zold remote update' or use --tolerate-quorum=1"
138
138
  end
139
139
  end
140
140
  @log.info("#{done.value} copies of #{id} fetched in #{Age.new(start)} with the total score of \
141
- #{total.value} from #{nodes.value} nodes (#{masters.value} master nodes)")
141
+ #{total.value} from #{nodes.value - masters.value}+#{masters.value}m nodes")
142
142
  list = cps.all.map do |c|
143
143
  " ##{c[:name]}: #{c[:score]} #{c[:total]}n #{Wallet.new(c[:path]).mnemo} \
144
144
  #{Size.new(File.size(c[:path]))}/#{Age.new(File.mtime(c[:path]))}#{c[:master] ? ' master' : ''}"
@@ -65,7 +65,7 @@ Available options:"
65
65
  default: false
66
66
  o.integer '--depth',
67
67
  'How many levels down we try to pull other wallets if their confirmations are required (default: 0)',
68
- default: 1
68
+ default: 0
69
69
  o.bool '--allow-negative-balance',
70
70
  'Don\'t check for the negative balance of the wallet after the merge',
71
71
  default: false
@@ -124,7 +124,7 @@ Available options:"
124
124
  wallet = Wallet.new(c[:path])
125
125
  baseline = idx.zero? && (c[:master] || opts['edge-baseline']) && !opts['no-baseline']
126
126
  name = "#{c[:name]}/#{idx}/#{c[:score]}#{baseline ? '/baseline' : ''}"
127
- merge_one(opts, patch, wallet, name, baseline: baseline)
127
+ merge_one(opts, patch, wallet, name, baseline: baseline, master: c[:master])
128
128
  score += c[:score]
129
129
  end
130
130
  @wallets.acq(id) do |w|
@@ -152,11 +152,11 @@ into #{@wallets.acq(id, &:mnemo)} in #{Age.new(start, limit: 0.1 + cps.count * 0
152
152
  modified
153
153
  end
154
154
 
155
- def merge_one(opts, patch, wallet, name, baseline: false)
155
+ def merge_one(opts, patch, wallet, name, baseline: false, master: false)
156
156
  start = Time.now
157
- @log.debug("Building a patch for #{wallet.id} from remote copy ##{name} with #{wallet.mnemo}...")
157
+ @log.debug("Adding copy ##{name}#{master ? ' (master)' : ''} to the patch #{wallet.mnemo}...")
158
158
  if opts['depth'].positive?
159
- patch.join(wallet, ledger: opts['ledger'], baseline: baseline) do |txn|
159
+ patch.join(wallet, ledger: opts['ledger'], baseline: baseline, master: master) do |txn|
160
160
  trusted = IO.read(opts['trusted']).split(',')
161
161
  if trusted.include?(txn.bnf.to_s)
162
162
  @log.debug("Won't PULL #{txn.bnf} since it is already trusted, among #{trusted.count} others")
@@ -176,7 +176,7 @@ into #{@wallets.acq(id, &:mnemo)} in #{Age.new(start, limit: 0.1 + cps.count * 0
176
176
  true
177
177
  end
178
178
  else
179
- patch.join(wallet, ledger: opts['ledger'], baseline: baseline) do |txn|
179
+ patch.join(wallet, ledger: opts['ledger'], baseline: baseline, master: master) do |txn|
180
180
  @log.debug("Paying wallet #{txn.bnf} is incomplete but there is not enough depth to PULL: #{txn.to_text}")
181
181
  false
182
182
  end
@@ -457,9 +457,13 @@ the node won\'t connect to the network like that; try to do "zold remote reset"
457
457
  end
458
458
  require_relative 'routines/spread'
459
459
  metronome.add(Routines::Spread.new(opts, @wallets, @remotes, @copies, log: @log))
460
+ require_relative 'routines/retire'
461
+ metronome.add(Routines::Retire.new(opts, log: @log))
460
462
  if @remotes.master?(host, port)
461
463
  require_relative 'routines/reconcile'
462
464
  metronome.add(Routines::Reconcile.new(opts, @wallets, @remotes, @copies, "#{host}:#{port}", log: @log))
465
+ else
466
+ @log.info('This is not master, no need to reconcile')
463
467
  end
464
468
  @log.info('Metronome started (use --no-metronome to disable it)')
465
469
  metronome
@@ -148,6 +148,7 @@ the difference is #{(amount - from.balance).to_i} zents"
148
148
  @log.debug("Keygap \"#{'*' * opts['keygap'].length}\" injected into the RSA private key")
149
149
  end
150
150
  key = Zold::Key.new(text: pem)
151
+ from.refurbish
151
152
  txn = from.sub(amount, invoice, key, details, time: Txn.parse_time(opts['time']))
152
153
  @log.debug("#{amount} sent from #{from} to #{txn.bnf}: #{details}")
153
154
  @log.debug("Don't forget to do 'zold push #{from}'")
@@ -31,6 +31,7 @@ require_relative '../thread_pool'
31
31
  require_relative '../hands'
32
32
  require_relative '../age'
33
33
  require_relative '../size'
34
+ require_relative '../tax'
34
35
  require_relative '../log'
35
36
  require_relative '../id'
36
37
  require_relative '../http'
@@ -98,6 +99,9 @@ Available options:"
98
99
  @wallets.acq(id) do |wallet|
99
100
  raise "The wallet #{id} is absent at #{wallet.path}" unless wallet.exists?
100
101
  end
102
+ if @wallets.acq(id) { |w| Tax.new(w).in_debt? }
103
+ @log.info("Taxes in #{id} are not paid, most likely the wallet won't be accepted by any node")
104
+ end
101
105
  start = Time.now
102
106
  total = Concurrent::AtomicFixnum.new
103
107
  nodes = Concurrent::AtomicFixnum.new
@@ -121,7 +125,7 @@ Available options:"
121
125
  run 'zold remote update' or use --tolerate-quorum=1"
122
126
  end
123
127
  end
124
- @log.info("Push finished to #{done.value} nodes (#{masters.value} master nodes) \
128
+ @log.info("Push finished to #{done.value - masters.value}+#{masters.value}m nodes \
125
129
  out of #{nodes.value} in #{Age.new(start)}, total score for #{id} is #{total.value}")
126
130
  end
127
131
 
@@ -261,7 +261,8 @@ Available options:"
261
261
  @remotes.remove(r[:host], r[:port]) if !opts['masters-too'] || !r[:master]
262
262
  @log.debug("#{r[:host]}:#{r[:port]} removed because of #{r[:errors]} errors (over #{opts['tolerate']})")
263
263
  end
264
- @log.info("The list of #{all.count} remotes trimmed down to #{@remotes.all.count} nodes")
264
+ @log.info("The list of #{all.count} remotes trimmed down to #{@remotes.all.count} nodes \
265
+ (#{@remotes.all.count { |r| r[:master] }} masters)")
265
266
  end
266
267
 
267
268
  def update(opts)
@@ -299,7 +300,9 @@ Available options:"
299
300
  if total.zero?
300
301
  @log.info("The list of remotes is #{Rainbow('empty').red}, run 'zold remote reset'!")
301
302
  else
302
- @log.info("There are #{total} known remotes with the overall score of \
303
+ @log.info("There are #{total} known remotes \
304
+ (#{@remotes.all.count { |r| r[:master] }} masters) \
305
+ with the overall score of \
303
306
  #{@remotes.all.map { |r| r[:score] }.inject(&:+)}, after update in #{Age.new(st)}")
304
307
  end
305
308
  end
@@ -354,7 +357,8 @@ it's recommended to reboot, but I don't do it because of --never-reboot")
354
357
  @remotes.remove(r[:host], r[:port])
355
358
  @log.debug("Remote #{r[:host]}:#{r[:port]}/#{r[:score]}/#{r[:errors]}e removed from the list")
356
359
  end
357
- @log.info("#{@remotes.all.count} best remote nodes were selected to stay in the list")
360
+ @log.info("#{@remotes.all.count} best remote nodes were selected to stay in the list \
361
+ (#{@remotes.all.count { |r| r[:master] }} masters)")
358
362
  end
359
363
 
360
364
  def terminate
@@ -48,10 +48,15 @@ class Zold::Routines::Reconcile
48
48
  next if r.to_mnemo == @address
49
49
  res = r.http('/wallets').get
50
50
  r.assert_code(200, res)
51
- res.body.strip.split("\n").compact
51
+ missing = res.body.strip.split("\n").compact
52
52
  .select { |i| /^[a-f0-9]{16}$/.match?(i) }
53
53
  .reject { |i| @wallets.acq(Zold::Id.new(i), &:exists?) }
54
- .each { |i| pull(i) }
54
+ missing.each { |i| pull(i) }
55
+ if missing.empty?
56
+ log.info("Nothing to reconcile with #{r}, we are good at #{@address}")
57
+ else
58
+ @log.info("Reconcile routine pulled #{missing.count} wallets from #{r}")
59
+ end
55
60
  end
56
61
  end
57
62
 
@@ -44,16 +44,31 @@ class Zold::Routines::Reconnect
44
44
  score = @farm.best[0]
45
45
  args << "--ignore-node=#{Shellwords.escape("#{score.host}:#{score.port}")}" if score
46
46
  cmd.run(args + ['masters']) unless @opts['routine-immediately']
47
- all = @remotes.all
48
- return if @opts['routine-immediately'] && all.empty?
47
+ return if @opts['routine-immediately'] && @remotes.all.empty?
49
48
  cmd.run(args + ['select'])
50
- if all.count < Zold::Remotes::MAX_NODES / 2 ||
51
- all.any? { |r| r[:errors] > Zold::Remotes::TOLERANCE } || (step % 10).zero?
52
- cmd.run(args + ['update'] + (@opts['never-reboot'] ? [] : ['--reboot']))
49
+ if (step % 10).zero?
50
+ @log.info("It is round ##{step}, time to update the list of remotes")
51
+ update(cmd, args)
52
+ end
53
+ if @remotes.all.any? { |r| r[:errors] > Zold::Remotes::TOLERANCE }
54
+ @log.info('There are a few remote nodes with too many errors, it\'s time to update')
55
+ update(cmd, args)
56
+ else
57
+ @log.debug("All #{@remotes.all.count} remote nodes are still more or less error-free, won't update")
58
+ end
59
+ if @remotes.all.count < Zold::Remotes::MAX_NODES / 2
60
+ @log.info("There are just #{@remotes.all.count} remotes in the list, time to update")
61
+ update(cmd, args)
53
62
  end
54
63
  cmd.run(args + ['trim'])
55
64
  cmd.run(args + ['select'])
56
65
  @log.info("Reconnected, there are #{@remotes.all.count} remote notes: \
57
66
  #{@remotes.all.map { |r| "#{r[:host]}:#{r[:port]}/#{r[:score]}/#{r[:errors]}" }.join(', ')}")
58
67
  end
68
+
69
+ private
70
+
71
+ def update(cmd, args)
72
+ cmd.run(args + ['update'] + (@opts['never-reboot'] ? [] : ['--reboot']))
73
+ end
59
74
  end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2018-2019 Zerocracy, Inc.
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the 'Software'), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in all
13
+ # copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ # SOFTWARE.
22
+
23
+ require 'shellwords'
24
+ require_relative '../routines'
25
+ require_relative '../remote'
26
+ require_relative '../../node/farm'
27
+
28
+ # Kill the node if it's too old.
29
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
30
+ # Copyright:: Copyright (c) 2018 Yegor Bugayenko
31
+ # License:: MIT
32
+ class Zold::Routines::Retire
33
+ def initialize(opts, log: Log::NULL)
34
+ @opts = opts
35
+ @log = log
36
+ @start = Time.now
37
+ end
38
+
39
+ def exec(step = 0)
40
+ sleep(60) unless @opts['routine-immediately']
41
+ days = 4
42
+ return if step < days * 24 * 60 && Time.now - @start < days * 24 * 60 * 60
43
+ return if @opts['never-reboot']
44
+ @log.info("We are too old, step ##{step}, it's time to retire (use --never-reboot to avoid this)")
45
+ require_relative '../../node/front'
46
+ Zold::Front.stop!
47
+ end
48
+ end
@@ -36,7 +36,7 @@ module Zold
36
36
  JsonPage.new(
37
37
  Http.new(uri: 'https://rubygems.org/api/v1/versions/zold/latest.json').get.body
38
38
  ).to_hash['version']
39
- rescue StandardError => _
39
+ rescue StandardError => _e
40
40
  '0.0.0'
41
41
  end
42
42
  end
@@ -167,7 +167,7 @@ at #{host}:#{port}, strength is #{@strength}")
167
167
  loop do
168
168
  begin
169
169
  s << @pipeline.pop(true)
170
- rescue ThreadError => _
170
+ rescue ThreadError
171
171
  sleep(0.25)
172
172
  end
173
173
  s.compact!
@@ -111,7 +111,7 @@ for #{score.value}/#{score.strength} at #{score.host}:#{score.port}")
111
111
  begin
112
112
  buffer << stdout.read_nonblock(16 * 1024)
113
113
  # rubocop:disable Lint/HandleExceptions
114
- rescue IO::WaitReadable => _
114
+ rescue IO::WaitReadable
115
115
  # rubocop:enable Lint/HandleExceptions
116
116
  # nothing to do here
117
117
  rescue StandardError => e
@@ -232,6 +232,7 @@ this is not a normal behavior, you may want to report a bug to our GitHub reposi
232
232
  total_mem: total_mem,
233
233
  threads: "#{Thread.list.select { |t| t.status == 'run' }.count}/#{Thread.list.count}",
234
234
  wallets: total_wallets,
235
+ journal: DirItems.new(settings.journal_dir).fetch.count,
235
236
  remotes: all_remotes.count,
236
237
  nscore: all_remotes.map { |r| r[:score] }.inject(&:+) || 0,
237
238
  farm: settings.farm.to_json,
@@ -69,7 +69,10 @@ module Zold
69
69
  # The "baseline" flag, when set to TRUE, means that we should NOT validate
70
70
  # the presence of positive incoming transactions in their correspondent
71
71
  # wallets. We shall just trust them.
72
- def join(wallet, ledger: '/dev/null', baseline: false)
72
+ #
73
+ # If the "master" flag is set, this copy is coming from a master node
74
+ # and we should allow it to overwrite negative transactions.
75
+ def join(wallet, ledger: '/dev/null', baseline: false, master: false)
73
76
  if @id.nil?
74
77
  @id = wallet.id
75
78
  @key = wallet.key
@@ -95,11 +98,16 @@ module Zold
95
98
  seen += 1
96
99
  if txn.amount.negative?
97
100
  dup = @txns.find { |t| t.id == txn.id && t.amount.negative? }
98
- if dup
101
+ if dup && !master
99
102
  @log.error("An attempt to overwrite existing transaction #{dup.to_text.inspect} \
100
103
  with a new one #{txn.to_text.inspect} from #{wallet.mnemo}")
101
104
  next
102
105
  end
106
+ if dup && master
107
+ @log.debug("An overwrite to the existing transaction #{dup.to_text.inspect} \
108
+ is coming from a master node: #{txn.to_text.inspect} from #{wallet.mnemo}")
109
+ @txns.reject! { |t| t.id == txn.id && t.amount.negative? }
110
+ end
103
111
  unless Signature.new(@network).valid?(@key, wallet.id, txn)
104
112
  @log.error("Invalid RSA signature at the transaction ##{txn.id} of #{wallet.id}: #{txn.to_text.inspect}")
105
113
  next
@@ -34,6 +34,7 @@ require_relative 'http'
34
34
  require_relative 'hands'
35
35
  require_relative 'thread_pool'
36
36
  require_relative 'node/farm'
37
+ require_relative 'commands/fetch'
37
38
 
38
39
  # The list of remotes.
39
40
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
@@ -118,7 +119,12 @@ at #{response.headers['X-Zold-Path']}"
118
119
  MAX_NODES = 16
119
120
 
120
121
  # Default nodes and their ports
121
- MASTERS = CSV.read(File.expand_path(File.join(File.dirname(__FILE__), '../../resources/masters')))
122
+ MASTERS = CSV.read(File.expand_path(File.join(File.dirname(__FILE__), '../../resources/masters'))).map do |r|
123
+ {
124
+ host: r[0].strip,
125
+ port: r[1].to_i
126
+ }
127
+ end.freeze
122
128
  private_constant :MASTERS
123
129
 
124
130
  # Empty, for standalone mode
@@ -168,9 +174,9 @@ at #{response.headers['X-Zold-Path']}"
168
174
  def masters
169
175
  MASTERS.each do |r|
170
176
  if block_given?
171
- next unless yield(r[0], r[1].to_i)
177
+ next unless yield(r[:host], r[:port])
172
178
  end
173
- add(r[0], r[1].to_i)
179
+ add(r[:host], r[:port])
174
180
  end
175
181
  end
176
182
 
@@ -255,7 +261,7 @@ at #{response.headers['X-Zold-Path']}"
255
261
  end
256
262
 
257
263
  def master?(host, port)
258
- !MASTERS.find { |r| r[0] == host && r[1].to_i == port }.nil?
264
+ !MASTERS.find { |r| r[:host] == host && r[:port] == port }.nil?
259
265
  end
260
266
 
261
267
  private
@@ -25,7 +25,7 @@
25
25
  # Copyright:: Copyright (c) 2018 Yegor Bugayenko
26
26
  # License:: MIT
27
27
  module Zold
28
- VERSION = '0.29.27'
28
+ VERSION = '0.29.28'
29
29
  PROTOCOL = 2
30
30
  REPO = 'zold-io/zold'
31
31
  end
@@ -36,7 +36,8 @@ class TestReconnect < Zold::Test
36
36
  Dir.mktmpdir do |dir|
37
37
  remotes = Zold::Remotes.new(file: File.join(dir, 'remotes.csv'))
38
38
  remotes.clean
39
- stub_request(:get, 'http://b1.zold.io:80/remotes').to_return(status: 404)
39
+ remotes.add('localhost', 4096)
40
+ stub_request(:get, 'http://localhost:4096/remotes').to_return(status: 404)
40
41
  opts = { 'never-reboot' => true, 'routine-immediately' => true }
41
42
  routine = Zold::Routines::Reconnect.new(opts, remotes, log: test_log)
42
43
  routine.exec
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2018-2019 Zerocracy, Inc.
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the 'Software'), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in all
13
+ # copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ # SOFTWARE.
22
+
23
+ require 'minitest/autorun'
24
+ require 'tmpdir'
25
+ require 'webmock/minitest'
26
+ require_relative '../../test__helper'
27
+ require_relative '../../../lib/zold/remotes'
28
+ require_relative '../../../lib/zold/commands/routines/retire.rb'
29
+
30
+ # Retire test.
31
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
32
+ # Copyright:: Copyright (c) 2018 Yegor Bugayenko
33
+ # License:: MIT
34
+ class TestRetire < Zold::Test
35
+ def test_retires
36
+ opts = { 'never-reboot' => false, 'routine-immediately' => true }
37
+ routine = Zold::Routines::Retire.new(opts, log: test_log)
38
+ routine.exec(10 * 24 * 60)
39
+ end
40
+ end
@@ -56,7 +56,7 @@ class TestNode < Zold::Test
56
56
  wallets: wallets, copies: copies.root,
57
57
  remotes: remotes, log: test_log
58
58
  ).run(['fetch', '--ignore-score-weakness', '--tolerate-edges', '--tolerate-quorum=1'])
59
- rescue StandardError => _
59
+ rescue StandardError => _e
60
60
  sleep 1
61
61
  retry if (retries += 1) < 3
62
62
  end
@@ -107,8 +107,9 @@ class TestPay < Zold::Test
107
107
  FakeHome.new(log: test_log).run do |home|
108
108
  wallet = home.create_wallet
109
109
  amount = Zold::Amount.new(zld: 2.0)
110
+ wallets = home.wallets
110
111
  Threads.new(10).assert do
111
- Zold::Pay.new(wallets: home.wallets, copies: home.dir, remotes: home.remotes, log: test_log).run(
112
+ Zold::Pay.new(wallets: wallets, copies: home.dir, remotes: home.remotes, log: test_log).run(
112
113
  [
113
114
  'pay', '--force', '--private-key=fixtures/id_rsa',
114
115
  wallet.id.to_s, 'NOPREFIX@dddd0000dddd0000', amount.to_zld, '-'
@@ -64,6 +64,7 @@ class FrontTest < Zold::Test
64
64
  assert_equal('zold-io/zold', json['repo'])
65
65
  assert(json['pid'].positive?, json)
66
66
  assert(json['cpus'].positive?, json)
67
+ assert(!json['journal'].negative?, json)
67
68
  assert(json['memory'].positive?, json)
68
69
  assert(!json['load'].negative?, json)
69
70
  assert(json['wallets'].positive?, json)
@@ -62,18 +62,18 @@ and suggests a different architecture for digital wallet maintenance.'
62
62
  s.rdoc_options = ['--charset=UTF-8']
63
63
  s.extra_rdoc_files = ['README.md', 'LICENSE.txt']
64
64
  s.add_runtime_dependency 'backtrace', '>=0.3'
65
- s.add_runtime_dependency 'concurrent-ruby', '1.1.3'
66
- s.add_runtime_dependency 'diffy', '3.2.1'
65
+ s.add_runtime_dependency 'concurrent-ruby', '1.1.5'
66
+ s.add_runtime_dependency 'diffy', '3.3.0'
67
67
  s.add_runtime_dependency 'futex', '>=0.8.5'
68
68
  s.add_runtime_dependency 'get_process_mem', '~>0.2'
69
69
  s.add_runtime_dependency 'haml', '5.0.4'
70
- s.add_runtime_dependency 'json', '2.1.0'
71
- s.add_runtime_dependency 'memory_profiler', '0.9.12'
72
- s.add_runtime_dependency 'mimic', '0.4.2'
70
+ s.add_runtime_dependency 'json', '2.2.0'
71
+ s.add_runtime_dependency 'memory_profiler', '0.9.13'
72
+ s.add_runtime_dependency 'mimic', '0.4.4'
73
73
  s.add_runtime_dependency 'openssl', '2.1.2'
74
74
  s.add_runtime_dependency 'rainbow', '3.0.0'
75
75
  s.add_runtime_dependency 'semantic', '1.6.1'
76
- s.add_runtime_dependency 'sinatra', '2.0.4'
76
+ s.add_runtime_dependency 'sinatra', '2.0.5'
77
77
  s.add_runtime_dependency 'slop', '4.6.2'
78
78
  s.add_runtime_dependency 'sys-proctable', '1.2.1'
79
79
  s.add_runtime_dependency 'thin', '1.7.2'
@@ -83,19 +83,19 @@ and suggests a different architecture for digital wallet maintenance.'
83
83
  s.add_runtime_dependency 'usagewatch_ext', '0.2.1'
84
84
  s.add_runtime_dependency 'zache', '>=0.12'
85
85
  s.add_runtime_dependency 'zold-score', '0.4.6'
86
- s.add_development_dependency 'codecov', '0.1.13'
86
+ s.add_development_dependency 'codecov', '0.1.14'
87
87
  s.add_development_dependency 'cucumber', '3.1.2'
88
88
  s.add_development_dependency 'guard', '2.15.0'
89
89
  s.add_development_dependency 'guard-minitest', '2.4.6'
90
90
  s.add_development_dependency 'minitest', '5.11.3'
91
91
  s.add_development_dependency 'minitest-fail-fast', '0.1.0'
92
92
  s.add_development_dependency 'minitest-hooks', '1.5.0'
93
- s.add_development_dependency 'rake', '12.3.1'
93
+ s.add_development_dependency 'rake', '12.3.2'
94
94
  s.add_development_dependency 'random-port', '0.3.1'
95
- s.add_development_dependency 'rdoc', '4.3.0'
96
- s.add_development_dependency 'rspec-rails', '3.8.1'
97
- s.add_development_dependency 'rubocop', '0.62.0'
98
- s.add_development_dependency 'rubocop-rspec', '1.31.0'
99
- s.add_development_dependency 'webmock', '3.4.2'
95
+ s.add_development_dependency 'rdoc', '6.1.1'
96
+ s.add_development_dependency 'rspec-rails', '3.8.2'
97
+ s.add_development_dependency 'rubocop', '0.69.0'
98
+ s.add_development_dependency 'rubocop-rspec', '1.33.0'
99
+ s.add_development_dependency 'webmock', '3.5.1'
100
100
  s.add_development_dependency 'xcop', '>=0.6'
101
101
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zold
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.29.27
4
+ version: 0.29.28
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yegor Bugayenko
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-03-20 00:00:00.000000000 Z
11
+ date: 2019-05-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: backtrace
@@ -30,28 +30,28 @@ dependencies:
30
30
  requirements:
31
31
  - - '='
32
32
  - !ruby/object:Gem::Version
33
- version: 1.1.3
33
+ version: 1.1.5
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - '='
39
39
  - !ruby/object:Gem::Version
40
- version: 1.1.3
40
+ version: 1.1.5
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: diffy
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - '='
46
46
  - !ruby/object:Gem::Version
47
- version: 3.2.1
47
+ version: 3.3.0
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - '='
53
53
  - !ruby/object:Gem::Version
54
- version: 3.2.1
54
+ version: 3.3.0
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: futex
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -100,42 +100,42 @@ dependencies:
100
100
  requirements:
101
101
  - - '='
102
102
  - !ruby/object:Gem::Version
103
- version: 2.1.0
103
+ version: 2.2.0
104
104
  type: :runtime
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - '='
109
109
  - !ruby/object:Gem::Version
110
- version: 2.1.0
110
+ version: 2.2.0
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: memory_profiler
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
115
  - - '='
116
116
  - !ruby/object:Gem::Version
117
- version: 0.9.12
117
+ version: 0.9.13
118
118
  type: :runtime
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
122
  - - '='
123
123
  - !ruby/object:Gem::Version
124
- version: 0.9.12
124
+ version: 0.9.13
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: mimic
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
129
  - - '='
130
130
  - !ruby/object:Gem::Version
131
- version: 0.4.2
131
+ version: 0.4.4
132
132
  type: :runtime
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
136
  - - '='
137
137
  - !ruby/object:Gem::Version
138
- version: 0.4.2
138
+ version: 0.4.4
139
139
  - !ruby/object:Gem::Dependency
140
140
  name: openssl
141
141
  requirement: !ruby/object:Gem::Requirement
@@ -184,14 +184,14 @@ dependencies:
184
184
  requirements:
185
185
  - - '='
186
186
  - !ruby/object:Gem::Version
187
- version: 2.0.4
187
+ version: 2.0.5
188
188
  type: :runtime
189
189
  prerelease: false
190
190
  version_requirements: !ruby/object:Gem::Requirement
191
191
  requirements:
192
192
  - - '='
193
193
  - !ruby/object:Gem::Version
194
- version: 2.0.4
194
+ version: 2.0.5
195
195
  - !ruby/object:Gem::Dependency
196
196
  name: slop
197
197
  requirement: !ruby/object:Gem::Requirement
@@ -324,14 +324,14 @@ dependencies:
324
324
  requirements:
325
325
  - - '='
326
326
  - !ruby/object:Gem::Version
327
- version: 0.1.13
327
+ version: 0.1.14
328
328
  type: :development
329
329
  prerelease: false
330
330
  version_requirements: !ruby/object:Gem::Requirement
331
331
  requirements:
332
332
  - - '='
333
333
  - !ruby/object:Gem::Version
334
- version: 0.1.13
334
+ version: 0.1.14
335
335
  - !ruby/object:Gem::Dependency
336
336
  name: cucumber
337
337
  requirement: !ruby/object:Gem::Requirement
@@ -422,14 +422,14 @@ dependencies:
422
422
  requirements:
423
423
  - - '='
424
424
  - !ruby/object:Gem::Version
425
- version: 12.3.1
425
+ version: 12.3.2
426
426
  type: :development
427
427
  prerelease: false
428
428
  version_requirements: !ruby/object:Gem::Requirement
429
429
  requirements:
430
430
  - - '='
431
431
  - !ruby/object:Gem::Version
432
- version: 12.3.1
432
+ version: 12.3.2
433
433
  - !ruby/object:Gem::Dependency
434
434
  name: random-port
435
435
  requirement: !ruby/object:Gem::Requirement
@@ -450,70 +450,70 @@ dependencies:
450
450
  requirements:
451
451
  - - '='
452
452
  - !ruby/object:Gem::Version
453
- version: 4.3.0
453
+ version: 6.1.1
454
454
  type: :development
455
455
  prerelease: false
456
456
  version_requirements: !ruby/object:Gem::Requirement
457
457
  requirements:
458
458
  - - '='
459
459
  - !ruby/object:Gem::Version
460
- version: 4.3.0
460
+ version: 6.1.1
461
461
  - !ruby/object:Gem::Dependency
462
462
  name: rspec-rails
463
463
  requirement: !ruby/object:Gem::Requirement
464
464
  requirements:
465
465
  - - '='
466
466
  - !ruby/object:Gem::Version
467
- version: 3.8.1
467
+ version: 3.8.2
468
468
  type: :development
469
469
  prerelease: false
470
470
  version_requirements: !ruby/object:Gem::Requirement
471
471
  requirements:
472
472
  - - '='
473
473
  - !ruby/object:Gem::Version
474
- version: 3.8.1
474
+ version: 3.8.2
475
475
  - !ruby/object:Gem::Dependency
476
476
  name: rubocop
477
477
  requirement: !ruby/object:Gem::Requirement
478
478
  requirements:
479
479
  - - '='
480
480
  - !ruby/object:Gem::Version
481
- version: 0.62.0
481
+ version: 0.69.0
482
482
  type: :development
483
483
  prerelease: false
484
484
  version_requirements: !ruby/object:Gem::Requirement
485
485
  requirements:
486
486
  - - '='
487
487
  - !ruby/object:Gem::Version
488
- version: 0.62.0
488
+ version: 0.69.0
489
489
  - !ruby/object:Gem::Dependency
490
490
  name: rubocop-rspec
491
491
  requirement: !ruby/object:Gem::Requirement
492
492
  requirements:
493
493
  - - '='
494
494
  - !ruby/object:Gem::Version
495
- version: 1.31.0
495
+ version: 1.33.0
496
496
  type: :development
497
497
  prerelease: false
498
498
  version_requirements: !ruby/object:Gem::Requirement
499
499
  requirements:
500
500
  - - '='
501
501
  - !ruby/object:Gem::Version
502
- version: 1.31.0
502
+ version: 1.33.0
503
503
  - !ruby/object:Gem::Dependency
504
504
  name: webmock
505
505
  requirement: !ruby/object:Gem::Requirement
506
506
  requirements:
507
507
  - - '='
508
508
  - !ruby/object:Gem::Version
509
- version: 3.4.2
509
+ version: 3.5.1
510
510
  type: :development
511
511
  prerelease: false
512
512
  version_requirements: !ruby/object:Gem::Requirement
513
513
  requirements:
514
514
  - - '='
515
515
  - !ruby/object:Gem::Version
516
- version: 3.4.2
516
+ version: 3.5.1
517
517
  - !ruby/object:Gem::Dependency
518
518
  name: xcop
519
519
  requirement: !ruby/object:Gem::Requirement
@@ -550,7 +550,11 @@ extra_rdoc_files:
550
550
  files:
551
551
  - ".0pdd.yml"
552
552
  - ".gitattributes"
553
+ - ".github/CODE_OF_CONDUCT.md"
554
+ - ".github/CONTRIBUTING.md"
553
555
  - ".github/ISSUE_TEMPLATE.md"
556
+ - ".github/ISSUE_TEMPLATE/bug_report.md"
557
+ - ".github/ISSUE_TEMPLATE/feature_request.md"
554
558
  - ".github/PULL_REQUEST_TEMPLATE.md"
555
559
  - ".gitignore"
556
560
  - ".pdd"
@@ -600,6 +604,12 @@ files:
600
604
  - fixtures/merge/missed_wallets/copies/0123456789abcdef/1.zc
601
605
  - fixtures/merge/missed_wallets/copies/0123456789abcdef/scores.zc
602
606
  - fixtures/merge/missed_wallets/opts
607
+ - fixtures/merge/negative_overwriting/0123456789abcdef.z
608
+ - fixtures/merge/negative_overwriting/146b852f2d9ad984.z
609
+ - fixtures/merge/negative_overwriting/assert.rb
610
+ - fixtures/merge/negative_overwriting/copies/0123456789abcdef/1.zc
611
+ - fixtures/merge/negative_overwriting/copies/0123456789abcdef/scores.zc
612
+ - fixtures/merge/negative_overwriting/opts
603
613
  - fixtures/merge/negatives_in_between/0000000000000000.z
604
614
  - fixtures/merge/negatives_in_between/0123456789abcdef.z
605
615
  - fixtures/merge/negatives_in_between/assert.rb
@@ -664,6 +674,7 @@ files:
664
674
  - lib/zold/commands/routines/gc.rb
665
675
  - lib/zold/commands/routines/reconcile.rb
666
676
  - lib/zold/commands/routines/reconnect.rb
677
+ - lib/zold/commands/routines/retire.rb
667
678
  - lib/zold/commands/routines/spread.rb
668
679
  - lib/zold/commands/show.rb
669
680
  - lib/zold/commands/taxes.rb
@@ -721,6 +732,7 @@ files:
721
732
  - test/commands/routines/test_gc.rb
722
733
  - test/commands/routines/test_reconcile.rb
723
734
  - test/commands/routines/test_reconnect.rb
735
+ - test/commands/routines/test_retire.rb
724
736
  - test/commands/test_alias.rb
725
737
  - test/commands/test_calculate.rb
726
738
  - test/commands/test_clean.rb
@@ -801,7 +813,7 @@ licenses:
801
813
  - MIT
802
814
  metadata: {}
803
815
  post_install_message: |-
804
- Thanks for installing Zold 0.29.27!
816
+ Thanks for installing Zold 0.29.28!
805
817
  Study our White Paper: https://papers.zold.io/wp.pdf
806
818
  Read our blog posts: https://blog.zold.io
807
819
  Try ZLD online wallet at: https://wts.zold.io
@@ -836,6 +848,7 @@ test_files:
836
848
  - test/commands/routines/test_gc.rb
837
849
  - test/commands/routines/test_reconcile.rb
838
850
  - test/commands/routines/test_reconnect.rb
851
+ - test/commands/routines/test_retire.rb
839
852
  - test/commands/test_alias.rb
840
853
  - test/commands/test_calculate.rb
841
854
  - test/commands/test_clean.rb