zold 0.14.3 → 0.14.4

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9a77da32d7c42f8614442e76efa0eb9560e645a8
4
- data.tar.gz: 5840bb2844ef57929752da61d40158a2f2eba758
3
+ metadata.gz: d8506b67f7b833f450efcf81d313c1598cc8a8dc
4
+ data.tar.gz: bbb006a82c64e5647c975d116543ebc1412b237e
5
5
  SHA512:
6
- metadata.gz: ebf8e676c08b13bf103d7cf155191bbf05e95d09138a815d0357782a2e9fba499c1bb8499dfbdf39f6cf8541d181f3ad26bfd0d0399bba1912a0db28727cfb31
7
- data.tar.gz: a8d9e92bfa9a5f4660bb089a6ea80862547f51b84f5fc454d5d22bd18f79a36858dbfc2949efffde70da25f6d90ba7bca68585f64062e5c58db27c8edc8b44cf
6
+ metadata.gz: 6c93783eea87d06905b377242838684e8e9d58e653cd3dcfeb1c384ceaec4ddc5f70ba29cb8a6089c8c0b03f03f6162a225fcb70c1f31da6b65a7a568fa987e9
7
+ data.tar.gz: b4dc313ac468f1484d5288c180876878150a4d9628f9a7905fb1851509aa34d54d6ad5361a1c6a203a47c142407e39fdf66b762938f8cb3b711892063fe2943a
data/bin/zold CHANGED
@@ -187,7 +187,7 @@ Available options:"
187
187
  Zold::Push.new(wallets: wallets, remotes: remotes, log: log).run(args)
188
188
  when 'alias'
189
189
  require_relative '../lib/zold/commands/alias'
190
- Zold::Alias.new(wallets: wallets, remotes: remotes, log: log).run(args)
190
+ Zold::Alias.new(wallets: wallets, log: log).run(args)
191
191
  when 'score'
192
192
  require_relative '../lib/zold/commands/calculate'
193
193
  Zold::Calculate.new(log: log).run(args)
@@ -6,9 +6,8 @@ require_relative '../log'
6
6
  module Zold
7
7
  # Command to set an alias for wallet ID
8
8
  class Alias
9
- def initialize(wallets:, remotes:, log: Log::Quiet.new)
9
+ def initialize(wallets:, log: Log::Quiet.new)
10
10
  @wallets = wallets
11
- @remotes = remotes
12
11
  @log = log
13
12
  end
14
13
 
@@ -57,8 +57,12 @@ Available options:"
57
57
 
58
58
  def clean(cps, _)
59
59
  deleted = cps.clean
