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 +4 -4
- data/.rubocop.yml +2 -0
- data/fixtures/scripts/distribute-wallet.sh +1 -1
- data/lib/zold/commands/calculate.rb +1 -1
- data/lib/zold/commands/clean.rb +1 -1
- data/lib/zold/commands/fetch.rb +1 -1
- data/lib/zold/commands/next.rb +1 -1
- data/lib/zold/commands/node.rb +3 -3
- data/lib/zold/commands/push.rb +3 -4
- data/lib/zold/commands/remote.rb +1 -1
- data/lib/zold/commands/taxes.rb +4 -3
- data/lib/zold/gem.rb +3 -1
- data/lib/zold/http.rb +1 -1
- data/lib/zold/node/farm.rb +55 -29
- data/lib/zold/node/farmers.rb +1 -1
- data/lib/zold/node/front.rb +2 -0
- data/lib/zold/remotes.rb +3 -4
- data/lib/zold/version.rb +1 -1
- data/lib/zold/wallet.rb +1 -1
- data/test/commands/test_fetch.rb +3 -3
- data/test/commands/test_merge.rb +1 -1
- data/test/commands/test_pull.rb +2 -2
- data/test/commands/test_remote.rb +2 -2
- data/test/commands/test_taxes.rb +1 -1
- data/test/fake_home.rb +1 -1
- data/test/node/test_farm.rb +13 -1
- data/test/node/test_farmers.rb +1 -1
- data/test/node/test_front.rb +3 -3
- data/test/test_http.rb +1 -1
- data/test/test_tax.rb +3 -3
- data/zold.gemspec +2 -1
- metadata +18 -7
- data/lib/zold/score.rb +0 -203
- data/test/test_score.rb +0 -161
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5bdb355d25ef5197cfcc131d383d5391bec683efb8f5db52ba6b60d690bf4e3f
|
4
|
+
data.tar.gz: dc2f83cf4bdbc787de4232aa56fb3570f721f887b93069b4fa766fc0eeee2597
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: de19e0642f74972e9a28f7506fea7397d51473d7bc308b0da64353e9177cea7c2f16a56f1f0ca537f15f90d8001b6625c9762b9f1294eda20888539dc018c890
|
7
|
+
data.tar.gz: 19275bbdfe0cc8baea050d14656edcacad9b1d87846f4ddd9752f85517c20009515079c46050727bbb843b8448a5bd5feebcf8406584536720f9323c565b5011
|
data/.rubocop.yml
CHANGED
@@ -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 ..
|
data/lib/zold/commands/clean.rb
CHANGED
@@ -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.
|
data/lib/zold/commands/fetch.rb
CHANGED
@@ -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
|
|
data/lib/zold/commands/next.rb
CHANGED
data/lib/zold/commands/node.rb
CHANGED
@@ -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
|
data/lib/zold/commands/push.rb
CHANGED
@@ -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 #{
|
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 #{
|
109
|
-
|
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
|
data/lib/zold/commands/remote.rb
CHANGED
@@ -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
|
|
data/lib/zold/commands/taxes.rb
CHANGED
@@ -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 =
|
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}"
|
data/lib/zold/gem.rb
CHANGED
@@ -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
|
data/lib/zold/http.rb
CHANGED
data/lib/zold/node/farm.rb
CHANGED
@@ -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
|
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 =
|
112
|
-
a = (0..max).take_while do
|
113
|
-
sleep 0.
|
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(
|
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 =
|
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
|
-
|
221
|
-
|
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
|
data/lib/zold/node/farmers.rb
CHANGED
data/lib/zold/node/front.rb
CHANGED
@@ -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}"
|
data/lib/zold/remotes.rb
CHANGED
@@ -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:
|
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}:
|
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
|
data/lib/zold/version.rb
CHANGED
data/lib/zold/wallet.rb
CHANGED
data/test/commands/test_fetch.rb
CHANGED
@@ -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:
|
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',
|
59
|
+
remotes.add('localhost', 4096)
|
60
60
|
remotes.add('localhost', 81)
|
61
61
|
copies = home.copies(wallet)
|
62
62
|
begin
|
data/test/commands/test_merge.rb
CHANGED
@@ -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'
|
data/test/commands/test_pull.rb
CHANGED
@@ -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',
|
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:
|
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
|
-
|
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,
|
data/test/commands/test_taxes.rb
CHANGED
data/test/fake_home.rb
CHANGED
data/test/node/test_farm.rb
CHANGED
@@ -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)
|
data/test/node/test_farmers.rb
CHANGED
data/test/node/test_front.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
210
|
+
host: 'localhost', port: 999,
|
211
211
|
invoice: 'NOPREFIX@ffffffffffffffff',
|
212
212
|
strength: 1
|
213
213
|
)
|
data/test/test_http.rb
CHANGED
@@ -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)
|
data/test/test_tax.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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)
|
data/zold.gemspec
CHANGED
@@ -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.
|
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.
|
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-
|
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.
|
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.
|
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
|
data/lib/zold/score.rb
DELETED
@@ -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
|
data/test/test_score.rb
DELETED
@@ -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
|