zold 0.16.9 → 0.16.10

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
  SHA256:
3
- metadata.gz: 5fa4b6ced7df2e9773120703da57a11e317396caedc756a8b42d9316fb900ff7
4
- data.tar.gz: e1e4f91dda7d2954bb7cb34adf5f56b71202ebe59102a7a85a805e4425041be0
3
+ metadata.gz: 5bdb355d25ef5197cfcc131d383d5391bec683efb8f5db52ba6b60d690bf4e3f
4
+ data.tar.gz: dc2f83cf4bdbc787de4232aa56fb3570f721f887b93069b4fa766fc0eeee2597
5
5
  SHA512:
6
- metadata.gz: f5b2ccce4eec666e4036448517f18ee4e36e71637100b85d900536891bf7e04306b5e7fd764037df5616b07998526b472759f9aa873874ffedaa640256217b2f
7
- data.tar.gz: 16287fd3da5be69b02e5d3ef232ca18eaa6cd1dafaeafbbe07ec3d4fc98f34e21f23fcd867591b19f5fe18ff6302a66aba3901432d8781fe672c82ef283d2f56
6
+ metadata.gz: de19e0642f74972e9a28f7506fea7397d51473d7bc308b0da64353e9177cea7c2f16a56f1f0ca537f15f90d8001b6625c9762b9f1294eda20888539dc018c890
7
+ data.tar.gz: 19275bbdfe0cc8baea050d14656edcacad9b1d87846f4ddd9752f85517c20009515079c46050727bbb843b8448a5bd5feebcf8406584536720f9323c565b5011
@@ -5,6 +5,8 @@ AllCops:
5
5
  DisplayCopNames: true
6
6
  TargetRubyVersion: 2.3.3
7
7
 
8
+ Layout/EmptyLineAfterGuardClause:
9
+ Enabled: false
8
10
  Metrics/CyclomaticComplexity:
9
11
  Max: 25
10
12
  Metrics/MethodLength:
