zold 0.14.28 → 0.14.29

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