zold 0.13.46 → 0.14.0

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 (78) hide show
  1. checksums.yaml +4 -4
  2. data/.ruby-version +1 -0
  3. data/.rultor.yml +2 -2
  4. data/.simplecov +1 -1
  5. data/.travis.yml +3 -1
  6. data/INSTALL.md +4 -1
  7. data/README.md +98 -3
  8. data/Rakefile +1 -0
  9. data/bin/zold +10 -1
  10. data/fixtures/merge/into-no-wallet/assert.rb +23 -0
  11. data/fixtures/merge/{random-expenses/0123456789abcdef → into-no-wallet/copies/0123456789abcdef/1.z} +0 -0
  12. data/fixtures/merge/into-no-wallet/copies/0123456789abcdef/scores.z +1 -0
  13. data/fixtures/merge/random-expenses/{0000000000000000 → 0000000000000000.z} +0 -0
  14. data/fixtures/merge/{simple-case/copies/0123456789abcdef/1 → random-expenses/0123456789abcdef.z} +0 -0
  15. data/fixtures/merge/random-expenses/copies/0123456789abcdef/{1 → 1.z} +0 -0
  16. data/fixtures/merge/random-expenses/copies/0123456789abcdef/{2 → 2.z} +0 -0
  17. data/fixtures/merge/random-expenses/copies/0123456789abcdef/{3 → 3.z} +0 -0
  18. data/fixtures/merge/random-expenses/copies/0123456789abcdef/{4 → 4.z} +0 -0
  19. data/fixtures/merge/random-expenses/copies/0123456789abcdef/{5 → 5.z} +0 -0
  20. data/fixtures/merge/random-expenses/copies/0123456789abcdef/scores.z +5 -0
  21. data/fixtures/merge/simple-case/{0000000000000000 → 0000000000000000.z} +0 -0
  22. data/fixtures/merge/simple-case/{0123456789abcdef → 0123456789abcdef.z} +0 -1
  23. data/fixtures/merge/simple-case/copies/0123456789abcdef/1.z +6 -0
  24. data/fixtures/merge/simple-case/copies/0123456789abcdef/scores.z +1 -0
  25. data/fixtures/scripts/push-and-pull.sh +1 -0
  26. data/lib/zold/atomic_file.rb +7 -6
  27. data/lib/zold/commands/alias.rb +37 -0
  28. data/lib/zold/commands/calculate.rb +5 -2
  29. data/lib/zold/commands/diff.rb +2 -2
  30. data/lib/zold/commands/fetch.rb +23 -3
  31. data/lib/zold/commands/merge.rb +12 -7
  32. data/lib/zold/commands/node.rb +5 -2
  33. data/lib/zold/commands/pay.rb +11 -0
  34. data/lib/zold/commands/push.rb +1 -1
  35. data/lib/zold/commands/remote.rb +28 -2
  36. data/lib/zold/commands/taxes.rb +14 -2
  37. data/lib/zold/copies.rb +9 -8
  38. data/lib/zold/hungry_wallets.rb +12 -0
  39. data/lib/zold/log.rb +17 -2
  40. data/lib/zold/node/async_entrance.rb +48 -9
  41. data/lib/zold/node/entrance.rb +1 -1
  42. data/lib/zold/node/front.rb +28 -3
  43. data/lib/zold/node/safe_entrance.rb +3 -3
  44. data/lib/zold/node/spread_entrance.rb +1 -1
  45. data/lib/zold/patch.rb +8 -4
  46. data/lib/zold/remotes.rb +7 -0
  47. data/lib/zold/score.rb +2 -2
  48. data/lib/zold/tax.rb +0 -1
  49. data/lib/zold/upgrades.rb +57 -0
  50. data/lib/zold/version.rb +2 -1
  51. data/lib/zold/version_file.rb +39 -0
  52. data/lib/zold/wallet.rb +17 -4
  53. data/lib/zold/wallets.rb +9 -6
  54. data/test/commands/routines/test_spread.rb +1 -0
  55. data/test/commands/test_alias.rb +7 -0
  56. data/test/commands/test_create.rb +2 -2
  57. data/test/commands/test_fetch.rb +2 -1
  58. data/test/commands/test_merge.rb +2 -0
  59. data/test/commands/test_node.rb +1 -0
  60. data/test/commands/test_pay.rb +24 -0
  61. data/test/commands/test_remote.rb +28 -0
  62. data/test/node/test_async_entrance.rb +6 -13
  63. data/test/node/test_front.rb +2 -1
  64. data/test/test__helper.rb +3 -2
  65. data/test/test_atomic_file.rb +0 -5
  66. data/test/test_copies.rb +14 -2
  67. data/test/test_remotes.rb +12 -0
  68. data/test/test_score.rb +14 -0
  69. data/test/test_tax.rb +5 -0
  70. data/test/test_upgrades.rb +97 -0
  71. data/test/test_version.rb +13 -0
  72. data/test/test_wallet.rb +21 -1
  73. data/test/test_wallets.rb +8 -0
  74. data/upgrades/2.rb +20 -0
  75. data/zold.gemspec +3 -3
  76. metadata +38 -23
  77. data/fixtures/merge/random-expenses/copies/0123456789abcdef/scores +0 -5
  78. data/fixtures/merge/simple-case/copies/0123456789abcdef/scores +0 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 625ff3a7512954db5e783a2fb126775e0fd92faa