@@ -6,7 +6,7 @@ function start_node {
6
6
  cd ${port}
7
7
  zold node --trace --invoice=DISTRWALLET@ffffffffffffffff \
8
8
  --host=localhost --port=${port} --bind-port=${port} \
9
- --threads=0 --routine-immediately > log.txt &
9
+ --threads=0 --routine-immediately --never-reboot > log.txt &
10
10
  pid=$!
11
11
  echo ${pid} > pid
12
12
  cd ..
@@ -21,8 +21,8 @@
21
21
  # SOFTWARE.
22
22
 
23
23
  require 'slop'
24
+ require 'zold/score'
24
25
  require_relative '../log'
25
- require_relative '../score'
26
26
 
27
27
  # SCORE command.
28
28
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
@@ -26,12 +26,12 @@ require 'time'
26
26
  require 'futex'
27
27
  require 'slop'
28
28
  require 'rainbow'
29
+ require 'zold/score'
29
30
  require_relative 'args'
30
31
  require_relative '../age'
31
32
  require_relative '../size'
32
33
  require_relative '../log'
33
34
  require_relative '../http'
34
- require_relative '../score'
35
35
  require_relative '../copies'
36
36
 
37
37
  # CLEAN command.
@@ -27,12 +27,12 @@ require 'tempfile'
27
27
  require 'slop'
28
28
  require 'rainbow'
29
29
  require 'concurrent/atomics'
30
+ require 'zold/score'
30
31
  require_relative 'args'
31
32
  require_relative '../log'
32
33
  require_relative '../age'
33
34
  require_relative '../http'
34
35
  require_relative '../size'
35
- require_relative '../score'
36
36
  require_relative '../json_page'
37
37
  require_relative '../copies'
38
38
 
@@ -21,8 +21,8 @@
21
21
  # SOFTWARE.
22
22
 
23
23
  require 'slop'
24
+ require 'zold/score'
24
25
  require_relative '../log'
25
- require_relative '../score'
26
26
 
27
27
  # NEXT command.
28
28
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
@@ -24,9 +24,9 @@ require 'open3'
24
24
  require 'slop'
25
25
  require 'backtrace'
26
26
  require 'concurrent'
27
+ require 'zold/score'
27
28
  require_relative '../version'
28
29
  require_relative '../age'
29
- require_relative '../score'
30
30
  require_relative '../metronome'
31
31
  require_relative '../wallet'
32
32
  require_relative '../wallets'
@@ -79,8 +79,8 @@ module Zold
79
79
  "The strength of the score (default: #{Score::STRENGTH})",
80
80
  default: Score::STRENGTH
81
81
  o.integer '--threads',
82
- "How many threads to use for scores finding (default: #{Concurrent.processor_count})",
83
- default: Concurrent.processor_count
82
+ "How many threads to use for scores finding (default: #{[Concurrent.processor_count, 4].max})",
83
+ default: [Concurrent.processor_count, 4].max
84
84
  o.bool '--dump-errors',
85
85
  'Make HTTP front-end errors visible in the log (false by default)',
86
86
  default: false
@@ -95,8 +95,7 @@ total score for #{id} is #{total}")
95
95
  response = r.http(uri).put(content)
96
96
  @wallets.find(id) do |wallet|
97
97
  if response.code == '304'
98
- @log.info("#{r}: same version #{Size.new(content.length)} of #{wallet.memo} \
99
- there, in #{Age.new(start, limit: 0.5)}")
98
+ @log.info("#{r}: same version of #{wallet.memo} there, in #{Age.new(start, limit: 0.5)}")
100
99
  return 0
101
100
  end
102
101
  r.assert_code(200, response)
@@ -105,8 +104,8 @@ there, in #{Age.new(start, limit: 0.5)}")
105
104
  r.assert_valid_score(score)
106
105
  r.assert_score_ownership(score)
107
106
  r.assert_score_strength(score) unless opts['ignore-score-weakness']
108
- @log.info("#{r} accepted #{Size.new(content.length)} of #{wallet.memo} \
109
- in #{Age.new(start, limit: 4)}: #{Rainbow(score.value).green} (#{json['version']})")
107
+ @log.info("#{r} accepted #{wallet.memo} in #{Age.new(start, limit: 4)}: \
108
+ #{Rainbow(score.value).green} (#{json['version']})")
110
109
  score.value
111
110
  end
112
111
  end
@@ -26,6 +26,7 @@ require 'rainbow'
26
26
  require 'net/http'
27
27
  require 'json'
28
28
  require 'time'
29
+ require 'zold/score'
29
30
  require_relative 'args'
30
31
  require_relative '../node/farm'
31
32
  require_relative '../log'
@@ -33,7 +34,6 @@ require_relative '../age'
33
34
  require_relative '../json_page'
34
35
  require_relative '../http'
35
36
  require_relative '../remotes'
36
- require_relative '../score'
37
37
  require_relative '../wallet'
38
38
  require_relative '../gem'
39
39
 
@@ -23,11 +23,11 @@
23
23
  require 'slop'
24
24
  require 'json'
25
25
  require 'rainbow'
26
+ require 'zold/score'
26
27
  require_relative 'args'
27
28
  require_relative 'pay'
28
29
  require_relative '../log'
29
30
  require_relative '../json_page'
30
- require_relative '../score'
31
31
  require_relative '../id'
32
32
  require_relative '../tax'
33
33
  require_relative '../http'
@@ -121,13 +121,14 @@ the balance is #{wallet.balance}: #{tax.to_text}")
121
121
  @log.debug("No need to pay taxes yet, while the debt is less than #{Tax::TRIAL} (#{Tax::TRIAL.to_i} zents)")
122
122
  return
123
123
  end
124
- top = everybody = top_scores(opts)
124
+ top = top_scores(opts)
125
+ everybody = top.dup
125
126
  paid = 0
126
127
  while debt > Tax::TRIAL
127
128
  if top.empty?
128
129
  msg = [
129
130
  "There were #{everybody.count} remote nodes as tax collecting candidates;",
130
- "#{paid} payments have been made",
131
+ "#{paid} payments have been made;",
131
132
  "there was not enough score power to pay the total debt of #{total} for #{wallet.id};",
132
133
  "the residual amount to pay is #{debt} (trial amount is #{Tax::TRIAL});",
133
134
  "the formula ingredients are #{tax.to_text}"
@@ -21,9 +21,9 @@
21
21
  # SOFTWARE.
22
22
 
23
23
  require 'uri'
24
+ require 'zold/score'
24
25
  require_relative 'json_page'
25
26
  require_relative 'http'
26
- require_relative 'score'
27
27
 
28
28
  # Class representing the Zold gem on Rubygems
29
29
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
@@ -36,6 +36,8 @@ module Zold
36
36
  JsonPage.new(
37
37
  Http.new(uri: 'https://rubygems.org/api/v1/versions/zold/latest.json', score: Score::ZERO).get.body
38
38
  ).to_hash['version']
39
+ rescue StandardError => _
40
+ '0.0.0'
39
41
  end
40
42
  end
41
43
  end
@@ -25,8 +25,8 @@ require 'uri'
25
25
  require 'timeout'
26
26
  require 'net/http'
27
27
  require 'backtrace'
28
+ require 'zold/score'
28
29
  require_relative 'version'
29
- require_relative 'score'
30
30
 
31
31
  # HTTP page.
32
32
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
@@ -25,8 +25,8 @@ require 'open3'
25
25
  require 'backtrace'
26
26
  require 'futex'
27
27
  require 'json'
28
+ require 'zold/score'
28
29
  require_relative '../log'
29
- require_relative '../score'
30
30
  require_relative '../age'
31
31
  require_relative '../verbose_thread'
32
32
  require_relative 'farmers'
@@ -45,16 +45,32 @@ module Zold
45
45
  end
46
46
  end
47
47
 
48
+ # Makes an instance of a farm. There should be only farm in the entire
49
+ # application, but you can, of course, start as many of them as necessary for the
50
+ # purpose of unit testing.
51
+ #
52
+ # <tt>cache</tt> is the file where the farm will keep all the scores it
53
+ # manages to find. If the file is absent, it will be created, together with
54
+ # the necesary parent directories.
55
+ #
56
+ # <tt>lifetime</tt> is the amount of seconds for a score to live in the farm, by default
57
+ # it's the entire day, since the Score expires in 24 hours; can be decreased for the
58
+ # purpose of unit testing.
48
59
  def initialize(invoice, cache = File.join(Dir.pwd, 'farm'), log: Log::Quiet.new,
49
- farmer: Farmers::Plain.new)
60
+ farmer: Farmers::Plain.new, lifetime: 24 * 60 * 60)
50
61
  @log = log
51
- @cache = cache
62
+ @cache = File.expand_path(cache)
52
63
  @invoice = invoice
53
64
  @pipeline = Queue.new
54
65
  @farmer = farmer
55
66
  @threads = []
67
+ @lifetime = lifetime
56
68
  end
57
69
 
70
+ # Returns the list of best scores the farm managed to find up to now. The
71
+ # list is NEVER empty, even if the farm has just started. If it's empty,
72
+ # it's definitely a bug. If the farm is just fresh start, the list will
73
+ # contain a single score with a zero value.
58
74
  def best
59
75
  load
60
76
  end
@@ -62,7 +78,7 @@ module Zold
62
78
  def to_text
63
79
  [
64
80
  "Current time: #{Time.now.utc.iso8601}",
65
- "Ruby processes: #{`ps -a | grep zold | wc -l`}",
81
+ "Ruby processes: #{`ps ax | grep zold | wc -l`}",
66
82
  JSON.pretty_generate(to_json),
67
83
  @threads.map do |t|
68
84
  trace = t.backtrace || []
@@ -87,10 +103,25 @@ module Zold
87
103
  }
88
104
  end
89
105
 
106
+ # Starts a farm, all threads, and yields the block provided. You are
107
+ # supposed to use it only with the block:
108
+ #
109
+ # Farm.new.start('example.org', 4096) do |farm|
110
+ # score = farm.best[0]
111
+ # # Everything else...
112
+ # end
113
+ #
114
+ # The farm will stop all its threads and close all resources safely
115
+ # right after the block provided exists.
90
116
  def start(host, port, strength: 8, threads: 8)
117
+ raise 'Block is required for the farm to start' unless block_given?
91
118
  @log.info('Zero-threads farm won\'t score anything!') if threads.zero?
119
+ if best.empty?
120
+ @log.info("No scores found in cache at #{@cache}")
121
+ else
122
+ @log.info("#{best.size} scores pre-loaded from #{@cache}, the best is: #{best[0]}")
123
+ end
92
124
  cleanup(host, port, strength, threads)
93
- @log.info("#{@pipeline.size} scores pre-loaded, the best is: #{best[0]}")
94
125
  @alive = true
95
126
  @threads = (1..threads).map do |t|
96
127
  Thread.new do
@@ -108,9 +139,9 @@ module Zold
108
139
  Thread.current.abort_on_exception = true
109
140
  Thread.current.name = 'cleanup'
110
141
  loop do
111
- max = 600
112
- a = (0..max).take_while do
113
- sleep 0.1
142
+ max = 100
143
+ a = (0..max - 1).take_while do
144
+ sleep 0.01
114
145
  @alive
115
146
  end
116
147
  unless a.count == max
@@ -131,7 +162,7 @@ module Zold
131
162
  start = Time.now
132
163
  finish(@cleanup)
133
164
  @threads.each { |t| finish(t) }
134
- @log.info("Farm stopped in #{Age.new(start)}")
165
+ @log.info("Farm stopped in #{Age.new(start)} (threads=#{threads}, strength=#{strength})")
135
166
  end
136
167
  end
137
168
 
@@ -144,7 +175,7 @@ module Zold
144
175
  loop do
145
176
  delay = Time.now - start
146
177
  if thread.join(0.1)
147
- @log.info("Thread \"#{thread.name}\" finished in #{Age.new(start)}")
178
+ @log.info("Thread \"#{thread.name}\" peacefully finished in #{Age.new(start)}")
148
179
  break
149
180
  end
150
181
  if delay > 1
@@ -157,16 +188,13 @@ module Zold
157
188
  def cleanup(host, port, strength, threads)
158
189
  scores = load
159
190
  before = scores.map(&:value).max.to_i
160
- save(threads, [Score.new(time: Time.now, host: host, port: port, invoice: @invoice, strength: strength)])
191
+ save(threads, [Score.new(host: host, port: port, invoice: @invoice, strength: strength)])
161
192
  scores = load
162
- push(scores)
163
- after = scores.map(&:value).max.to_i
164
- @log.debug("#{Thread.current.name}: best score is #{scores[0]}") if before != after && !after.zero?
165
- end
166
-
167
- def push(scores)
168
193
  free = scores.reject { |s| @threads.find { |t| t.name == s.to_mnemo } }
169
194
  @pipeline << free[0] if @pipeline.size.zero? && !free.empty?
195
+ after = scores.map(&:value).max.to_i
196
+ return unless before != after && !after.zero?
197
+ @log.debug("#{Thread.current.name}: best score of #{scores.count} is #{scores[0]}")
170
198
  end
171
199
 
172
200
  def cycle(host, port, strength, threads)
@@ -189,14 +217,14 @@ module Zold
189
217
  Thread.current.name = s.to_mnemo
190
218
  Thread.current.thread_variable_set(:start, Time.now.utc.iso8601)
191
219
  score = @farmer.up(s)
192
- @log.debug("New score discovered: #{score}")
220
+ @log.debug("New score discovered: #{score}") if strength > 4
193
221
  save(threads, [score])
194
222
  cleanup(host, port, strength, threads)
195
223
  end
196
224
 
197
225
  def save(threads, list = [])
198
226
  scores = load + list
199
- period = 24 * 60 * 60 / [threads, 1].max
227
+ period = @lifetime / [threads, 1].max
200
228
  Futex.new(@cache, log: @log).open do |f|
201
229
  IO.write(
202
230
  f,
@@ -216,20 +244,18 @@ module Zold
216
244
  def load
217
245
  Futex.new(@cache, log: @log).open do |f|
218
246
  if File.exist?(f)
219
- IO.read(f).split(/\n/)
220
- .map { |t| parse_score_line(t) }
221
- .reject(&:zero?)
247
+ IO.read(f).split(/\n/).map do |t|
248
+ begin
249
+ Score.parse(t)
250
+ rescue StandardError => e
251
+ @log.error(Backtrace.new(e).to_s)
252
+ nil
253
+ end
254
+ end.compact
222
255
  else
223
256
  []
224
257
  end
225
258
  end
226
259
  end
227
-
228
- def parse_score_line(line)
229
- Score.parse(line)
230
- rescue StandardError => e
231
- @log.error(Backtrace.new(e).to_s)
232
- Score::ZERO
233
- end
234
260
  end
235
261
  end
@@ -22,8 +22,8 @@
22
22
 
23
23
  require 'open3'
24
24
  require 'backtrace'
25
+ require 'zold/score'
25
26
  require_relative '../log'
26
- require_relative '../score'
27
27
  require_relative '../age'
28
28
 
29
29
  # Farmers.
@@ -38,6 +38,7 @@ require_relative '../wallet'
38
38
  require_relative '../age'
39
39
  require_relative '../copies'
40
40
  require_relative '../log'
41
+ require_relative '../tax'
41
42
  require_relative '../id'
42
43
  require_relative '../http'
43
44
 
@@ -298,6 +299,7 @@ in #{Age.new(@start, limit: 1)}")
298
299
  '--',
299
300
  "Balance: #{wallet.balance.to_zld(8)} ZLD (#{wallet.balance.to_i} zents)",
300
301
  "Transactions: #{wallet.txns.count}",
302
+ "Taxes: #{Tax.new(wallet).paid} paid, the debt is #{Tax.new(wallet).debt}",
301
303
  "File size: #{File.size(wallet.path)} bytes (#{Copies.new(File.join(settings.copies, id)).all.count} copies)",
302
304
  "Modified: #{wallet.mtime.utc.iso8601} (#{Age.new(wallet.mtime.utc.iso8601)} ago)",
303
305
  "Digest: #{wallet.digest}"
@@ -28,8 +28,8 @@ require 'time'
28
28
  require 'futex'
29
29
  require 'fileutils'
30
30
  require 'backtrace'
31
+ require 'zold/score'
31
32
  require_relative 'age'
32
- require_relative 'score'
33
33
  require_relative 'http'
34
34
  require_relative 'node/farm'
35
35
 
@@ -119,7 +119,7 @@ module Zold
119
119
  end
120
120
  end
121
121
 
122
- def initialize(file:, network: 'test', timeout: 16)
122
+ def initialize(file:, network: 'test', timeout: Http::READ_TIMEOUT + Http::CONNECT_TIMEOUT)
123
123
  @file = file
124
124
  @network = network
125
125
  @timeout = timeout
@@ -181,7 +181,6 @@ module Zold
181
181
  list = all
182
182
  return if list.empty?
183
183
  best = farm.best[0]
184
- require_relative 'score'
185
184
  score = best.nil? ? Score::ZERO : best
186
185
  idx = 0
187
186
  pool = Concurrent::FixedThreadPool.new([list.count, Concurrent.processor_count * 4].min, max_queue: 0)
@@ -202,7 +201,7 @@ module Zold
202
201
  raise 'Took too long to execute' if (Time.now - start).round > @timeout
203
202
  rescue StandardError => e
204
203
  error(r[:host], r[:port])
205
- log.info("#{Rainbow("#{r[:host]}:#{r[:port]}").red}: \"#{e.message}\" in #{Age.new(start)}")
204
+ log.info("#{Rainbow("#{r[:host]}:#{r[:port]}").red}: #{e.message} in #{Age.new(start)}")
206
205
  log.debug(Backtrace.new(e).to_s)
207
206
  remove(r[:host], r[:port]) if errors > Remotes::TOLERANCE
208
207
  end
@@ -25,6 +25,6 @@
25
25
  # Copyright:: Copyright (c) 2018 Yegor Bugayenko
26
26
  # License:: MIT
27
27
  module Zold
28
- VERSION = '0.16.9'
28
+ VERSION = '0.16.10'
29
29
  PROTOCOL = 2
30
30
  end
@@ -72,7 +72,7 @@ module Zold
72
72
  end
73
73
 
74
74
  def memo
75
- "#{id}/#{balance.to_zld(4)}/#{txns.count}t/#{digest[0, 6]}/Size.new(File.size(@file))}"
75
+ "#{id}/#{balance.to_zld(4)}/#{txns.count}t/#{digest[0, 6]}/#{Size.new(File.size(@file))}"
76
76
  end
77
77
 
78
78
  def to_text
@@ -25,6 +25,7 @@ require 'tmpdir'
25
25
  require 'json'
26
26
  require 'time'
27
27
  require 'webmock/minitest'
28
+ require 'zold/score'
28
29
  require_relative '../test__helper'
29
30
  require_relative '../fake_home'
30
31
  require_relative '../../lib/zold/wallet'
@@ -33,7 +34,6 @@ require_relative '../../lib/zold/remotes'
33
34
  require_relative '../../lib/zold/id'
34
35
  require_relative '../../lib/zold/copies'
35
36
  require_relative '../../lib/zold/key'
36
- require_relative '../../lib/zold/score'
37
37
  require_relative '../../lib/zold/commands/fetch'
38
38
 
39
39
  # FETCH test.
@@ -44,7 +44,7 @@ class TestFetch < Minitest::Test
44
44
  def test_fetches_wallet
45
45
  FakeHome.new(log: test_log).run do |home|
46
46
  wallet = home.create_wallet
47
- stub_request(:get, "http://localhost:80/wallet/#{wallet.id}").to_return(
47
+ stub_request(:get, "http://localhost:4096/wallet/#{wallet.id}").to_return(
48
48
  status: 200,
49
49
  body: {
50
50
  'score': Zold::Score::ZERO.to_h,
@@ -56,7 +56,7 @@ class TestFetch < Minitest::Test
56
56
  status: 404
57
57
  )
58
58
  remotes = home.remotes
59
- remotes.add('localhost', 80)
59
+ remotes.add('localhost', 4096)
60
60
  remotes.add('localhost', 81)
61
61
  copies = home.copies(wallet)
62
62
  begin
@@ -24,6 +24,7 @@ require 'minitest/autorun'
24
24
  require 'tmpdir'
25
25
  require 'time'
26
26
  require 'webmock/minitest'
27
+ require 'zold/score'
27
28
  require_relative '../test__helper'
28
29
  require_relative '../fake_home'
29
30
  require_relative '../../lib/zold/wallet'
@@ -31,7 +32,6 @@ require_relative '../../lib/zold/wallets'
31
32
  require_relative '../../lib/zold/id'
32
33
  require_relative '../../lib/zold/copies'
33
34
  require_relative '../../lib/zold/key'
34
- require_relative '../../lib/zold/score'
35
35
  require_relative '../../lib/zold/patch'
36
36
  require_relative '../../lib/zold/commands/merge'
37
37
  require_relative '../../lib/zold/commands/pay'
@@ -36,10 +36,10 @@ class TestPull < Minitest::Test
36
36
  def test_pull_wallet
37
37
  FakeHome.new(log: test_log).run do |home|
38
38
  remotes = home.remotes
39
- remotes.add('localhost', 80)
39
+ remotes.add('localhost', 4096)
40
40
  json = home.create_wallet_json
41
41
  id = Zold::JsonPage.new(json).to_hash['id']
42
- stub_request(:get, "http://localhost:80/wallet/#{id}").to_return(status: 200, body: json)
42
+ stub_request(:get, "http://localhost:4096/wallet/#{id}").to_return(status: 200, body: json)
43
43
  Zold::Pull.new(wallets: home.wallets, remotes: remotes, copies: home.copies.root.to_s, log: test_log).run(
44
44
  ['--ignore-this-stupid-option', 'pull', id.to_s]
45
45
  )
@@ -23,13 +23,13 @@
23
23
  require 'minitest/autorun'
24
24
  require 'tmpdir'
25
25
  require 'webmock/minitest'
26
+ require 'zold/score'
26
27
  require_relative '../test__helper'
27
28
  require_relative '../../lib/zold/version'
28
29
  require_relative '../../lib/zold/wallets'
29
30
  require_relative '../../lib/zold/remotes'
30
31
  require_relative '../../lib/zold/key'
31
32
  require_relative '../../lib/zold/log'
32
- require_relative '../../lib/zold/score'
33
33
  require_relative '../../lib/zold/commands/remote'
34
34
 
35
35
  # REMOTE test.
@@ -133,7 +133,7 @@ class TestRemote < Minitest::Test
133
133
  Dir.mktmpdir do |dir|
134
134
  remotes = Zold::Remotes.new(file: File.join(dir, 'remotes.txt'))
135
135
  score = Zold::Score.new(
136
- time: Time.now, host: 'aa1.example.org', port: 9999, invoice: 'NOPREFIX4@ffffffffffffffff'
136
+ host: 'aa1.example.org', port: 9999, invoice: 'NOPREFIX4@ffffffffffffffff'
137
137
  )
138
138
  stub_request(:get, 'http://localhost:8883/version').to_return(
139
139
  status: 200,
@@ -70,7 +70,7 @@ class TestTaxes < Minitest::Test
70
70
  )
71
71
  wallet.flush
72
72
  assert(tax.paid.positive?, tax.paid)
73
- assert_equal(before - debt, wallet.balance)
73
+ assert_equal((before - debt).to_zld(6), wallet.balance.to_zld(6))
74
74
  end
75
75
  end
76
76
  end
@@ -63,7 +63,7 @@ class FakeHome
63
63
  end
64
64
 
65
65
  def create_wallet_json(id = Zold::Id.new)
66
- require_relative '../lib/zold/score'
66
+ require 'zold/score'
67
67
  score = Zold::Score::ZERO
68
68
  Dir.mktmpdir 'wallets' do |external_dir|
69
69
  wallet = create_wallet(id, external_dir)
@@ -49,6 +49,16 @@ class FarmTest < Minitest::Test
49
49
  end
50
50
  end
51
51
 
52
+ def test_makes_many_scores
53
+ Dir.mktmpdir do |dir|
54
+ farm = Zold::Farm.new('NOPREFIX6@ffffffffffffffff', File.join(dir, 'f'),
55
+ log: test_log, lifetime: 10, farmer: Zold::Farmers::Plain.new)
56
+ farm.start('localhost', 80, threads: 4, strength: 1) do
57
+ assert_wait { farm.best.length == 4 }
58
+ end
59
+ end
60
+ end
61
+
52
62
  def test_makes_best_score_in_background
53
63
  Dir.mktmpdir do |dir|
54
64
  farm = Zold::Farm.new('NOPREFIX1@ffffffffffffffff', File.join(dir, 'f'), log: test_log)
@@ -76,10 +86,12 @@ class FarmTest < Minitest::Test
76
86
 
77
87
  def test_pre_loads_history
78
88
  Dir.mktmpdir do |dir|
79
- cache = File.join(dir, 'cache')
89
+ cache = File.join(dir, 'a/b/c/cache')
80
90
  farm = Zold::Farm.new('NOPREFIX3@cccccccccccccccc', cache, log: test_log)
81
91
  farm.start('example.com', 8080, threads: 0, strength: 1) do
82
92
  score = farm.best[0]
93
+ assert(!score.nil?, 'The list of best scores can\'t be empty!')
94
+ assert(File.exist?(cache), 'The cache file has to be created!')
83
95
  assert_equal(0, score.value)
84
96
  assert(!score.expired?)
85
97
  assert_equal('example.com', score.host)
@@ -22,8 +22,8 @@
22
22
 
23
23
  require 'minitest/autorun'
24
24
  require 'time'
25
+ require 'zold/score'
25
26
  require_relative '../test__helper'
26
- require_relative '../../lib/zold/score'
27
27
  require_relative '../../lib/zold/node/farmers'
28
28
 
29
29
  class FarmersTest < Minitest::Test
@@ -25,13 +25,13 @@ require 'json'
25
25
  require 'time'
26
26
  require 'securerandom'
27
27
  require 'threads'
28
+ require 'zold/score'
28
29
  require_relative '../test__helper'
29
30
  require_relative 'fake_node'
30
31
  require_relative '../fake_home'
31
32
  require_relative '../../lib/zold/http'
32
33
  require_relative '../../lib/zold/age'
33
34
  require_relative '../../lib/zold/json_page'
34
- require_relative '../../lib/zold/score'
35
35
 
36
36
  class FrontTest < Minitest::Test
37
37
  def app
@@ -96,7 +96,7 @@ class FrontTest < Minitest::Test
96
96
  def test_updates_list_of_remotes
97
97
  FakeNode.new(log: test_log).run(['--ignore-score-weakness']) do |port|
98
98
  score = Zold::Score.new(
99
- time: Time.now, host: 'localhost', port: port, invoice: 'NOPREFIX@ffffffffffffffff', strength: 1
99
+ host: 'localhost', port: port, invoice: 'NOPREFIX@ffffffffffffffff', strength: 1
100
100
  ).next.next.next.next
101
101
  response = Zold::Http.new(uri: "http://localhost:#{port}/remotes", score: score).get
102
102
  assert_equal('200', response.code, response.body)
@@ -207,7 +207,7 @@ class FrontTest < Minitest::Test
207
207
  '16' => 'https://www.zold.io/images/logo-green.png'
208
208
  }.each do |num, path|
209
209
  score = Zold::Score.new(
210
- time: Time.now, host: 'localhost', port: 999,
210
+ host: 'localhost', port: 999,
211
211
  invoice: 'NOPREFIX@ffffffffffffffff',
212
212
  strength: 1
213
213
  )
@@ -24,8 +24,8 @@ require 'minitest/autorun'
24
24
  require 'tmpdir'
25
25
  require 'uri'
26
26
  require 'webmock/minitest'
27
+ require 'zold/score'
27
28
  require_relative '../lib/zold/http'
28
- require_relative '../lib/zold/score'
29
29
 
30
30
  # Http test.
31
31
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
@@ -21,6 +21,7 @@
21
21
  # SOFTWARE.
22
22
 
23
23
  require 'minitest/autorun'
24
+ require 'zold/score'
24
25
  require 'time'
25
26
  require_relative 'test__helper'
26
27
  require_relative 'fake_home'
@@ -31,7 +32,6 @@ require_relative '../lib/zold/tax'
31
32
  require_relative '../lib/zold/key'
32
33
  require_relative '../lib/zold/amount'
33
34
  require_relative '../lib/zold/prefixes'
34
- require_relative '../lib/zold/score'
35
35
 
36
36
  # Tax test.
37
37
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
@@ -73,7 +73,7 @@ class TestTax < Minitest::Test
73
73
  )
74
74
  end
75
75
  score = Zold::Score.new(
76
- time: Time.now, host: 'localhost', port: 80, invoice: 'NOPREFIX@cccccccccccccccc',
76
+ host: 'localhost', port: 80, invoice: 'NOPREFIX@cccccccccccccccc',
77
77
  suffixes: %w[A B C D E F G H I J K L M N O P Q R S T U V]
78
78
  )
79
79
  tax = Zold::Tax.new(wallet)
@@ -126,7 +126,7 @@ class TestTax < Minitest::Test
126
126
  invoice = "#{Zold::Prefixes.new(target).create}@#{target.id}"
127
127
  tax = Zold::Tax.new(wallet)
128
128
  score = Zold::Score.new(
129
- time: Time.now, host: 'localhost', port: 80, invoice: invoice,
129
+ host: 'localhost', port: 80, invoice: invoice,
130
130
  suffixes: %w[A B C D E F G H I J K L M N O P Q R S T U V]
131
131
  )
132
132
  tax.pay(Zold::Key.new(file: 'fixtures/id_rsa'), score)
@@ -65,7 +65,7 @@ and suggests a different architecture for digital wallet maintenance.'
65
65
  s.add_runtime_dependency 'posix-spawn', '~>0.3'
66
66
  s.add_runtime_dependency 'rainbow', '~>3'
67
67
  s.add_runtime_dependency 'rake', '~>12' # has to stay here for Heroku
68
- s.add_runtime_dependency 'rubocop', '0.58.1' # has to stay here for Heroku
68
+ s.add_runtime_dependency 'rubocop', '0.60.0' # has to stay here for Heroku
69
69
  s.add_runtime_dependency 'rubocop-rspec', '~>1' # has to stay here for Heroku
70
70
  s.add_runtime_dependency 'semantic', '~>1'
71
71
  s.add_runtime_dependency 'sinatra', '~>2'
@@ -76,6 +76,7 @@ and suggests a different architecture for digital wallet maintenance.'
76
76
  s.add_runtime_dependency 'usagewatch_ext', '~>0'
77
77
  s.add_runtime_dependency 'xcop', '~>0'
78
78
  s.add_runtime_dependency 'zache', '~>0'
79
+ s.add_runtime_dependency 'zold-score', '~>0'
79
80
  s.add_development_dependency 'codecov', '~>0'
80
81
  s.add_development_dependency 'minitest', '~>5'
81
82
  s.add_development_dependency 'random-port', '~>0'
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.16.9
4
+ version: 0.16.10
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-11-02 00:00:00.000000000 Z
11
+ date: 2018-11-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: backtrace
@@ -170,14 +170,14 @@ dependencies:
170
170
  requirements:
171
171
  - - '='
172
172
  - !ruby/object:Gem::Version
173
- version: 0.58.1
173
+ version: 0.60.0
174
174
  type: :runtime
175
175
  prerelease: false
176
176
  version_requirements: !ruby/object:Gem::Requirement
177
177
  requirements:
178
178
  - - '='
179
179
  - !ruby/object:Gem::Version
180
- version: 0.58.1
180
+ version: 0.60.0
181
181
  - !ruby/object:Gem::Dependency
182
182
  name: rubocop-rspec
183
183
  requirement: !ruby/object:Gem::Requirement
@@ -318,6 +318,20 @@ dependencies:
318
318
  - - "~>"
319
319
  - !ruby/object:Gem::Version
320
320
  version: '0'
321
+ - !ruby/object:Gem::Dependency
322
+ name: zold-score
323
+ requirement: !ruby/object:Gem::Requirement
324
+ requirements:
325
+ - - "~>"
326
+ - !ruby/object:Gem::Version
327
+ version: '0'
328
+ type: :runtime
329
+ prerelease: false
330
+ version_requirements: !ruby/object:Gem::Requirement
331
+ requirements:
332
+ - - "~>"
333
+ - !ruby/object:Gem::Version
334
+ version: '0'
321
335
  - !ruby/object:Gem::Dependency
322
336
  name: codecov
323
337
  requirement: !ruby/object:Gem::Requirement
@@ -536,7 +550,6 @@ files:
536
550
  - lib/zold/patch.rb
537
551
  - lib/zold/prefixes.rb
538
552
  - lib/zold/remotes.rb
539
- - lib/zold/score.rb
540
553
  - lib/zold/signature.rb
541
554
  - lib/zold/size.rb
542
555
  - lib/zold/sync_wallets.rb
@@ -601,7 +614,6 @@ files:
601
614
  - test/test_patch.rb
602
615
  - test/test_prefixes.rb
603
616
  - test/test_remotes.rb
604
- - test/test_score.rb
605
617
  - test/test_signature.rb
606
618
  - test/test_size.rb
607
619
  - test/test_sync_wallets.rb
@@ -701,7 +713,6 @@ test_files:
701
713
  - test/test_patch.rb
702
714
  - test/test_prefixes.rb
703
715
  - test/test_remotes.rb
704
- - test/test_score.rb
705
716
  - test/test_signature.rb
706
717
  - test/test_size.rb
707
718
  - test/test_sync_wallets.rb
@@ -1,203 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Copyright (c) 2018 Yegor Bugayenko
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 'openssl'
24
- require 'time'
25
-
26
- # The score.
27
- # Author:: Yegor Bugayenko (yegor256@gmail.com)
28
- # Copyright:: Copyright (c) 2018 Yegor Bugayenko
29
- # License:: MIT
30
- module Zold
31
- # Score
32
- class Score
33
- # Default strength for the entire system, in production mode.
34
- STRENGTH = 6
35
-
36
- attr_reader :time, :host, :port, :invoice, :suffixes, :strength, :created
37
-
38
- def initialize(time: Time.now, host:, port:, invoice:, suffixes: [],
39
- strength: Score::STRENGTH, created: Time.now)
40
- @time = time
41
- @host = host
42
- @port = port
43
- @invoice = invoice
44
- @suffixes = suffixes
45
- @strength = strength
46
- @created = created
47
- end
48
-
49
- # The default no-value score.
50
- ZERO = Score.new(time: Time.now, host: 'localhost', port: 80, invoice: 'NOPREFIX@ffffffffffffffff')
51
-
52
- def self.parse_json(json)
53
- raise "Time in JSON is broken: #{json}" unless json['time'] =~ /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$/
54
- raise "Host is wrong: #{json}" unless json['host'] =~ /^[0-9a-z\.\-]+$/
55
- raise "Port is wrong: #{json}" unless json['port'].is_a?(Integer)
56
- raise "Invoice is wrong: #{json}" unless json['invoice'] =~ /^[a-zA-Z0-9]{8,32}@[a-f0-9]{16}$/
57
- raise "Suffixes not array: #{json}" unless json['suffixes'].is_a?(Array)
58
- Score.new(
59
- time: Time.parse(json['time']), host: json['host'],
60
- port: json['port'], invoice: json['invoice'], suffixes: json['suffixes'],
61
- strength: json['strength']
62
- )
63
- end
64
-
65
- def self.parse(text)
66
- re = Regexp.new(
67
- '^' + [
68
- '([0-9]+)/(?<strength>[0-9]+):',
69
- ' (?<time>[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z)',
70
- ' (?<host>[0-9a-z\.\-]+)',
71
- ' (?<port>[0-9]+)',
72
- ' (?<invoice>[a-zA-Z0-9]{8,32}@[a-f0-9]{16})',
73
- '(?<suffixes>( [a-zA-Z0-9]+)*)'
74
- ].join + '$'
75
- )
76
- m = re.match(text.strip)
77
- raise "Invalid score '#{text}', doesn't match: #{re}" if m.nil?
78
- Score.new(
79
- time: Time.parse(m[:time]), host: m[:host],
80
- port: m[:port].to_i, invoice: m[:invoice],
81
- suffixes: m[:suffixes].split(' '),
82
- strength: m[:strength].to_i
83
- )
84
- end
85
-
86
- def self.parse_text(text)
87
- parts = text.split(' ', 7)
88
- Score.new(
89
- time: Time.at(parts[1].hex),
90
- host: parts[2],
91
- port: parts[3].hex,
92
- invoice: "#{parts[4]}@#{parts[5]}",
93
- suffixes: parts[6] ? parts[6].split(' ') : [],
94
- strength: parts[0].to_i
95
- )
96
- end
97
-
98
- def hash
99
- raise 'Score has zero value, there is no hash' if @suffixes.empty?
100
- @suffixes.reduce(prefix) do |pfx, suffix|
101
- OpenSSL::Digest::SHA256.new("#{pfx} #{suffix}").hexdigest
102
- end
103
- end
104
-
105
- def to_mnemo
106
- "#{value}:#{@time.strftime('%H%M')}"
107
- end
108
-
109
- def to_text
110
- pfx, bnf = @invoice.split('@')
111
- [
112
- @strength,
113
- @time.to_i.to_s(16),
114
- @host,
115
- @port.to_s(16),
116
- pfx,
117
- bnf,
118
- @suffixes.join(' ')
119
- ].join(' ')
120
- end
121
-
122
- def to_s
123
- [
124
- "#{value}/#{@strength}:",
125
- @time.utc.iso8601,
126
- @host,
127
- @port,
128
- @invoice,
129
- @suffixes.join(' ')
130
- ].join(' ').strip
131
- end
132
-
133
- def to_h
134
- {
135
- value: value,
136
- host: @host,
137
- port: @port,
138
- invoice: @invoice,
139
- time: @time.utc.iso8601,
140
- suffixes: @suffixes,
141
- strength: @strength,
142
- hash: value.zero? ? nil : hash,
143
- expired: expired?,
144
- valid: valid?,
145
- age: (age / 60).round,
146
- created: @created.utc.iso8601
147
- }
148
- end
149
-
150
- def reduced(max = 4)
151
- Score.new(
152
- time: @time, host: @host, port: @port, invoice: @invoice,
153
- suffixes: @suffixes[0..[max, suffixes.count].min - 1],
154
- strength: @strength
155
- )
156
- end
157
-
158
- def next
159
- raise 'This score is not valid' unless valid?
160
- idx = 0
161
- loop do
162
- suffix = idx.to_s(16)
163
- score = Score.new(
164
- time: @time, host: @host, port: @port,
165
- invoice: @invoice, suffixes: @suffixes + [suffix],
166
- strength: @strength
167
- )
168
- return score if score.valid?
169
- if score.expired?
170
- return Score.new(
171
- time: Time.now, host: @host, port: @port, invoice: @invoice,
172
- suffixes: [], strength: @strength
173
- )
174
- end
175
- idx += 1
176
- end
177
- end
178
-
179
- def age
180
- Time.now - @time
181
- end
182
-
183
- def expired?(hours = 24)
184
- age > hours * 60 * 60
185
- end
186
-
187
- def prefix
188
- "#{@time.utc.iso8601} #{@host} #{@port} #{@invoice}"
189
- end
190
-
191
- def valid?
192
- @suffixes.empty? || hash.end_with?('0' * @strength)
193
- end
194
-
195
- def value
196
- @suffixes.length
197
- end
198
-
199
- def zero?
200
- equal?(Score::ZERO)
201
- end
202
- end
203
- end
@@ -1,161 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Copyright (c) 2018 Yegor Bugayenko
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 'time'
26
- require_relative 'test__helper'
27
- require_relative '../lib/zold/score'
28
-
29
- # Score test.
30
- # Author:: Yegor Bugayenko (yegor256@gmail.com)
31
- # Copyright:: Copyright (c) 2018 Yegor Bugayenko
32
- # License:: MIT
33
- class TestScore < Minitest::Test
34
- def test_reduces_itself
35
- score = Zold::Score.new(
36
- time: Time.parse('2017-07-19T21:24:51Z'),
37
- host: 'localhost', port: 443, invoice: 'NOPREFIX@ffffffffffffffff',
38
- suffixes: %w[A B C D E F G]
39
- ).reduced(2)
40
- assert_equal(2, score.value)
41
- assert_equal(64, score.hash.length)
42
- end
43
-
44
- def test_drops_to_zero_when_expired
45
- score = Zold::Score.new(
46
- time: Time.now - 24 * 60 * 60,
47
- host: 'some-host', port: 9999, invoice: 'NOPREFIX@ffffffffffffffff',
48
- strength: 50
49
- ).next
50
- assert(score.valid?)
51
- assert(!score.expired?)
52
- assert_equal(0, score.value)
53
- end
54
-
55
- def test_validates_wrong_score
56
- score = Zold::Score.new(
57
- time: Time.parse('2017-07-19T21:24:51Z'),
58
- host: 'localhost', port: 443, invoice: 'NOPREFIX@ffffffffffffffff',
59
- suffixes: %w[xxx yyy zzz]
60
- )
61
- assert_equal(3, score.value)
62
- assert(!score.valid?)
63
- end
64
-
65
- def test_prints_mnemo
66
- score = Zold::Score.new(
67
- time: Time.parse('2017-07-19T22:32:51Z'),
68
- host: 'localhost', port: 443, invoice: 'NOPREFIX@ffffffffffffffff'
69
- )
70
- assert_equal('0:2232', score.to_mnemo)
71
- end
72
-
73
- def test_prints_and_parses
74
- time = Time.now
75
- score = Zold::Score.parse(
76
- Zold::Score.new(
77
- time: time, host: 'localhost', port: 999, invoice: 'NOPREFIX@ffffffffffffffff',
78
- strength: 1
79
- ).next.next.to_s
80
- )
81
- assert_equal(2, score.value)
82
- assert_equal(score.time.to_s, time.to_s)
83
- assert_equal('localhost', score.host)
84
- assert_equal(999, score.port)
85
- end
86
-
87
- def test_prints_and_parses_text
88
- time = Time.now
89
- score = Zold::Score.parse_text(
90
- Zold::Score.new(
91
- time: time, host: 'a.example.com', port: 999, invoice: 'NOPREFIX@ffffffffffffffff',
92
- strength: 1
93
- ).next.next.next.to_text
94
- )
95
- assert_equal(3, score.value)
96
- assert_equal(score.time.utc.to_s, time.utc.to_s)
97
- assert_equal('a.example.com', score.host)
98
- assert_equal(999, score.port)
99
- end
100
-
101
- def test_prints_and_parses_text_zero_score
102
- time = Time.now
103
- score = Zold::Score.parse_text(
104
- Zold::Score.new(
105
- time: time, host: '192.168.0.1', port: 1, invoice: 'NOPREFIX@ffffffffffffffff', suffixes: []
106
- ).to_text
107
- )
108
- assert_equal(0, score.value)
109
- assert(!score.expired?)
110
- end
111
-
112
- def test_prints_and_parses_zero_score
113
- time = Time.now
114
- score = Zold::Score.parse(
115
- Zold::Score.new(
116
- time: time, host: '192.168.0.1', port: 1, invoice: 'NOPREFIX@ffffffffffffffff', suffixes: []
117
- ).to_s
118
- )
119
- assert_equal(0, score.value)
120
- assert(!score.expired?)
121
- end
122
-
123
- def test_finds_next_score
124
- score = Zold::Score.new(
125
- time: Time.now, host: 'localhost', port: 443,
126
- invoice: 'NOPREFIX@ffffffffffffffff', strength: 2
127
- ).next.next.next
128
- assert_equal(3, score.value)
129
- assert(score.valid?)
130
- assert(!score.expired?)
131
- end
132
-
133
- def test_dont_expire_correctly
134
- score = Zold::Score.new(
135
- time: Time.now - 10 * 60 * 60, host: 'localhost', port: 443,
136
- invoice: 'NOPREFIX@ffffffffffffffff', strength: 2
137
- ).next.next.next
138
- assert(!score.expired?)
139
- end
140
-
141
- def test_correct_number_of_zeroes
142
- score = Zold::Score.new(
143
- time: Time.now, host: 'localhost', port: 443,
144
- invoice: 'NOPREFIX@ffffffffffffffff', strength: 3
145
- ).next
146
- assert(score.hash.end_with?('000'))
147
- end
148
-
149
- def test_generates_hash_correctly
150
- score = Zold::Score.new(
151
- time: Time.parse('2018-06-27T06:22:41Z'), host: 'b2.zold.io', port: 4096,
152
- invoice: 'THdonv1E@abcdabcdabcdabcd', suffixes: ['3a934b']
153
- )
154
- assert_equal('c9c72efbf6beeea13408c5e720ec42aec017c11c3db335e05595c03755000000', score.hash)
155
- score = Zold::Score.new(
156
- time: Time.parse('2018-06-27T06:22:41Z'), host: 'b2.zold.io', port: 4096,
157
- invoice: 'THdonv1E@abcdabcdabcdabcd', suffixes: %w[3a934b 1421217]
158
- )
159
- assert_equal('e04ab4e69f86aa17be1316a52148e7bc3187c6d3df581d885a862d8850000000', score.hash)
160
- end
161
- end