zold 0.11.14 → 0.11.15

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
  SHA1:
3
- metadata.gz: f6e2499c65eb639ec4dd6a1177e4cf6186269688
4
- data.tar.gz: c5482c8cb8b66a97f097626009ee0b461a57cc19
3
+ metadata.gz: ca4077a7a79a8ff6e6cc6ca27ebeda18571a3b7a
4
+ data.tar.gz: b5259cec4a2a73e33be07e387466a3b020d30be7
5
5
  SHA512:
6
- metadata.gz: 6e0cad7598ca9560cfde7a8a7e9cc3ffb53065931c063e0f7ff69d8668e489d9a72f795707ee931a1ddf5715340fb38bb160a56fd366ae239aa368fb094340d3
7
- data.tar.gz: 423b9534d67f3479accfcc33db73818c9574161c21131d62dae5b149179394da25ce9812dcf196bfc89412984f2b846e62dcc89926d00e9fc6881e0cf10f752c
6
+ metadata.gz: 4251510624adf3efade782f91cf3ba44bccbd1dfd2561da972253abbd3ab0aff08940c57a66e642a25ea5d42c706167d892babb1871bf8fbe25f684a4fd48da9
7
+ data.tar.gz: 27a737d9cccff7cd12c97ff096b69860ee0542f01f2a33908d05bbce0828429d847b6ca12c1d71c03f3273ed83196cfccc18f056a71ec4c972cdef605c829342
data/INSTALL.md CHANGED
@@ -14,16 +14,16 @@ then the [gem](https://rubygems.org/gems/zold).
14
14
 
15
15
  ```bash
16
16
  $ sudo apt update -y
17
- $ sudo apt install -y ruby-dev rubygems zlib1g-dev libssl-dev make
18
- $ gem install zold
17
+ $ sudo apt install -y ruby-dev rubygems zlib1g-dev libssl-dev make build-essential
18
+ $ gem install --no-ri --no-rdoc zold
19
19
  ```
20
20
 
21
21
  ## Ubuntu 16.04
22
22
 
23
23
  ```bash
24
24
  $ sudo apt-get update -y
25
- $ sudo apt-get install -y ruby-dev rubygems zlib1g-dev libssl-dev
26
- $ gem install zold
25
+ $ sudo apt-get install -y ruby-dev rubygems zlib1g-dev libssl-dev build-essential
26
+ $ gem install --no-ri --no-rdoc zold
27
27
  ```
28
28
 
29
29
  ## OSX
@@ -35,7 +35,7 @@ $ brew install rbenv ruby-build
35
35
  $ rbenv install 2.5.1
36
36
  $ rbenv global 2.5.1
37
37
  $ ruby -v
38
- $ gem install zold
38
+ $ gem install --no-ri --no-rdoc zold
39
39
  ```
40
40
 
41
41
  Without homebrew:
@@ -63,12 +63,16 @@ Available options:"
63
63
  private
64
64
 
65
65
  def diff(wallet, cps, _)
66
- raise 'There are no remote copies, try FETCH first' if cps.all.empty?
66
+ raise "There are no remote copies, try 'zold fetch' first" if cps.all.empty?
67
67
  cps = cps.all.sort_by { |c| c[:score] }.reverse
68
68
  patch = Patch.new
69
- patch.start(Wallet.new(cps[0][:path]))
70
- cps[1..-1].each do |c|
71
- patch.join(Wallet.new(c[:path]))
69
+ cps.each do |c|
70
+ begin
71
+ patch.join(Wallet.new(c[:path]))
72
+ rescue StandardError => e
73
+ @log.error("Can't use a copy of #{wallet.id} from #{c[:host]}:#{c[:port]}; #{e.class.name}: #{e.message}")
74
+ @log.debug(e.backtrace.join("\n\t"))
75
+ end
72
76
  end
73
77
  before = AtomicFile.new(wallet.path).read
74
78
  after = ''
@@ -65,22 +65,18 @@ Available options:"
65
65
  @log.error("There are no remote copies of #{id}, try 'zold fetch' first")
66
66
  return
67
67
  end
68
- wallet = @wallets.find(id)
69
68
  cps = cps.all.sort_by { |c| c[:score] }.reverse
70
69
  patch = Patch.new
71
- main = Wallet.new(cps[0][:path])
72
- patch.start(main)
73
- cps[1..-1].each do |c|
74
- extra = Wallet.new(c[:path])
75
- if extra.network != main.network
76
- @log.error("The wallet is from a different network '#{extra.network}', ours is '#{main.network}'")
77
- next
78
- end
79
- if extra.key != main.key
80
- @log.error('Public key mismatch')
81
- next
82
- end
83
- patch.join(extra)
70
+ cps.each do |c|
71
+ merge_one(patch, Wallet.new(c[:path]), "#{c[:host]}:#{c[:port]}")
72
+ @log.debug("#{c[:host]}:#{c[:port]} merged: #{patch}")
73
+ end
74
+ wallet = @wallets.find(id)
75
+ if wallet.exists?
76
+ merge_one(patch, wallet, 'localhost')
77
+ @log.debug("Local copy merged: #{patch}")
78
+ else
79
+ @log.debug("Local copy is absent, won't merge")
84
80
  end
85
81
  modified = patch.save(wallet.path, overwrite: true)
86
82
  if modified
@@ -90,5 +86,12 @@ Available options:"
90
86
  end
91
87
  modified
92
88
  end
89
+
90
+ def merge_one(patch, wallet, name)
91
+ patch.join(wallet)
92
+ rescue StandardError => e
93
+ @log.error("Can't merge a copy coming from #{name}; #{e.class.name}: #{e.message}")
94
+ @log.debug(e.backtrace.join("\n\t"))
95
+ end
93
96
  end
94
97
  end
@@ -94,6 +94,8 @@ module Zold
94
94
  load.group_by { |s| s[:name] }.map do |name, scores|
95
95
  {
96
96
  name: name,
97
+ host: scores[0][:host],
98
+ port: scores[0][:port],
97
99
  path: File.join(@dir, name),
98
100
  score: scores.select { |s| s[:time] > Time.now - 24 * 60 * 60 }
99
101
  .map { |s| s[:score] }
@@ -77,7 +77,7 @@ module Zold
77
77
  end
78
78
  s = @scores.pop
79
79
  next unless s.valid?
80
- next if s.expired?
80
+ next if s.expired?(20)
81
81
  next if s.strength < strength
82
82
  @semaphore.synchronize do
83
83
  save(s)
@@ -149,7 +149,7 @@ module Zold
149
149
  wallet = settings.wallets.find(id)
150
150
  request.body.rewind
151
151
  after = request.body.read.to_s
152
- before = wallet.exists? ? AtomicFile.new(wallet.path).read : ''
152
+ before = wallet.exists? ? AtomicFile.new(wallet.path).read.to_s : ''
153
153
  if before == after
154
154
  status 304
155
155
  return
@@ -30,14 +30,23 @@ require_relative 'atomic_file'
30
30
  module Zold
31
31
  # A patch
32
32
  class Patch
33
- def start(wallet)
34
- @id = wallet.id
35
- @key = wallet.key
36
- @txns = wallet.txns
37
- @network = wallet.network
33
+ def to_s
34
+ return 'empty' if @id.nil?
35
+ "#{@txns.count} txns"
38
36
  end
39
37
 
40
38
  def join(wallet)
39
+ if @id.nil?
40
+ @id = wallet.id
41
+ @key = wallet.key
42
+ @txns = wallet.txns
43
+ @network = wallet.network
44
+ end
45
+ if wallet.network != @network
46
+ raise "The wallet is from a different network '#{wallet.network}', ours is '#{@network}'"
47
+ end
48
+ raise 'Public key mismatch' if wallet.key != @key
49
+ raise "Wallet ID mismatch: #{@id} != #{wallet.id}" if wallet.id != @id
41
50
  negative = @txns.select { |t| t.amount.negative? }
42
51
  max = negative.empty? ? 0 : negative.max_by(&:id).id
43
52
  wallet.txns.each do |txn|
@@ -47,13 +56,16 @@ module Zold
47
56
  (txn.id <= max ||
48
57
  @txns.find { |t| t.id == txn.id } ||
49
58
  @txns.map(&:amount).inject(&:+) < txn.amount)
50
- next unless Signature.new.valid?(@key, wallet.id, txn)
59
+ unless Signature.new.valid?(@key, wallet.id, txn)
60
+ raise "Invalid RSA signature at transaction ##{txn.id} of #{wallet.id}"
61
+ end
51
62
  @txns << txn
52
63
  end
53
64
  end
54
65
 
55
66
  # Returns TRUE if the file was actually modified
56
67
  def save(file, overwrite: false)
68
+ raise 'You have to join at least one wallet in' if @id.nil?
57
69
  before = ''
58
70
  before = AtomicFile.new(file).read if File.exist?(file)
59
71
  wallet = Wallet.new(file)
@@ -167,8 +167,8 @@ module Zold
167
167
  (Time.now - @time) / 60
168
168
  end
169
169
 
170
- def expired?
171
- @time < Time.now - 24 * 60 * 60
170
+ def expired?(hours = 24)
171
+ @time < Time.now - hours * 60 * 60
172
172
  end
173
173
 
174
174
  def prefix
@@ -23,5 +23,5 @@
23
23
  # Copyright:: Copyright (c) 2018 Yegor Bugayenko
24
24
  # License:: MIT
25
25
  module Zold
26
- VERSION = '0.11.14'.freeze
26
+ VERSION = '0.11.15'.freeze
27
27
  end
@@ -160,8 +160,10 @@ module Zold
160
160
  end
161
161
 
162
162
  def lines
163
- raise "File '#{@file}' is absent" unless File.exist?(@file)
164
- AtomicFile.new(@file).read.split(/\n/)
163
+ raise "Wallet file '#{@file}' is absent" unless File.exist?(@file)
164
+ lines = AtomicFile.new(@file).read.split(/\n/)
165
+ raise "Not enough lines in #{@file}, just #{lines.count}" if lines.count < 4
166
+ lines
165
167
  end
166
168
  end
167
169
  end
@@ -79,4 +79,31 @@ class TestMerge < Minitest::Test
79
79
  assert(wallet.id, modified[0])
80
80
  end
81
81
  end
82
+
83
+ def test_merges_with_a_broken_copy
84
+ FakeHome.new.run do |home|
85
+ wallet = home.create_wallet
86
+ copies = home.copies(wallet)
87
+ copies.add(File.read(wallet.path), 'good-host', 80, 5)
88
+ copies.add('some garbage', 'bad-host', 80, 5)
89
+ modified = Zold::Merge.new(wallets: home.wallets, copies: copies.root, log: test_log).run(
90
+ ['merge', wallet.id.to_s]
91
+ )
92
+ assert(modified.empty?)
93
+ end
94
+ end
95
+
96
+ def test_merges_a_copy_on_top
97
+ FakeHome.new.run do |home|
98
+ wallet = home.create_wallet
99
+ copies = home.copies(wallet)
100
+ copies.add(File.read(wallet.path), 'good-host', 80, 5)
101
+ key = Zold::Key.new(file: 'fixtures/id_rsa')
102
+ wallet.sub(Zold::Amount.new(zld: 9.99), "NOPREFIX@#{Zold::Id.new}", key)
103
+ Zold::Merge.new(wallets: home.wallets, copies: copies.root, log: test_log).run(
104
+ ['merge', wallet.id.to_s]
105
+ )
106
+ assert(!wallet.balance.zero?)
107
+ end
108
+ end
82
109
  end
@@ -46,9 +46,13 @@ class TestPatch < Minitest::Test
46
46
  t = third.sub(Zold::Amount.new(zld: 10.0), "NOPREFIX@#{Zold::Id.new}", key)
47
47
  third.add(t.inverse(first.id))
48
48
  patch = Zold::Patch.new
49
- patch.start(first)
50
- patch.join(second)
51
- patch.join(third)
49
+ begin
50
+ patch.join(first)
51
+ patch.join(second)
52
+ patch.join(third)
53
+ rescue StandardError => e
54
+ test_log.info("Ignore it: #{e.message}")
55
+ end
52
56
  FileUtils.rm(first.path)
53
57
  assert_equal(true, patch.save(first.path))
54
58
  assert_equal(Zold::Amount.new(zld: -53.0), first.balance)
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.11.14
4
+ version: 0.11.15
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yegor Bugayenko