4
- data.tar.gz: d959c632de322a3ff1ddaa489a4b3d0abbebe739
3
+ metadata.gz: 22288b6f4438266980018f938ab695cb09064eec
4
+ data.tar.gz: 986101be3001551301d2fff682197314eca1baff
5
5
  SHA512:
6
- metadata.gz: c0558d0d5bf65cb36fd726b1a6e1ffe89a69c6f804001c46226aac260a086bf83be248271cb4bb32d8bcd19edb73edff8c800cb0c0aec85f90d61798cdbc69c5
7
- data.tar.gz: 6b06b4e039bbac0a7d421dba1b096322aab860f5b512abfb7d6bbdbfade89837b762b6345a698edc596acd5fdbd85111974c3c3af1f2fc279a81c386e8727609
6
+ metadata.gz: 5bb4185d912befc802f4050e8cbe7baf2fc1ac957fb6b8bbbc5b4bba6aa48648519e4960c0ea64ab96680afa8586b0b9993baa1a55422dc937f1f4bc0ba122da
7
+ data.tar.gz: 4779556696ca19d5deef4405cd218fd0423b051e99cd28e3377f5010bcee315a52717f47fd9bb10be05f00314bb7d9d10c0ea7a7f7ea3978c5aab8c343689da9
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.3.3
data/.rultor.yml CHANGED
@@ -12,7 +12,7 @@ release:
12
12
  rm -rf *.gem
13
13
  sed -i "s/0\.0\.0/${tag}/g" lib/zold/version.rb
14
14
  bundle install
15
- rake
15
+ rake --quiet
16
16
  git add lib/zold/version.rb
17
17
  git commit -m "version set to ${tag}"
18
18
  gem build zold.gemspec
@@ -38,7 +38,7 @@ architect:
38
38
  merge:
39
39
  script: |-
40
40
  bundle install
41
- rake
41
+ rake --quiet
42
42
  pdd -f /dev/null -v
43
43
  deploy:
44
44
  script: |-
data/.simplecov CHANGED
@@ -35,6 +35,6 @@ else
35
35
  SimpleCov.start do
36
36
  add_filter "/test/"
37
37
  add_filter "/features/"
38
- #minimum_coverage 100
38
+ minimum_coverage 30
39
39
  end
40
40
  end
data/.travis.yml CHANGED
@@ -7,7 +7,9 @@ branches:
7
7
  - master
8
8
  install:
9
9
  - travis_retry bundle update
