zold 0.14.28 → 0.14.29

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.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -1
  3. data/appveyor.yml +9 -8
  4. data/bin/zold +8 -4
  5. data/fixtures/scripts/distribute-wallet.sh +4 -3
  6. data/lib/zold/commands/create.rb +6 -5
  7. data/lib/zold/commands/diff.rb +5 -7
  8. data/lib/zold/commands/fetch.rb +3 -2
  9. data/lib/zold/commands/invoice.rb +4 -3
  10. data/lib/zold/commands/merge.rb +14 -13
  11. data/lib/zold/commands/node.rb +40 -17
  12. data/lib/zold/commands/pay.rb +16 -9
  13. data/lib/zold/commands/propagate.rb +24 -21
  14. data/lib/zold/commands/push.rb +23 -22
  15. data/lib/zold/commands/remote.rb +16 -23
  16. data/lib/zold/commands/routines/reconnect.rb +5 -1
  17. data/lib/zold/commands/show.rb +3 -1
  18. data/lib/zold/commands/taxes.rb +9 -3
  19. data/lib/zold/copies.rb +2 -2
  20. data/lib/zold/hungry_wallets.rb +21 -1
  21. data/lib/zold/node/async_entrance.rb +5 -6
  22. data/lib/zold/node/entrance.rb +3 -2
  23. data/lib/zold/node/front.rb +119 -88
  24. data/lib/zold/node/nodup_entrance.rb +3 -2
  25. data/lib/zold/node/sync_entrance.rb +81 -0
  26. data/lib/zold/node/trace.rb +75 -0
  27. data/lib/zold/patch.rb +2 -3
  28. data/lib/zold/remotes.rb +1 -1
  29. data/lib/zold/sync_wallets.rb +78 -0
  30. data/lib/zold/version.rb +1 -1
  31. data/lib/zold/wallet.rb +1 -0
  32. data/lib/zold/wallets.rb +5 -5
  33. data/test/commands/test_create.rb +9 -6
  34. data/test/commands/test_diff.rb +1 -1
  35. data/test/commands/test_invoice.rb +7 -6
  36. data/test/commands/test_list.rb +4 -3
  37. data/test/commands/test_merge.rb +2 -2
  38. data/test/commands/test_pull.rb +3 -1
  39. data/test/commands/test_remote.rb +4 -0
  40. data/test/commands/test_show.rb +5 -4
  41. data/test/fake_home.rb +2 -1
  42. data/test/node/test_async_entrance.rb +1 -1
  43. data/test/node/test_farm.rb +2 -2
  44. data/test/node/test_front.rb +63 -17
  45. data/test/node/test_sync_entrance.rb +41 -0
  46. data/test/node/test_trace.rb +36 -0
  47. data/test/test__helper.rb +18 -0
  48. data/test/test_copies.rb +1 -1
  49. data/test/test_metronome.rb +2 -3
  50. data/test/test_patch.rb +1 -1
  51. data/test/test_remotes.rb +3 -3
  52. data/test/test_sync_wallets.rb +69 -0
  53. data/test/test_upgrades.rb +0 -0
  54. data/test/test_wallet.rb +1 -1
  55. data/test/test_wallets.rb +14 -10
  56. data/test/test_zold.rb +2 -2
  57. data/test/upgrades/test_protocol_up.rb +3 -2
  58. data/zold.gemspec +1 -0
  59. metadata +25 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e31d92a96dac32c4a2c347ea562e35176e481a4c
4
- data.tar.gz: '0695b4884ed252ffc7d0e0bb5baf322bb9f16755'
3
+ metadata.gz: 9b4acd567c5e890ca57ca7503ef5620cb7011c92
4
+ data.tar.gz: '08020f9c49dcd23340fe4f614190d3d24be30201'
5
5
  SHA512:
