zold 0.29.27 → 0.29.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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