zold 0.17.5 → 0.17.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/zold/commands/node.rb +10 -3
- data/lib/zold/node/async_entrance.rb +9 -2
- data/lib/zold/node/farm.rb +18 -23
- data/lib/zold/node/farmers.rb +6 -4
- data/lib/zold/node/front.rb +11 -4
- data/lib/zold/node/soft_error.rb +32 -0
- data/lib/zold/remotes.rb +6 -5
- data/lib/zold/version.rb +1 -1
- data/test/node/test_front.rb +16 -1
- data/zold.gemspec +1 -1
- metadata +6 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c7a2934cd243231fd712085b3f87a94d6bb4bf614cc1f5a1e9cada9f7268939d
|
4
|
+
data.tar.gz: f92eb91031505dee84d3bdbbc072e3d7384494e4954a5420b7656b8089d425e7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7d974ce11c5bf502b56ce917c19ac1d388d3a28399ddcf84e0fc3860dd2935576965451f26750bcf52744c9b33f411a7e885d6c84cdcdcfbecc1699e008d7e5f
|
7
|
+
data.tar.gz: 7bb56302734385c3a20a824b0c9d312ed5d88b02adca2c6c0d9c68554e91d598f26ed29f2019e0435d4622308c5b0e889cade6737773ace52c62701b4fc2570c
|
data/lib/zold/commands/node.rb
CHANGED
@@ -159,7 +159,7 @@ module Zold
|
|
159
159
|
default: false
|
160
160
|
o.string '--alias',
|
161
161
|
'The alias of the node (default: host:port)'
|
162
|
-
o.
|
162
|
+
o.boolean '--no-spawn',
|
163
163
|
'Don\'t use child processes for the score farm',
|
164
164
|
default: false
|
165
165
|
o.bool '--help', 'Print instructions'
|
@@ -259,8 +259,7 @@ module Zold
|
|
259
259
|
network: opts['network']
|
260
260
|
).start do |entrance|
|
261
261
|
Front.set(:entrance, entrance)
|
262
|
-
|
263
|
-
Farm.new(invoice, File.join(home, 'farm'), log: @log, farmer: farmer, strength: opts[:strength])
|
262
|
+
Farm.new(invoice, File.join(home, 'farm'), log: @log, farmer: farmer(opts), strength: opts[:strength])
|
264
263
|
.start(host, opts[:port], threads: opts[:threads]) do |farm|
|
265
264
|
Front.set(:farm, farm)
|
266
265
|
metronome(farm, opts).start do |metronome|
|
@@ -276,6 +275,14 @@ module Zold
|
|
276
275
|
|
277
276
|
private
|
278
277
|
|
278
|
+
def farmer(opts)
|
279
|
+
if opts['no-spawn']
|
280
|
+
@log.debug('Plain farmer is used, only one CPU will be utilized')
|
281
|
+
return Farmers::Plain.new
|
282
|
+
end
|
283
|
+
Farmers::Fork.new(log: @log)
|
284
|
+
end
|
285
|
+
|
279
286
|
# Returns exit code
|
280
287
|
def exec(cmd, nohup_log)
|
281
288
|
start = Time.now
|
@@ -28,6 +28,7 @@ require_relative '../size'
|
|
28
28
|
require_relative '../id'
|
29
29
|
require_relative '../endless'
|
30
30
|
require_relative '../dir_items'
|
31
|
+
require_relative 'soft_error'
|
31
32
|
|
32
33
|
# The async entrance of the web front.
|
33
34
|
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
@@ -49,7 +50,8 @@ module Zold
|
|
49
50
|
def to_json
|
50
51
|
@entrance.to_json.merge(
|
51
52
|
'queue': @queue.size,
|
52
|
-
'threads': @threads.count
|
53
|
+
'threads': @threads.count,
|
54
|
+
'queue_limit': @queue_limit
|
53
55
|
)
|
54
56
|
end
|
55
57
|
|
@@ -80,7 +82,12 @@ module Zold
|
|
80
82
|
|
81
83
|
# Always returns an array with a single ID of the pushed wallet
|
82
84
|
def push(id, body)
|
83
|
-
|
85
|
+
if @queue.size > @queue_limit
|
86
|
+
raise(
|
87
|
+
SoftError,
|
88
|
+
"Queue is too long (#{@queue.size} wallets), can't add #{id}/#{Size.new(body.length)}, try again later"
|
89
|
+
)
|
90
|
+
end
|
84
91
|
start = Time.now
|
85
92
|
loop do
|
86
93
|
uuid = SecureRandom.uuid
|
data/lib/zold/node/farm.rb
CHANGED
@@ -196,33 +196,28 @@ at #{host}:#{port}, strength is #{@strength}")
|
|
196
196
|
def save(threads, list = [])
|
197
197
|
scores = load + list
|
198
198
|
period = @lifetime / [threads, 1].max
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
.uniq
|
211
|
-
.join("\n")
|
212
|
-
)
|
213
|
-
end
|
199
|
+
body = scores.select(&:valid?)
|
200
|
+
.reject(&:expired?)
|
201
|
+
.reject { |s| s.strength < @strength }
|
202
|
+
.sort_by(&:value)
|
203
|
+
.reverse
|
204
|
+
.uniq(&:time)
|
205
|
+
.uniq { |s| (s.age / period).round }
|
206
|
+
.map(&:to_s)
|
207
|
+
.uniq
|
208
|
+
.join("\n")
|
209
|
+
Futex.new(@cache).open { |f| IO.write(f, body) }
|
214
210
|
end
|
215
211
|
|
216
212
|
def load
|
217
213
|
return [] unless File.exist?(@cache)
|
218
|
-
Futex.new(@cache).open(false)
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
end
|
214
|
+
body = Futex.new(@cache).open(false) { |f| IO.read(f) }
|
215
|
+
body.split(/\n/).reject(&:empty?).map do |t|
|
216
|
+
Score.parse(t)
|
217
|
+
rescue StandardError => e
|
218
|
+
@log.error(Backtrace.new(e).to_s)
|
219
|
+
nil
|
220
|
+
end.compact
|
226
221
|
end
|
227
222
|
end
|
228
223
|
end
|
data/lib/zold/node/farmers.rb
CHANGED
@@ -61,15 +61,17 @@ module Zold
|
|
61
61
|
|
62
62
|
def up(score)
|
63
63
|
start = Time.now
|
64
|
-
|
64
|
+
stdout, stdin = IO.pipe
|
65
65
|
pid = Process.fork do
|
66
|
-
|
66
|
+
stdin.puts(score.next)
|
67
67
|
end
|
68
68
|
at_exit { Farmers.kill(@log, pid, start) }
|
69
69
|
Process.wait
|
70
|
-
stdout.close
|
71
|
-
after = Score.parse(stdin.read.strip)
|
72
70
|
stdin.close
|
71
|
+
text = stdout.read.strip
|
72
|
+
stdout.close
|
73
|
+
raise "No score was calculated in the process ##{pid} in #{Age.new(start)}" if text.empty?
|
74
|
+
after = Score.parse(text)
|
73
75
|
@log.debug("Next score #{after.value}/#{after.strength} found in proc ##{pid} \
|
74
76
|
for #{after.host}:#{after.port} in #{Age.new(start)}: #{after.suffixes}")
|
75
77
|
after
|
data/lib/zold/node/front.rb
CHANGED
@@ -38,6 +38,7 @@ require_relative '../log'
|
|
38
38
|
require_relative '../tax'
|
39
39
|
require_relative '../id'
|
40
40
|
require_relative '../http'
|
41
|
+
require_relative 'soft_error'
|
41
42
|
|
42
43
|
# The web front of the node.
|
43
44
|
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
@@ -46,6 +47,10 @@ require_relative '../http'
|
|
46
47
|
module Zold
|
47
48
|
# Web front
|
48
49
|
class Front < Sinatra::Base
|
50
|
+
# The minimum score required in order to recongnize a requestor
|
51
|
+
# as a valuable node and add it to the list of remotes.
|
52
|
+
MIN_SCORE = 16
|
53
|
+
|
49
54
|
configure do
|
50
55
|
Thread.current.name = 'sinatra'
|
51
56
|
set :bind, '0.0.0.0'
|
@@ -76,6 +81,7 @@ module Zold
|
|
76
81
|
use Rack::Deflater
|
77
82
|
|
78
83
|
before do
|
84
|
+
Thread.current.name = "#{request.request_method}:#{request.url}"
|
79
85
|
Thread.current.thread_variable_set(:uri, request.url)
|
80
86
|
Thread.current.thread_variable_set(:ip, request.ip)
|
81
87
|
@start = Time.now
|
@@ -101,6 +107,7 @@ while #{settings.address} is in '#{settings.opts['network']}'")
|
|
101
107
|
s = Score.parse_text(header)
|
102
108
|
error(400, 'The score is invalid') unless s.valid?
|
103
109
|
error(400, 'The score is weak') if s.strength < Score::STRENGTH && !settings.opts['ignore-score-weakness']
|
110
|
+
return if s.value < Front::MIN_SCORE && !settings.opts['ignore-score-weakness']
|
104
111
|
if settings.address == "#{s.host}:#{s.port}" && !settings.opts['ignore-score-weakness']
|
105
112
|
error(400, 'Self-requests are prohibited')
|
106
113
|
end
|
@@ -120,10 +127,11 @@ while #{settings.address} is in '#{settings.opts['network']}'")
|
|
120
127
|
# Currently there are no tests at all that would verify the headers.
|
121
128
|
after do
|
122
129
|
headers['Cache-Control'] = 'no-cache'
|
130
|
+
headers['X-Zold-Path'] = request.url
|
123
131
|
headers['X-Zold-Version'] = settings.opts['expose-version']
|
124
132
|
headers[Http::PROTOCOL_HEADER] = settings.protocol.to_s
|
125
133
|
headers['Access-Control-Allow-Origin'] = '*'
|
126
|
-
headers[Http::SCORE_HEADER] = score.reduced(
|
134
|
+
headers[Http::SCORE_HEADER] = score.reduced(Front::MIN_SCORE).to_s
|
127
135
|
headers['X-Zold-Thread'] = Thread.current.object_id.to_s
|
128
136
|
unless @start.nil?
|
129
137
|
if Time.now - @start > 1
|
@@ -199,7 +207,7 @@ in #{Age.new(@start, limit: 1)}")
|
|
199
207
|
require 'get_process_mem'
|
200
208
|
mem = GetProcessMem.new.bytes.to_i
|
201
209
|
if mem > 256 * 1024 * 1024 && !settings.opts['skip-oom']
|
202
|
-
settings.log.error(
|
210
|
+
settings.log.error("We are too big in memory (#{Size.new(mem)}), quitting; use --skip-oom to never quit")
|
203
211
|
Front.stop!
|
204
212
|
end
|
205
213
|
mem
|
@@ -420,8 +428,7 @@ in #{Age.new(@start, limit: 1)}")
|
|
420
428
|
e = env['sinatra.error']
|
421
429
|
content_type 'text/plain'
|
422
430
|
headers['X-Zold-Error'] = e.message
|
423
|
-
|
424
|
-
settings.log.error(Backtrace.new(e).to_s)
|
431
|
+
settings.log.error(Backtrace.new(e).to_s) unless e.is_a?(SoftError)
|
425
432
|
Backtrace.new(e).to_s
|
426
433
|
end
|
427
434
|
|
@@ -0,0 +1,32 @@
|
|
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
|
+
# Soft error.
|
24
|
+
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
25
|
+
# Copyright:: Copyright (c) 2018 Yegor Bugayenko
|
26
|
+
# License:: MIT
|
27
|
+
module Zold
|
28
|
+
# Soft error
|
29
|
+
module SoftError
|
30
|
+
# Nothing special
|
31
|
+
end
|
32
|
+
end
|
data/lib/zold/remotes.rb
CHANGED
@@ -104,20 +104,21 @@ module Zold
|
|
104
104
|
|
105
105
|
def assert_valid_score(score)
|
106
106
|
raise "Invalid score #{score}" unless score.valid?
|
107
|
-
raise "Expired score (#{Age.new(score.time)}) #{score}" if score.expired?
|
107
|
+
raise "Expired score (#{Age.new(score.time)}) #{score.reduce(4)}" if score.expired?
|
108
108
|
end
|
109
109
|
|
110
110
|
def assert_score_ownership(score)
|
111
|
-
raise "Masqueraded host #{@host} as #{score.host}: #{score}" if @host != score.host
|
112
|
-
raise "Masqueraded port #{@port} as #{score.port}: #{score}" if @port != score.port
|
111
|
+
raise "Masqueraded host #{@host} as #{score.host}: #{score.reduce(4)}" if @host != score.host
|
112
|
+
raise "Masqueraded port #{@port} as #{score.port}: #{score.reduce(4)}" if @port != score.port
|
113
113
|
end
|
114
114
|
|
115
115
|
def assert_score_strength(score)
|
116
|
-
|
116
|
+
return if score.strength >= Score::STRENGTH
|
117
|
+
raise "Score #{score.strength} is too weak (<#{Score::STRENGTH}): #{score.reduce(4)}"
|
117
118
|
end
|
118
119
|
|
119
120
|
def assert_score_value(score, min)
|
120
|
-
raise "Score #{score.value} is too small (<#{min}): #{score}" if score.value < min
|
121
|
+
raise "Score #{score.value} is too small (<#{min}): #{score.reduce(4)}" if score.value < min
|
121
122
|
end
|
122
123
|
end
|
123
124
|
|
data/lib/zold/version.rb
CHANGED
data/test/node/test_front.rb
CHANGED
@@ -266,7 +266,7 @@ class FrontTest < Zold::Test
|
|
266
266
|
|
267
267
|
def test_performance
|
268
268
|
times = Queue.new
|
269
|
-
FakeNode.new(log: test_log).run(['--threads=4', '--strength=6', '--no-metronome'
|
269
|
+
FakeNode.new(log: test_log).run(['--threads=4', '--strength=6', '--no-metronome']) do |port|
|
270
270
|
Threads.new(10).assert(100) do
|
271
271
|
start = Time.now
|
272
272
|
Zold::Http.new(uri: URI("http://localhost:#{port}/")).get
|
@@ -278,6 +278,21 @@ class FrontTest < Zold::Test
|
|
278
278
|
test_log.info("Average response time is #{all.inject(&:+) / all.count}")
|
279
279
|
end
|
280
280
|
|
281
|
+
# The score exposed via the HTTP header must be reduced to the value of 16.
|
282
|
+
# We need this in order to optimize the amount of data we transfer in each
|
283
|
+
# HTTP request. This value is enough to identify a valueable node, and filter
|
284
|
+
# out those that are too weak.
|
285
|
+
def test_score_is_reduced
|
286
|
+
FakeNode.new(log: test_log).run(['--threads=1', '--strength=1', '--no-metronome', '--no-spawn']) do |port|
|
287
|
+
res = Zold::Http.new(uri: URI("http://localhost:#{port}/")).get
|
288
|
+
assert_wait { Zold::Score.parse(res.headers[Zold::Http::SCORE_HEADER]).value > Zold::Front::MIN_SCORE - 1 }
|
289
|
+
sleep(1)
|
290
|
+
assert_equal_wait(Zold::Front::MIN_SCORE) do
|
291
|
+
Zold::Score.parse(res.headers[Zold::Http::SCORE_HEADER]).value
|
292
|
+
end
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
281
296
|
def test_headers_are_being_set_correctly
|
282
297
|
Time.stub :now, Time.at(0) do
|
283
298
|
FakeNode.new(log: test_log).run(['--expose-version=9.9.9', '--no-metronome', '--threads=0']) do |port|
|
data/zold.gemspec
CHANGED
@@ -65,7 +65,7 @@ and suggests a different architecture for digital wallet maintenance.'
|
|
65
65
|
s.add_runtime_dependency 'concurrent-ruby', '1.1.3'
|
66
66
|
s.add_runtime_dependency 'cucumber', '3.1.2' # has to stay here for Heroku
|
67
67
|
s.add_runtime_dependency 'diffy', '3.2.1'
|
68
|
-
s.add_runtime_dependency 'futex', '0.
|
68
|
+
s.add_runtime_dependency 'futex', '0.6.1'
|
69
69
|
s.add_runtime_dependency 'get_process_mem', '0.2.3'
|
70
70
|
s.add_runtime_dependency 'json', '2.1.0'
|
71
71
|
s.add_runtime_dependency 'memory_profiler', '0.9.12'
|
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.17.
|
4
|
+
version: 0.17.6
|
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-12-
|
11
|
+
date: 2018-12-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: backtrace
|
@@ -72,14 +72,14 @@ dependencies:
|
|
72
72
|
requirements:
|
73
73
|
- - '='
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: 0.
|
75
|
+
version: 0.6.1
|
76
76
|
type: :runtime
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - '='
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: 0.
|
82
|
+
version: 0.6.1
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: get_process_mem
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -603,6 +603,7 @@ files:
|
|
603
603
|
- lib/zold/node/nodup_entrance.rb
|
604
604
|
- lib/zold/node/nospam_entrance.rb
|
605
605
|
- lib/zold/node/safe_entrance.rb
|
606
|
+
- lib/zold/node/soft_error.rb
|
606
607
|
- lib/zold/node/spread_entrance.rb
|
607
608
|
- lib/zold/node/sync_entrance.rb
|
608
609
|
- lib/zold/node/trace.rb
|
@@ -699,7 +700,7 @@ licenses:
|
|
699
700
|
- MIT
|
700
701
|
metadata: {}
|
701
702
|
post_install_message: |-
|
702
|
-
Thanks for installing Zold 0.17.
|
703
|
+
Thanks for installing Zold 0.17.6!
|
703
704
|
Study our White Paper: https://papers.zold.io/wp.pdf
|
704
705
|
Read our blog posts: https://blog.zold.io
|
705
706
|
Try online wallet at: https://wts.zold.io
|