6
- metadata.gz: 978a5f61ef0c5db91e7611b8d56f063b4f506387ce302d04361c49fd2f989158ccbc1bccf6379ddceb2eb16fe215cbbba0717fa57315c88e018890b347565f4b
7
- data.tar.gz: a1a6d275a59aaf7ce4f1eb4b436738bd0832dcaaa83e1ed9f843d35dee2c878639b8752230aa9e8a394a21ac94d2107e4427ab4595e6e693f37c955e7bc93d99
6
+ metadata.gz: b31303f911f6a4f90b9e5a646e719f0df55163e3f3a4923a7b4953fc9f89fe436d6ed0f846a3115e1852e3308ffe4751a86da717ea0c7aaec13ea3ddf99d16e2
7
+ data.tar.gz: a33a1e676dfa1557baafb3f886c38de513ba7c98481d806313a96b5780c723bea580321768e3d1efc502138142ac785394effdaedc56de6e9b7948eed9007254
@@ -16,7 +16,7 @@ Metrics/AbcSize:
16
16
  Metrics/BlockLength:
17
17
  Max: 100
18
18
  Metrics/ClassLength:
19
- Max: 300
19
+ Max: 400
20
20
  Layout/EndOfLine:
21
21
  EnforcedStyle: lf
22
22
  Metrics/ParameterLists:
@@ -9,12 +9,12 @@ branches:
9
9
  os: Windows Server 2012
10
10
  environment:
11
11
  matrix:
12
- - RUBY_VERSION: 23
13
- - RUBY_VERSION: 24
14
- - RUBY_VERSION: 25
12
+ - ruby_version: "23-x64"
13
+ - ruby_version: "24-x64"
14
+ - ruby_version: "25-x64"
15
15
  install:
16
16
  - ps: |
17
- $Env:PATH = "C:\Ruby${Env:ruby_version}-X64\bin;${Env:PATH}"
17
+ $Env:PATH = "C:\Ruby${Env:ruby_version}\bin;${Env:PATH}"
18
18
  if ($Env:ruby_version -match "^23" ) {
19
19
  # RubyInstaller; download OpenSSL headers from OpenKnapsack Project
20
20
  $Env:openssl_dir = "C:\Ruby${Env:ruby_version}"
@@ -25,13 +25,14 @@ install:
25
25
  # RubyInstaller2; openssl package seems to be installed already
26
26
  $Env:openssl_dir = "C:\msys64\mingw64"
27
27
  }
28
- - cmd: ruby --version
29
- - cmd: git --version
30
- - cmd: bundle config --local path vendor/bundle
28
+ - bundle config --local path vendor/bundle
29
+ - bundle config build.openssl --with-openssl-dir=%openssl_dir%
30
+ - ruby -v
31
+ - bundle -v
31
32
  build_script:
32
33
  - bundle update
33
34
  - bundle install
34
35
  test_script:
35
- - rake
36
+ - bundle exec rake --quiet
36
37
  cache:
37
38
  - vendor/bundle
data/bin/zold CHANGED
@@ -35,6 +35,7 @@ require_relative '../lib/zold'
35
35
  require_relative '../lib/zold/version'
36
36
  require_relative '../lib/zold/wallet'
37
37
  require_relative '../lib/zold/wallets'
38
+ require_relative '../lib/zold/sync_wallets'
38
39
  require_relative '../lib/zold/log'
39
40
  require_relative '../lib/zold/key'
40
41
  require_relative '../lib/zold/amount'
@@ -43,6 +44,7 @@ require_relative '../lib/zold/remotes'
43
44
  require_relative '../lib/zold/upgrades'
44
45
  require_relative '../lib/zold/version_file'
45
46
 
47
+ Thread.current.name = 'main'
46
48
 
47
49
  Encoding.default_external = Encoding::UTF_8
48
50
  Encoding.default_internal = Encoding::UTF_8
@@ -138,7 +140,9 @@ Available options:"
138
140
  FileUtils.mkdir_p(opts[:home])
139
141
  Dir.chdir(opts[:home])
140
142
 
141
- Zold::Upgrades.new(Zold::VersionFile.new('.zoldata/version'), 'upgrades').run
143
+ zoldata = File.expand_path(File.join(Dir.pwd, '.zoldata'))
144
+
145
+ Zold::Upgrades.new(Zold::VersionFile.new(File.join(zoldata, 'version')), 'upgrades').run
142
146
 
