zold 0.14.13 → 0.14.14
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/fixtures/scripts/distribute-wallet.sh +3 -2
- data/lib/zold/amount.rb +0 -0
- data/lib/zold/commands/calculate.rb +0 -0
- data/lib/zold/commands/node.rb +18 -12
- data/lib/zold/commands/pay.rb +1 -1
- data/lib/zold/commands/remote.rb +7 -6
- data/lib/zold/commands/routines/reconnect.rb +8 -8
- data/lib/zold/commands/routines/spread.rb +13 -11
- data/lib/zold/copies.rb +0 -0
- data/lib/zold/http.rb +10 -4
- data/lib/zold/metronome.rb +1 -0
- data/lib/zold/node/async_entrance.rb +2 -0
- data/lib/zold/node/entrance.rb +2 -2
- data/lib/zold/node/farm.rb +3 -0
- data/lib/zold/node/front.rb +26 -8
- data/lib/zold/node/nodup_entrance.rb +73 -0
- data/lib/zold/remotes.rb +3 -2
- data/lib/zold/score.rb +0 -0
- data/lib/zold/tax.rb +1 -1
- data/lib/zold/txn.rb +0 -0
- data/lib/zold/type.rb +0 -0
- data/lib/zold/upgrades.rb +0 -0
- data/lib/zold/version.rb +1 -1
- data/lib/zold/version_file.rb +0 -0
- data/lib/zold/wallet.rb +3 -1
- data/test/commands/routines/test_spread.rb +1 -4
- data/test/commands/test_node.rb +0 -0
- data/test/node/fake_node.rb +0 -0
- data/test/node/test_farm.rb +0 -0
- data/test/node/test_front.rb +0 -0
- data/test/node/test_nodup_entrance.rb +49 -0
- data/test/test_http.rb +0 -0
- data/test/test_score.rb +0 -0
- data/test/test_tax.rb +0 -0
- data/test/test_upgrades.rb +0 -0
- data/test/test_version.rb +0 -0
- data/test/test_wallet.rb +12 -0
- data/test/upgrades/test_protocol_up.rb +0 -0
- data/upgrades/2.rb +0 -0
- data/upgrades/protocol_up.rb +0 -0
- data/upgrades/rename_foreign_wallets.rb +0 -0
- metadata +5 -5
- data/lib/zold/commands/routines/bonuses.rb +0 -78
- data/test/commands/routines/test_bonuses.rb +0 -76
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 71369b8c56264180688b1f2e6fa6f9ce74bdbfd7
|
4
|
+
data.tar.gz: ae47e1e2501eab7fbb340b061f87c075884da2f0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0445e6669bb843b41ffee95c9ea388ec452551fc7c833d3ddc3cfd7fbdd0bbba646974289500ed47ab7ed93e4928ac1e4e1d146fbfcd0bbff5f4e5218153b560
|
7
|
+
data.tar.gz: 4a1ecaea86ffa87784b43c92ec23415032bfd41e929f86759512beea2c778a333a4e05b4c64dbd892fe7c530c4d012e99505ddf67abdde88d1a70639c6d284a5
|
@@ -33,7 +33,8 @@ zold --home=${second} remote add localhost ${first}
|
|
33
33
|
# the wallet to the remote, expecting it to distribute it to the second
|
34
34
|
# wallet automatically.
|
35
35
|
zold --public-key=id_rsa.pub create 0000000000000000
|
36
|
-
zold pay --private-key=id_rsa 0000000000000000 NOPREFIX@aaaabbbbccccdddd 4.95 '
|
36
|
+
zold pay --private-key=id_rsa 0000000000000000 NOPREFIX@aaaabbbbccccdddd 4.95 'For the book'
|
37
|
+
zold remote clean
|
37
38
|
zold remote add localhost ${first}
|
38
39
|
zold push 0000000000000000
|
39
40
|
zold remote clean
|
@@ -78,7 +79,7 @@ until zold fetch 0000000000000000 --ignore-score-weakness; do
|
|
78
79
|
((i++)) || sleep 1
|
79
80
|
if ((i==5)); then
|
80
81
|
cat ${first}/log.txt
|
81
|
-
echo "The wallet has not been spread, after ${i} attempts"
|
82
|
+
echo "The wallet 0000000000000000 has not been spread, after ${i} attempts"
|
82
83
|
exit 8
|
83
84
|
fi
|
84
85
|
sleep 1
|
data/lib/zold/amount.rb
CHANGED
File without changes
|
File without changes
|
data/lib/zold/commands/node.rb
CHANGED
@@ -34,6 +34,7 @@ require_relative '../node/entrance'
|
|
34
34
|
require_relative '../node/safe_entrance'
|
35
35
|
require_relative '../node/spread_entrance'
|
36
36
|
require_relative '../node/async_entrance'
|
37
|
+
require_relative '../node/nodup_entrance'
|
37
38
|
require_relative '../node/front'
|
38
39
|
require_relative '../node/farm'
|
39
40
|
require_relative 'pull'
|
@@ -165,20 +166,25 @@ module Zold
|
|
165
166
|
invoice = Invoice.new(wallets: @wallets, log: @log).run(['invoice', invoice])
|
166
167
|
end
|
167
168
|
SafeEntrance.new(
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
169
|
+
NoDupEntrance.new(
|
170
|
+
AsyncEntrance.new(
|
171
|
+
SpreadEntrance.new(
|
172
|
+
Entrance.new(@wallets, @remotes, @copies, address, log: @log, network: opts['network']),
|
173
|
+
@wallets, @remotes, address,
|
174
|
+
log: @log,
|
175
|
+
ignore_score_weakeness: opts['ignore-score-weakness']
|
176
|
+
),
|
177
|
+
File.join(Dir.pwd, '.zoldata/entrance'), log: @log
|
178
|
+
),
|
179
|
+
@wallets
|
180
|
+
),
|
181
|
+
network: opts['network']
|
176
182
|
).start do |entrance|
|
177
183
|
Front.set(:entrance, entrance)
|
178
184
|
Farm.new(invoice, File.join(Dir.pwd, 'farm'), log: @log)
|
179
185
|
.start(host, opts[:port], threads: opts[:threads], strength: opts[:strength]) do |farm|
|
180
186
|
Front.set(:farm, farm)
|
181
|
-
metronome(farm,
|
187
|
+
metronome(farm, opts).start do |metronome|
|
182
188
|
Front.set(:metronome, metronome)
|
183
189
|
@log.info("Starting up the web front at http://#{host}:#{opts[:port]}...")
|
184
190
|
Front.run!
|
@@ -244,13 +250,13 @@ module Zold
|
|
244
250
|
pid
|
245
251
|
end
|
246
252
|
|
247
|
-
def metronome(farm,
|
253
|
+
def metronome(farm, opts)
|
248
254
|
metronome = Metronome.new(@log)
|
249
255
|
require_relative 'routines/spread'
|
250
|
-
metronome.add(Routines::Spread.new(opts, @wallets,
|
256
|
+
metronome.add(Routines::Spread.new(opts, @wallets, @remotes, log: @log))
|
251
257
|
unless opts['standalone']
|
252
258
|
require_relative 'routines/reconnect'
|
253
|
-
metronome.add(Routines::Reconnect.new(opts, @remotes, farm, log: Log::Quiet.new))
|
259
|
+
metronome.add(Routines::Reconnect.new(opts, @remotes, farm, network: opts['network'], log: Log::Quiet.new))
|
254
260
|
end
|
255
261
|
@log.info('Metronome created')
|
256
262
|
metronome
|
data/lib/zold/commands/pay.rb
CHANGED
@@ -81,7 +81,7 @@ Available options:"
|
|
81
81
|
if Tax.new(from).in_debt? && !opts['dont-pay-taxes']
|
82
82
|
require_relative 'taxes'
|
83
83
|
Taxes.new(wallets: @wallets, remotes: @remotes, log: @log).run(
|
84
|
-
['taxes', "--private-key=#{opts['private-key']}", id.to_s]
|
84
|
+
['taxes', 'pay', "--private-key=#{opts['private-key']}", id.to_s]
|
85
85
|
)
|
86
86
|
end
|
87
87
|
pay(from, invoice, amount, details, opts)
|
data/lib/zold/commands/remote.rb
CHANGED
@@ -80,6 +80,9 @@ Available options:"
|
|
80
80
|
o.bool '--ignore-score-value',
|
81
81
|
'Don\'t complain when their score is too small',
|
82
82
|
default: false
|
83
|
+
o.bool '--min-score',
|
84
|
+
"The minimum score required for winning the election (default: #{Tax::EXACT_SCORE})",
|
85
|
+
default: Tax::EXACT_SCORE
|
83
86
|
o.bool '--force',
|
84
87
|
'Add/remove if if this operation is not possible',
|
85
88
|
default: false
|
@@ -192,7 +195,7 @@ Available options:"
|
|
192
195
|
r.assert_valid_score(score)
|
193
196
|
r.assert_score_ownership(score)
|
194
197
|
r.assert_score_strength(score) unless opts['ignore-score-weakness']
|
195
|
-
r.assert_score_value(score,
|
198
|
+
r.assert_score_value(score, opts['min-score']) unless opts['ignore-score-value']
|
196
199
|
scores << score
|
197
200
|
end
|
198
201
|
scores = scores.sample(1)
|
@@ -254,11 +257,9 @@ in #{(Time.now - start).round(2)}s")
|
|
254
257
|
end
|
255
258
|
|
256
259
|
def select(opts)
|
257
|
-
|
258
|
-
@
|
259
|
-
|
260
|
-
(@remotes.all - selected_remotes).each do |weak_remote|
|
261
|
-
@remotes.remove(weak_remote[:host], weak_remote[:port])
|
260
|
+
selected = @remotes.all.sort_by { |r| r[:score] }.first(opts['max-nodes'])
|
261
|
+
(@remotes.all - selected).each do |r|
|
262
|
+
@remotes.remove(r[:host], r[:port])
|
262
263
|
end
|
263
264
|
end
|
264
265
|
|
@@ -32,22 +32,22 @@ module Zold
|
|
32
32
|
module Routines
|
33
33
|
# Reconnect to the network
|
34
34
|
class Reconnect
|
35
|
-
def initialize(opts, remotes, farm = Farm::Empty.new, log: Log::Quiet.new)
|
35
|
+
def initialize(opts, remotes, farm = Farm::Empty.new, network: 'test', log: Log::Quiet.new)
|
36
36
|
@opts = opts
|
37
37
|
@remotes = remotes
|
38
38
|
@farm = farm
|
39
|
+
@network = network
|
39
40
|
@log = log
|
40
41
|
end
|
41
42
|
|
42
43
|
def exec(_ = 0)
|
43
44
|
sleep(60) unless @opts['routine-immediately']
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
)
|
45
|
+
cmd = Remote.new(remotes: @remotes, log: @log, farm: @farm)
|
46
|
+
args = ['remote', "--network=#{@opts['network']}"]
|
47
|
+
cmd.run(args + ['add', 'b1.zold.io', '80', '--force']) unless @opts['routine-immediately']
|
48
|
+
cmd.run(args + ['trim'])
|
49
|
+
cmd.run(args + ['select'])
|
50
|
+
cmd.run(args + ['update'] + (@opts['never-reboot'] ? [] : ['--reboot']))
|
51
51
|
end
|
52
52
|
end
|
53
53
|
end
|
@@ -20,9 +20,8 @@
|
|
20
20
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
21
|
# SOFTWARE.
|
22
22
|
|
23
|
-
require_relative '
|
24
|
-
require_relative '
|
25
|
-
require_relative '../pay'
|
23
|
+
require_relative '../../log'
|
24
|
+
require_relative '../../id'
|
26
25
|
require_relative '../push'
|
27
26
|
|
28
27
|
# Spread random wallets to the network.
|
@@ -34,22 +33,25 @@ module Zold
|
|
34
33
|
module Routines
|
35
34
|
# Spread them
|
36
35
|
class Spread
|
37
|
-
def initialize(opts, wallets,
|
36
|
+
def initialize(opts, wallets, remotes, log: Log::Quiet.new)
|
38
37
|
@opts = opts
|
39
38
|
@wallets = wallets
|
40
|
-
@
|
39
|
+
@remotes = remotes
|
41
40
|
@log = log
|
42
41
|
end
|
43
42
|
|
44
43
|
def exec(_ = 0)
|
44
|
+
return if @remotes.all.empty?
|
45
45
|
sleep(60) unless @opts['routine-immediately']
|
46
|
-
|
47
|
-
@wallets.
|
48
|
-
|
49
|
-
|
50
|
-
|
46
|
+
ids = @wallets.all.sample(10)
|
47
|
+
Push.new(wallets: @wallets, remotes: @remotes, log: @log).run(
|
48
|
+
['push', "--network=#{@opts['network']}"] + ids
|
49
|
+
)
|
50
|
+
if ids.empty?
|
51
|
+
@log.info("Spread didn't push any wallets, we are empty")
|
52
|
+
else
|
53
|
+
@log.info("Spread #{ids.count} random wallets out of #{@wallets.all.count}: #{ids.join(', ')}")
|
51
54
|
end
|
52
|
-
@log.info("Spread #{pushed.count} random wallets out of #{@wallets.all.count}: #{pushed.join(', ')}")
|
53
55
|
end
|
54
56
|
end
|
55
57
|
end
|
data/lib/zold/copies.rb
CHANGED
File without changes
|
data/lib/zold/http.rb
CHANGED
@@ -54,6 +54,12 @@ module Zold
|
|
54
54
|
# protocol.
|
55
55
|
PROTOCOL_HEADER = 'X-Zold-Protocol'
|
56
56
|
|
57
|
+
# Read timeout in seconds
|
58
|
+
READ_TIMEOUT = 32
|
59
|
+
|
60
|
+
# Connect timeout in seconds
|
61
|
+
CONNECT_TIMEOUT = 8
|
62
|
+
|
57
63
|
# @todo #98:30m/DEV The following two statements are seen as issues by rubocop
|
58
64
|
# raising a Lint/AmbiguousBlockAssociation offense. It is somthing
|
59
65
|
# that could be solved by changing the TargetRubyVersion in .rubocop.yml
|
@@ -70,8 +76,8 @@ module Zold
|
|
70
76
|
|
71
77
|
def get
|
72
78
|
http = Net::HTTP.new(uri.host, uri.port)
|
73
|
-
http.read_timeout =
|
74
|
-
http.open_timeout =
|
79
|
+
http.read_timeout = Http::READ_TIMEOUT
|
80
|
+
http.open_timeout = Http::CONNECT_TIMEOUT
|
75
81
|
path = uri.path
|
76
82
|
path += '?' + uri.query if uri.query
|
77
83
|
http.request_get(path, headers)
|
@@ -81,8 +87,8 @@ module Zold
|
|
81
87
|
|
82
88
|
def put(body)
|
83
89
|
http = Net::HTTP.new(uri.host, uri.port)
|
84
|
-
http.read_timeout =
|
85
|
-
http.open_timeout =
|
90
|
+
http.read_timeout = Http::READ_TIMEOUT
|
91
|
+
http.open_timeout = Http::CONNECT_TIMEOUT
|
86
92
|
path = uri.path
|
87
93
|
path += '?' + uri.query if uri.query
|
88
94
|
http.request_put(
|
data/lib/zold/metronome.rb
CHANGED
data/lib/zold/node/entrance.rb
CHANGED
@@ -95,8 +95,8 @@ module Zold
|
|
95
95
|
@log.info("Accepted #{id} in #{sec}s and modified #{modified.join(', ')}")
|
96
96
|
end
|
97
97
|
@mutex.synchronize do
|
98
|
-
@history.shift if @history.length
|
99
|
-
@speed.shift if @speed.length
|
98
|
+
@history.shift if @history.length >= 16
|
99
|
+
@speed.shift if @speed.length >= 64
|
100
100
|
wallet = @wallets.find(id)
|
101
101
|
@history << "#{id}/#{sec}/#{modified.count}/#{wallet.balance.to_zld}/#{wallet.txns.count}t"
|
102
102
|
@speed << sec
|
data/lib/zold/node/farm.rb
CHANGED
@@ -76,6 +76,7 @@ module Zold
|
|
76
76
|
@log.info("#{@pipeline.size} scores pre-loaded, the best is: #{best[0]}")
|
77
77
|
@threads = (1..threads).map do |t|
|
78
78
|
Thread.new do
|
79
|
+
Thread.current.abort_on_exception = true
|
79
80
|
Thread.current.name = "f#{t}"
|
80
81
|
Thread.current.priority = -100
|
81
82
|
loop do
|
@@ -87,7 +88,9 @@ module Zold
|
|
87
88
|
end
|
88
89
|
alive = true
|
89
90
|
@cleanup = Thread.new do
|
91
|
+
Thread.current.abort_on_exception = true
|
90
92
|
Thread.current.name = 'cleanup'
|
93
|
+
Thread.current.priority = -100
|
91
94
|
while alive
|
92
95
|
sleep(60) unless strength == 1 # which will only happen in tests
|
93
96
|
VerboseThread.new(@log).run do
|
data/lib/zold/node/front.rb
CHANGED
@@ -71,7 +71,8 @@ module Zold
|
|
71
71
|
before do
|
72
72
|
check_header(Http::NETWORK_HEADER) do |header|
|
73
73
|
if header != settings.network
|
74
|
-
raise "Network name mismatch
|
74
|
+
raise "Network name mismatch at #{request.url}, #{request.ip} is in '#{header}', \
|
75
|
+
while #{settings.address} is in '#{settings.network}'"
|
75
76
|
end
|
76
77
|
end
|
77
78
|
check_header(Http::PROTOCOL_HEADER) do |header|
|
@@ -162,6 +163,8 @@ module Zold
|
|
162
163
|
content_type 'application/json'
|
163
164
|
{
|
164
165
|
version: settings.version,
|
166
|
+
protocol: settings.protocol,
|
167
|
+
id: wallet.id.to_s,
|
165
168
|
score: score.to_h,
|
166
169
|
wallets: settings.wallets.all.count,
|
167
170
|
mtime: wallet.mtime.utc.iso8601,
|
@@ -171,6 +174,25 @@ module Zold
|
|
171
174
|
}.to_json
|
172
175
|
end
|
173
176
|
|
177
|
+
get %r{/wallet/(?<id>[A-Fa-f0-9]{16}).json} do
|
178
|
+
id = Id.new(params[:id])
|
179
|
+
wallet = settings.wallets.find(id)
|
180
|
+
error 404 unless wallet.exists?
|
181
|
+
content_type 'application/json'
|
182
|
+
{
|
183
|
+
version: settings.version,
|
184
|
+
protocol: settings.protocol,
|
185
|
+
id: wallet.id.to_s,
|
186
|
+
score: score.to_h,
|
187
|
+
wallets: settings.wallets.all.count,
|
188
|
+
key: wallet.key.to_pub,
|
189
|
+
mtime: wallet.mtime.utc.iso8601,
|
190
|
+
digest: wallet.digest,
|
191
|
+
balance: wallet.balance.to_i,
|
192
|
+
txns: wallet.txns.count
|
193
|
+
}.to_json
|
194
|
+
end
|
195
|
+
|
174
196
|
get %r{/wallet/(?<id>[A-Fa-f0-9]{16})/balance} do
|
175
197
|
id = Id.new(params[:id])
|
176
198
|
wallet = settings.wallets.find(id)
|
@@ -184,7 +206,7 @@ module Zold
|
|
184
206
|
wallet = settings.wallets.find(id)
|
185
207
|
error 404 unless wallet.exists?
|
186
208
|
content_type 'text/plain'
|
187
|
-
wallet.key.
|
209
|
+
wallet.key.to_pub
|
188
210
|
end
|
189
211
|
|
190
212
|
get %r{/wallet/(?<id>[A-Fa-f0-9]{16})/mtime} do
|
@@ -225,16 +247,12 @@ module Zold
|
|
225
247
|
end
|
226
248
|
|
227
249
|
put %r{/wallet/(?<id>[A-Fa-f0-9]{16})/?} do
|
228
|
-
id = Id.new(params[:id])
|
229
|
-
wallet = settings.wallets.find(id)
|
230
250
|
request.body.rewind
|
231
|
-
|
232
|
-
|
233
|
-
if before == after
|
251
|
+
modified = settings.entrance.push(Id.new(params[:id]), request.body.read.to_s)
|
252
|
+
if modified.empty?
|
234
253
|
status 304
|
235
254
|
return
|
236
255
|
end
|
237
|
-
settings.entrance.push(id, after)
|
238
256
|
JSON.pretty_generate(
|
239
257
|
version: settings.version,
|
240
258
|
score: score.to_h,
|
@@ -0,0 +1,73 @@
|
|
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 'tempfile'
|
24
|
+
require_relative '../log'
|
25
|
+
require_relative '../wallet'
|
26
|
+
require_relative '../atomic_file'
|
27
|
+
|
28
|
+
# The entrance that ignores duplicates.
|
29
|
+
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
30
|
+
# Copyright:: Copyright (c) 2018 Yegor Bugayenko
|
31
|
+
# License:: MIT
|
32
|
+
module Zold
|
33
|
+
# The safe entrance
|
34
|
+
class NoDupEntrance
|
35
|
+
def initialize(entrance, wallets, log: Log::Quiet.new)
|
36
|
+
raise 'Entrance can\'t be nil' if entrance.nil?
|
37
|
+
@entrance = entrance
|
38
|
+
raise 'Wallets can\'t be nil' if wallets.nil?
|
39
|
+
@wallets = wallets
|
40
|
+
raise 'Log can\'t be nil' if log.nil?
|
41
|
+
@log = log
|
42
|
+
end
|
43
|
+
|
44
|
+
def start
|
45
|
+
@entrance.start { yield(self) }
|
46
|
+
end
|
47
|
+
|
48
|
+
def to_json
|
49
|
+
@entrance.to_json
|
50
|
+
end
|
51
|
+
|
52
|
+
# Returns a list of modifed wallets (as Zold::Id)
|
53
|
+
def push(id, body)
|
54
|
+
raise 'Id can\'t be nil' if id.nil?
|
55
|
+
raise 'Id must be of type Id' unless id.is_a?(Id)
|
56
|
+
raise 'Body can\'t be nil' if body.nil?
|
57
|
+
Tempfile.open(['', Wallet::EXTENSION]) do |f|
|
58
|
+
File.write(f, body)
|
59
|
+
wallet = Wallet.new(f.path)
|
60
|
+
wallet.refurbish
|
61
|
+
after = File.read(wallet.path)
|
62
|
+
wallet = @wallets.find(id)
|
63
|
+
before = wallet.exists? ? AtomicFile.new(wallet.path).read.to_s : ''
|
64
|
+
if before == after
|
65
|
+
@log.info("Duplicate of #{id}/#{wallet.digest[0, 6]}/#{after.length}b/#{wallet.txns.count}t ignored")
|
66
|
+
return []
|
67
|
+
end
|
68
|
+
@log.info("New content for #{id} arrived, #{before.length}b before and #{after.length}b after")
|
69
|
+
@entrance.push(id, body)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
data/lib/zold/remotes.rb
CHANGED
@@ -186,6 +186,7 @@ module Zold
|
|
186
186
|
pool = Concurrent::FixedThreadPool.new([all.count, Concurrent.processor_count * 4].min, max_queue: 0)
|
187
187
|
all.each do |r|
|
188
188
|
pool.post do
|
189
|
+
Thread.current.abort_on_exception = true
|
189
190
|
Thread.current.name = 'remotes'
|
190
191
|
Thread.current.priority = -100
|
191
192
|
start = Time.now
|
@@ -197,14 +198,14 @@ module Zold
|
|
197
198
|
error(r[:host], r[:port])
|
198
199
|
errors = errors(r[:host], r[:port])
|
199
200
|
log.info("#{Rainbow("#{r[:host]}:#{r[:port]}").red}: #{e.message} \
|
200
|
-
|
201
|
+
in #{(Time.now - start).round}s; errors=#{errors}")
|
201
202
|
log.debug(Backtrace.new(e).to_s)
|
202
203
|
remove(r[:host], r[:port]) if errors > Remotes::TOLERANCE
|
203
204
|
end
|
204
205
|
end
|
205
206
|
end
|
206
207
|
pool.shutdown
|
207
|
-
|
208
|
+
pool.kill unless pool.wait_for_termination(5 * 60)
|
208
209
|
end
|
209
210
|
|
210
211
|
def errors(host, port = Remotes::PORT)
|
data/lib/zold/score.rb
CHANGED
File without changes
|
data/lib/zold/tax.rb
CHANGED
data/lib/zold/txn.rb
CHANGED
File without changes
|
data/lib/zold/type.rb
CHANGED
File without changes
|
data/lib/zold/upgrades.rb
CHANGED
File without changes
|
data/lib/zold/version.rb
CHANGED
data/lib/zold/version_file.rb
CHANGED
File without changes
|
data/lib/zold/wallet.rb
CHANGED
@@ -172,7 +172,9 @@ module Zold
|
|
172
172
|
end
|
173
173
|
|
174
174
|
def refurbish
|
175
|
-
AtomicFile.new(@file).write(
|
175
|
+
AtomicFile.new(@file).write(
|
176
|
+
"#{network}\n#{protocol}\n#{id}\n#{key.to_pub}\n\n#{txns.map { |t| t.to_s + "\n" }.join}"
|
177
|
+
)
|
176
178
|
end
|
177
179
|
|
178
180
|
private
|
@@ -39,10 +39,7 @@ class TestSpread < Minitest::Test
|
|
39
39
|
opts = {
|
40
40
|
'routine-immediately' => true
|
41
41
|
}
|
42
|
-
|
43
|
-
home.wallets, home.remotes, home.copies(home.create_wallet).root, 'x', log: test_log
|
44
|
-
)
|
45
|
-
Zold::Routines::Spread.new(opts, home.wallets, entrance, log: test_log).exec
|
42
|
+
Zold::Routines::Spread.new(opts, home.wallets, home.remotes, log: test_log).exec
|
46
43
|
end
|
47
44
|
end
|
48
45
|
end
|
data/test/commands/test_node.rb
CHANGED
File without changes
|
data/test/node/fake_node.rb
CHANGED
File without changes
|
data/test/node/test_farm.rb
CHANGED
File without changes
|
data/test/node/test_front.rb
CHANGED
File without changes
|
@@ -0,0 +1,49 @@
|
|
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_relative '../fake_home'
|
25
|
+
require_relative '../test__helper'
|
26
|
+
require_relative '../../lib/zold/id'
|
27
|
+
require_relative '../../lib/zold/node/nodup_entrance'
|
28
|
+
require_relative 'fake_entrance'
|
29
|
+
|
30
|
+
# NoDupEntrance test.
|
31
|
+
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
32
|
+
# Copyright:: Copyright (c) 2018 Yegor Bugayenko
|
33
|
+
# License:: MIT
|
34
|
+
class TestAsyncEntrance < Minitest::Test
|
35
|
+
def test_ignores_dup
|
36
|
+
FakeHome.new.run do |home|
|
37
|
+
wallet = home.create_wallet
|
38
|
+
Zold::NoDupEntrance.new(RealEntrance.new, home.wallets, log: test_log).start do |e|
|
39
|
+
assert(e.push(wallet.id, File.read(wallet.path)).empty?)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class RealEntrance < FakeEntrance
|
45
|
+
def push(id, _)
|
46
|
+
[id]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/test/test_http.rb
CHANGED
File without changes
|
data/test/test_score.rb
CHANGED
File without changes
|
data/test/test_tax.rb
CHANGED
File without changes
|
data/test/test_upgrades.rb
CHANGED
File without changes
|
data/test/test_version.rb
CHANGED
File without changes
|
data/test/test_wallet.rb
CHANGED
@@ -56,9 +56,21 @@ class TestWallet < Minitest::Test
|
|
56
56
|
key = Zold::Key.new(file: 'fixtures/id_rsa')
|
57
57
|
wallet.sub(amount, "NOPREFIX@#{Zold::Id.new}", key)
|
58
58
|
wallet.sub(amount, "NOPREFIX@#{Zold::Id.new}", key)
|
59
|
+
before = File.read(wallet.path)
|
59
60
|
File.write(wallet.path, File.read(wallet.path) + "\n\n\n")
|
60
61
|
wallet.refurbish
|
61
62
|
assert_equal(amount * -2, wallet.balance)
|
63
|
+
assert_equal(before, File.read(wallet.path))
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_refurbishes_empty_wallet
|
68
|
+
FakeHome.new.run do |home|
|
69
|
+
wallet = home.create_wallet
|
70
|
+
before = File.read(wallet.path)
|
71
|
+
File.write(wallet.path, File.read(wallet.path) + "\n\n\n")
|
72
|
+
wallet.refurbish
|
73
|
+
assert_equal(before, File.read(wallet.path))
|
62
74
|
end
|
63
75
|
end
|
64
76
|
|
File without changes
|
data/upgrades/2.rb
CHANGED
File without changes
|
data/upgrades/protocol_up.rb
CHANGED
File without changes
|
File without changes
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: zold
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.14.
|
4
|
+
version: 0.14.14
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yegor Bugayenko
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-07-
|
11
|
+
date: 2018-07-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: concurrent-ruby
|
@@ -405,7 +405,6 @@ files:
|
|
405
405
|
- lib/zold/commands/pull.rb
|
406
406
|
- lib/zold/commands/push.rb
|
407
407
|
- lib/zold/commands/remote.rb
|
408
|
-
- lib/zold/commands/routines/bonuses.rb
|
409
408
|
- lib/zold/commands/routines/reconnect.rb
|
410
409
|
- lib/zold/commands/routines/spread.rb
|
411
410
|
- lib/zold/commands/show.rb
|
@@ -424,6 +423,7 @@ files:
|
|
424
423
|
- lib/zold/node/entrance.rb
|
425
424
|
- lib/zold/node/farm.rb
|
426
425
|
- lib/zold/node/front.rb
|
426
|
+
- lib/zold/node/nodup_entrance.rb
|
427
427
|
- lib/zold/node/safe_entrance.rb
|
428
428
|
- lib/zold/node/spread_entrance.rb
|
429
429
|
- lib/zold/patch.rb
|
@@ -441,7 +441,6 @@ files:
|
|
441
441
|
- lib/zold/wallet.rb
|
442
442
|
- lib/zold/wallets.rb
|
443
443
|
- resources/remotes
|
444
|
-
- test/commands/routines/test_bonuses.rb
|
445
444
|
- test/commands/routines/test_reconnect.rb
|
446
445
|
- test/commands/routines/test_spread.rb
|
447
446
|
- test/commands/test_alias.rb
|
@@ -468,6 +467,7 @@ files:
|
|
468
467
|
- test/node/test_entrance.rb
|
469
468
|
- test/node/test_farm.rb
|
470
469
|
- test/node/test_front.rb
|
470
|
+
- test/node/test_nodup_entrance.rb
|
471
471
|
- test/node/test_safe_entrance.rb
|
472
472
|
- test/node/test_spread_entrance.rb
|
473
473
|
- test/test__helper.rb
|
@@ -528,7 +528,6 @@ test_files:
|
|
528
528
|
- features/gem_package.feature
|
529
529
|
- features/step_definitions/steps.rb
|
530
530
|
- features/support/env.rb
|
531
|
-
- test/commands/routines/test_bonuses.rb
|
532
531
|
- test/commands/routines/test_reconnect.rb
|
533
532
|
- test/commands/routines/test_spread.rb
|
534
533
|
- test/commands/test_alias.rb
|
@@ -555,6 +554,7 @@ test_files:
|
|
555
554
|
- test/node/test_entrance.rb
|
556
555
|
- test/node/test_farm.rb
|
557
556
|
- test/node/test_front.rb
|
557
|
+
- test/node/test_nodup_entrance.rb
|
558
558
|
- test/node/test_safe_entrance.rb
|
559
559
|
- test/node/test_spread_entrance.rb
|
560
560
|
- test/test__helper.rb
|
@@ -1,78 +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_relative '../remote'
|
24
|
-
require_relative '../pull'
|
25
|
-
require_relative '../pay'
|
26
|
-
require_relative '../push'
|
27
|
-
|
28
|
-
# Pay bonuses routine.
|
29
|
-
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
30
|
-
# Copyright:: Copyright (c) 2018 Yegor Bugayenko
|
31
|
-
# License:: MIT
|
32
|
-
module Zold
|
33
|
-
# Routines module
|
34
|
-
module Routines
|
35
|
-
# Pay bonuses to random nodes
|
36
|
-
class Bonuses
|
37
|
-
def initialize(opts, wallets, remotes, copies, farm, log: Log::Quiet.new)
|
38
|
-
@opts = opts
|
39
|
-
@wallets = wallets
|
40
|
-
@remotes = remotes
|
41
|
-
@copies = copies
|
42
|
-
@farm = farm
|
43
|
-
@log = log
|
44
|
-
end
|
45
|
-
|
46
|
-
def exec(_ = 0)
|
47
|
-
sleep(@opts['bonus-time'] * 60) unless @opts['routine-immediately']
|
48
|
-
raise '--private-key is required to pay bonuses' unless @opts['private-key']
|
49
|
-
raise '--bonus-wallet is required to pay bonuses' unless @opts['bonus-wallet']
|
50
|
-
raise '--bonus-amount is required to pay bonuses' unless @opts['bonus-amount']
|
51
|
-
winners = Remote.new(remotes: @remotes, log: @log, farm: @farm).run(
|
52
|
-
['remote', 'elect', @opts['bonus-wallet'], '--private-key', @opts['private-key']] +
|
53
|
-
(@opts['ignore-score-weakness'] ? ['--ignore-score-weakness'] : [])
|
54
|
-
)
|
55
|
-
return if winners.empty?
|
56
|
-
unless @wallets.find(Id.new(@opts['bonus-wallet'])).exists?
|
57
|
-
Pull.new(wallets: @wallets, remotes: @remotes, copies: @copies, log: @log).run(
|
58
|
-
['pull', @opts['bonus-wallet']] +
|
59
|
-
(@opts['ignore-score-weakness'] ? ['--ignore-score-weakness'] : [])
|
60
|
-
)
|
61
|
-
end
|
62
|
-
winners.each do |score|
|
63
|
-
Pay.new(wallets: @wallets, remotes: @remotes, log: @log).run(
|
64
|
-
[
|
65
|
-
'pay', @opts['bonus-wallet'], score.invoice, @opts['bonus-amount'].to_s,
|
66
|
-
"Hosting bonus for #{score.host} #{score.port} #{score.value}",
|
67
|
-
'--private-key', @opts['private-key']
|
68
|
-
]
|
69
|
-
)
|
70
|
-
end
|
71
|
-
Push.new(wallets: @wallets, remotes: @remotes, log: @log).run(
|
72
|
-
['push', @opts['bonus-wallet']] +
|
73
|
-
(@opts['ignore-score-weakness'] ? ['--ignore-score-weakness'] : [])
|
74
|
-
)
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
@@ -1,76 +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 'webmock/minitest'
|
25
|
-
require_relative '../../test__helper'
|
26
|
-
require_relative '../../fake_home'
|
27
|
-
require_relative '../../node/fake_node'
|
28
|
-
require_relative '../../../lib/zold/node/farm.rb'
|
29
|
-
require_relative '../../../lib/zold/commands/push'
|
30
|
-
require_relative '../../../lib/zold/commands/pay'
|
31
|
-
require_relative '../../../lib/zold/commands/routines/bonuses.rb'
|
32
|
-
|
33
|
-
# Bonuses test.
|
34
|
-
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
35
|
-
# Copyright:: Copyright (c) 2018 Yegor Bugayenko
|
36
|
-
# License:: MIT
|
37
|
-
class TestBonuses < Minitest::Test
|
38
|
-
def test_pays_bonuses
|
39
|
-
FakeHome.new.run do |home|
|
40
|
-
FakeNode.new(log: test_log).run(['--ignore-score-weakness']) do |port|
|
41
|
-
bank = home.create_wallet
|
42
|
-
Zold::Pay.new(wallets: home.wallets, remotes: home.remotes, log: test_log).run(
|
43
|
-
['pay', home.create_wallet.id.to_s, bank.id.to_s, '100', '--force', '--private-key=id_rsa']
|
44
|
-
)
|
45
|
-
assert_equal(Zold::Amount.new(zld: 100.0), bank.balance)
|
46
|
-
opts = {
|
47
|
-
'ignore-score-weakness' => true,
|
48
|
-
'routine-immediately' => true,
|
49
|
-
'private-key' => 'id_rsa',
|
50
|
-
'bonus-wallet' => bank.id.to_s,
|
51
|
-
'bonus-amount' => 1,
|
52
|
-
'bonus-time' => 0
|
53
|
-
}
|
54
|
-
score = Zold::Score.new(
|
55
|
-
time: Time.now, host: 'fake-node.local', port: 999, invoice: 'NOPREFIX@ffffffffffffffff', strength: 1
|
56
|
-
)
|
57
|
-
16.times { score = score.next }
|
58
|
-
remotes = home.remotes
|
59
|
-
remotes.add('localhost', port)
|
60
|
-
remotes.add(score.host, score.port)
|
61
|
-
stub_request(:get, "http://#{score.host}:#{score.port}/").to_return(
|
62
|
-
status: 200,
|
63
|
-
body: {
|
64
|
-
version: Zold::VERSION,
|
65
|
-
score: score.to_h
|
66
|
-
}.to_json
|
67
|
-
)
|
68
|
-
Zold::Routines::Bonuses.new(
|
69
|
-
opts, home.wallets, remotes, home.copies(bank).root,
|
70
|
-
Zold::Farm::Empty.new, log: test_log
|
71
|
-
).exec
|
72
|
-
assert_equal(Zold::Amount.new(zld: 99.0), bank.balance)
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|