zold 0.13.46 → 0.14.0

Sign up to get free protection for your applications and to get access to all the features.
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