zold 0.14.13 → 0.14.14
Sign up to get free protection for your applications and to get access to all the features.
- 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
|