zold 0.16.8 → 0.16.9

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1399da979b61a827097b2b29a04b31920f6da3a65e2af8920fc493bbb52064ba
4
- data.tar.gz: 255d50d0c687709e5b15f1ce1fc17eec7ab656b24a7c8356aec320d8620d911c
3
+ metadata.gz: 5fa4b6ced7df2e9773120703da57a11e317396caedc756a8b42d9316fb900ff7
4
+ data.tar.gz: e1e4f91dda7d2954bb7cb34adf5f56b71202ebe59102a7a85a805e4425041be0
5
5
  SHA512:
6
- metadata.gz: acf61ff6782dcb26a24f17f2f208cf64d7110c1204ccb048240433541c99978f298f21de0c96974aa7c67321acf800131e80a518d5eef37709c714e7642c1c41
7
- data.tar.gz: d0816cade1db2f054b08a321aa7bde96a6af4eb3beb8ea42d54ba3d66b88c254464d48809e3a7e1fca80a155653420f21c779f93a2db1b7c255b38e652448187
6
+ metadata.gz: f5b2ccce4eec666e4036448517f18ee4e36e71637100b85d900536891bf7e04306b5e7fd764037df5616b07998526b472759f9aa873874ffedaa640256217b2f
7
+ data.tar.gz: 16287fd3da5be69b02e5d3ef232ca18eaa6cd1dafaeafbbe07ec3d4fc98f34e21f23fcd867591b19f5fe18ff6302a66aba3901432d8781fe672c82ef283d2f56
data/INSTALL.md CHANGED
@@ -14,6 +14,8 @@ We recommend to host nodes at
14
14
  [AWS](https://aws.amazon.com/) or
15
15
  [DigitalOcean](https://www.digitalocean.com/).
16
16
 
17
+ It is recommended to have at least 2 CPUs and 2 Gb RAM.
18
+
17
19
  ## Debian 9.4
18
20
 
19
21
  ```bash
@@ -48,9 +50,9 @@ Without homebrew:
48
50
 
49
51
  ## Windows
50
52
 
51
- Download and install [RubyInstaller (with Devkit)](https://rubyinstaller.org/downloads/).
52
- If Windows Defender (or antivirus software) throws an error, ignore it and allow the file. This file is known to trigger [false positives](https://groups.google.com/forum/#!topic/rubyinstaller/LCR-CbBoGOI).
53
- Download and install [RubyGems](https://rubygems.org/pages/download). Manual install `ruby setup.rb` works.
53
+ Download and install [RubyInstaller (with Devkit)](https://rubyinstaller.org/downloads/).
54
+ If Windows Defender (or antivirus software) throws an error, ignore it and allow the file. This file is known to trigger [false positives](https://groups.google.com/forum/#!topic/rubyinstaller/LCR-CbBoGOI).
55
+ Download and install [RubyGems](https://rubygems.org/pages/download). Manual install `ruby setup.rb` works.
54
56
  Install [Zold gem](https://rubygems.org/gems/zold) `gem install --no-ri --no-rdoc zold`
55
57
 
56
58
  ## CentOS 7.5
@@ -68,8 +68,8 @@ Available options:"
68
68
  in #{Age.new(start, limit: 0.01)}, #{cps.all.count} left:\n" +
69
69
  cps.all.map do |c|
70
70
  wallet = Wallet.new(c[:path])
71
- " #{c[:name]}: #{c[:score]} #{wallet.balance}/#{wallet.txns.count}t/\
72
- #{wallet.digest[0, 6]}/#{Size.new(File.size(c[:path]))}/#{Age.new(File.mtime(c[:path]))}"
71
+ " #{c[:name]}: #{c[:score]} #{wallet.memo} \
72
+ #{Size.new(File.size(c[:path]))}/#{Age.new(File.mtime(c[:path]))}"
73
73
  end.join("\n")
74
74
  )
75
75
  end
@@ -93,8 +93,8 @@ Available options:"
93
93
  @log.debug("#{cps.all.count} local copies:")
94
94
  cps.all.each do |c|
95
95
  wallet = Wallet.new(c[:path])
96
- @log.debug(" #{c[:name]}: #{c[:score]} #{wallet.balance}/#{wallet.txns.count}t/\
97
- #{wallet.digest[0, 6]}/#{Size.new(File.size(c[:path]))}/#{Age.new(File.mtime(c[:path]))}")
96
+ @log.debug(" #{c[:name]}: #{c[:score]} #{wallet.memo} \
97
+ #{Size.new(File.size(c[:path]))}/#{Age.new(File.mtime(c[:path]))}")
98
98
  end
99
99
  end
100
100
 
@@ -128,7 +128,7 @@ Available options:"
128
128
  raise "The balance of #{id} is #{wallet.balance} and it's not a root wallet"
129
129
  end
130
130
  copy = cps.add(IO.read(f), score.host, score.port, score.value)
131
- @log.info("#{r} returned #{Size.new(body.length)}/#{wallet.balance}/#{wallet.txns.count}t/\
131
+ @log.info("#{r} returned #{Size.new(body.length)} #{wallet.memo} \
132
132
  #{digest(json)}/#{Age.new(json['mtime'])}/#{json['copies']}c \
133
133
  as copy #{copy} of #{id} in #{Age.new(start, limit: 4)}: #{Rainbow(score.value).green} (#{json['version']})")
134
134
  end
@@ -38,7 +38,7 @@ module Zold
38
38
  def run(_ = [])
39
39
  @wallets.all.each do |id|
40
40
  @wallets.find(id) do |wallet|
41
- msg = "#{id}: #{wallet.balance}/#{wallet.txns.count}t"
41
+ msg = "#{id}: #{wallet.memo}"
42
42
  msg += " (net:#{wallet.network})" if wallet.network != Wallet::MAIN_NETWORK
43
43
  @log.info(msg)
44
44
  end
@@ -88,7 +88,7 @@ Available options:"
88
88
  wallet.flush
89
89
  if modified
90
90
  @log.info("#{cps.count} copies with the total score of #{score} successfully merged \
91
- into #{wallet.id}/#{wallet.balance}/#{wallet.txns.count}t in #{Age.new(start, limit: 0.1 + cps.count * 0.01)}")
91
+ into #{wallet.memo} in #{Age.new(start, limit: 0.1 + cps.count * 0.01)}")
92
92
  else
93
93
  @log.info("Nothing changed in #{wallet.id} after merge of #{cps.count} copies")
94
94
  end
@@ -114,18 +114,10 @@ Available options:"
114
114
  @log.debug("#{amount} sent from #{from} to #{txn.bnf}: #{details}")
115
115
  @log.debug("Don't forget to do 'zold push #{from}'")
116
116
  @log.info(txn.id)
117
- notify_of_tax_debt(from)
117
+ tax = Tax.new(from)
118
+ @log.info("The tax debt of #{from.memo} is #{tax.debt} \
119
+ (#{tax.in_debt? ? 'too high' : 'still acceptable'})")
118
120
  txn
119
121
  end
120
-
121
- # @todo #79:40min Extract message cretion into a separate method for easier
122
- # testing. Add tests for when in debt and not. Extract to a
123
- # module, possibly Notify.
124
- def notify_of_tax_debt(wallet)
125
- tax = Tax.new(wallet)
126
- message = "The tax debt of #{wallet} is #{tax.debt}"
127
- message += ' (still acceptable)' unless tax.in_debt?
128
- @log.info(message)
129
- end
130
122
  end
131
123
  end
@@ -95,8 +95,8 @@ total score for #{id} is #{total}")
95
95
  response = r.http(uri).put(content)
96
96
  @wallets.find(id) do |wallet|
97
97
  if response.code == '304'
98
- @log.info("#{r}: same version #{Size.new(content.length)}/#{wallet.txns.count}t \
99
- of #{wallet.id} there, in #{Age.new(start, limit: 0.5)}")
98
+ @log.info("#{r}: same version #{Size.new(content.length)} of #{wallet.memo} \
99
+ there, in #{Age.new(start, limit: 0.5)}")
100
100
  return 0
101
101
  end
102
102
  r.assert_code(200, response)
@@ -105,8 +105,8 @@ of #{wallet.id} there, in #{Age.new(start, limit: 0.5)}")
105
105
  r.assert_valid_score(score)
106
106
  r.assert_score_ownership(score)
107
107
  r.assert_score_strength(score) unless opts['ignore-score-weakness']
108
- @log.info("#{r} accepted #{Size.new(content.length)}/#{wallet.digest[0, 6]}/#{wallet.txns.count}t \
109
- of #{wallet.id} in #{Age.new(start, limit: 4)}: #{Rainbow(score.value).green} (#{json['version']})")
108
+ @log.info("#{r} accepted #{Size.new(content.length)} of #{wallet.memo} \
109
+ in #{Age.new(start, limit: 4)}: #{Rainbow(score.value).green} (#{json['version']})")
110
110
  score.value
111
111
  end
112
112
  end
@@ -115,7 +115,7 @@ Available options:"
115
115
  raise 'The wallet is absent' unless wallet.exists?
116
116
  tax = Tax.new(wallet)
117
117
  debt = total = tax.debt
118
- @log.info("The current debt of #{wallet.id}/#{wallet.txns.count}t is #{debt} (#{debt.to_i} zents), \
118
+ @log.info("The current debt of #{wallet.memo} is #{debt} (#{debt.to_i} zents), \
119
119
  the balance is #{wallet.balance}: #{tax.to_text}")
120
120
  unless tax.in_debt?
121
121
  @log.debug("No need to pay taxes yet, while the debt is less than #{Tax::TRIAL} (#{Tax::TRIAL.to_i} zents)")
@@ -144,7 +144,8 @@ the balance is #{wallet.balance}: #{tax.to_text}")
144
144
  txn = tax.pay(Zold::Key.new(file: opts['private-key']), best)
145
145
  debt += txn.amount
146
146
  paid += 1
147
- @log.info("#{txn.amount} of taxes paid to #{txn.bnf} (payment no.#{paid}), #{debt} left to pay")
147
+ @log.info("#{txn.amount * -1} of taxes paid from #{wallet.id} to #{txn.bnf} \
148
+ (payment no.#{paid}, txn ##{txn.id}/#{wallet.txns.count}), #{debt} left to pay")
148
149
  end
149
150
  @log.info('The wallet is in good standing, all taxes paid') unless tax.in_debt?
150
151
  end
@@ -91,7 +91,7 @@ module Zold
91
91
  @history.shift if @history.length >= 16
92
92
  @speed.shift if @speed.length >= 64
93
93
  @wallets.find(id) do |wallet|
94
- @history << "#{id}/#{sec}/#{modified.count}/#{wallet.balance.to_zld}/#{wallet.txns.count}t"
94
+ @history << "#{id}/#{sec}/#{modified.count}/#{wallet.memo}"
95
95
  end
96
96
  @speed << sec
97
97
  end
@@ -62,6 +62,7 @@ module Zold
62
62
  def to_text
63
63
  [
64
64
  "Current time: #{Time.now.utc.iso8601}",
65
+ "Ruby processes: #{`ps -a | grep zold | wc -l`}",
65
66
  JSON.pretty_generate(to_json),
66
67
  @threads.map do |t|
67
68
  trace = t.backtrace || []
@@ -326,8 +326,8 @@ in #{Age.new(@start, limit: 1)}")
326
326
  "\n\n" +
327
327
  copies.all.map do |c|
328
328
  w = Wallet.new(c[:path])
329
- "#{c[:name]}: #{c[:score]} #{w.balance}/#{w.txns.count}t/\
330
- #{w.digest[0, 6]}/#{Size.new(File.size(c[:path]))}/#{Age.new(File.mtime(c[:path]))}"
329
+ "#{c[:name]}: #{c[:score]} #{w.memo} \
330
+ #{Size.new(File.size(c[:path]))}/#{Age.new(File.mtime(c[:path]))}"
331
331
  end.join("\n")
332
332
  end
333
333
  end
@@ -64,7 +64,7 @@ module Zold
64
64
  end
65
65
  if before == after
66
66
  @log.info(
67
- "Duplicate of #{id}/#{wallet.digest[0, 6]}/#{Size.new(after.length)}/#{wallet.txns.count}t ignored"
67
+ "Duplicate of #{Size.new(after.length)} #{wallet.memo} ignored"
68
68
  )
69
69
  return []
70
70
  end
@@ -75,7 +75,8 @@ module Zold
75
75
  Emission.new(wallet).check
76
76
  tax = Tax.new(wallet)
77
77
  if tax.in_debt?
78
- raise "Taxes are not paid, can't accept the wallet; the debt is #{tax.debt} (#{tax.debt.to_i} zents)"
78
+ raise "Taxes are not paid, can't accept the wallet #{wallet.memo}; the debt is #{tax.debt} \
79
+ (#{tax.debt.to_i} zents); formula ingredients are #{tax.to_text}"
79
80
  end
80
81
  @entrance.push(id, body)
81
82
  end
data/lib/zold/tax.rb CHANGED
@@ -40,7 +40,7 @@ module Zold
40
40
  # The correct amount should be 1 ZLD, but we allow bigger amounts
41
41
  # now since the amount of nodes in the network is still small. When
42
42
  # the network grows up, let's put this number back to 1 ZLD.
43
- MAX_PAYMENT = Amount.new(zld: 64.0)
43
+ MAX_PAYMENT = Amount.new(zld: 16.0)
44
44
 
45
45
  # This is how much we charge per one transaction per hour
46
46
  # of storage. A wallet of 4096 transactions will pay
@@ -56,9 +56,10 @@ module Zold
56
56
  # Text prefix for taxes details
57
57
  PREFIX = 'TAXES'
58
58
 
59
- def initialize(wallet)
59
+ def initialize(wallet, ignore_score_weakness: false)
60
60
  raise "The wallet must be of type Wallet: #{wallet.class.name}" unless wallet.is_a?(Wallet)
61
61
  @wallet = wallet
62
+ @ignore_score_weakness = ignore_score_weakness
62
63
  end
63
64
 
64
65
  # Check whether this tax payment already exists in the wallet.
@@ -71,7 +72,7 @@ module Zold
71
72
  end
72
73
 
73
74
  def pay(pvt, best)
74
- @wallet.sub(Tax::MAX_PAYMENT, best.invoice, pvt, details(best))
75
+ @wallet.sub([Tax::MAX_PAYMENT, debt].min, best.invoice, pvt, details(best))
75
76
  end
76
77
 
77
78
  def in_debt?
@@ -93,11 +94,11 @@ module Zold
93
94
  next if pfx != Tax::PREFIX || body.nil?
94
95
  score = Score.parse_text(body)
95
96
  next if !score.valid? || score.value != Tax::EXACT_SCORE
96
- next if score.strength < Score::STRENGTH
97
+ next if score.strength < Score::STRENGTH && !@ignore_score_weakness
97
98
  next if t.amount > Tax::MAX_PAYMENT
98
99
  t
99
100
  end.compact.uniq(&:details)
100
- scored.empty? ? Amount::ZERO : scored.map(&:amount).inject(&:+)
101
+ scored.empty? ? Amount::ZERO : scored.map(&:amount).inject(&:+) * -1
101
102
  end
102
103
  end
103
104
  end
data/lib/zold/version.rb CHANGED
@@ -25,6 +25,6 @@
25
25
  # Copyright:: Copyright (c) 2018 Yegor Bugayenko
26
26
  # License:: MIT
27
27
  module Zold
28
- VERSION = '0.16.8'
28
+ VERSION = '0.16.9'
29
29
  PROTOCOL = 2
30
30
  end
data/lib/zold/wallet.rb CHANGED
@@ -32,6 +32,7 @@ require_relative 'amount'
32
32
  require_relative 'hexnum'
33
33
  require_relative 'signature'
34
34
  require_relative 'txns'
35
+ require_relative 'size'
35
36
  require_relative 'head'
36
37
 
37
38
  # The wallet.
@@ -70,6 +71,10 @@ module Zold
70
71
  id.to_s
71
72
  end
72
73
 
74
+ def memo
75
+ "#{id}/#{balance.to_zld(4)}/#{txns.count}t/#{digest[0, 6]}/Size.new(File.size(@file))}"
76
+ end
77
+
73
78
  def to_text
74
79
  (@head.fetch + [''] + @txns.fetch.map(&:to_text)).join("\n")
75
80
  end
@@ -42,14 +42,16 @@ class TestTaxes < Minitest::Test
42
42
  wallets = home.wallets
43
43
  wallet = home.create_wallet
44
44
  fund = Zold::Amount.new(zld: 19.99)
45
- wallet.add(
46
- Zold::Txn.new(
47
- 1,
48
- Time.now - 24 * 60 * 60 * 365 * 300,
49
- fund,
50
- 'NOPREFIX', Zold::Id.new, '-'
45
+ 10.times do |i|
46
+ wallet.add(
47
+ Zold::Txn.new(
48
+ i + 1,
49
+ Time.now - 24 * 60 * 60 * 365 * 300,
50
+ fund,
51
+ 'NOPREFIX', Zold::Id.new, '-'
52
+ )
51
53
  )
52
- )
54
+ end
53
55
  remotes = home.remotes
54
56
  score = Zold::Score.new(host: 'localhost', port: 80, strength: 1, invoice: 'NOPREFIX@0000000000000000')
55
57
  Zold::Tax::EXACT_SCORE.times { score = score.next }
@@ -60,25 +62,15 @@ class TestTaxes < Minitest::Test
60
62
  score: score.to_h
61
63
  }.to_json
62
64
  )
65
+ before = wallet.balance
66
+ tax = Zold::Tax.new(wallet, ignore_score_weakness: true)
67
+ debt = tax.debt
63
68
  Zold::Taxes.new(wallets: wallets, remotes: remotes, log: test_log).run(
64
69
  ['taxes', '--private-key=fixtures/id_rsa', '--ignore-score-weakness', 'pay', wallet.id.to_s]
65
70
  )
66
- assert_equal(fund - Zold::Tax::MAX_PAYMENT, wallet.balance)
67
- wallet.add(
68
- Zold::Txn.new(
69
- 2,
70
- Time.now - 24 * 60 * 60 * 365 * 300,
71
- fund,
72
- 'NOPREFIX', Zold::Id.new, '-'
73
- )
74
- )
75
- Zold::Taxes.new(wallets: wallets, remotes: remotes, log: test_log).run(
76
- [
77
- 'taxes', '--private-key=fixtures/id_rsa', '--ignore-score-weakness',
78
- '--ignore-nodes-absence', 'pay', wallet.id.to_s
79
- ]
80
- )
81
- assert_equal(fund + fund - Zold::Tax::MAX_PAYMENT, wallet.balance)
71
+ wallet.flush
72
+ assert(tax.paid.positive?, tax.paid)
73
+ assert_equal(before - debt, wallet.balance)
82
74
  end
83
75
  end
84
76
  end
@@ -63,11 +63,14 @@ class FakeNode
63
63
  end
64
64
  end
65
65
  uri = "http://localhost:#{port}/"
66
+ attempt = 0
66
67
  loop do
67
68
  ping = Zold::Http.new(uri: uri, network: Zold::Front.network).get
68
69
  break unless ping.code == '599' && node.alive?
69
- @log.debug("Waiting for #{uri}: ##{ping.code}...")
70
+ @log.debug("Waiting for #{uri} (attempt no.#{attempt}): ##{ping.code}...")
70
71
  sleep 0.5
72
+ attempt += 1
73
+ break if attempt > 10
71
74
  end
72
75
  raise "The node is dead at #{uri}" unless node.alive?
73
76
  begin
@@ -35,7 +35,7 @@ class TestDirItems < Minitest::Test
35
35
  def test_intensive_write_in_threads
36
36
  Dir.mktmpdir do |dir|
37
37
  file = File.join(dir, 'hey.txt')
38
- Thread.start do
38
+ back = Thread.start do
39
39
  loop do
40
40
  Zold::DirItems.new(dir).fetch
41
41
  end
@@ -48,6 +48,7 @@ class TestDirItems < Minitest::Test
48
48
  test_log.debug("Saved in #{Zold::Age.new(start)}")
49
49
  sleep 1
50
50
  end
51
+ back.kill
51
52
  end
52
53
  end
53
54
 
data/test/test_tax.rb CHANGED
@@ -77,8 +77,9 @@ class TestTax < Minitest::Test
77
77
  suffixes: %w[A B C D E F G H I J K L M N O P Q R S T U V]
78
78
  )
79
79
  tax = Zold::Tax.new(wallet)
80
+ debt = tax.debt
80
81
  txn = tax.pay(Zold::Key.new(file: 'fixtures/id_rsa'), score)
81
- assert_equal(Zold::Tax::MAX_PAYMENT * -1, txn.amount)
82
+ assert_equal(debt, txn.amount * -1)
82
83
  end
83
84
  end
84
85
 
@@ -93,18 +94,20 @@ class TestTax < Minitest::Test
93
94
  def test_takes_tax_payment_into_account
94
95
  FakeHome.new(log: test_log).run do |home|
95
96
  wallet = home.create_wallet
97
+ amount = Zold::Amount.new(zents: 95_596_800)
96
98
  wallet.add(
97
99
  Zold::Txn.new(
98
100
  1,
99
101
  Time.now,
100
- Zold::Amount.new(zents: 95_596_800),
102
+ amount * -1,
101
103
  'NOPREFIX', Zold::Id.new('912ecc24b32dbe74'),
102
104
  "TAXES 6 5b5a21a9 b2.zold.io 1000 DCexx0hG 912ecc24b32dbe74 \
103
105
  386d4a ec9eae 306e3d 119d073 1c00dba 1376703 203589 5b55f7"
104
106
  )
105
107
  )
106
108
  tax = Zold::Tax.new(wallet)
107
- assert(tax.debt < Zold::Amount::ZERO)
109
+ assert_equal(amount, tax.paid)
110
+ assert(tax.debt < Zold::Amount::ZERO, tax.debt)
108
111
  end
109
112
  end
110
113
 
data/test/test_wallet.rb CHANGED
@@ -43,6 +43,13 @@ class TestWallet < Minitest::Test
43
43
  end
44
44
  end
45
45
 
46
+ def test_generates_memo
47
+ FakeHome.new(log: test_log).run do |home|
48
+ wallet = home.create_wallet
49
+ assert(!wallet.memo.nil?)
50
+ end
51
+ end
52
+
46
53
  def test_reads_large_wallet
47
54
  key = Zold::Key.new(file: 'fixtures/id_rsa')
48
55
  FakeHome.new(log: test_log).run do |home|
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zold
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.16.8
4
+ version: 0.16.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yegor Bugayenko