10
+ - gem install pdd
10
11
  script:
11
- - rake
12
+ - pdd -f /dev/null
13
+ - rake --quiet
12
14
  after_success:
13
15
  - "bash <(curl -s https://codecov.io/bash)"
data/INSTALL.md CHANGED
@@ -48,7 +48,10 @@ Without homebrew:
48
48
 
49
49
  ## Windows
50
50
 
51
- ... please contribute ...
51
+ Download and install [RubyInstaller (with Devkit)](https://rubyinstaller.org/downloads/).
52
+ If Windows Defender (or antivirus software) throws an error, ignore it and allow the file. This file is known to trigger [false positives](https://groups.google.com/forum/#!topic/rubyinstaller/LCR-CbBoGOI).
53
+ Download and install [RubyGems](https://rubygems.org/pages/download). Manual install `ruby setup.rb` works.
54
+ Install [Zold gem](https://rubygems.org/gems/zold) `gem install --no-ri --no-rdoc zold`
52
55
 
53
56
  ## CentOS 7.5
54
57
 
data/README.md CHANGED
@@ -13,7 +13,7 @@
13
13
  [![Gem Version](https://badge.fury.io/rb/zold.svg)](http://badge.fury.io/rb/zold)
14
14
  [![Test Coverage](https://img.shields.io/codecov/c/github/zold-io/zold.svg)](https://codecov.io/github/zold-io/zold?branch=master)
15
15
 
16
- [![Maintainability](https://api.codeclimate.com/v1/badges/7489c1d2bacde40ffc09/maintainability)](https://codeclimate.com/github/zold-io/zold/maintainability)
16
+ [![Maintainability](https://api.codeclimate.com/v1/badges/2861728929db934eb376/maintainability)](https://codeclimate.com/github/zold-io/zold/maintainability)
17
17
 
18
18
  **NOTICE**: It's an experiment and a very early draft! Please, feel free to
19
19
  submit your ideas and/or pull requests.
@@ -37,7 +37,7 @@ To make sure it's installed, try:
37
37
  $ zold --help
38
38
  ```
39
39
 
40
- You will need PGP private and public keys in `~/.ssh`.
40
+ You will need RSA private and public keys in `~/.ssh`.
41
41
  If you don't have them yet, run this in order to generate a new pair
42
42
  (just hit <kbd>Enter</kbd> when it asks you for a password):
43
43
 
@@ -122,7 +122,7 @@ send you bonuses for keeping the node online (approximately 1 ZLD per day).
122
122
 
123
123
  ## Frequently Asked Questions
124
124
 
125
- > Where are my PGP private/public keys?
125
+ > Where are my RSA private/public keys?
126
126
 
127
127
  They are in `~/.ssh/id_rsa` (private key) and `~/.ssh/id_rsa.pub` (public key).
128
128
  Make sure you have a copy of your private key in some safe place.
@@ -225,6 +225,101 @@ To be continued...
225
225
 
226
226
  `hours_alive` is the time in hours your server is alive without a reboot.
227
227
 
228
+ ## SDK
229
+
230
+ Here is how you use Zold SDK from your Ruby app. First, you should
231
+ add `zold` [gem](https://rubygems.org/gems/zold)
232
+ to your [`Gemfile`](https://bundler.io/gemfile.html) or just:
233
+
234
+ ```bash
235
+ $ gem install zold
236
+ ```
237
+
238
+ Then, you will need a directory where wallets and other supplementary data will be kept.
239
+ This can be any directory, including a temporary one. If it doesn't exist,
240
+ it will automatically be created:
241
+
242
+ ```ruby
243
+ home = '/tmp/my-zold-dir'
244
+ ```
245
+
246
+ Then, you need to create three objects:
247
+
248
+ ```ruby
249
+ require 'zold/wallets'
250
+ require 'zold/remotes'
251
+ wallets = Zold::Wallets.new(home)
252
+ remotes = Zold::Remotes.new(File.join(home, 'remotes'))
253
+ copies = File.join(home, 'copies')
254
+ ```
255
+
256
+ The first step is to update the list of remote nodes, in order
257
+ to be properly connected to the network:
258
+
259
+ ```ruby
260
+ require 'zold/commands/remote'
261
+ Zold::Remote.new(remotes: remotes).run(['remote', 'update'])
262
+ ```
263
+
264
+ Now you are ready to create a wallet:
265
+
266
+ ```ruby
267
+ require 'zold/commands/create'
268
+ Zold::Create.new(wallets: wallets).run(['create', '--public-key=/tmp/id_rsa.pub'])
269
+ ```
270
+
271
+ Here `--public-key=/tmp/id_rsa.pub` points to the absolute location of
272
+ a public RSA key for the wallet you want to create.
273
+
274
+ You can also pull a wallet from the network:
275
+
276
+ ```ruby
277
+ require 'zold/commands/pull'
278
+ Zold::Pull.new(wallets: wallets, remotes: remotes, copies: copies).run(['pull', '00000000000ff1ce'])
279
+ ```
280
+
281
+ Then, you can make a payment:
282
+
283
+ ```ruby
284
+ require 'zold/commands/pay'
285
+ Zold::Pay.new(wallets: wallets).run(
286
+ ['pay', '17737fee5b825835', '00000000000ff1ce', '19.99', 'For a pizza', '--private-key=/tmp/id_rsa']
287
+ )
288
+ ```
289
+
290
+ Here `--private-key=/tmp/id_rsa` points to the absolute location of the private RSA key of
291
+ the paying wallet.
292
+
293
+ Finally, you can push a wallet to the network:
294
+
295
+ ```ruby
296
+ require 'zold/commands/push'
297
+ Zold::Push.new(wallets: wallets, remotes: remotes).run(%w[push 17737fee5b825835])
298
+ ```
299
+
300
+ By default, all commands will work quietly, reporting absolutely nothing
301
+ to the console. To change that, you can use `log` argument of their constructors.
302
+ For example, `Zold::Log::Verbose` will print a lot of information to the console:
303
+
304
+ ```ruby
305
+ require 'zold/commands/push'
306
+ Zold::Push.new(wallets: wallets, remotes: remotes, log: Zold::Log::Verbose.new).run(['push'])
307
+ ```
308
+
309
+ Also, all commands by default assume that you are working in a `test` network.
310
+ This is done in order to protect our production network from your test cases.
311
+ In order to instruct them to deal with real data and real nodes, you should
312
+ give them `--network=zold` argument, for example:
313
+
314
+ ```ruby
315
+ require 'zold/commands/push'
316
+ Zold::Push.new(wallets: wallets, remotes: remotes).run(%w[push 17737fee5b825835 --network=zold])
317
+ ```
318
+
319
+ If anything doesn't work as explained above, please
320
+ [submit at ticket](https://github.com/zold-io/zold/issues) or join our
321
+ [Telegram group](https://t.me/zold_io) and complain there.
322
+
228
323
  ## How to Contribute
229
324
 
230
325
  It is a Ruby command line gem. First, install
data/Rakefile CHANGED
@@ -36,6 +36,7 @@ task default: %i[clean test features rubocop xcop copyright]
36
36
  require 'rake/testtask'
37
37
  desc 'Run all unit tests'
38
38
  Rake::TestTask.new(:test) do |test|
39
+ ENV['TEST_QUIET_LOG'] = 'true' if ARGV.include?('--quiet')
39
40
  Rake::Cleaner.cleanup_files(['coverage'])
40
41
  test.libs << 'lib' << 'test'
41
42
  test.pattern = 'test/**/test_*.rb'
data/bin/zold CHANGED
@@ -40,6 +40,8 @@ require_relative '../lib/zold/key'
40
40
  require_relative '../lib/zold/amount'
41
41
  require_relative '../lib/zold/copies'
42
42
  require_relative '../lib/zold/remotes'
43
+ require_relative '../lib/zold/upgrades'
44
+ require_relative '../lib/zold/version_file'
43
45
 
44
46
 
45
47
  Encoding.default_external = Encoding::UTF_8
@@ -91,7 +93,9 @@ Available commands:
91
93
  Pay taxes, check their status
92
94
  #{Rainbow('node').green} [options]
93
95
  Run node at the given TCP port
94
- #{Rainbow('score').green} host port strength [options]
96
+ #{Rainbow('alias').green} [alias] [wallet ID]
97
+ Set an alias for a wallet
98
+ #{Rainbow('score').green} [options]
95
99
  Generate score for the given host and port
96
100
  Available options:"
97
101
  o.string '--home',
@@ -132,6 +136,8 @@ Available options:"
132
136
  FileUtils.mkdir_p(opts[:home])
133
137
  Dir.chdir(opts[:home])
134
138
 
139
+ Zold::Upgrades.new(Zold::VersionFile.new('.zoldata/version'), 'upgrades').run
140
+
135
141
  wallets = Zold::Wallets.new('.')
136
142
  remotes = Zold::Remotes.new('./.zoldata/remotes', network: opts['network'])
137
143
  copies = './.zoldata/copies'
@@ -179,6 +185,9 @@ Available options:"
179
185
  when 'push'
180
186
  require_relative '../lib/zold/commands/push'
181
187
  Zold::Push.new(wallets: wallets, remotes: remotes, log: log).run(args)
188
+ when 'alias'
189
+ require_relative '../lib/zold/commands/alias'
190
+ Zold::Alias.new(wallets: wallets, remotes: remotes, log: log).run(args)
182
191
  when 'score'
183
192
  require_relative '../lib/zold/commands/calculate'
184
193
  Zold::Calculate.new(log: log).run(args)
@@ -0,0 +1,23 @@
1
+ # Copyright (c) 2018 Yegor Bugayenko
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the 'Software'), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all
11
+ # copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ # SOFTWARE.
20
+
21
+ require_relative 'asserts'
22
+ wallet = Zold::Wallet.new(Zold::Id.new('0123456789abcdef'))
23
+ assert_equal(Zold::Amount.new(zld: 512.0), wallet.balance)
@@ -0,0 +1 @@
1
+ 1,0.0.0.0,4096,50,NOW
@@ -0,0 +1,5 @@
1
+ 1,0.0.0.0,4096,10,NOW
2
+ 2,0.0.0.0,4096,20,NOW
3
+ 3,0.0.0.0,4096,30,NOW
4
+ 4,0.0.0.0,4096,40,NOW
5
+ 5,0.0.0.0,4096,50,NOW
@@ -2,4 +2,3 @@ test
2
2
  1
3
3
  0123456789abcdef
4
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
-
@@ -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;2018-06-22T07:38:23Z;0000020000000000;g6hVRJNH;0000000000000000;To help you;
@@ -0,0 +1 @@
1
+ 1,0.0.0.0,4096,50,NOW
@@ -29,6 +29,7 @@ zold taxes debt 0000000000000000
29
29
 
30
30
  zold remote show
31
31
  zold push 0000000000000000
32
+ sleep 2
32
33
  zold fetch 0000000000000000 --ignore-score-weakness
33
34
  zold diff 0000000000000000
34
35
  zold merge 0000000000000000
@@ -28,20 +28,21 @@ module Zold
28
28
  def initialize(file)
29
29
  raise 'File can\'t be nil' if file.nil?
30
30
  @file = file
31
+ @mutex = Mutex.new
31
32
  end
32
33
 
33
34
  def read
34
- File.open(@file, 'rb') do |f|
35
- f.flock(File::LOCK_EX)
36
- f.read
35
+ @mutex.synchronize do
36
+ File.open(@file, 'rb', &:read)
37
37
  end
38
38
  end
39
39
 
40
40
  def write(content)
41
41
  raise 'Content can\'t be nil' if content.nil?
42
- File.open(@file, 'wb') do |f|
43
- f.flock(File::LOCK_EX)
44
- f.write(content)
42
+ @mutex.synchronize do
43
+ File.open(@file, 'wb') do |f|
44
+ f.write(content)
45
+ end
45
46
  end
46
47
  end
47
48
  end
@@ -0,0 +1,37 @@
1
+ require 'slop'
2
+ require 'rainbow'
3
+ require_relative 'args'
4
+ require_relative '../log'
5
+
6
+ module Zold
7
+ # Command to set an alias for wallet ID
8
+ class Alias
9
+ def initialize(wallets:, remotes:, log: Log::Quiet.new)
10
+ @wallets = wallets
11
+ @remotes = remotes
12
+ @log = log
13
+ end
14
+
15
+ def run(args = [])
16
+ opts = Slop.parse(args, help: true, suppress_errors: true) do |o|
17
+ o.banner = "Usage: zold alias [args]
18
+ #{Rainbow('alias set <wallet> <alias>').green}
19
+ Make wallet known under an alias.
20
+ #{Rainbow('alias remove <alias>').green}
21
+ Remove an alias.
22
+ #{Rainbow('alias show <alias>').green}
23
+ Show where the alias is pointing to.
24
+ Available options:"
25
+ o.bool '--help', 'Print instructions'
26
+ end
27
+ mine = Args.new(opts, @log).take || return
28
+ command = mine[0]
29
+ raise "A command is required, try 'zold alias --help'" unless command
30
+
31
+ # @todo #279:30min Implement command handling. As in other commands,
32
+ # there should be case/when command/end loop and commands should be
33
+ # implemented as methods.
34
+ raise NotImplementedError, 'This is not yet implemented'
35
+ end
36
+ end
37
+ end
@@ -35,8 +35,11 @@ module Zold
35
35
 
36
36
  def run(args = [])
37
37
  opts = Slop.parse(args, help: true, suppress_errors: true) do |o|
38
- o.banner = "Usage: zold push [ID...] [options]
38
+ o.banner = "Usage: zold score [options]
39
39
  Available options:"
40
+ o.string '--time',
41
+ 'The time to start a score prefix with (default: current time)',
42
+ default: Time.now.utc.iso8601
40
43
  o.string '--invoice',
41
44
  'The invoice you want to collect money to'
42
45
  o.integer '--port',
@@ -71,7 +74,7 @@ Available options:"
71
74
  strength = opts[:strength]
72
75
  raise "Invalid strength: #{strength}" if strength <= 0 || strength > 8
73
76
  score = Zold::Score.new(
74
- Time.now, opts[:host], opts[:port].to_i,
77
+ Time.parse(opts[:time]), opts[:host], opts[:port].to_i,
75
78
  opts[:invoice], strength: strength
76
79
  )
77
80
  loop do
@@ -71,8 +71,8 @@ Available options:"
71
71
  end
72
72
  before = AtomicFile.new(wallet.path).read
73
73
  after = ''
74
- Tempfile.open do |f|
75
- patch.save(f, overwrite: true)
74
+ Tempfile.open(['', Wallet::EXTENSION]) do |f|
75
+ patch.save(f.path, overwrite: true)
76
76
  after = File.read(f)
77
77
  end
78
78
  diff = Diffy::Diff.new(before, after, context: 0).to_s(:color)
@@ -77,7 +77,8 @@ Available options:"
77
77
  end
78
78
  raise "There are no remote nodes, run 'zold remote reset'" if nodes.zero?
79
79
  raise "No nodes out of #{nodes} have the wallet #{id}" if done.zero?
80
- @log.debug("#{nodes} copies of #{id} fetched for the total score of #{total}, #{cps.all.count} local copies")
80
+ @log.debug("#{nodes} copies of #{id} fetched for the total score of #{total}, \
81
+ #{cps.all.count} local copies:\n #{cps.all.map { |c| "#{c[:name]}: #{c[:score]}" }.join("\n ")}")
81
82
  end
82
83
 
83
84
  def fetch_one(id, r, cps, opts)
@@ -94,15 +95,34 @@ Available options:"
94
95
  r.assert_valid_score(score)
95
96
  r.assert_score_ownership(score)
96
97
  r.assert_score_strength(score) unless opts['ignore-score-weakness']
97
- Tempfile.open do |f|
98
+ Tempfile.open(['', Wallet::EXTENSION]) do |f|
98
99
  body = json['body']
99
100
  File.write(f, body)
100
101
  wallet = Wallet.new(f.path)
101
102
  copy = cps.add(body, score.host, score.port, score.value)
102
- @log.info("#{r} returned #{body.length}b/#{wallet.txns.count}t as copy ##{copy} \
103
+ @log.info("#{r} returned #{body.length}b/#{wallet.txns.count}t/#{digest(json)}/#{age(json)} as copy #{copy} \
103
104
  of #{id} in #{(Time.now - start).round(2)}s: #{Rainbow(score.value).green} (#{json['version']})")
104
105
  end
105
106
  score.value
106
107
  end
108
+
109
+ def digest(json)
110
+ hash = json['digest']
111
+ return '?' if hash.nil?
112
+ hash[0, 6]
113
+ end
114
+
115
+ def age(json)
116
+ mtime = json['mtime']
117
+ return '?' if mtime.nil?
118
+ sec = Time.now - Time.parse(mtime)
119
+ if sec < 60
120
+ "#{sec}s"
121
+ elsif sec < 60 * 60
122
+ "#{(sec / 60).round}m"
123
+ else
124
+ "#{(sec / 3600).round}h"
125
+ end
126
+ end
107
127
  end
108
128
  end
@@ -67,20 +67,23 @@ Available options:"
67
67
  def merge(id, cps, opts)
68
68
  cps = cps.all.sort_by { |c| c[:score] }.reverse
69
69
  patch = Patch.new(@wallets, log: @log)
70
- cps.each do |c|
71
- merge_one(opts, patch, Wallet.new(c[:path]), c[:name])
72
- @log.debug("Copy ##{c[:name]} merged: #{patch}")
70
+ score = 0
71
+ cps.each_with_index do |c, idx|
72
+ wallet = Wallet.new(c[:path])
73
+ merge_one(opts, patch, wallet, "#{c[:name]}/#{idx}/#{c[:score]}")
74
+ score += c[:score]
73
75
  end
74
76
  wallet = @wallets.find(id)
75
77
  if wallet.exists?
76
78
  merge_one(opts, patch, wallet, 'localhost')
77
- @log.debug("Local copy merged: #{patch}")
79
+ @log.debug("Local copy of #{id} merged: #{patch}")
78
80
  else
79
- @log.debug("Local copy is absent, won't merge")
81
+ @log.debug("Local copy of #{id} is absent, nothing to merge")
80
82
  end
81
83
  modified = patch.save(wallet.path, overwrite: true)
82
84
  if modified
83
- @log.debug("#{cps.count} copies merged successfully into #{wallet.id}, balance is #{wallet.balance}")
85
+ @log.debug("#{cps.count} copies with the total score of #{score} successfully merged \
86
+ into #{wallet.id}/#{wallet.balance}/#{wallet.txns.count}t")
84
87
  else
85
88
  @log.debug("Nothing changed in #{wallet.id} after merge of #{cps.count} copies")
86
89
  end
@@ -88,9 +91,11 @@ Available options:"
88
91
  end
89
92
 
90
93
  def merge_one(opts, patch, wallet, name)
94
+ @log.debug("Building a patch for #{wallet.id} from remote copy #{name}...")
91
95
  patch.join(wallet, !opts['no-baseline'])
96
+ @log.debug("Copy #{name} of #{wallet.id} merged: #{patch}")
92
97
  rescue StandardError => e
93
- @log.error("Can't merge copy ##{name}: #{e.message}")
98
+ @log.error("Can't merge copy #{name}: #{e.message}")
94
99
  @log.debug(Backtrace.new(e).to_s)
95
100
  end
96
101
  end
@@ -25,6 +25,7 @@ require_relative '../backtrace'
25
25
  require_relative '../metronome'
26
26
  require_relative '../wallet'
27
27
  require_relative '../wallets'
28
+ require_relative '../hungry_wallets'
28
29
  require_relative '../remotes'
29
30
  require_relative '../verbose_thread'
30
31
  require_relative '../node/entrance'
@@ -45,7 +46,7 @@ module Zold
45
46
  # NODE command
46
47
  class Node
47
48
  def initialize(wallets:, remotes:, copies:, log: Log::Quiet.new)
48
- @wallets = wallets
49
+ @wallets = HungryWallets.new(wallets)
49
50
  @remotes = remotes
50
51
  @copies = copies
51
52
  @log = log
@@ -128,11 +129,13 @@ module Zold
128
129
  end
129
130
  Front.set(:log, @log)
130
131
  Front.set(:version, opts['expose-version'])
132
+ Front.set(:protocol, Zold::PROTOCOL)
131
133
  Front.set(:logging, @log.debug?)
132
134
  Front.set(:home, Dir.pwd)
133
135
  @log.info("Home directory: #{Dir.pwd}")
134
136
  @log.info("Ruby version: #{RUBY_VERSION}")
135
137
  @log.info("Zold gem version: #{Zold::VERSION}")
138
+ @log.info("Zold protocol version: #{Zold::PROTOCOL}")
136
139
  @log.info("Network ID: #{opts['network']}")
137
140
  host = opts[:host] || ip
138
141
  address = "#{host}:#{opts[:port]}".downcase
@@ -174,7 +177,7 @@ module Zold
174
177
  @wallets, @remotes, address,
175
178
  log: @log,
176
179
  ignore_score_weakeness: opts['ignore-score-weakness']
177
- ), log: @log
180
+ ), File.join(Dir.pwd, '.zoldata/entrance'), log: @log
178
181
  ), network: opts['network']
179
182
  ).start do |entrance|
180
183
  Front.set(:entrance, entrance)
@@ -103,7 +103,18 @@ Available options:"
103
103
  @log.debug("#{amount} sent from #{from} to #{txn.bnf}: #{details}")
104
104
  @log.debug("Don't forget to do 'zold push #{from}'")
105
105
  @log.info(txn.id)
106
+ notify_of_tax_debt(from)
106
107
  txn
107
108
  end
109
+
110
+ # @todo #79:40min Extract message cretion into a separate method for easier
111
+ # testing. Add tests for when in debt and not. Extract to a
112
+ # module, possibly Notify.
113
+ def notify_of_tax_debt(wallet)
114
+ tax = Tax.new(wallet)
115
+ message = "The tax debt of #{wallet} is #{tax.debt}"
116
+ message += ' (still acceptable)' unless tax.in_debt?
117
+ @log.info(message)
118
+ end
108
119
  end
109
120
  end
@@ -98,7 +98,7 @@ of #{wallet.id} there, in #{(Time.now - start).round(2)}s")
98
98
  r.assert_valid_score(score)
99
99
  r.assert_score_ownership(score)
100
100
  r.assert_score_strength(score) unless opts['ignore-score-weakness']
101
- @log.info("#{r} accepted #{content.length}b/#{wallet.txns.count}t of #{wallet.id} \
101
+ @log.info("#{r} accepted #{content.length}b/#{wallet.digest[0, 6]}/#{wallet.txns.count}t of #{wallet.id} \
102
102
  in #{(Time.now - start).round(2)}s: #{Rainbow(score.value).green} (#{json['version']})")
103
103
  score.value
104
104
  end