zold 0.14.35 → 0.14.36
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/bin/zold +13 -11
- data/lib/zold/commands/invoice.rb +3 -0
- data/lib/zold/commands/next.rb +1 -1
- data/lib/zold/commands/node.rb +7 -4
- data/lib/zold/http.rb +2 -6
- data/lib/zold/node/async_entrance.rb +1 -1
- data/lib/zold/node/farm.rb +49 -22
- data/lib/zold/node/front.rb +5 -3
- data/lib/zold/version.rb +1 -1
- data/resources/remotes +5 -0
- data/test/commands/test_remote.rb +1 -1
- data/test/node/fake_node.rb +6 -4
- data/test/node/test_farm.rb +8 -2
- data/test/node/test_front.rb +18 -7
- data/test/test__helper.rb +1 -1
- data/test/test_http.rb +24 -0
- data/zold.gemspec +1 -0
- metadata +15 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e0ac9a7fc3634c563abae9dce0f68ca709d46490
|
4
|
+
data.tar.gz: 59bb7653c11021d3d46c6cab7124480c9db2a103
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cc4d99b314585fc077c82779463f09505d71f787a560087a2d55f3ab17184580df1aa0f12de8e0afb49914a0f2bff5d5064f343d579a9fe0d289562cacf94efe
|
7
|
+
data.tar.gz: 1995bae0601aa6cd84b5de1f3eeb58b27914f2d4d2935a503fa5226c88d12eaa659a6a76bcac58dae8b7103dac813ba90be1e66597490af4bf899e8f77ead092
|
data/bin/zold
CHANGED
@@ -113,6 +113,7 @@ Available options:"
|
|
113
113
|
default: Zold::Wallet::MAIN_NETWORK
|
114
114
|
o.bool '-h', '--help', 'Show these instructions'
|
115
115
|
o.bool '--trace', 'Show full stack trace in case of a problem'
|
116
|
+
o.bool '--skip-upgrades', 'Don\'t upgrade the storage', default: false
|
116
117
|
o.bool '--ignore-global-config', 'Don\'t read options from the ~/.zold file'
|
117
118
|
o.on '--no-colors', 'Disable colors in the ouput' do
|
118
119
|
Rainbow.enabled = false
|
@@ -146,17 +147,18 @@ Available options:"
|
|
146
147
|
|
147
148
|
zoldata = File.expand_path(File.join(Dir.pwd, '.zoldata'))
|
148
149
|
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
150
|
+
unless opts['skip-upgrades']
|
151
|
+
Zold::Upgrades.new(Zold::VersionFile.new(File.join(zoldata, 'version')), 'upgrades').run
|
152
|
+
# @todo #384:30min This is a workaround, move this code into Upgrades, somehow.
|
153
|
+
# We should find a way to run these arbitrary scripts and pass arguments
|
154
|
+
# to them. Each of them may need its own set of arguments.
|
155
|
+
require_relative '../upgrades/2'
|
156
|
+
Zold::UpgradeTo2.new(Dir.pwd, log).exec
|
157
|
+
require_relative '../upgrades/protocol_up'
|
158
|
+
Zold::ProtocolUp.new(Dir.pwd, log).exec
|
159
|
+
require_relative '../upgrades/rename_foreign_wallets'
|
160
|
+
Zold::RenameForeignWallets.new(Dir.pwd, opts['network'], log).exec
|
161
|
+
end
|
160
162
|
|
161
163
|
wallets = Zold::SyncWallets.new(Zold::Wallets.new('.'), File.join(zoldata, 'locks'), log: log)
|
162
164
|
remotes = Zold::Remotes.new(file: File.join(zoldata, 'remotes'), network: opts['network'])
|
@@ -48,6 +48,9 @@ Available options:"
|
|
48
48
|
o.integer '--length',
|
49
49
|
'The length of the invoice prefix (default: 8)',
|
50
50
|
default: 8
|
51
|
+
o.string '--network',
|
52
|
+
'The name of the network we work in',
|
53
|
+
default: 'test'
|
51
54
|
o.bool '--help', 'Print instructions'
|
52
55
|
end
|
53
56
|
mine = Args.new(opts, @log).take || return
|
data/lib/zold/commands/next.rb
CHANGED
data/lib/zold/commands/node.rb
CHANGED
@@ -76,8 +76,8 @@ module Zold
|
|
76
76
|
"The strength of the score (default: #{Score::STRENGTH})",
|
77
77
|
default: Score::STRENGTH
|
78
78
|
o.integer '--threads',
|
79
|
-
'How many threads to use for scores finding (default:
|
80
|
-
default:
|
79
|
+
'How many threads to use for scores finding (default: 2)',
|
80
|
+
default: 2
|
81
81
|
o.bool '--dump-errors',
|
82
82
|
'Make HTTP front-end errors visible in the log (false by default)',
|
83
83
|
default: false
|
@@ -302,14 +302,17 @@ module Zold
|
|
302
302
|
|
303
303
|
def metronome(farm, opts)
|
304
304
|
metronome = Metronome.new(@log)
|
305
|
-
|
305
|
+
if opts['no-metronome']
|
306
|
+
@log.info('Metronome hasn\'t been started because of --no-metronome')
|
307
|
+
return metronome
|
308
|
+
end
|
306
309
|
require_relative 'routines/spread'
|
307
310
|
metronome.add(Routines::Spread.new(opts, @wallets, @remotes, log: @log))
|
308
311
|
unless opts['standalone']
|
309
312
|
require_relative 'routines/reconnect'
|
310
313
|
metronome.add(Routines::Reconnect.new(opts, @remotes, farm, network: opts['network'], log: @log))
|
311
314
|
end
|
312
|
-
@log.info('Metronome
|
315
|
+
@log.info('Metronome started (use --no-metronome to disable it)')
|
313
316
|
metronome
|
314
317
|
end
|
315
318
|
|
data/lib/zold/http.rb
CHANGED
@@ -66,12 +66,8 @@ module Zold
|
|
66
66
|
# that is already taken care of in another issue. I am leaving a todo
|
67
67
|
# to check that rubocop doesn't complain anymore, otherwise find another
|
68
68
|
# solution
|
69
|
-
attribute :uri, (Types::Class.constructor
|
70
|
-
|
71
|
-
end)
|
72
|
-
attribute :score, (Types::Class.constructor do |value|
|
73
|
-
value.nil? ? Score::ZERO : value
|
74
|
-
end)
|
69
|
+
attribute :uri, (Types::Class.constructor { |v| v.is_a?(URI) ? v : URI(v) })
|
70
|
+
attribute :score, (Types::Class.constructor { |v| v.nil? ? Score::ZERO : v })
|
75
71
|
attribute :network, Types::Strict::String.optional.default('test')
|
76
72
|
|
77
73
|
def get
|
data/lib/zold/node/farm.rb
CHANGED
@@ -42,7 +42,7 @@ module Zold
|
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
45
|
-
def initialize(invoice, cache, log: Log::Quiet.new)
|
45
|
+
def initialize(invoice, cache = File.join(Dir.pwd, 'farm'), log: Log::Quiet.new)
|
46
46
|
@log = log
|
47
47
|
@cache = cache
|
48
48
|
@invoice = invoice
|
@@ -92,8 +92,15 @@ module Zold
|
|
92
92
|
@cleanup = Thread.new do
|
93
93
|
Thread.current.abort_on_exception = true
|
94
94
|
Thread.current.name = 'cleanup'
|
95
|
-
|
96
|
-
|
95
|
+
loop do
|
96
|
+
a = [0..600].take_while do
|
97
|
+
sleep 0.1
|
98
|
+
@alive
|
99
|
+
end
|
100
|
+
unless a.count == 600
|
101
|
+
@log.info("It's time to stop the cleanup thread...")
|
102
|
+
break
|
103
|
+
end
|
97
104
|
VerboseThread.new(@log).run do
|
98
105
|
cleanup(host, port, strength, threads)
|
99
106
|
end
|
@@ -106,25 +113,31 @@ module Zold
|
|
106
113
|
ensure
|
107
114
|
@log.info("Terminating the farm with #{@threads.count} threads...")
|
108
115
|
start = Time.now
|
109
|
-
@
|
110
|
-
|
111
|
-
@cleanup.join
|
112
|
-
@log.info("Cleanup thread finished in #{(Time.now - start).round(2)}s")
|
113
|
-
else
|
114
|
-
@cleanup.exit
|
115
|
-
@log.info("Cleanup thread killed in #{(Time.now - start).round(2)}s")
|
116
|
-
end
|
117
|
-
@threads.each do |t|
|
118
|
-
tstart = Time.now
|
119
|
-
t.join(0.1)
|
120
|
-
@log.info("Thread #{t.name} finished in #{(Time.now - tstart).round(2)}s")
|
121
|
-
end
|
116
|
+
finish(@cleanup)
|
117
|
+
@threads.each { |t| finish(t) }
|
122
118
|
@log.info("Farm stopped in #{(Time.now - start).round(2)}s")
|
123
119
|
end
|
124
120
|
end
|
125
121
|
|
126
122
|
private
|
127
123
|
|
124
|
+
def finish(thread)
|
125
|
+
start = Time.now
|
126
|
+
@alive = false
|
127
|
+
@log.info("Attempting to terminate the thread \"#{thread.name}\"...")
|
128
|
+
loop do
|
129
|
+
delay = (Time.now - start).round(2)
|
130
|
+
if thread.join(0.1)
|
131
|
+
@log.info("Thread \"#{thread.name}\" finished in #{delay}s")
|
132
|
+
break
|
133
|
+
end
|
134
|
+
if delay > 10
|
135
|
+
thread.exit
|
136
|
+
@log.error("Thread \"#{thread.name}\" forcefully terminated after #{delay}s")
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
128
141
|
def cleanup(host, port, strength, threads)
|
129
142
|
scores = load
|
130
143
|
before = scores.map(&:value).max.to_i
|
@@ -141,14 +154,25 @@ module Zold
|
|
141
154
|
end
|
142
155
|
|
143
156
|
def cycle(host, port, strength, threads)
|
144
|
-
s =
|
157
|
+
s = []
|
158
|
+
loop do
|
159
|
+
return unless @alive
|
160
|
+
begin
|
161
|
+
s << @pipeline.pop(true)
|
162
|
+
rescue ThreadError => _
|
163
|
+
sleep 0.25
|
164
|
+
end
|
165
|
+
s.compact!
|
166
|
+
break unless s.empty?
|
167
|
+
end
|
168
|
+
s = s[0]
|
145
169
|
return unless s.valid?
|
146
170
|
return unless s.host == host
|
147
171
|
return unless s.port == port
|
148
172
|
return unless s.strength >= strength
|
149
173
|
Thread.current.name = s.to_mnemo
|
150
174
|
bin = File.expand_path(File.join(File.dirname(__FILE__), '../../../bin/zold'))
|
151
|
-
Open3.popen2e("ruby #{bin} next \"#{s}\"") do |stdin, stdout, thr|
|
175
|
+
Open3.popen2e("ruby #{bin} --skip-upgrades next \"#{s}\"") do |stdin, stdout, thr|
|
152
176
|
@log.debug("Score counting started in process ##{thr.pid}")
|
153
177
|
begin
|
154
178
|
stdin.close
|
@@ -157,18 +181,21 @@ module Zold
|
|
157
181
|
begin
|
158
182
|
buffer << stdout.read_nonblock(1024)
|
159
183
|
rescue IO::WaitReadable => e
|
160
|
-
@log.debug("Still waiting for data from the
|
184
|
+
@log.debug("Still waiting for the data from the process ##{thr.pid}: #{e.message}")
|
161
185
|
end
|
162
|
-
if buffer.end_with?("\n")
|
186
|
+
if buffer.end_with?("\n") && thr.value.to_i.zero?
|
163
187
|
score = Score.parse(buffer.strip)
|
164
188
|
@log.debug("New score discovered: #{score}")
|
165
189
|
save(threads, [score])
|
166
190
|
cleanup(host, port, strength, threads)
|
167
191
|
break
|
168
192
|
end
|
169
|
-
|
193
|
+
if stdout.closed?
|
194
|
+
raise "Failed to calculate the score (##{thr.value}): #{buffer}" unless thr.value.to_i.zero?
|
195
|
+
break
|
196
|
+
end
|
170
197
|
break unless @alive
|
171
|
-
sleep 0.
|
198
|
+
sleep 0.25
|
172
199
|
end
|
173
200
|
rescue StandardError => e
|
174
201
|
@log.error(Backtrace.new(e).to_s)
|
data/lib/zold/node/front.rb
CHANGED
@@ -27,6 +27,7 @@ require 'sinatra/base'
|
|
27
27
|
require 'webrick'
|
28
28
|
require 'get_process_mem'
|
29
29
|
require 'diffy'
|
30
|
+
require 'usagewatch_ext'
|
30
31
|
require 'concurrent'
|
31
32
|
require_relative '../backtrace'
|
32
33
|
require_relative '../version'
|
@@ -66,7 +67,7 @@ module Zold
|
|
66
67
|
set :farm, nil? # to be injected at node.rb
|
67
68
|
set :metronome, nil? # to be injected at node.rb
|
68
69
|
set :entrance, nil? # to be injected at node.rb
|
69
|
-
set :network,
|
70
|
+
set :network, 'test' # to be injected at node.rb
|
70
71
|
set :wallets, nil? # to be injected at node.rb
|
71
72
|
set :remotes, nil? # to be injected at node.rb
|
72
73
|
set :copies, nil? # to be injected at node.rb
|
@@ -162,13 +163,14 @@ while #{settings.address} is in '#{settings.network}'"
|
|
162
163
|
score: score.to_h,
|
163
164
|
pid: Process.pid,
|
164
165
|
cpus: Concurrent.processor_count,
|
165
|
-
memory: GetProcessMem.new.bytes,
|
166
|
+
memory: GetProcessMem.new.bytes.to_i,
|
166
167
|
platform: RUBY_PLATFORM,
|
168
|
+
load: Usagewatch.uw_load.to_f,
|
167
169
|
uptime: `uptime`.strip,
|
168
170
|
threads: "#{Thread.list.select { |t| t.status == 'run' }.count}/#{Thread.list.count}",
|
169
171
|
wallets: settings.wallets.all.count,
|
170
172
|
remotes: settings.remotes.all.count,
|
171
|
-
nscore: settings.remotes.all.map { |r| r[:score] }.inject(&:+),
|
173
|
+
nscore: settings.remotes.all.map { |r| r[:score] }.inject(&:+) || 0,
|
172
174
|
farm: settings.farm.to_json,
|
173
175
|
entrance: settings.entrance.to_json,
|
174
176
|
date: Time.now.utc.iso8601,
|
data/lib/zold/version.rb
CHANGED
data/resources/remotes
CHANGED
@@ -155,7 +155,7 @@ class TestRemote < Minitest::Test
|
|
155
155
|
)
|
156
156
|
cmd.run(%W[remote add localhost #{port}])
|
157
157
|
end
|
158
|
-
assert_equal(
|
158
|
+
assert_equal(11 + File.readlines('resources/remotes').count, remotes.all.count)
|
159
159
|
cmd.run(%w[remote select --max-nodes=5])
|
160
160
|
assert_equal(5, remotes.all.count)
|
161
161
|
end
|
data/test/node/fake_node.rb
CHANGED
@@ -68,11 +68,13 @@ class FakeNode
|
|
68
68
|
end
|
69
69
|
end
|
70
70
|
uri = "http://localhost:#{port}/"
|
71
|
-
|
72
|
-
|
73
|
-
|
71
|
+
loop do
|
72
|
+
ping = Zold::Http.new(uri: uri, score: nil, network: Zold::Front.network).get
|
73
|
+
break unless ping.code == '599' && node.alive?
|
74
|
+
@log.debug("Waiting for #{uri}: ##{ping.code}...")
|
75
|
+
sleep 0.5
|
74
76
|
end
|
75
|
-
raise
|
77
|
+
raise "The node is dead at #{uri}" unless node.alive?
|
76
78
|
begin
|
77
79
|
yield port
|
78
80
|
ensure
|
data/test/node/test_farm.rb
CHANGED
@@ -40,7 +40,7 @@ class FarmTest < Minitest::Test
|
|
40
40
|
def test_renders_in_json
|
41
41
|
Dir.mktmpdir do |dir|
|
42
42
|
farm = Zold::Farm.new('NOPREFIX6@ffffffffffffffff', File.join(dir, 'f'), log: test_log)
|
43
|
-
farm.start('localhost', 80, threads:
|
43
|
+
farm.start('localhost', 80, threads: 2, strength: 2) do
|
44
44
|
assert_wait { !farm.best.empty? && !farm.best[0].value.zero? }
|
45
45
|
count = 0
|
46
46
|
100.times { count += farm.to_json[:best].length }
|
@@ -61,7 +61,7 @@ class FarmTest < Minitest::Test
|
|
61
61
|
def test_makes_best_score_in_background
|
62
62
|
Dir.mktmpdir do |dir|
|
63
63
|
farm = Zold::Farm.new('NOPREFIX1@ffffffffffffffff', File.join(dir, 'f'), log: test_log)
|
64
|
-
farm.start('localhost', 80, threads:
|
64
|
+
farm.start('localhost', 80, threads: 1, strength: 3) do
|
65
65
|
assert_wait { !farm.best.empty? && farm.best[0].value >= 3 }
|
66
66
|
score = farm.best[0]
|
67
67
|
assert(!score.expired?)
|
@@ -143,4 +143,10 @@ class FarmTest < Minitest::Test
|
|
143
143
|
end
|
144
144
|
end
|
145
145
|
end
|
146
|
+
|
147
|
+
def test_terminates_farm_entirely
|
148
|
+
Zold::Farm.new('NOPREFIX4@ffffffffffffffff', log: test_log).start('localhost', 4096, threads: 1, strength: 10) do
|
149
|
+
sleep 1
|
150
|
+
end
|
151
|
+
end
|
146
152
|
end
|
data/test/node/test_front.rb
CHANGED
@@ -32,6 +32,23 @@ require_relative '../../lib/zold/json_page'
|
|
32
32
|
require_relative '../../lib/zold/score'
|
33
33
|
|
34
34
|
class FrontTest < Minitest::Test
|
35
|
+
def test_renders_front_json
|
36
|
+
FakeNode.new(log: test_log).run(['--no-metronome', '--network=foo', '--threads=0']) do |port|
|
37
|
+
res = Zold::Http.new(uri: "http://localhost:#{port}/", network: 'foo', score: nil).get
|
38
|
+
json = JSON.parse(res.body)
|
39
|
+
assert_equal(Zold::VERSION, json['version'])
|
40
|
+
assert_equal(Zold::PROTOCOL, json['protocol'])
|
41
|
+
assert_equal('foo', json['network'])
|
42
|
+
assert(json['pid'].positive?)
|
43
|
+
assert(json['cpus'].positive?)
|
44
|
+
assert(json['memory'].positive?)
|
45
|
+
assert(json['load'].positive?)
|
46
|
+
assert(json['wallets'].positive?)
|
47
|
+
assert(json['remotes'].zero?)
|
48
|
+
assert(json['nscore'].zero?)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
35
52
|
def test_renders_public_pages
|
36
53
|
FakeNode.new(log: test_log).run(['--ignore-score-weakness']) do |port|
|
37
54
|
{
|
@@ -219,13 +236,7 @@ class FrontTest < Minitest::Test
|
|
219
236
|
'*',
|
220
237
|
response.header['Access-Control-Allow-Origin']
|
221
238
|
)
|
222
|
-
|
223
|
-
time: Time.now, host: 'localhost', port: port, invoice: 'NOPREFIX@ffffffffffffffff', strength: 2
|
224
|
-
)
|
225
|
-
assert_equal(
|
226
|
-
score.to_s,
|
227
|
-
response.header[Zold::Http::SCORE_HEADER]
|
228
|
-
)
|
239
|
+
assert(!response.header[Zold::Http::SCORE_HEADER].nil?)
|
229
240
|
end
|
230
241
|
end
|
231
242
|
end
|
data/test/test__helper.rb
CHANGED
data/test/test_http.rb
CHANGED
@@ -51,4 +51,28 @@ class TestHttp < Minitest::Test
|
|
51
51
|
res = Zold::Http.new(uri: 'http://good-host/', score: nil).get
|
52
52
|
assert_equal('200', res.code)
|
53
53
|
end
|
54
|
+
|
55
|
+
def test_sends_valid_network_header
|
56
|
+
stub_request(:get, 'http://some-host-1/')
|
57
|
+
.with(headers: { 'X-Zold-Network' => 'xyz' })
|
58
|
+
.to_return(status: 200)
|
59
|
+
res = Zold::Http.new(uri: 'http://some-host-1/', score: nil, network: 'xyz').get
|
60
|
+
assert_equal('200', res.code)
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_sends_valid_protocol_header
|
64
|
+
stub_request(:get, 'http://some-host-2/')
|
65
|
+
.with(headers: { 'X-Zold-Protocol' => Zold::PROTOCOL })
|
66
|
+
.to_return(status: 200)
|
67
|
+
res = Zold::Http.new(uri: 'http://some-host-2/', score: nil).get
|
68
|
+
assert_equal('200', res.code)
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_sends_valid_version_header
|
72
|
+
stub_request(:get, 'http://some-host-3/')
|
73
|
+
.with(headers: { 'X-Zold-Version' => Zold::VERSION })
|
74
|
+
.to_return(status: 200)
|
75
|
+
res = Zold::Http.new(uri: 'http://some-host-3/', score: nil).get
|
76
|
+
assert_equal('200', res.code)
|
77
|
+
end
|
54
78
|
end
|
data/zold.gemspec
CHANGED
@@ -71,6 +71,7 @@ and suggests a different architecture for digital wallet maintenance.'
|
|
71
71
|
s.add_runtime_dependency 'sinatra', '~>2.0'
|
72
72
|
s.add_runtime_dependency 'slop', '~>4.4'
|
73
73
|
s.add_runtime_dependency 'sys-proctable', '1.1.5'
|
74
|
+
s.add_runtime_dependency 'usagewatch_ext', '0.2.0'
|
74
75
|
s.add_runtime_dependency 'xcop', '~>0.5'
|
75
76
|
s.add_development_dependency 'codecov', '0.1.10'
|
76
77
|
s.add_development_dependency 'minitest', '5.11.3'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: zold
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.14.
|
4
|
+
version: 0.14.36
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yegor Bugayenko
|
@@ -248,6 +248,20 @@ dependencies:
|
|
248
248
|
- - '='
|
249
249
|
- !ruby/object:Gem::Version
|
250
250
|
version: 1.1.5
|
251
|
+
- !ruby/object:Gem::Dependency
|
252
|
+
name: usagewatch_ext
|
253
|
+
requirement: !ruby/object:Gem::Requirement
|
254
|
+
requirements:
|
255
|
+
- - '='
|
256
|
+
- !ruby/object:Gem::Version
|
257
|
+
version: 0.2.0
|
258
|
+
type: :runtime
|
259
|
+
prerelease: false
|
260
|
+
version_requirements: !ruby/object:Gem::Requirement
|
261
|
+
requirements:
|
262
|
+
- - '='
|
263
|
+
- !ruby/object:Gem::Version
|
264
|
+
version: 0.2.0
|
251
265
|
- !ruby/object:Gem::Dependency
|
252
266
|
name: xcop
|
253
267
|
requirement: !ruby/object:Gem::Requirement
|