zold 0.14.3 → 0.14.4

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