143
147
  # @todo #384:30min This is a workaround, move this code into Upgrades, somehow.
144
148
  # We should find a way to run these arbitrary scripts and pass arguments
@@ -150,9 +154,9 @@ Available options:"
150
154
  require_relative '../upgrades/rename_foreign_wallets'
151
155
  Zold::RenameForeignWallets.new(Dir.pwd, opts['network'], log).exec
152
156
 
153
- wallets = Zold::Wallets.new('.')
154
- remotes = Zold::Remotes.new(file: './.zoldata/remotes', network: opts['network'])
155
- copies = './.zoldata/copies'
157
+ wallets = Zold::SyncWallets.new(Zold::Wallets.new('.'), File.join(zoldata, 'locks'), log: log)
158
+ remotes = Zold::Remotes.new(file: File.join(zoldata, 'remotes'), network: opts['network'])
159
+ copies = File.join(zoldata, 'copies')
156
160
 
157
161
  case command
158
162
  when 'node'
@@ -73,15 +73,16 @@ if [ ! $(echo ${json} | jq -r '.wallets') == "1" ]; then
73
73
  fi
74
74
 
75
75
  # Now, we remove the wallet from the second node and expect the first
76
- # one to "spread" it again, almost immediately.
77
- rm ${second}/0000000000000000.z
76
+ # one to "spread" it again, almost immediately. The second node should
77
+ # have the wallet very soon.
78
+ rm -f ${second}/0000000000000000.z
78
79
  i=0
79
80
  until zold fetch 0000000000000000 --ignore-score-weakness; do
80
81
  echo 'Failed to fetch, let us try again'
81
82
  ((i++)) || sleep 0
82
83
  if ((i==5)); then
84
+ echo "The wallet 0000000000000000 has not been spread, after ${i} attempts, here is the log:"
83
85
  cat ${first}/log.txt
84
- echo "The wallet 0000000000000000 has not been spread, after ${i} attempts"
85
86
  exit 8
86
87
  fi
87
88
  sleep 5
@@ -60,12 +60,13 @@ Available options:"
60
60
  private
61
61
 
62
62
  def create(id, opts)
63
- wallet = @wallets.find(id)
64
63
  key = Zold::Key.new(file: opts['public-key'])
65
- wallet.init(id, key, network: opts['network'])
66
- @log.info(wallet.id)
67
- @log.debug("Wallet #{Rainbow(wallet).green} created at #{@wallets.path}")
68
- wallet
64
+ @wallets.find(id) do |wallet|
65
+ wallet.init(id, key, network: opts['network'])
66
+ @log.debug("Wallet #{Rainbow(wallet).green} created at #{@wallets.path}")
67
+ end
68
+ @log.info(id)
69
+ id
69
70
  end
70
71
  end
71
72
  end
@@ -53,25 +53,23 @@ Available options:"
53
53
  raise 'At least one wallet ID is required' if mine.empty?
54
54
  stdout = ''
55
55
  mine.map { |i| Id.new(i) }.each do |id|
56
- stdout += diff(
57
- @wallets.find(id),
58
- Copies.new(File.join(@copies, id)),
59
- opts
60
- )
56
+ stdout += diff(id, Copies.new(File.join(@copies, id)), opts)
61
57
  end
62
58
  stdout
63
59
  end
64
60
 
65
61
  private
66
62
 
67
- def diff(wallet, cps, _)
63
+ def diff(id, cps, _)
68
64
  raise "There are no remote copies, try 'zold fetch' first" if cps.all.empty?
69
65
  cps = cps.all.sort_by { |c| c[:score] }.reverse
70
66
  patch = Patch.new(@wallets, log: @log)
71
67
  cps.each do |c|
72
68
  patch.join(Wallet.new(c[:path]))
73
69
  end
74
- before = AtomicFile.new(wallet.path).read
70
+ before = @wallets.find(id) do |wallet|
71
+ AtomicFile.new(wallet.path).read
72
+ end
75
73
  after = ''
76
74
  Tempfile.open(['', Wallet::EXTENSION]) do |f|
77
75
  patch.save(f.path, overwrite: true)
@@ -77,6 +77,7 @@ Available options:"
77
77
  private
