zold 0.7 → 0.8

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cb70a77181642453c08fcda55cd1179d84ad47d3
4
- data.tar.gz: 4d5c99e488c3196efcb4b98b5f698fadddd72625
3
+ metadata.gz: 5ea54309f6fdd147d4338a76415d536e802ffa00
4
+ data.tar.gz: 2cc82cfbe9c204480db65348cc551abad0817d92
5
5
  SHA512:
6
- metadata.gz: b692c87274e9fe516d80cccee43ccc172f03b151732d33271bf6a256e0fd2355af8d0bce3517dc19e7f7b9842c2f778734c0501c3093e6130b561f60da2c933b
7
- data.tar.gz: b0c91ee622378ebcb8b96816c8281ac463153fc6d2daca6591322f3fbd8011cf3b2df954ce5178834efa9833a0711f29f25bd09831597cd153d65d5926971503
6
+ metadata.gz: 64bfd2b5f86befba60e4f976cef6e4e17d3233c5a8d7d48b214dc4e4bbe787afe351a4e783355baa63f844410d1ef923feac211d6186db45215512c79fc79c8e
7
+ data.tar.gz: f648ceffd6b1b5c2d34fd88816cc77dc8705bf3382ae2b6a22397894fd3d1d010168736c38ce2e934196c20b50deabb41d507d6992b1c9531fc8e01a4374136a
data/README.md CHANGED
@@ -93,3 +93,22 @@ $ zold node --invoice=5f96e731e48ae21f
93
93
 
94
94
  Grateful users of the system will pay "taxes" to your wallet for processing
95
95
  of their transactions.