60
- @log.debug("#{deleted} expired local copies removed for #{cps}, \
61
- #{cps.all.count} left")
60
+ @log.debug("#{deleted} expired local copies removed for #{cps}, #{cps.all.count} left:")
61
+ cps.all.each do |c|
62
+ wallet = Wallet.new(c[:path])
63
+ @log.debug(" #{c[:name]}: #{c[:score]} #{wallet.balance}/#{wallet.txns.count}t/\
64
+ #{wallet.digest[0, 6]}/#{File.size(c[:path])}b")
65
+ end
62
66
  end
63
67
  end
64
68
  end
@@ -55,6 +55,9 @@ Available options:"
55
55
  o.array '--ignore-node',
56
56
  'Ignore this node and don\'t fetch from it',
57
57
  default: []
58
+ o.string '--network',
59
+ 'The name of the network we work in',
60
+ default: 'test'
58
61
  o.bool '--help', 'Print instructions'
59
62
  end
60
63
  mine = Args.new(opts, @log).take || return
@@ -99,9 +102,19 @@ Available options:"
99
102
  body = json['body']
100
103
  File.write(f, body)
101
104
  wallet = Wallet.new(f.path)
102
- copy = cps.add(body, score.host, score.port, score.value)
103
- @log.info("#{r} returned #{body.length}b/#{wallet.txns.count}t/#{digest(json)}/#{age(json)} as copy #{copy} \
104
- of #{id} in #{(Time.now - start).round(2)}s: #{Rainbow(score.value).green} (#{json['version']})")
105
+ wallet.refurbish
106
+ if wallet.protocol != Zold::PROTOCOL
107
+ raise "Protocol #{wallet.protocol} doesn't match #{Zold::PROTOCOL} in #{id}"
108
+ end
109
+ if wallet.network != opts['network']
110
+ raise "The wallet #{id} is in network #{wallet.network}, while we are in #{opts['network']}"
111
+ end
112
+ if wallet.balance.negative? && !wallet.root?
113
+ raise "The balance of #{id} is #{wallet.balance} and it's not a root wallet"
114
+ end
115
+ copy = cps.add(File.read(f), score.host, score.port, score.value)
116
+ @log.info("#{r} returned #{body.length}b/#{wallet.balance}/#{wallet.txns.count}t/#{digest(json)}/#{age(json)} \
117
+ as copy #{copy} of #{id} in #{(Time.now - start).round(2)}s: #{Rainbow(score.value).green} (#{json['version']})")
105
118
  end
106
119
  score.value
107
120
  end
@@ -117,7 +130,7 @@ of #{id} in #{(Time.now - start).round(2)}s: #{Rainbow(score.value).green} (#{js
117
130
  return '?' if mtime.nil?
118
131
  sec = Time.now - Time.parse(mtime)
119
132
  if sec < 60
120
- "#{sec}s"
133
+ "#{sec.round(2)}s"
121
134
  elsif sec < 60 * 60
122
135
  "#{(sec / 60).round}m"
123
136
  else
data/lib/zold/copies.rb CHANGED
@@ -23,6 +23,7 @@ require 'csv'
23
23
  require_relative 'atomic_file'
24
24
  require_relative 'log'
25
25
  require_relative 'wallet'
26
+ require_relative 'backtrace'
26
27
 
27
28
  # The list of copies.
28
29
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
@@ -53,14 +54,26 @@ module Zold
53
54
  list.reject! { |s| s[:time] < Time.now - 24 * 60 * 60 }
54
55
  save(list)
55
56
  deleted = 0
56
- Dir.new(@dir).select { |f| File.basename(f, Wallet::EXTENSION) =~ /^[0-9]+$/ }.each do |f|
57
+ files.each do |f|
57
58
  next unless list.find { |s| s[:name] == File.basename(f, Wallet::EXTENSION) }.nil?
58
59
  file = File.join(@dir, f)
59
60
  size = File.size(file)
60
61
  File.delete(file)
61
- @log.debug("Copy ##{f} deleted: #{size}b")
62
+ @log.debug("Copy at #{f} deleted: #{size}b")
62
63
  deleted += 1
63
64
  end
65
+ files.each do |f|
66
+ file = File.join(@dir, f)
67
+ wallet = Wallet.new(file)
68
+ begin
69
+ wallet.refurbish
70
+ raise "Invalid protocol #{wallet.protocol} in #{file}" unless wallet.protocol == Zold::PROTOCOL
71
+ rescue StandardError => e
72
+ File.delete(file)
73
+ @log.debug("Copy at #{f} deleted: #{Backtrace.new(e)}")
74
+ deleted += 1
75
+ end
76
+ end
64
77
  deleted
65
78
  end
66
79
  end
@@ -153,6 +166,10 @@ module Zold
153
166
  )
154
167
  end
155
168
 
169
+ def files
170
+ Dir.new(@dir).select { |f| File.basename(f, Wallet::EXTENSION) =~ /^[0-9]+$/ }
171
+ end
172
+
156
173
  def file
157
174
  File.join(@dir, "scores#{Wallet::EXTENSION}")
158
175
  end
@@ -165,11 +165,20 @@ module Zold
165
165
  def load
166
166
  @mutex.synchronize do
167
167
  if File.exist?(@cache)
168
- AtomicFile.new(@cache).read.split(/\n/).map { |t| Score.parse(t) }
168
+ AtomicFile.new(@cache).read.split(/\n/)
169
+ .map { |t| parse_score_line(t) }
170
+ .reject(&:zero?)
169
171
  else
170
172
  []
171
173
  end
172
174
  end
173
175
  end
176
+
177
+ def parse_score_line(line)
178
+ Score.parse(line)
179
+ rescue StandardError => e
180
+ @log.error(Backtrace.new(e).to_s)
181
+ Score::ZERO
182
+ end
174
183
  end
175
184
  end
@@ -138,6 +138,7 @@ module Zold
138
138
  threads: "#{Thread.list.select { |t| t.status == 'run' }.count}/#{Thread.list.count}",
139
139
  wallets: settings.wallets.all.count,
140
140
  remotes: settings.remotes.all.count,
141
+ nscore: settings.remotes.all.map { |r| r[:score] }.inject(&:+),
141
142
  farm: settings.farm.to_json,
142
143
  entrance: settings.entrance.to_json,
143
144
  date: Time.now.utc.iso8601,
data/lib/zold/score.rb CHANGED
@@ -191,5 +191,9 @@ module Zold
191
191
  def value
192
192
  @suffixes.length
193
193
  end
194
+
195
+ def zero?
196
+ equal?(Score::ZERO)
197
+ end
194
198
  end
195
199
  end
data/lib/zold/version.rb CHANGED
@@ -23,6 +23,6 @@
23
23
  # Copyright:: Copyright (c) 2018 Yegor Bugayenko
24
24
  # License:: MIT
25
25
  module Zold
26
- VERSION = '0.14.3'.freeze
26
+ VERSION = '0.14.4'.freeze
27
27
  PROTOCOL = 2
28
28
  end
data/lib/zold/wallet.rb CHANGED
@@ -165,6 +165,10 @@ module Zold
165
165
  .sort_by { |t| [t.date, t.amount * -1] }
166
166
  end
167
167
 
168
+ def refurbish
169
+ AtomicFile.new(@file).write("#{network}\n#{protocol}\n#{id}\n#{key.to_pub}\n\n#{txns.join("\n")}\n")
170
+ end
171
+
168
172
  private
169
173
 
170
174
  def max
@@ -1,7 +1,54 @@
1
1
  require 'minitest/autorun'
2
+ require_relative '../test__helper'
3
+ require_relative '../fake_home'
4
+ require_relative '../../lib/zold/commands/alias'
2
5
 
3
- # @todo #279:30min Write unit tests for the alias command.
4
- # It should test all the subcommands (set, remove and show)
5
- # and any options.
6
6
  class TestAlias < Minitest::Test
7
+ # alias set <wallet> <alias>
8
+ # @todo #322:30min Implement the set command and unskip this test.
9
+ # The syntax is already documented in the alias command in the help.
10
+ def test_set_writes_alias_to_the_alias_file
11
+ skip
12
+ FakeHome.new.run do |home|
13
+ wallet = home.create_wallet
14
+ Zold::Alias.new(wallets: home.wallets, log: test_log).run(%W[set #{wallet.id} my-alias])
15
+ assert_equal read_alias_file(home), %W[my-alias #{wallet.id}]
16
+ end
17
+ end
18
+
19
+ # alias remove <alias>
20
+ # @todo #322:30min Implement the remove command and unskip this test.
21
+ # The syntax is already documented in the alias command in the help.
22
+ def test_remove_removes_the_alias_from_the_alias_file
23
+ skip
24
+ FakeHome.new.run do |home|
25
+ wallet = home.create_wallet
26
+ cmd = Zold::Alias.new(wallets: home.wallets, log: test_log)
27
+ cmd.run(%W[set #{wallet.id} my-alias])
28
+ assert_equal read_alias_file(home), %W[my-alias #{wallet.id}]
29
+ cmd.run(%w[remove my-alias])
30
+ assert_empty read_alias_file(home)
31
+ end
32
+ end
33
+
34
+ # alias show <alias>
35
+ # @todo #322:30min Implement the show command and unskip this test.
36
+ # The syntax is already documented in the alias command in the help.
37
+ def test_show_prints_out_the_aliased_wallet_id
38
+ skip
39
+ FakeHome.new.run do |home|
40
+ wallet = home.create_wallet
41
+ cmd = Zold::Alias.new(wallets: home.wallets, log: test_log)
42
+ cmd.run(%W[set #{wallet.id} my-alias])
43
+ assert_equal read_alias_file(home), %W[my-alias #{wallet.id}]
44
+ stdout, = capture_io { cmd.run(%w[show my-alias]) }
45
+ assert_match wallet.id.to_s, stdout
46
+ end
47
+ end
48
+
49
+ private
50
+
51
+ def read_alias_file(home)
52
+ File.read(File.join(home.dir, 'aliases')).split(' ')
53
+ end
7
54
  end
@@ -26,6 +26,15 @@ require_relative '../../lib/zold/log'
26
26
  require_relative '../../lib/zold/node/farm'
27
27
 
28
28
  class FarmTest < Minitest::Test
29
+ class SaveLastMessageLogger
30
+ attr_reader :msg
31
+ def error(msg)
32
+ @msg = msg
33
+ end
34
+
35
+ def debug(msg); end
36
+ end
37
+
29
38
  def test_renders_in_json
30
39
  Dir.mktmpdir 'test' do |dir|
31
40
  farm = Zold::Farm.new('NOPREFIX@ffffffffffffffff', File.join(dir, 'f'), log: test_log)
@@ -107,4 +116,28 @@ class FarmTest < Minitest::Test
107
116
  end
108
117
  end
109
118
  end
119
+
120
+ def test_garbage_farm_file
121
+ log = SaveLastMessageLogger.new
122
+ Dir.mktmpdir 'test' do |dir|
123
+ file = File.join(dir, 'corrupted_farm')
124
+ [
125
+ '0/6: 2018-06-26ABCT00:32:43Z 178.128.165.12 4096 MIRhypo1@c13620484b46caa4',
126
+ 'some garbage'
127
+ ].each do |score_garbage_line|
128
+ valid_score = Zold::Score.new(
129
+ Time.parse('2017-07-19T21:24:51Z'),
130
+ 'some-host', 9999, 'NOPREFIX@ffffffffffffffff', %w[13f7f01 b2b32b 4ade7e],
131
+ strength: 6
132
+ )
133
+ File.open(file, 'w') do |f|
134
+ f.puts(score_garbage_line)
135
+ f.puts(valid_score)
136
+ end
137
+ farm = Zold::Farm.new('NOPREFIX@ffffffffffffffff', file, log: log)
138
+ assert_equal(1, farm.best.count)
139
+ assert(log.msg.include?('Invalid score'))
140
+ end
141
+ end
142
+ end
110
143
  end
data/test/test_copies.rb CHANGED
@@ -21,6 +21,9 @@
21
21
  require 'minitest/autorun'
22
22
  require 'tmpdir'
23
23
  require 'time'
24
+ require_relative 'fake_home'
25
+ require_relative 'test__helper'
26
+ require_relative '../lib/zold/id'
24
27
  require_relative '../lib/zold/copies'
25
28
  require_relative '../lib/zold/wallet'
26
29
 
@@ -31,32 +34,32 @@ require_relative '../lib/zold/wallet'
31
34
  class TestCopies < Minitest::Test
32
35
  def test_adds_and_removes_copies
33
36
  Dir.mktmpdir 'test' do |dir|
34
- copies = Zold::Copies.new(File.join(dir, 'my/a/copies'))
35
- copies.add('hello 1', '192.168.0.1', 80, 1)
36
- copies.add('hello 2', '192.168.0.2', 80, 3)
37
- copies.add('hello 2', '192.168.0.3', 80, 7)
38
- copies.add('hello 1', '192.168.0.4', 80, 10)
39
- copies.add('hello-to-delete', '192.168.0.5', 80, 10)
37
+ copies = Zold::Copies.new(File.join(dir, 'my/a/copies'), log: test_log)
38
+ copies.add(content('alpha'), '192.168.0.1', 80, 1)
39
+ copies.add(content('beta'), '192.168.0.2', 80, 3)
40
+ copies.add(content('beta'), '192.168.0.3', 80, 7)
41
+ copies.add(content('alpha'), '192.168.0.4', 80, 10)
42
+ copies.add(content('hello-to-delete'), '192.168.0.5', 80, 10)
40
43
  copies.remove('192.168.0.5', 80)
41
- assert(2, copies.all.count)
42
- assert(copies.all.find { |c| c[:name] == '1' }[:score] == 11)
44
+ assert_equal(2, copies.all.count)
45
+ assert_equal(11, copies.all.find { |c| c[:name] == '1' }[:score])
43
46
  end
44
47
  end
45
48
 
46
49
  def test_lists_empty_dir
47
50
  Dir.mktmpdir 'test' do |dir|
48
- copies = Zold::Copies.new(File.join(dir, 'xxx'))
51
+ copies = Zold::Copies.new(File.join(dir, 'xxx'), log: test_log)
49
52
  assert(copies.all.empty?, "#{copies.all.count} is not zero")
50
53
  end
51
54
  end
52
55
 
53
56
  def test_overwrites_host
54
57
  Dir.mktmpdir 'test' do |dir|
55
- copies = Zold::Copies.new(File.join(dir, 'my/a/copies'))
58
+ copies = Zold::Copies.new(File.join(dir, 'my/a/copies-2'), log: test_log)
56
59
  host = 'b1.zold.io'
57
- copies.add('z1', host, 80, 5)
58
- copies.add('z1', host, 80, 6)
59
- copies.add('z1', host, 80, 7)
60
+ copies.add(content('z1'), host, 80, 5)
61
+ copies.add(content('z1'), host, 80, 6)
62
+ copies.add(content('z1'), host, 80, 7)
60
63
  assert(copies.all.count == 1, "#{copies.all.count} is not equal to 1")
61
64
  assert(copies.all[0][:score] == 7, "#{copies.all[0][:score]} is not 7")
62
65
  end
@@ -64,9 +67,9 @@ class TestCopies < Minitest::Test
64
67
 
65
68
  def test_cleans_copies
66
69
  Dir.mktmpdir 'test' do |dir|
67
- copies = Zold::Copies.new(dir)
68
- copies.add('h1', 'zold.io', 50, 80, Time.now - 25 * 60 * 60)
69
- copies.add('h1', 'zold.io', 33, 80, Time.now - 26 * 60 * 60)
70
+ copies = Zold::Copies.new(dir, log: test_log)
71
+ copies.add(content('h1'), 'zold.io', 4096, 10, Time.now - 25 * 60 * 60)
72
+ copies.add(content('h1'), 'zold.io', 4097, 20, Time.now - 26 * 60 * 60)
70
73
  assert(File.exist?(File.join(dir, "1#{Zold::Wallet::EXTENSION}")))
71
74
  copies.clean
72
75
  assert(copies.all.empty?, "#{copies.all.count} is not empty")
@@ -74,10 +77,19 @@ class TestCopies < Minitest::Test
74
77
  end
75
78
  end
76
79
 
80
+ def test_cleans_broken_copies
81
+ Dir.mktmpdir 'test' do |dir|
82
+ copies = Zold::Copies.new(dir, log: test_log)
83
+ copies.add('broken wallet content', 'zold.io', 4096, 10, Time.now)
84
+ copies.clean
85
+ assert(copies.all.empty?, "#{copies.all.count} is not empty")
86
+ end
87
+ end
88
+
77
89
  def test_ignores_garbage
78
90
  Dir.mktmpdir 'test' do |dir|
79
- copies = Zold::Copies.new(dir)
80
- copies.add('h1', 'zold.io', 50, 80, Time.now - 25 * 60 * 60)
91
+ copies = Zold::Copies.new(dir, log: test_log)
92
+ copies.add(content('h1'), 'zold.io', 50, 80, Time.now - 25 * 60 * 60)
81
93
  FileUtils.mkdir(File.join(dir, '55'))
82
94
  assert_equal(1, copies.all.count)
83
95
  end
@@ -85,20 +97,33 @@ class TestCopies < Minitest::Test
85
97
 
86
98
  def test_sorts_them_by_score
87
99
  Dir.mktmpdir 'test' do |dir|
88
- copies = Zold::Copies.new(dir)
89
- copies.add('content-1', '1.zold.io', 80, 1)
90
- copies.add('content-2', '2.zold.io', 80, 2)
91
- copies.add('content-3', '3.zold.io', 80, 50)
92
- copies.add('content-4', '4.zold.io', 80, 3)
100
+ copies = Zold::Copies.new(dir, log: test_log)
101
+ copies.add(content('content-1'), '1.zold.io', 80, 1)
102
+ copies.add(content('content-2'), '2.zold.io', 80, 2)
103
+ copies.add(content('content-3'), '3.zold.io', 80, 50)
104
+ copies.add(content('content-4'), '4.zold.io', 80, 3)
93
105
  assert_equal('50 3 2 1', copies.all.map { |c| c[:score] }.join(' '))
94
106
  end
95
107
  end
96
108
 
97
109
  def test_ignores_too_old_scores
98
110
  Dir.mktmpdir 'test' do |dir|
99
- copies = Zold::Copies.new(dir)
100
- copies.add('h1', 'zold.io', 50, 80, Time.now - 1000 * 60 * 60)
111
+ copies = Zold::Copies.new(dir, log: test_log)
112
+ copies.add(content('h1'), 'zold.io', 50, 80, Time.now - 1000 * 60 * 60)
101
113
  assert_equal(0, copies.all[0][:score])
102
114
  end
103
115
  end
116
+
117
+ private
118
+
119
+ def content(text)
120
+ id = Zold::Id.new('aaaabbbbccccdddd')
121
+ FakeHome.new.run do |home|
122
+ wallet = home.create_wallet(id)
123
+ amount = Zold::Amount.new(zld: 1.99)
124
+ key = Zold::Key.new(file: 'fixtures/id_rsa')
125
+ wallet.sub(amount, "NOPREFIX@#{id}", key, text)
126
+ File.read(wallet.path)
127
+ end
128
+ end
104
129
  end
data/test/test_wallet.rb CHANGED
@@ -47,6 +47,19 @@ class TestWallet < Minitest::Test
47
47
  end
48
48
  end
49
49
 
50
+ def test_refurbishes_wallet
51
+ FakeHome.new.run do |home|
52
+ wallet = home.create_wallet
53
+ amount = Zold::Amount.new(zld: 5.99)
54
+ key = Zold::Key.new(file: 'fixtures/id_rsa')
55
+ wallet.sub(amount, "NOPREFIX@#{Zold::Id.new}", key)
56
+ wallet.sub(amount, "NOPREFIX@#{Zold::Id.new}", key)
57
+ File.write(wallet.path, File.read(wallet.path) + "\n\n\n")
58
+ wallet.refurbish
59
+ assert_equal(amount * -2, wallet.balance)
60
+ end
61
+ end
62
+
50
63
  def test_positive_transactions_go_first
51
64
  FakeHome.new.run do |home|
52
65
  wallet = home.create_wallet
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.14.3
4
+ version: 0.14.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yegor Bugayenko
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-07-10 00:00:00.000000000 Z
11
+ date: 2018-07-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby