zold 0.16.20 → 0.16.21
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/README.md +6 -0
- data/bin/zold +1 -1
- data/fixtures/scripts/_head.sh +1 -1
- data/fixtures/scripts/distribute-wallet.sh +7 -7
- data/fixtures/scripts/pull-on-start.sh +4 -4
- data/fixtures/scripts/push-and-pull.sh +2 -2
- data/fixtures/scripts/redeploy-on-upgrade.sh +2 -2
- data/fixtures/scripts/spread-wallets.sh +6 -6
- data/lib/zold/amount.rb +9 -8
- data/lib/zold/commands/node.rb +3 -3
- data/lib/zold/commands/routines/reconnect.rb +1 -1
- data/lib/zold/http.rb +13 -16
- data/lib/zold/id.rb +5 -1
- data/lib/zold/log.rb +5 -4
- data/lib/zold/node/front.rb +12 -5
- data/lib/zold/remotes.rb +9 -8
- data/lib/zold/tax.rb +10 -9
- data/lib/zold/txn.rb +19 -14
- data/lib/zold/version.rb +1 -1
- data/test/commands/test_taxes.rb +1 -1
- data/test/node/test_farm.rb +1 -1
- data/test/node/test_front.rb +16 -0
- data/test/test_http.rb +26 -14
- data/zold.gemspec +3 -2
- metadata +20 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f9ed770c6f66e7627f1c23329a2ad5723c1d9ea8dd714db3341fcb48645597c9
|
4
|
+
data.tar.gz: 4055ca5daecab2762c3155406c597550188223e2358b1908dd5ed8240a4159a4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7ebc0ae599f38f53b31fd85b30e5beb2cb97c517dff0bd4a1ddb01b3d9e4b2138ed3fa8dfdf0ec741309ba0ed0eabe95b23703d985b48870c5b305ea1966fe7f
|
7
|
+
data.tar.gz: 7fb53797974d1af0adbfa2a19d99fc6e8c31e70c326c4a4b24b231d61fad6cd58c6d6a43b574d4b6efebec3f65eb1940f72a7db3c457a31f0ce84683a3d481e0
|
data/README.md
CHANGED
@@ -121,6 +121,12 @@ Grateful users of the system will pay "taxes" to your wallet
|
|
121
121
|
for the maintenance of their wallets, and the system will occasionally
|
122
122
|
send you bonuses for keeping the node online (approximately 1 ZLD per day).
|
123
123
|
|
124
|
+
If you are lost, run this:
|
125
|
+
|
126
|
+
```bash
|
127
|
+
$ zold node --help
|
128
|
+
```
|
129
|
+
|
124
130
|
## Frequently Asked Questions
|
125
131
|
|
126
132
|
> Where are my RSA private/public keys?
|
data/bin/zold
CHANGED
@@ -105,7 +105,7 @@ Available options:"
|
|
105
105
|
"Home directory (default: #{Dir.pwd})",
|
106
106
|
default: Dir.pwd
|
107
107
|
o.string '--network',
|
108
|
-
"The name of the network we work in (default: #{Zold::Wallet::MAIN_NETWORK}",
|
108
|
+
"The name of the network we work in (default: #{Zold::Wallet::MAIN_NETWORK})",
|
109
109
|
required: true,
|
110
110
|
default: Zold::Wallet::MAIN_NETWORK
|
111
111
|
o.bool '-h', '--help', 'Show these instructions'
|
data/fixtures/scripts/_head.sh
CHANGED
@@ -49,7 +49,7 @@ function wait_for_file {
|
|
49
49
|
|
50
50
|
function halt_nodes {
|
51
51
|
for p in "$@"; do
|
52
|
-
pid=$(curl --silent "http://
|
52
|
+
pid=$(curl --silent "http://127.0.0.1:$p/pid?halt=test" || echo 'absent')
|
53
53
|
if [[ "${pid}" =~ ^[0-9]+$ ]]; then
|
54
54
|
i=0
|
55
55
|
while kill -0 ${pid}; do
|
@@ -5,12 +5,12 @@ function start_node {
|
|
5
5
|
mkdir ${port}
|
6
6
|
cd ${port}
|
7
7
|
zold node --trace --invoice=DISTRWALLET@ffffffffffffffff \
|
8
|
-
--host=
|
8
|
+
--host=127.0.0.1 --port=${port} --bind-port=${port} \
|
9
9
|
--threads=0 --routine-immediately --never-reboot > log.txt &
|
10
10
|
pid=$!
|
11
11
|
echo ${pid} > pid
|
12
12
|
cd ..
|
13
|
-
wait_for_url http://
|
13
|
+
wait_for_url http://127.0.0.1:${port}/
|
14
14
|
echo ${port}
|
15
15
|
}
|
16
16
|
|
@@ -24,9 +24,9 @@ trap "halt_nodes ${first} ${second}" EXIT
|
|
24
24
|
# is linked to the first one. The --home argument specifies their
|
25
25
|
# locations.
|
26
26
|
zold --home=${first} remote clean
|
27
|
-
zold --home=${first} remote add
|
27
|
+
zold --home=${first} remote add 127.0.0.1 ${second}
|
28
28
|
zold --home=${second} remote clean
|
29
|
-
zold --home=${second} remote add
|
29
|
+
zold --home=${second} remote add 127.0.0.1 ${first}
|
30
30
|
|
31
31
|
# Locally we create a new root wallet (to avoid negative balance checking)
|
32
32
|
# and connect our local Zold home to the first remote node. Then, we push
|
@@ -35,10 +35,10 @@ zold --home=${second} remote add localhost ${first}
|
|
35
35
|
zold --public-key=id_rsa.pub create 0000000000000000
|
36
36
|
zold pay --private-key=id_rsa 0000000000000000 NOPREFIX@aaaabbbbccccdddd 4.95 'For the book'
|
37
37
|
zold remote clean
|
38
|
-
zold remote add
|
38
|
+
zold remote add 127.0.0.1 ${first}
|
39
39
|
zold push 0000000000000000
|
40
40
|
zold remote clean
|
41
|
-
zold remote add
|
41
|
+
zold remote add 127.0.0.1 ${second}
|
42
42
|
|
43
43
|
# Here we fetch the wallet from the second remote node. The wallet has
|
44
44
|
# to be visible there. We are doing a number of attempts with a small
|
@@ -58,7 +58,7 @@ done
|
|
58
58
|
|
59
59
|
# Here we check the JSON of the first node to make sure all status
|
60
60
|
# indicators are clean.
|
61
|
-
json=$(curl --silent --show-error http://
|
61
|
+
json=$(curl --silent --show-error http://127.0.0.1:${first})
|
62
62
|
if [ ! $(echo ${json} | jq -r '.entrance.queue') == "0" ]; then
|
63
63
|
echo "The queue is not empty after PUSH, it's a bug"
|
64
64
|
exit 5
|
@@ -4,14 +4,14 @@ port=$(reserve_port)
|
|
4
4
|
mkdir server
|
5
5
|
cd server
|
6
6
|
zold node --trace --invoice=PULLONSTART@ffffffffffffffff --no-metronome \
|
7
|
-
--host=
|
7
|
+
--host=127.0.0.1 --port=${port} --bind-port=${port} \
|
8
8
|
--threads=0 --standalone &
|
9
9
|
cd ..
|
10
10
|
|
11
11
|
wait_for_port ${port}
|
12
12
|
|
13
13
|
zold remote clean
|
14
|
-
zold remote add
|
14
|
+
zold remote add 127.0.0.1 ${port}
|
15
15
|
|
16
16
|
zold --public-key=id_rsa.pub create abcdabcdabcdabcd
|
17
17
|
zold push abcdabcdabcdabcd
|
@@ -22,9 +22,9 @@ second_port=$(reserve_port)
|
|
22
22
|
mkdir second
|
23
23
|
cd second
|
24
24
|
zold remote clean
|
25
|
-
zold remote add
|
25
|
+
zold remote add 127.0.0.1 ${port}
|
26
26
|
zold node --trace --invoice=abcdabcdabcdabcd --no-metronome \
|
27
|
-
--host=
|
27
|
+
--host=127.0.0.1 --port=${second_port} --bind-port=${second_port} \
|
28
28
|
--threads=0 &
|
29
29
|
|
30
30
|
wait_for_port ${second_port}
|
@@ -5,7 +5,7 @@ port=$(reserve_port)
|
|
5
5
|
mkdir server
|
6
6
|
cd server
|
7
7
|
zold node --trace --invoice=PUSHNPULL@ffffffffffffffff \
|
8
|
-
--host=
|
8
|
+
--host=127.0.0.1 --port=${port} --bind-port=${port} \
|
9
9
|
--threads=0 --standalone &
|
10
10
|
pid=$!
|
11
11
|
trap "halt_nodes ${port}" EXIT
|
@@ -14,7 +14,7 @@ cd ..
|
|
14
14
|
wait_for_port ${port}
|
15
15
|
|
16
16
|
zold remote clean
|
17
|
-
zold remote add
|
17
|
+
zold remote add 127.0.0.1 ${port}
|
18
18
|
zold remote trim
|
19
19
|
zold remote show
|
20
20
|
|
@@ -7,7 +7,7 @@ function start_node {
|
|
7
7
|
zold node $3 --nohup --nohup-command='touch restarted' --nohup-log=log --nohup-max-cycles=0 --nohup-log-truncate=10240 \
|
8
8
|
--expose-version=$2 --save-pid=pid --routine-immediately \
|
9
9
|
--verbose --trace --invoice=REDEPLOY@ffffffffffffffff \
|
10
|
-
--host=
|
10
|
+
--host=127.0.0.1 --port=$1 --bind-port=$1 --threads=1 --strength=20 > /dev/null 2>&1
|
11
11
|
wait_for_port $1
|
12
12
|
cat pid
|
13
13
|
cd ..
|
@@ -20,7 +20,7 @@ low=$(reserve_port)
|
|
20
20
|
secondary=$(start_node ${low} 1.1.1)
|
21
21
|
|
22
22
|
zold remote clean
|
23
|
-
zold remote add
|
23
|
+
zold remote add 127.0.0.1 ${high} --home=${low} --skip-ping
|
24
24
|
|
25
25
|
trap "halt_nodes ${high}" EXIT
|
26
26
|
|
@@ -5,7 +5,7 @@ function start_node {
|
|
5
5
|
mkdir ${port}
|
6
6
|
cd ${port}
|
7
7
|
zold node --trace --invoice=SPREADWALLETS@ffffffffffffffff \
|
8
|
-
--host=
|
8
|
+
--host=127.0.0.1 --port=${port} --bind-port=${port} \
|
9
9
|
--threads=0 > log.txt &
|
10
10
|
pid=$!
|
11
11
|
echo ${pid} > pid
|
@@ -19,16 +19,16 @@ second=$(start_node)
|
|
19
19
|
trap "halt_nodes ${first} ${second}" EXIT
|
20
20
|
|
21
21
|
zold --home=${first} remote clean
|
22
|
-
zold --home=${first} remote add
|
22
|
+
zold --home=${first} remote add 127.0.0.1 ${second}
|
23
23
|
zold --home=${second} remote clean
|
24
|
-
zold --home=${second} remote add
|
24
|
+
zold --home=${second} remote add 127.0.0.1 ${first}
|
25
25
|
|
26
26
|
zold --public-key=id_rsa.pub create 0000000000000000
|
27
27
|
zold pay --private-key=id_rsa 0000000000000000 NOPREFIX@aaaabbbbccccdddd 4.95 'To help you, dude!'
|
28
|
-
zold remote add
|
28
|
+
zold remote add 127.0.0.1 ${first}
|
29
29
|
zold push 0000000000000000
|
30
30
|
zold remote clean
|
31
|
-
zold remote add
|
31
|
+
zold remote add 127.0.0.1 ${second}
|
32
32
|
|
33
33
|
i=0
|
34
34
|
until zold fetch 0000000000000000 --ignore-score-weakness; do
|
@@ -42,7 +42,7 @@ until zold fetch 0000000000000000 --ignore-score-weakness; do
|
|
42
42
|
sleep 2
|
43
43
|
done
|
44
44
|
|
45
|
-
json=$(curl --silent --show-error http://
|
45
|
+
json=$(curl --silent --show-error http://127.0.0.1:${first})
|
46
46
|
if [ ! $(echo ${json} | jq -r '.entrance.queue') == "0" ]; then
|
47
47
|
echo "The queue is not empty after PUSH, it's a bug"
|
48
48
|
exit -1
|
data/lib/zold/amount.rb
CHANGED
@@ -29,24 +29,25 @@ require 'rainbow'
|
|
29
29
|
module Zold
|
30
30
|
# Amount
|
31
31
|
class Amount
|
32
|
-
# How many zents are in one ZLD: 2^FRACTION
|
33
|
-
FRACTION = 32
|
34
|
-
|
35
32
|
# Maximum amount of zents
|
36
33
|
MAX = 2**63
|
37
34
|
|
35
|
+
# How many zents are in one ZLD: 2^FRACTION
|
36
|
+
FRACTION = 32
|
37
|
+
private_constant :FRACTION
|
38
|
+
|
38
39
|
def initialize(zents: nil, zld: nil)
|
39
40
|
if !zents.nil?
|
40
41
|
raise "Integer is required, while #{zents.class} provided: #{zents}" unless zents.is_a?(Integer)
|
41
42
|
@zents = zents
|
42
43
|
elsif !zld.nil?
|
43
44
|
raise "Float is required, while #{zld.class} provided: #{zld}" unless zld.is_a?(Float)
|
44
|
-
@zents = (zld * 2**
|
45
|
+
@zents = (zld * 2**FRACTION).to_i
|
45
46
|
else
|
46
47
|
raise 'You can\'t specify both coints and zld'
|
47
48
|
end
|
48
|
-
raise "The amount is too big: #{@zents}" if @zents >
|
49
|
-
raise "The amount is too small: #{@zents}" if @zents < -
|
49
|
+
raise "The amount is too big: #{@zents}" if @zents > MAX
|
50
|
+
raise "The amount is too small: #{@zents}" if @zents < -MAX
|
50
51
|
end
|
51
52
|
|
52
53
|
ZERO = Amount.new(zents: 0)
|
@@ -56,7 +57,7 @@ module Zold
|
|
56
57
|
end
|
57
58
|
|
58
59
|
def to_zld(digits = 2)
|
59
|
-
format("%0.#{digits}f", @zents.to_f / 2**
|
60
|
+
format("%0.#{digits}f", @zents.to_f / 2**FRACTION)
|
60
61
|
end
|
61
62
|
|
62
63
|
def to_s
|
@@ -120,7 +121,7 @@ module Zold
|
|
120
121
|
def *(other)
|
121
122
|
raise '* may only work with a number' unless other.is_a?(Integer) || other.is_a?(Float)
|
122
123
|
c = (@zents * other).to_i
|
123
|
-
raise "Overflow, can't multiply #{@zents} by #{m}" if c >
|
124
|
+
raise "Overflow, can't multiply #{@zents} by #{m}" if c > MAX
|
124
125
|
Amount.new(zents: c)
|
125
126
|
end
|
126
127
|
|
data/lib/zold/commands/node.rb
CHANGED
@@ -172,9 +172,9 @@ module Zold
|
|
172
172
|
Front.set(:logging, @log.debug?)
|
173
173
|
home = File.expand_path(opts['home'])
|
174
174
|
Front.set(:home, home)
|
175
|
-
@log.info("Time: #{Time.now.utc.iso8601}")
|
175
|
+
@log.info("Time: #{Time.now.utc.iso8601}; CPUs: #{Concurrent.processor_count}")
|
176
176
|
@log.info("Home directory: #{home}")
|
177
|
-
@log.info("Ruby version: #{RUBY_VERSION}")
|
177
|
+
@log.info("Ruby version: #{RUBY_VERSION}/#{RUBY_PLATFORM}")
|
178
178
|
@log.info("Zold gem version: #{Zold::VERSION}")
|
179
179
|
@log.info("Zold protocol version: #{Zold::PROTOCOL}")
|
180
180
|
@log.info("Network ID: #{opts['network']}")
|
@@ -182,7 +182,7 @@ module Zold
|
|
182
182
|
port = opts[:port]
|
183
183
|
address = "#{host}:#{port}".downcase
|
184
184
|
@log.info("Node location: #{address}")
|
185
|
-
@log.info("Local address: http://
|
185
|
+
@log.info("Local address: http://127.0.0.1:#{opts['bind-port']}/")
|
186
186
|
@log.info("Remote nodes (#{@remotes.all.count}): \
|
187
187
|
#{@remotes.all.map { |r| "#{r[:host]}:#{r[:port]}" }.join(', ')}")
|
188
188
|
@log.info("Wallets at: #{@wallets.path}")
|
@@ -48,9 +48,9 @@ module Zold
|
|
48
48
|
args << "--ignore-node=#{score.host}:#{score.port}" if score
|
49
49
|
cmd.run(args + ['defaults']) unless @opts['routine-immediately']
|
50
50
|
return if @opts['routine-immediately'] && @remotes.all.empty?
|
51
|
+
cmd.run(args + ['update'] + (@opts['never-reboot'] ? [] : ['--reboot']))
|
51
52
|
cmd.run(args + ['trim'])
|
52
53
|
cmd.run(args + ['select'])
|
53
|
-
cmd.run(args + ['update'] + (@opts['never-reboot'] ? [] : ['--reboot']))
|
54
54
|
@log.info("Reconnected, there are #{@remotes.all.count} remote notes: \
|
55
55
|
#{@remotes.all.map { |r| "#{r[:host]}:#{r[:port]}" }.join(', ')}")
|
56
56
|
end
|
data/lib/zold/http.rb
CHANGED
@@ -22,7 +22,6 @@
|
|
22
22
|
|
23
23
|
require 'rainbow'
|
24
24
|
require 'uri'
|
25
|
-
require 'timeout'
|
26
25
|
require 'net/http'
|
27
26
|
require 'backtrace'
|
28
27
|
require 'zold/score'
|
@@ -56,9 +55,11 @@ module Zold
|
|
56
55
|
|
57
56
|
# Read timeout in seconds
|
58
57
|
READ_TIMEOUT = 1
|
58
|
+
private_constant :READ_TIMEOUT
|
59
59
|
|
60
60
|
# Connect timeout in seconds
|
61
61
|
CONNECT_TIMEOUT = 0.4
|
62
|
+
private_constant :CONNECT_TIMEOUT
|
62
63
|
|
63
64
|
def initialize(uri:, score: Score::ZERO, network: 'test')
|
64
65
|
@uri = uri.is_a?(URI) ? uri : URI(uri)
|
@@ -66,36 +67,32 @@ module Zold
|
|
66
67
|
@network = network
|
67
68
|
end
|
68
69
|
|
69
|
-
def get(timeout:
|
70
|
+
def get(timeout: READ_TIMEOUT + CONNECT_TIMEOUT)
|
70
71
|
http = Net::HTTP.new(@uri.host, @uri.port)
|
71
72
|
http.use_ssl = @uri.scheme == 'https'
|
72
73
|
http.read_timeout = timeout
|
73
|
-
http.open_timeout =
|
74
|
+
http.open_timeout = CONNECT_TIMEOUT
|
74
75
|
path = @uri.path
|
75
76
|
path += '?' + @uri.query if @uri.query
|
76
|
-
|
77
|
-
http.request_get(path, headers)
|
78
|
-
end
|
77
|
+
http.request_get(path, headers)
|
79
78
|
rescue StandardError => e
|
80
79
|
Error.new(e)
|
81
80
|
end
|
82
81
|
|
83
|
-
def put(body, timeout:
|
82
|
+
def put(body, timeout: READ_TIMEOUT + CONNECT_TIMEOUT)
|
84
83
|
http = Net::HTTP.new(@uri.host, @uri.port)
|
85
84
|
http.use_ssl = @uri.scheme == 'https'
|
86
85
|
http.read_timeout = timeout
|
87
|
-
http.open_timeout =
|
86
|
+
http.open_timeout = CONNECT_TIMEOUT
|
88
87
|
path = @uri.path
|
89
88
|
path += '?' + @uri.query if @uri.query
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
'Content-Length': body.length.to_s
|
96
|
-
)
|
89
|
+
http.request_put(
|
90
|
+
path, body,
|
91
|
+
headers.merge(
|
92
|
+
'Content-Type': 'text/plain',
|
93
|
+
'Content-Length': body.length.to_s
|
97
94
|
)
|
98
|
-
|
95
|
+
)
|
99
96
|
rescue StandardError => e
|
100
97
|
Error.new(e)
|
101
98
|
end
|
data/lib/zold/id.rb
CHANGED
@@ -27,12 +27,16 @@
|
|
27
27
|
module Zold
|
28
28
|
# Id of the wallet
|
29
29
|
class Id
|
30
|
+
# Pattern to match the ID
|
31
|
+
PTN = Regexp.new('^[0-9a-fA-F]{16}$')
|
32
|
+
private_constant :PTN
|
33
|
+
|
30
34
|
def initialize(id = nil)
|
31
35
|
if id.nil?
|
32
36
|
@id = rand(2**32..2**64 - 1)
|
33
37
|
else
|
34
38
|
raise "Invalid wallet ID type: #{id.class.name}" unless id.is_a?(String)
|
35
|
-
raise "Invalid wallet ID: #{id}" unless id =~
|
39
|
+
raise "Invalid wallet ID: #{id}" unless id =~ PTN
|
36
40
|
@id = Integer("0x#{id}", 16)
|
37
41
|
end
|
38
42
|
end
|
data/lib/zold/log.rb
CHANGED
@@ -21,6 +21,7 @@
|
|
21
21
|
# SOFTWARE.
|
22
22
|
|
23
23
|
require 'rainbow'
|
24
|
+
require 'monitor'
|
24
25
|
|
25
26
|
STDOUT.sync = true
|
26
27
|
|
@@ -50,12 +51,12 @@ module Zold
|
|
50
51
|
class Sync
|
51
52
|
def initialize(log)
|
52
53
|
@log = log
|
53
|
-
@
|
54
|
+
@monitor = Monitor.new
|
54
55
|
end
|
55
56
|
|
56
57
|
def debug(msg)
|
57
58
|
return unless debug?
|
58
|
-
@
|
59
|
+
@monitor.synchronize do
|
59
60
|
@log.debug(msg)
|
60
61
|
end
|
61
62
|
end
|
@@ -66,7 +67,7 @@ module Zold
|
|
66
67
|
|
67
68
|
def info(msg)
|
68
69
|
return unless info?
|
69
|
-
@
|
70
|
+
@monitor.synchronize do
|
70
71
|
@log.info(msg)
|
71
72
|
end
|
72
73
|
end
|
@@ -76,7 +77,7 @@ module Zold
|
|
76
77
|
end
|
77
78
|
|
78
79
|
def error(msg)
|
79
|
-
@
|
80
|
+
@monitor.synchronize do
|
80
81
|
@log.error(msg)
|
81
82
|
end
|
82
83
|
end
|
data/lib/zold/node/front.rb
CHANGED
@@ -185,7 +185,7 @@ in #{Age.new(@start, limit: 1)}")
|
|
185
185
|
|
186
186
|
get '/' do
|
187
187
|
content_type('application/json')
|
188
|
-
|
188
|
+
pretty(
|
189
189
|
version: settings.opts['expose-version'],
|
190
190
|
alias: settings.node_alias,
|
191
191
|
network: settings.opts['network'],
|
@@ -222,7 +222,7 @@ in #{Age.new(@start, limit: 1)}")
|
|
222
222
|
id = Id.new(params[:id])
|
223
223
|
copy_of(id) do |wallet|
|
224
224
|
content_type('application/json')
|
225
|
-
|
225
|
+
pretty(
|
226
226
|
version: settings.opts['expose-version'],
|
227
227
|
alias: settings.node_alias,
|
228
228
|
protocol: settings.protocol,
|
@@ -244,7 +244,7 @@ in #{Age.new(@start, limit: 1)}")
|
|
244
244
|
id = Id.new(params[:id])
|
245
245
|
copy_of(id) do |wallet|
|
246
246
|
content_type('application/json')
|
247
|
-
|
247
|
+
pretty(
|
248
248
|
version: settings.opts['expose-version'],
|
249
249
|
alias: settings.node_alias,
|
250
250
|
protocol: settings.protocol,
|
@@ -367,7 +367,7 @@ in #{Age.new(@start, limit: 1)}")
|
|
367
367
|
status(304)
|
368
368
|
return
|
369
369
|
end
|
370
|
-
|
370
|
+
pretty(
|
371
371
|
version: settings.opts['expose-version'],
|
372
372
|
alias: settings.node_alias,
|
373
373
|
score: score.to_h,
|
@@ -377,7 +377,7 @@ in #{Age.new(@start, limit: 1)}")
|
|
377
377
|
|
378
378
|
get '/remotes' do
|
379
379
|
content_type('application/json')
|
380
|
-
|
380
|
+
pretty(
|
381
381
|
version: settings.opts['expose-version'],
|
382
382
|
alias: settings.node_alias,
|
383
383
|
score: score.to_h,
|
@@ -470,6 +470,13 @@ in #{Age.new(@start, limit: 1)}")
|
|
470
470
|
POSIX::Spawn::Child.new('ps', 'ax').out.split("\n").select { |t| t.include?('zold') }
|
471
471
|
end
|
472
472
|
|
473
|
+
def pretty(json)
|
474
|
+
json.to_json
|
475
|
+
# There seems to be some issue with memory leakage at this line, that's
|
476
|
+
# why it's disabled for now:
|
477
|
+
# JSON.pretty_generate(json)
|
478
|
+
end
|
479
|
+
|
473
480
|
def score
|
474
481
|
settings.zache.get(:score, lifetime: settings.opts['network'] == Wallet::MAIN_NETWORK ? 60 : 0) do
|
475
482
|
b = settings.farm.best
|
data/lib/zold/remotes.rb
CHANGED
@@ -51,6 +51,7 @@ module Zold
|
|
51
51
|
|
52
52
|
# Default nodes and their ports
|
53
53
|
DEFS = CSV.read(File.expand_path(File.join(File.dirname(__FILE__), '../../resources/remotes')))
|
54
|
+
private_constant :DEFS
|
54
55
|
|
55
56
|
# Empty, for standalone mode
|
56
57
|
class Empty
|
@@ -119,7 +120,7 @@ module Zold
|
|
119
120
|
end
|
120
121
|
end
|
121
122
|
|
122
|
-
def initialize(file:, network: 'test', timeout:
|
123
|
+
def initialize(file:, network: 'test', timeout: 60)
|
123
124
|
@file = file
|
124
125
|
@network = network
|
125
126
|
@timeout = timeout
|
@@ -141,19 +142,19 @@ module Zold
|
|
141
142
|
end
|
142
143
|
|
143
144
|
def defaults
|
144
|
-
|
145
|
+
DEFS.each do |r|
|
145
146
|
add(r[0], r[1].to_i)
|
146
147
|
end
|
147
148
|
end
|
148
149
|
|
149
|
-
def exists?(host, port =
|
150
|
+
def exists?(host, port = PORT)
|
150
151
|
raise 'Port has to be of type Integer' unless port.is_a?(Integer)
|
151
152
|
raise 'Host can\'t be nil' if host.nil?
|
152
153
|
raise 'Port can\'t be nil' if port.nil?
|
153
154
|
!load.find { |r| r[:host] == host.downcase && r[:port] == port }.nil?
|
154
155
|
end
|
155
156
|
|
156
|
-
def add(host, port =
|
157
|
+
def add(host, port = PORT)
|
157
158
|
raise 'Host can\'t be nil' if host.nil?
|
158
159
|
raise 'Host can\'t be empty' if host.empty?
|
159
160
|
raise 'Port can\'t be nil' if port.nil?
|
@@ -166,7 +167,7 @@ module Zold
|
|
166
167
|
end
|
167
168
|
end
|
168
169
|
|
169
|
-
def remove(host, port =
|
170
|
+
def remove(host, port = PORT)
|
170
171
|
raise 'Port has to be of type Integer' unless port.is_a?(Integer)
|
171
172
|
raise 'Host can\'t be nil' if host.nil?
|
172
173
|
raise 'Port can\'t be nil' if port.nil?
|
@@ -203,7 +204,7 @@ module Zold
|
|
203
204
|
error(r[:host], r[:port])
|
204
205
|
log.info("#{Rainbow("#{r[:host]}:#{r[:port]}").red}: #{e.message} in #{Age.new(start)}")
|
205
206
|
log.debug(Backtrace.new(e).to_s)
|
206
|
-
remove(r[:host], r[:port]) if errors >
|
207
|
+
remove(r[:host], r[:port]) if errors > TOLERANCE
|
207
208
|
end
|
208
209
|
end
|
209
210
|
idx += 1
|
@@ -212,7 +213,7 @@ module Zold
|
|
212
213
|
pool.kill unless pool.wait_for_termination(5 * 60)
|
213
214
|
end
|
214
215
|
|
215
|
-
def error(host, port =
|
216
|
+
def error(host, port = PORT)
|
216
217
|
raise 'Host can\'t be nil' if host.nil?
|
217
218
|
raise 'Port can\'t be nil' if port.nil?
|
218
219
|
raise 'Port has to be of type Integer' unless port.is_a?(Integer)
|
@@ -232,7 +233,7 @@ module Zold
|
|
232
233
|
end
|
233
234
|
|
234
235
|
def default?(host, port)
|
235
|
-
!
|
236
|
+
!DEFS.find { |r| r[0] == host && r[1].to_i == port }.nil?
|
236
237
|
end
|
237
238
|
|
238
239
|
private
|
data/lib/zold/tax.rb
CHANGED
@@ -55,6 +55,7 @@ module Zold
|
|
55
55
|
|
56
56
|
# Text prefix for taxes details
|
57
57
|
PREFIX = 'TAXES'
|
58
|
+
private_constant :PREFIX
|
58
59
|
|
59
60
|
def initialize(wallet, ignore_score_weakness: false)
|
60
61
|
raise "The wallet must be of type Wallet: #{wallet.class.name}" unless wallet.is_a?(Wallet)
|
@@ -64,38 +65,38 @@ module Zold
|
|
64
65
|
|
65
66
|
# Check whether this tax payment already exists in the wallet.
|
66
67
|
def exists?(details)
|
67
|
-
!@wallet.txns.find { |t| t.details.start_with?("#{
|
68
|
+
!@wallet.txns.find { |t| t.details.start_with?("#{PREFIX} ") && t.details == details }.nil?
|
68
69
|
end
|
69
70
|
|
70
71
|
def details(best)
|
71
|
-
"#{
|
72
|
+
"#{PREFIX} #{best.reduced(EXACT_SCORE).to_text}"
|
72
73
|
end
|
73
74
|
|
74
75
|
def pay(pvt, best)
|
75
|
-
@wallet.sub([
|
76
|
+
@wallet.sub([MAX_PAYMENT, debt].min, best.invoice, pvt, details(best))
|
76
77
|
end
|
77
78
|
|
78
79
|
def in_debt?
|
79
|
-
debt >
|
80
|
+
debt > TRIAL
|
80
81
|
end
|
81
82
|
|
82
83
|
def to_text
|
83
|
-
"A=#{@wallet.age.round} hours, F=#{
|
84
|
+
"A=#{@wallet.age.round} hours, F=#{FEE.to_i}z/th, T=#{@wallet.txns.count}t, Paid=#{paid}"
|
84
85
|
end
|
85
86
|
|
86
87
|
def debt
|
87
|
-
|
88
|
+
FEE * @wallet.txns.count * @wallet.age - paid
|
88
89
|
end
|
89
90
|
|
90
91
|
def paid
|
91
92
|
txns = @wallet.txns
|
92
93
|
scored = txns.map do |t|
|
93
94
|
pfx, body = t.details.split(' ', 2)
|
94
|
-
next if pfx !=
|
95
|
+
next if pfx != PREFIX || body.nil?
|
95
96
|
score = Score.parse_text(body)
|
96
|
-
next if !score.valid? || score.value !=
|
97
|
+
next if !score.valid? || score.value != EXACT_SCORE
|
97
98
|
next if score.strength < Score::STRENGTH && !@ignore_score_weakness
|
98
|
-
next if t.amount >
|
99
|
+
next if t.amount > MAX_PAYMENT
|
99
100
|
t
|
100
101
|
end.compact.uniq(&:details)
|
101
102
|
scored.empty? ? Amount::ZERO : scored.map(&:amount).inject(&:+) * -1
|
data/lib/zold/txn.rb
CHANGED
@@ -36,9 +36,11 @@ module Zold
|
|
36
36
|
class Txn
|
37
37
|
# Regular expression for details
|
38
38
|
RE_DETAILS = '[a-zA-Z0-9 @\!\?\*_\-\.:,\']+'
|
39
|
+
private_constant :RE_DETAILS
|
39
40
|
|
40
41
|
# Regular expression for prefix
|
41
42
|
RE_PREFIX = '[a-zA-Z0-9]+'
|
43
|
+
private_constant :RE_PREFIX
|
42
44
|
|
43
45
|
attr_reader :id, :date, :amount, :prefix, :bnf, :details, :sign
|
44
46
|
attr_writer :sign, :amount, :bnf
|
@@ -60,12 +62,12 @@ module Zold
|
|
60
62
|
raise 'Prefix can\'t be NIL' if prefix.nil?
|
61
63
|
raise "Prefix is too short: \"#{prefix}\"" if prefix.length < 8
|
62
64
|
raise "Prefix is too long: \"#{prefix}\"" if prefix.length > 32
|
63
|
-
raise "Prefix is wrong: \"#{prefix}\" (#{
|
65
|
+
raise "Prefix is wrong: \"#{prefix}\" (#{RE_PREFIX})" unless prefix =~ Regexp.new("^#{RE_PREFIX}$")
|
64
66
|
@prefix = prefix
|
65
67
|
raise 'Details can\'t be NIL' if details.nil?
|
66
68
|
raise 'Details can\'t be empty' if details.empty?
|
67
69
|
raise "Details are too long: \"#{details}\"" if details.length > 512
|
68
|
-
raise "Wrong details \"#{details}\" (#{
|
70
|
+
raise "Wrong details \"#{details}\" (#{RE_DETAILS})" unless details =~ Regexp.new("^#{RE_DETAILS}$")
|
69
71
|
@details = details
|
70
72
|
end
|
71
73
|
|
@@ -115,20 +117,23 @@ module Zold
|
|
115
117
|
t
|
116
118
|
end
|
117
119
|
|
120
|
+
# Pattern to match the transaction from text
|
121
|
+
PTN = Regexp.new(
|
122
|
+
'^' + [
|
123
|
+
'(?<id>[0-9a-f]{4})',
|
124
|
+
'(?<date>[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z)',
|
125
|
+
'(?<amount>[0-9a-f]{16})',
|
126
|
+
"(?<prefix>#{RE_PREFIX})",
|
127
|
+
'(?<bnf>[0-9a-f]{16})',
|
128
|
+
"(?<details>#{RE_DETAILS})",
|
129
|
+
'(?<sign>[A-Za-z0-9+/]+={0,3})?'
|
130
|
+
].join(';') + '$'
|
131
|
+
)
|
132
|
+
private_constant :PTN
|
133
|
+
|
118
134
|
def self.parse(line, idx = 0)
|
119
|
-
regex = Regexp.new(
|
120
|
-
'^' + [
|
121
|
-
'(?<id>[0-9a-f]{4})',
|
122
|
-
'(?<date>[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z)',
|
123
|
-
'(?<amount>[0-9a-f]{16})',
|
124
|
-
"(?<prefix>#{Txn::RE_PREFIX})",
|
125
|
-
'(?<bnf>[0-9a-f]{16})',
|
126
|
-
"(?<details>#{Txn::RE_DETAILS})",
|
127
|
-
'(?<sign>[A-Za-z0-9+/]+={0,3})?'
|
128
|
-
].join(';') + '$'
|
129
|
-
)
|
130
135
|
clean = line.strip
|
131
|
-
parts =
|
136
|
+
parts = PTN.match(clean)
|
132
137
|
raise "Invalid line ##{idx}: #{line.inspect} #{regex}" unless parts
|
133
138
|
txn = Txn.new(
|
134
139
|
Hexnum.parse(parts[:id]).to_i,
|
data/lib/zold/version.rb
CHANGED
data/test/commands/test_taxes.rb
CHANGED
@@ -54,7 +54,7 @@ class TestTaxes < Zold::Test
|
|
54
54
|
end
|
55
55
|
remotes = home.remotes
|
56
56
|
score = Zold::Score.new(host: 'localhost', port: 80, strength: 1, invoice: 'NOPREFIX@0000000000000000')
|
57
|
-
|
57
|
+
10.times { score = score.next }
|
58
58
|
remotes.add(score.host, score.port)
|
59
59
|
stub_request(:get, "http://#{score.host}:#{score.port}/").to_return(
|
60
60
|
status: 200,
|
data/test/node/test_farm.rb
CHANGED
@@ -164,7 +164,7 @@ class FarmTest < Zold::Test
|
|
164
164
|
end
|
165
165
|
farm = Zold::Farm.new('NOPREFIX5@ffffffffffffffff', file, log: log)
|
166
166
|
assert_equal(1, farm.best.count)
|
167
|
-
assert(log.msgs.find { |m| m.include?('Invalid score') })
|
167
|
+
assert(log.msgs.find { |m| m.include?('Invalid score') }, log.msgs)
|
168
168
|
end
|
169
169
|
end
|
170
170
|
end
|
data/test/node/test_front.rb
CHANGED
@@ -26,6 +26,7 @@ require 'time'
|
|
26
26
|
require 'securerandom'
|
27
27
|
require 'threads'
|
28
28
|
require 'zold/score'
|
29
|
+
require 'memory_profiler'
|
29
30
|
require_relative '../test__helper'
|
30
31
|
require_relative 'fake_node'
|
31
32
|
require_relative '../fake_home'
|
@@ -38,6 +39,21 @@ class FrontTest < Zold::Test
|
|
38
39
|
Zold::Front
|
39
40
|
end
|
40
41
|
|
42
|
+
# Use this test to check how much memory is being used after doing a large
|
43
|
+
# number of routine operations. There should be no suspicious information
|
44
|
+
# in the report, which will be printed to the console.
|
45
|
+
def test_memory_leakage
|
46
|
+
skip
|
47
|
+
report = MemoryProfiler.report(top: 10) do
|
48
|
+
FakeNode.new(log: test_log).run(['--no-metronome', '--network=foo', '--threads=0']) do |port|
|
49
|
+
100.times do
|
50
|
+
Zold::Http.new(uri: "http://localhost:#{port}/", network: 'foo').get
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
report.pretty_print
|
55
|
+
end
|
56
|
+
|
41
57
|
def test_renders_front_json
|
42
58
|
FakeNode.new(log: test_log).run(['--no-metronome', '--network=foo', '--threads=0']) do |port|
|
43
59
|
res = Zold::Http.new(uri: "http://localhost:#{port}/", network: 'foo').get
|
data/test/test_http.rb
CHANGED
@@ -25,8 +25,10 @@ require 'tmpdir'
|
|
25
25
|
require 'uri'
|
26
26
|
require 'webmock/minitest'
|
27
27
|
require 'zold/score'
|
28
|
+
require 'random-port'
|
28
29
|
require_relative 'test__helper'
|
29
30
|
require_relative '../lib/zold/http'
|
31
|
+
require_relative '../lib/zold/verbose_thread'
|
30
32
|
|
31
33
|
# Http test.
|
32
34
|
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
@@ -70,35 +72,45 @@ class TestHttp < Zold::Test
|
|
70
72
|
assert_equal('200', res.code)
|
71
73
|
end
|
72
74
|
|
73
|
-
def test_terminates_on_timeout
|
74
|
-
stub_request(:get, 'http://the-fake-host-99/').to_return do
|
75
|
-
sleep 100
|
76
|
-
{ body: 'This should never be returned!' }
|
77
|
-
end
|
78
|
-
res = Zold::Http.new(uri: 'http://the-fake-host-99/').get
|
79
|
-
assert_equal('599', res.code)
|
80
|
-
end
|
81
|
-
|
82
75
|
def test_doesnt_terminate_on_long_call
|
83
|
-
require 'random-port'
|
84
76
|
WebMock.allow_net_connect!
|
85
77
|
RandomPort::Pool::SINGLETON.acquire do |port|
|
86
78
|
thread = Thread.start do
|
87
|
-
|
88
|
-
|
79
|
+
Zold::VerboseThread.new(test_log).run do
|
80
|
+
server = TCPServer.new(port)
|
89
81
|
client = server.accept
|
82
|
+
client.puts("HTTP/1.1 200 OK\nContent-Length: 4\n\n")
|
90
83
|
sleep 1
|
91
|
-
client.puts(
|
84
|
+
client.puts('Good')
|
92
85
|
client.close
|
93
86
|
end
|
94
87
|
end
|
95
|
-
|
88
|
+
sleep 0.25
|
89
|
+
res = Zold::Http.new(uri: "http://127.0.0.1:#{port}/").get(timeout: 2)
|
96
90
|
assert_equal('200', res.code, res)
|
97
91
|
thread.kill
|
98
92
|
thread.join
|
99
93
|
end
|
100
94
|
end
|
101
95
|
|
96
|
+
def test_terminates_on_timeout
|
97
|
+
WebMock.allow_net_connect!
|
98
|
+
RandomPort::Pool::SINGLETON.acquire do |port|
|
99
|
+
thread = Thread.start do
|
100
|
+
Zold::VerboseThread.new(test_log).run do
|
101
|
+
server = TCPServer.new(port)
|
102
|
+
server.accept
|
103
|
+
sleep 400
|
104
|
+
end
|
105
|
+
end
|
106
|
+
sleep 0.25
|
107
|
+
res = Zold::Http.new(uri: "http://127.0.0.1:#{port}/").get(timeout: 0.1)
|
108
|
+
assert_equal('599', res.code, res)
|
109
|
+
thread.kill
|
110
|
+
thread.join
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
102
114
|
def test_sends_valid_version_header
|
103
115
|
stub_request(:get, 'http://some-host-3/')
|
104
116
|
.with(headers: { 'X-Zold-Version' => Zold::VERSION })
|
data/zold.gemspec
CHANGED
@@ -76,11 +76,12 @@ and suggests a different architecture for digital wallet maintenance.'
|
|
76
76
|
s.add_runtime_dependency 'usagewatch_ext', '0.2.1'
|
77
77
|
s.add_runtime_dependency 'xcop', '0.6'
|
78
78
|
s.add_runtime_dependency 'zache', '0.3.1'
|
79
|
-
s.add_runtime_dependency 'zold-score', '0.2.
|
79
|
+
s.add_runtime_dependency 'zold-score', '0.2.2'
|
80
80
|
s.add_development_dependency 'codecov', '0.1.13'
|
81
|
+
s.add_development_dependency 'memory_profiler', '0.9.12'
|
81
82
|
s.add_development_dependency 'minitest', '5.11.3'
|
82
83
|
s.add_development_dependency 'minitest-hooks', '1.5.0'
|
83
|
-
s.add_development_dependency 'random-port', '0.3.
|
84
|
+
s.add_development_dependency 'random-port', '0.3.1'
|
84
85
|
s.add_development_dependency 'rdoc', '4.3.0'
|
85
86
|
s.add_development_dependency 'rspec-rails', '3.8.1'
|
86
87
|
s.add_development_dependency 'webmock', '3.4.2'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: zold
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.16.
|
4
|
+
version: 0.16.21
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yegor Bugayenko
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-11-
|
11
|
+
date: 2018-11-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: backtrace
|
@@ -324,14 +324,14 @@ dependencies:
|
|
324
324
|
requirements:
|
325
325
|
- - '='
|
326
326
|
- !ruby/object:Gem::Version
|
327
|
-
version: 0.2.
|
327
|
+
version: 0.2.2
|
328
328
|
type: :runtime
|
329
329
|
prerelease: false
|
330
330
|
version_requirements: !ruby/object:Gem::Requirement
|
331
331
|
requirements:
|
332
332
|
- - '='
|
333
333
|
- !ruby/object:Gem::Version
|
334
|
-
version: 0.2.
|
334
|
+
version: 0.2.2
|
335
335
|
- !ruby/object:Gem::Dependency
|
336
336
|
name: codecov
|
337
337
|
requirement: !ruby/object:Gem::Requirement
|
@@ -346,6 +346,20 @@ dependencies:
|
|
346
346
|
- - '='
|
347
347
|
- !ruby/object:Gem::Version
|
348
348
|
version: 0.1.13
|
349
|
+
- !ruby/object:Gem::Dependency
|
350
|
+
name: memory_profiler
|
351
|
+
requirement: !ruby/object:Gem::Requirement
|
352
|
+
requirements:
|
353
|
+
- - '='
|
354
|
+
- !ruby/object:Gem::Version
|
355
|
+
version: 0.9.12
|
356
|
+
type: :development
|
357
|
+
prerelease: false
|
358
|
+
version_requirements: !ruby/object:Gem::Requirement
|
359
|
+
requirements:
|
360
|
+
- - '='
|
361
|
+
- !ruby/object:Gem::Version
|
362
|
+
version: 0.9.12
|
349
363
|
- !ruby/object:Gem::Dependency
|
350
364
|
name: minitest
|
351
365
|
requirement: !ruby/object:Gem::Requirement
|
@@ -380,14 +394,14 @@ dependencies:
|
|
380
394
|
requirements:
|
381
395
|
- - '='
|
382
396
|
- !ruby/object:Gem::Version
|
383
|
-
version: 0.3.
|
397
|
+
version: 0.3.1
|
384
398
|
type: :development
|
385
399
|
prerelease: false
|
386
400
|
version_requirements: !ruby/object:Gem::Requirement
|
387
401
|
requirements:
|
388
402
|
- - '='
|
389
403
|
- !ruby/object:Gem::Version
|
390
|
-
version: 0.3.
|
404
|
+
version: 0.3.1
|
391
405
|
- !ruby/object:Gem::Dependency
|
392
406
|
name: rdoc
|
393
407
|
requirement: !ruby/object:Gem::Requirement
|