96
+
97
+ ## How to Contribute
98
+
99
+ It is a Ruby command line gem. First, install
100
+ [Ruby](https://www.ruby-lang.org/en/documentation/installation/) 2.3+,
101
+ [Rubygems](https://rubygems.org/pages/download),
102
+ and
103
+ [Bundler](https://bundler.io/).
104
+ Then:
105
+
106
+ ```bash
107
+ $ bundle update
108
+ $ rake
109
+ ```
110
+
111
+ The build has to be clean. If it's not, [submit an issue](https://github.com/zerocracy/zold/issues).
112
+
113
+ Then, make your changes, make sure the build is still clean,
114
+ and [submit a pull request](https://www.yegor256.com/2014/04/15/github-guidelines.html).
@@ -19,6 +19,7 @@
19
19
  # SOFTWARE.
20
20
 
21
21
  require_relative '../log'
22
+ require_relative '../wallet'
22
23
 
23
24
  # LIST command.
24
25
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
@@ -35,7 +36,9 @@ module Zold
35
36
  def run(_ = [])
36
37
  @wallets.all.each do |id|
37
38
  wallet = Wallet.new(File.join(@wallets.path, id))
38
- @log.info("#{id}: #{wallet.balance}")
39
+ msg = "#{id}: #{wallet.balance}"
40
+ msg += " (net:#{wallet.network})" if wallet.network != Wallet::MAIN_NETWORK
41
+ @log.info(msg)
39
42
  end
40
43
  end
41
44
  end
@@ -64,9 +64,13 @@ Available options:"
64
64
  @log.debug("#{t.amount * -1} to #{t.bnf}: wallet is absent")
65
65
  next
66
66
  end
67
+ unless target.network == wallet.network
68
+ @log.error("#{t.amount * -1} to #{t.bnf}: network mismatch, '#{target.network}'!='#{wallet.network}'")
69
+ next
70
+ end
67
71
  next if target.has?(t.id, me)
68
72
  unless Prefixes.new(target).valid?(t.prefix)
69
- @log.info("#{t.amount * -1} to #{t.bnf}: wrong prefix")
73
+ @log.error("#{t.amount * -1} to #{t.bnf}: wrong prefix")
70
74
  next
71
75
  end
72
76
  target.add(t.inverse(me))
@@ -24,6 +24,7 @@ require_relative 'args'
24
24
  require_relative '../log'
25
25
  require_relative '../id'
26
26
  require_relative '../amount'
27
+ require_relative '../wallet'
27
28
 
28
29
  # SHOW command.
29
30
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
@@ -61,7 +62,9 @@ Available options:"
61
62
  wallet.txns.each do |t|
62
63
  @log.info(t.to_text)
63
64
  end
64
- @log.info("The balance of #{wallet}: #{balance}")
65
+ msg = "The balance of #{wallet}: #{balance}"
66
+ msg += " (net:#{wallet.network})" if wallet.network != Wallet::MAIN_NETWORK
67
+ @log.info(msg)
65
68
  balance
66
69
  end
67
70
  end
@@ -0,0 +1,58 @@
1
+ # Copyright (c) 2018 Yegor Bugayenko
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the 'Software'), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all
11
+ # copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ # SOFTWARE.
20
+
21
+ require 'concurrent'
22
+ require 'tempfile'
23
+ require_relative '../log'
24
+ require_relative '../remotes'
25
+ require_relative '../copies'
26
+ require_relative '../tax'
27
+ require_relative '../commands/merge'
28
+ require_relative '../commands/fetch'
29
+ require_relative '../commands/push'
30
+
31
+ # The emission control point.
32
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
33
+ # Copyright:: Copyright (c) 2018 Yegor Bugayenko
34
+ # License:: MIT
35
+ module Zold
36
+ # The emission control poine
37
+ class Emission
38
+ def initialize(root)
39
+ @root = root
40
+ end
41
+
42
+ def quota
43
+ 2**(-2048 / @root.age)
44
+ end
45
+
46
+ def limit
47
+ max = 2**63
48
+ Amount.new(coins: (max * quota).to_i)
49
+ end
50
+
51
+ def check
52
+ return unless @root.root?
53
+ allowed = limit
54
+ balance = @root.balance
55
+ raise "The balance #{balance} of the root wallet is too low (max allowed: #{allowed})" if balance < allowed
56
+ end
57
+ end
58
+ end
@@ -19,6 +19,8 @@
19
19
  # SOFTWARE.
20
20
 
21
21
  require 'concurrent'
22
+ require 'tempfile'
23
+ require_relative 'emission'
22
24
  require_relative '../log'
23
25
  require_relative '../remotes'
24
26
  require_relative '../copies'
@@ -44,12 +46,28 @@ module Zold
44
46
  end
45
47
 
46
48
  def push(id, body)
49
+ check(body)
47
50
  @semaphores.put_if_absent(id, Mutex.new)
48
51
  @semaphores.get(id).synchronize do
49
52
  push_unsafe(id, body)
50
53
  end
51
54
  end
52
55
 
56
+ def check(body)
57
+ Tempfile.open do |f|
58
+ File.write(f.path, body)
59
+ wallet = Wallet.new(f)
60
+ break unless wallet.network == Wallet::MAIN_NETWORK
61
+ balance = wallet.balance
62
+ raise "The balance #{balance} is negative and it's not a root wallet" if balance.negative? && !wallet.root?
63
+ Emission.new(wallet).check
64
+ debt = Tax.new(wallet).debt
65
+ if debt > Tax::TRIAL
66
+ raise "Taxes are not paid, the debt is #{debt} (#{debt.to_i} zents), won't promote the wallet"
67
+ end
68
+ end
69
+ end
70
+
53
71
  def push_unsafe(id, body)
54
72
  copies = Copies.new(File.join(@copies, id.to_s))
55
73
  copies.add(body, 'remote', Remotes::PORT, 0)
@@ -59,10 +77,6 @@ module Zold
59
77
  modified = Merge.new(
60
78
  wallets: @wallets, copies: copies.root, log: @log
61
79
  ).run(['merge', id.to_s])
62
- debt = Tax.new(@wallets.find(id)).debt
63
- if debt > Tax::TRIAL
64
- raise "Taxes are not paid, the debt is #{debt} (#{debt.to_i} zents), won't promote the wallet"
65
- end
66
80
  copies.remove('remote', Remotes::PORT)
67
81
  modified.each do |m|
68
82
  Push.new(
data/lib/zold/tax.rb CHANGED
@@ -69,8 +69,7 @@ module Zold
69
69
  score
70
70
  end.reject(&:nil?).uniq(&:hash)
71
71
  paid = scores.empty? ? Amount::ZERO : scores.map(&:amount).inject(&:+) * -1
72
- age_hours = txns.empty? ? 0 : (Time.now - txns.sort_by(&:date)[0].date) / 60
73
- owned = Tax::FEE_TXN_HOUR * txns.count * age_hours
72
+ owned = Tax::FEE_TXN_HOUR * txns.count * @wallet.age
74
73
  owned - paid
75
74
  end
76
75
  end
data/lib/zold/version.rb CHANGED
@@ -23,5 +23,5 @@
23
23
  # Copyright:: Copyright (c) 2018 Yegor Bugayenko
24
24
  # License:: MIT
25
25
  module Zold
26
- VERSION = '0.7'.freeze
26
+ VERSION = '0.8'.freeze
27
27
  end
data/lib/zold/wallet.rb CHANGED
@@ -38,6 +38,10 @@ require_relative 'signature'
38
38
  module Zold
39
39
  # A single wallet
40
40
  class Wallet
41
+ # The name of the main production network. All other networks
42
+ # must have different names.
43
+ MAIN_NETWORK = 'zold'.freeze
44
+
41
45
  def initialize(file)
42
46
  @file = file
43
47
  end
@@ -127,6 +131,12 @@ module Zold
127
131
  end
128
132
  end
129
133
 
134
+ # Age of wallet in hours
135
+ def age
136
+ list = txns
137
+ list.empty? ? 0 : (Time.now - list.sort_by(&:date)[0].date) / 60
138
+ end
139
+
130
140
  def txns
131
141
  lines.drop(5)
132
142
  .each_with_index
@@ -0,0 +1,46 @@
1
+ # Copyright (c) 2018 Yegor Bugayenko
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the 'Software'), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all
11
+ # copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ # SOFTWARE.
20
+
21
+ require 'minitest/autorun'
22
+ require 'tmpdir'
23
+ require_relative '../test__helper'
24
+ require_relative '../../lib/zold/node/emission'
25
+ require_relative '../../lib/zold/amount'
26
+
27
+ class EmissionTest < Minitest::Test
28
+ def test_emission
29
+ (1..10).each do |year|
30
+ Dir.mktmpdir 'test' do |dir|
31
+ id = Zold::Id.new
32
+ wallet = Zold::Wallet.new(File.join(dir, id.to_s))
33
+ wallet.init(id, Zold::Key.new(file: 'fixtures/id_rsa.pub'))
34
+ wallet.add(
35
+ Zold::Txn.new(
36
+ 1, Time.now - 24 * 365 * year,
37
+ Zold::Amount.new(zld: 39.99),
38
+ 'NOPREFIX', Zold::Id::ROOT, '-'
39
+ )
40
+ )
41
+ $log.info("Year: #{year}, Quota: #{(Zold::Emission.new(wallet).quota * 100).round(2)}%, \
42
+ Limit: #{Zold::Emission.new(wallet).limit}")
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,29 @@
1
+ # Copyright (c) 2018 Yegor Bugayenko
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the 'Software'), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all
11
+ # copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ # SOFTWARE.
20
+
21
+ require 'minitest/autorun'
22
+ require_relative '../../lib/zold/node/entrance'
23
+ require_relative '../../lib/zold/amount'
24
+
25
+ class EntranceTest < Minitest::Test
26
+ def test_something
27
+ # tbd...
28
+ end
29
+ end
data/test/test__helper.rb CHANGED
@@ -31,6 +31,7 @@ end
31
31
 
32
32
  require_relative '../lib/zold/log'
33
33
  $log = Zold::Log::Quiet.new
34
+ # $log = Zold::Log::Verbose.new
34
35
 
35
36
  require 'minitest/autorun'
36
37
  require_relative '../lib/zold'
data/test/test_zold.rb CHANGED
@@ -21,6 +21,7 @@
21
21
  require 'minitest/autorun'
22
22
  require 'tmpdir'
23
23
  require 'English'
24
+ require_relative 'test__helper'
24
25
 
25
26
  # Zold main module test.
26
27
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
@@ -37,10 +38,8 @@ class TestZold < Minitest::Test
37
38
  bin = File.join(Dir.pwd, 'bin/zold')
38
39
  Dir.chdir(dir) do
39
40
  stdout = `/bin/bash #{f} #{bin} 2>&1`
40
- unless $CHILD_STATUS.exitstatus.zero?
41
- $log.info(stdout)
42
- assert_equal($CHILD_STATUS.exitstatus, 0)
43
- end
41
+ $log.info(stdout)
42
+ assert_equal(0, $CHILD_STATUS.exitstatus)
44
43
  end
45
44
  end
46
45
  end
data/wp/wp.tex CHANGED
@@ -5,6 +5,7 @@
5
5
  \usepackage{microtype}
6
6
  \usepackage{mathpazo} % Palantino font
7
7
  \usepackage{mdframed}
8
+ \usepackage{pgfplots}
8
9
  \usepackage{minted}
9
10
  \setminted{fontsize=\small}
10
11
  \setminted{breaklines}
@@ -92,11 +93,12 @@ One ZLD by convention equals to $2^{24}$ \emph{zents} (16,777,216).
92
93
  All amounts are stored as signed 64-bit integers.
93
94
  Thus, the technical capacity of the currency is 549,755,813,888 ZLD (half a trillion).
94
95
 
95
- \textbf{Zero Wallet}.
96
- There is no ``mining,'' the only way to get ZLD is to receive it from someone else.
97
- The wallet with the \dd{0x00} ID belongs to the
98
- issuer and may have a negative balance. All other wallets
99
- may only have positive balances.
96
+ \textbf{Root Wallet}.
97
+ Zold is a pre-mined currency.
98
+ The only way to get ZLD is to receive it from someone else.
99
+ The root wallet belongs to the issuer and may have a negative balance,
100
+ which can grow according to a pre-defined restrictive formula.
101
+ All other wallets may only have positive balances.
100
102
 
101
103
  \colorbox{yellow}{Let's compare each of these principles with other currencies and highlight similarities.}
102
104
 
@@ -268,6 +270,51 @@ Each transaction takes 900 symbols at most.
268
270
  The maximum amount of transactions in one wallet is 65536.
269
271
  Thus, a single wallet may be as big as a 59Mb text file, at most.
270
272
 
273
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
274
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
275
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
276
+ \section{Mining Formula}
277
+
278
+ The only way to get ZLD is to receive it from the \emph{root} wallet \dd{0000000000000000}.
279
+ This wallet is the only one that may have a negative ballance.
280
+ However, to prevent an uncontrolled emission of ZLD, the balance
281
+ of this wallet must satisfy the formula:
282
+
283
+ $$x = \frac{2048}{h};\quad z = 2^{63 - x}.$$
284
+
285
+ Here $h$ is the age of the root wallet in hours and $z$ is the maximum
286
+ amount of zents it can issue at that moment. The first
287
+ six years will look like this:
288
+
289
+ \vspace{\parskip}\begin{center}\begin{tabular}{lrr}
290
+ \hline
291
+ Year & ZLD & Share \\
292
+ \hline
293
+ 1st & 32m & 0.01\% \\
294
+ 2nd & 4b & 0.77\% \\
295
+ 3rd & 21b & 4\%\\
296
+ 4th & 48b & 9\% \\
297
+ 5th & 78b & 14\% \\
298
+ 6th & 108b & 20\% \\
299
+ \hline
300
+ \end{tabular}\end{center}
301
+
302
+ On a large perspective of 25 years total emission of ZLD will look
303
+ like this:
304
+
305
+ \vspace{\parskip}\begin{center}\begin{tikzpicture}
306
+ \begin{axis}[
307
+ axis lines=middle,
308
+ width=12cm,height=5cm,
309
+ xlabel={Age, in years},
310
+ ylabel={Billions of ZLD},
311
+ ]
312
+ \addplot[domain=-0:25, samples=25]{2^(39-2048/(x*24*365)) / 1000000000};
313
+ \end{axis}
314
+ \end{tikzpicture}\end{center}
315
+
316
+ The limitation is hardwired in Zold software and can't be eliminated.
317
+
271
318
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
272
319
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
273
320
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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.7'
4
+ version: '0.8'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yegor Bugayenko
@@ -298,6 +298,7 @@ files:
298
298
  - lib/zold/id.rb
299
299
  - lib/zold/key.rb
300
300
  - lib/zold/log.rb
301
+ - lib/zold/node/emission.rb
301
302
  - lib/zold/node/entrance.rb
302
303
  - lib/zold/node/farm.rb
303
304
  - lib/zold/node/front.rb
@@ -327,6 +328,8 @@ files:
327
328
  - test/commands/test_show.rb
328
329
  - test/commands/test_taxes.rb
329
330
  - test/node/fake_node.rb
331
+ - test/node/test_emission.rb
332
+ - test/node/test_entrance.rb
330
333
  - test/node/test_farm.rb
331
334
  - test/node/test_front.rb
332
335
  - test/test__helper.rb
@@ -396,6 +399,8 @@ test_files:
396
399
  - test/commands/test_show.rb
397
400
  - test/commands/test_taxes.rb
398
401
  - test/node/fake_node.rb
402
+ - test/node/test_emission.rb
403
+ - test/node/test_entrance.rb
399
404
  - test/node/test_farm.rb
400
405
  - test/node/test_front.rb
401
406
  - test/test__helper.rb