78
78
 
79
79
  def fetch(id, cps, opts)
80
+ start = Time.now
80
81
  total = Concurrent::AtomicFixnum.new
81
82
  nodes = Concurrent::AtomicFixnum.new
82
83
  done = Concurrent::AtomicFixnum.new
@@ -87,7 +88,7 @@ Available options:"
87
88
  end
88
89
  raise "There are no remote nodes, run 'zold remote reset'" if nodes.value.zero?
89
90
  raise "No nodes out of #{nodes.value} have the wallet #{id}" if done.value.zero? && !opts['quiet-if-absent']
90
- @log.info("#{done.value} copies of #{id} fetched with the total score of \
91
+ @log.info("#{done.value} copies of #{id} fetched in #{(Time.now - start).round}s with the total score of \
91
92
  #{total.value} from #{nodes.value} nodes")
92
93
  @log.debug("#{cps.all.count} local copies:")
93
94
  cps.all.each do |c|
@@ -127,7 +128,7 @@ Available options:"
127
128
  end
128
129
  copy = cps.add(File.read(f), score.host, score.port, score.value)
129
130
  @log.info("#{r} returned #{body.length}b/#{wallet.balance}/#{wallet.txns.count}t/\
130
- #{digest(json)}/#{Age.new(json['mtime'])} \
131
+ #{digest(json)}/#{Age.new(json['mtime'])}/#{json['copies']}c \
131
132
  as copy #{copy} of #{id} in #{(Time.now - start).round(2)}s: #{Rainbow(score.value).green} (#{json['version']})")
132
133
  end
133
134
  score.value
@@ -51,9 +51,10 @@ Available options:"
51
51
  mine = Args.new(opts, @log).take || return
52
52
  raise 'Receiver wallet ID is required' if mine[0].nil?
53
53
  id = Zold::Id.new(mine[0])
54
- wallet = @wallets.find(id)
55
- raise "Wallet #{id} doesn\'t exist in #{@wallets}, do 'zold pull' first" unless wallet.exists?
56
- invoice(wallet, opts)
54
+ @wallets.find(id) do |wallet|
55
+ raise "Wallet #{id} doesn\'t exist in #{@wallets}, do 'zold pull' first" unless wallet.exists?
56
+ invoice(wallet, opts)
57
+ end
57
58
  end
58
59
 
59
60
  private
@@ -75,21 +75,22 @@ Available options:"
75
75
  merge_one(opts, patch, wallet, "#{c[:name]}/#{idx}/#{c[:score]}")
76
76
  score += c[:score]
77
77
  end
78
- wallet = @wallets.find(id)
79
- if wallet.exists?
80
- merge_one(opts, patch, wallet, 'localhost')
81
- @log.debug("Local copy of #{id} merged: #{patch}")
82
- else
83
- @log.debug("Local copy of #{id} is absent, nothing to merge")
84
- end
85
- modified = patch.save(wallet.path, overwrite: true)
86
- if modified
87
- @log.info("#{cps.count} copies with the total score of #{score} successfully merged \
78
+ @wallets.find(id) do |wallet|
79
+ if wallet.exists?
80
+ merge_one(opts, patch, wallet, 'localhost')
81
+ @log.debug("Local copy of #{id} merged: #{patch}")
82
+ else
83
+ @log.debug("Local copy of #{id} is absent, nothing to merge")
84
+ end
85
+ modified = patch.save(wallet.path, overwrite: true)
86
+ if modified
87
+ @log.info("#{cps.count} copies with the total score of #{score} successfully merged \
88
88
  into #{wallet.id}/#{wallet.balance}/#{wallet.txns.count}t")
89
- else
90
- @log.info("Nothing changed in #{wallet.id} after merge of #{cps.count} copies")
89
+ else
90
+ @log.info("Nothing changed in #{wallet.id} after merge of #{cps.count} copies")
91
+ end
92
+ modified
91
93
  end
92
- modified
93
94
  end
94
95
 
95
96
  def merge_one(opts, patch, wallet, name)
@@ -28,19 +28,21 @@ require_relative '../backtrace'
28
28
  require_relative '../metronome'
29
29
  require_relative '../wallet'
30
30
  require_relative '../wallets'
31
- require_relative '../hungry_wallets'
32
31
  require_relative '../remotes'
33
32
  require_relative '../verbose_thread'
34
33
  require_relative '../node/entrance'
35
34
  require_relative '../node/safe_entrance'
36
35
  require_relative '../node/spread_entrance'
37
36
  require_relative '../node/async_entrance'
37
+ require_relative '../node/sync_entrance'
38
38
  require_relative '../node/nodup_entrance'
39
39
  require_relative '../node/front'
40
+ require_relative '../node/trace'
40
41
  require_relative '../node/farm'
41
42
  require_relative 'pull'
42
43
  require_relative 'push'
43
44
  require_relative 'pay'
45
+ require_relative 'remote'
44
46
 
45
47
  # NODE command.
46
48
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
@@ -50,10 +52,10 @@ module Zold
50
52
  # NODE command
51
53
  class Node
52
54
  def initialize(wallets:, remotes:, copies:, log: Log::Quiet.new)
53
- @wallets = HungryWallets.new(wallets)
54
55
  @remotes = remotes
55
56
  @copies = copies
56
57
  @log = log
58
+ @wallets = wallets
57
59
  end
58
60
 
59
61
  def run(args = [])
@@ -97,6 +99,9 @@ module Zold
97
99
  o.string '--halt-code',
98
100
  'The value of HTTP query parameter "halt," which will cause the front-end immediate termination',
99
101
  default: ''
102
+ o.integer '--trace-length',
103
+ 'Maximum length of the trace to keep in memory (default: 4096)',
104
+ default: 4096
100
105
  o.string '--save-pid',
101
106
  'The file to save process ID into right after start (only in NOHUP mode)'
102
107
  o.bool '--never-reboot',
@@ -140,7 +145,9 @@ module Zold
140
145
  @log.info(pid)
141
146
  return
142
147
  end
143
- Front.set(:log, @log)
148
+ trace = Trace.new(@log, opts['trace-length'])
149
+ Front.set(:log, trace)
150
+ Front.set(:trace, trace)
144
151
  Front.set(:version, opts['expose-version'])
145
152
  Front.set(:protocol, Zold::PROTOCOL)
146
153
  Front.set(:logging, @log.debug?)
@@ -152,9 +159,13 @@ module Zold
152
159
  @log.info("Zold protocol version: #{Zold::PROTOCOL}")
153
160
  @log.info("Network ID: #{opts['network']}")
154
161
  host = opts[:host] || ip
155
- address = "#{host}:#{opts[:port]}".downcase
162
+ port = opts[:port]
163
+ address = "#{host}:#{port}".downcase
156
164
  @log.info("Node location: #{address}")
157
165
  @log.info("Local address: http://localhost:#{opts['bind-port']}/")
166
+ @log.info("Remote nodes (#{@remotes.all.count}): \
167
+ #{@remotes.all.map { |r| "#{r[:host]}:#{r[:port]}" }.join(', ')}")
168
+ @log.info("Wallets at: #{@wallets.path}")
158
169
  Front.set(
159
170
  :server_settings,
160
171
  Logger: WebrickLog.new(@log),
@@ -163,6 +174,9 @@ module Zold
163
174
  if opts['standalone']
164
175
  @remotes = Zold::Remotes::Empty.new(file: '/tmp/standalone')
165
176
  @log.debug('Running in standalone mode! (will never talk to other remotes)')
177
+ else
178
+ Zold::Remote.new(remotes: @remotes).run(['remote', 'remove', host, port.to_s, '--force'])
179
+ @log.info("Removed current node (#{address}) from list of remotes")
166
180
  end
167
181
  Front.set(:ignore_score_weakness, opts['ignore-score-weakness'])
168
182
  Front.set(:network, opts['network'])
@@ -175,21 +189,22 @@ module Zold
175
189
  Front.set(:port, opts['bind-port'])
176
190
  Front.set(:reboot, !opts['never-reboot'])
177
191
  node_alias = opts[:alias] || address
178
- unless node_alias.eql?(address)
179
- re = Regexp.new(/^[a-z0-9]{4,16}$/)
180
- raise '--alias should be a 4 to 16 char long alphanumeric string' unless re.match(node_alias)
192
+ unless node_alias.eql?(address) || node_alias =~ /^[a-z0-9]{4,16}$/
193
+ raise "Alias should be a 4 to 16 char long alphanumeric string: #{node_alias}"
181
194
  end
182
195
  Front.set(:node_alias, node_alias)
183
196
  invoice = opts[:invoice]
184
197
  unless invoice.include?('@')
185
- if @wallets.find(Id.new(invoice)).exists?
186
- @log.info("Wallet #{invoice} already exists locally, won't pull")
187
- else
188
- @log.info("The wallet #{invoice} is not available locally, will pull now...")
189
- require_relative 'pull'
190
- Pull.new(wallets: @wallets, remotes: @remotes, copies: @copies, log: @log).run(
191
- ['pull', invoice, "--network=#{opts['network']}"]
192
- )
198
+ @wallets.find(Id.new(invoice)) do |wallet|
199
+ if wallet.exists?
200
+ @log.info("Wallet #{invoice} already exists locally, won't pull")
201
+ else
202
+ @log.info("The wallet #{invoice} is not available locally, will pull now...")
203
+ require_relative 'pull'
204
+ Pull.new(wallets: @wallets, remotes: @remotes, copies: @copies, log: @log).run(
205
+ ['pull', invoice, "--network=#{opts['network']}"]
206
+ )
207
+ end
193
208
  end
194
209
  require_relative 'invoice'
195
210
  invoice = Invoice.new(wallets: @wallets, log: @log).run(['invoice', invoice])
@@ -198,7 +213,15 @@ module Zold
198
213
  NoDupEntrance.new(
199
214
  AsyncEntrance.new(
200
215
  SpreadEntrance.new(
201
- Entrance.new(@wallets, @remotes, @copies, address, log: @log, network: opts['network']),
216
+ SyncEntrance.new(
217
+ Entrance.new(
218
+ @wallets,
219
+ @remotes, @copies, address,
220
+ log: @log, network: opts['network']
221
+ ),
222
+ File.join(Dir.pwd, '.zoldata/entrance'),
223
+ log: @log
224
+ ),
202
225
  @wallets, @remotes, address,
203
226
  log: @log,
204
227
  ignore_score_weakeness: opts['ignore-score-weakness']
@@ -293,7 +316,7 @@ module Zold
293
316
  metronome.add(Routines::Spread.new(opts, @wallets, @remotes, log: @log))
294
317
  unless opts['standalone']
295
318
  require_relative 'routines/reconnect'
296
- metronome.add(Routines::Reconnect.new(opts, @remotes, farm, network: opts['network'], log: Log::Quiet.new))
319
+ metronome.add(Routines::Reconnect.new(opts, @remotes, farm, network: opts['network'], log: @log))
297
320
  end
298
321
  @log.info('Metronome created')
299
322
  metronome
@@ -67,8 +67,6 @@ Available options:"
67
67
  mine = Args.new(opts, @log).take || return
68
68
  raise 'Payer wallet ID is required as the first argument' if mine[0].nil?
69
69
  id = Id.new(mine[0])
70
- from = @wallets.find(id)
71
- raise "Wallet #{id} doesn't exist, do 'zold pull' first" unless from.exists?
72
70
  raise 'Recepient\'s invoice or wallet ID is required as the second argument' if mine[1].nil?
73
71
  invoice = mine[1]
74
72
  unless invoice.include?('@')
@@ -78,20 +76,29 @@ Available options:"
78
76
  raise 'Amount is required (in ZLD) as the third argument' if mine[2].nil?
79
77
  amount = Amount.new(zld: mine[2].to_f)
80
78
  details = mine[3] || '-'
81
- if Tax.new(from).in_debt? && !opts['dont-pay-taxes']
82
- require_relative 'taxes'
83
- Taxes.new(wallets: @wallets, remotes: @remotes, log: @log).run(
84
- ['taxes', 'pay', "--private-key=#{opts['private-key']}", id.to_s]
85
- )
79
+ taxes(id)
80
+ @wallets.find(id) do |from|
81
+ pay(from, invoice, amount, details, opts)
86
82
  end
87
- pay(from, invoice, amount, details, opts)
88
83
  return if opts['skip-propagate']
89
84
  require_relative 'propagate'
90
- Propagate.new(wallets: @wallets, log: @log).run(['propagate', from.id.to_s])
85
+ Propagate.new(wallets: @wallets, log: @log).run(['propagate', id.to_s])
91
86
  end
92
87
 
93
88
  private
94
89
 
90
+ def taxes(id)
91
+ debt = @wallets.find(id) do |wallet|
92
+ raise "Wallet #{id} doesn't exist, do 'zold pull' first" unless wallet.exists?
93
+ Tax.new(wallet).in_debt? && !opts['dont-pay-taxes']
94
+ end
95
+ return unless debt
96
+ require_relative 'taxes'
97
+ Taxes.new(wallets: @wallets, remotes: @remotes, log: @log).run(
98
+ ['taxes', 'pay', "--private-key=#{opts['private-key']}", id.to_s]
99
+ )
100
+ end
101
+
95
102
  def pay(from, invoice, amount, details, opts)
96
103
  unless opts.force?
97
104
  raise 'The amount can\'t be zero' if amount.zero?
@@ -51,7 +51,7 @@ Available options:"
51
51
  mine = @wallets.all if mine.empty?
52
52
  modified = []
53
53
  mine.map { |i| Id.new(i) }.each do |id|
54
- modified += propagate(@wallets.find(id), opts)
54
+ modified += propagate(id, opts)
55
55
  end
56
56
  modified
57
57
  end
@@ -59,30 +59,33 @@ Available options:"
59
59
  private
60
60
 
61
61
  # Returns list of Wallet IDs which were affected
62
- def propagate(wallet, _)
63
- me = wallet.id
62
+ def propagate(id, _)
64
63
  modified = []
65
- wallet.txns.select { |t| t.amount.negative? }.each do |t|
66
- target = @wallets.find(t.bnf)
67
- unless target.exists?
68
- @log.debug("#{t.amount * -1} to #{t.bnf}: wallet is absent")
69
- next
64
+ @wallets.find(id) do |wallet|
65
+ wallet.txns.select { |t| t.amount.negative? }.each do |t|
66
+ next if t.bnf == id
67
+ @wallets.find(t.bnf) do |target|
68
+ unless target.exists?
69
+ @log.debug("#{t.amount * -1} to #{t.bnf}: wallet is absent")
70
+ next
71
+ end
72
+ unless target.network == wallet.network
73
+ @log.error("#{t.amount * -1} to #{t.bnf}: network mismatch, '#{target.network}'!='#{wallet.network}'")
74
+ next
75
+ end
76
+ next if target.has?(t.id, id)
77
+ unless target.prefix?(t.prefix)
78
+ @log.error("#{t.amount * -1} to #{t.bnf}: wrong prefix")
79
+ next
80
+ end
81
+ target.add(t.inverse(id))
82
+ @log.info("#{t.amount * -1} arrived to #{t.bnf}: #{t.details}")
83
+ modified << t.bnf
84
+ end
70
85
  end
71
- unless target.network == wallet.network
72
- @log.error("#{t.amount * -1} to #{t.bnf}: network mismatch, '#{target.network}'!='#{wallet.network}'")
73
- next
74
- end
75
- next if target.has?(t.id, me)
76
- unless target.prefix?(t.prefix)
77
- @log.error("#{t.amount * -1} to #{t.bnf}: wrong prefix")
78
- next
79
- end
80
- target.add(t.inverse(me))
81
- @log.info("#{t.amount * -1} arrived to #{t.bnf}: #{t.details}")
82
- modified << t.bnf
83
86
  end
84
87
  modified.uniq!
85
- @log.debug("Wallet #{me} propagated successfully, #{modified.count} wallets affected")
88
+ @log.debug("Wallet #{id} propagated successfully, #{modified.count} wallets affected")
86
89
  modified
87
90
  end
88
91
  end