zold 0.6.2 → 0.6.3

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: c34164f9da323f0a19a831a982d4904b2c3eaffd
4
- data.tar.gz: 77d4935724eab082b127abdc5505be79d02fe6e8
3
+ metadata.gz: 2005a5319083f1a638f7c4764776cf02c22fec87
4
+ data.tar.gz: 9ffb162b8a5c5daa797b0c1402283d49a81f5d26
5
5
  SHA512:
6
- metadata.gz: fa900d58a11e33b2f8855b62a7bd8503a39c68d1cdd3a270ad85defac1529fb120c38b3be8437513120911a0ec6725d8d23749503c92bd0ac8809dd8aa1767ac
7
- data.tar.gz: 9d73f149efa4a79c9acf55edec7caeb5c12613ec115310a5023ec962fd7786e6975b54c1070965bb21bc7484ff4ad01cb1a1e63ac79bd2a8c2895a4a29331e38
6
+ metadata.gz: 39f357589c34b08f98d405b8ee8307a8044c5809e51fce67a00e87ce53d713be7179ba2098ee548e4b7b9788aa276e9b40ebe271c4ade47cc7917d859a08079a
7
+ data.tar.gz: 18edefa475f83289160649fbfdd07df40e7c494722f5c5352650d3ae1e16d945ea269d430294a9e61e8f6f4d202c1f3efe7c66b4f72b0657dac7a9434e73e2ea
data/.gitattributes CHANGED
@@ -5,3 +5,4 @@
5
5
  * text=auto eol=lf
6
6
  *.rb ident
7
7
  *.xml ident
8
+ *.png binary
data/README.md CHANGED
@@ -45,8 +45,6 @@ yet, you can run:
45
45
  $ ssh-keygen -t rsa -b 4096
46
46
  ```
47
47
 
48
- ## Operations
49
-
50
48
  ### Remote
51
49
 
52
50
  Each node maintains a list of visible "remote" nodes.
@@ -157,42 +155,6 @@ Each HTTP response contains `Content-type` header.
157
155
 
158
156
  ## Files
159
157
 
160
- Each wallet is a text file with the name equal to the wallet ID, for example:
161
-
162
- ```text
163
- 12345678abcdef
164
- AAAAB3NzaC1yc2EAAAADAQABAAABAQCuLuVr4Tl2sXoN5Zb7b6SKMPrVjLxb...
165
-
166
- 34;2017-07-19T21:24:51Z;-560700;98bb82c81735c4ee;for services;SKMPrVjLxbM5oDm0IhniQQy3shF...
167
- 35;2017-07-19T21:25:07Z;-56990;98bb82c81735c4ee;;QCuLuVr4Tl2sXoN5Zb7b6SKMPrVjLxb...
168
- 134;2017-07-19T21:29:11Z;647388;18bb82dd1735b6e9;;
169
- 36;2017-07-19T22:18:43Z;-884733;38ab8fc8e735c4fc;for fun;2sXoN5Zb7b6SKMPrVjLxb7b6SKMPrVjLx...
170
- ```
171
-
172
- Lines are separated by either CR or CRLF, doesn't matter. There is a
173
- header and a ledger, separated by an empty line.
174
- The header includes two lines:
175
-
176
- * Wallet ID, a 64-bit unsigned integer;
177
- * Public RSA key of the wallet owner.
178
-
179
- The ledger includes transactions, one per line. Each transaction line
180
- contains fields separated by a semi-colon:
181
-
182
- * Transaction ID, an unsigned 16-bit integer;
183
- * Date and time, in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601);
184
- * Amount (integer);
185
- * Wallet ID of the beneficiary;
186
- * Details: `/[a-zA-Z0-9 -.]{1,128}/`;
187
- * RSA signature of the sender of "ID;amount;beneficiary;details" text.
188
-
189
- Transactions with positive amount don't
190
- have RSA signatures. Their IDs point to ID fields of corresponding
191
- beneficiaries' wallets.
192
-
193
- The combination "ID+Beneficiary" is unique in the entire wallet.
194
-
195
- The directory `.zold` is automatically created and contains system data.
196
158
 
197
159
  `.zold/remotes` is a comma-separated file with a list of remote nodes with
198
160
  these columns:
data/bin/zold CHANGED
@@ -167,18 +167,8 @@ Available options:"
167
167
  require_relative '../lib/zold/commands/push'
168
168
  Zold::Push.new(wallets: wallets, remotes: remotes, log: log).run(args)
169
169
  when 'score'
170
- require_relative '../lib/zold/score'
171
- raise 'Exactly four args required: host, port, invoice, strength' if args.length != 4
172
- host = args[0]
173
- port = args[1].to_i
174
- invoice = args[2]
175
- strength = args[3].to_i
176
- raise "Invalid strength: #{strength}" if strength <= 0 || strength > 8
177
- score = Zold::Score.new(Time.now, host, port, invoice, strength: strength)
178
- loop do
179
- log.info(score.to_s)
180
- score = score.next
181
- end
170
+ require_relative '../lib/zold/commands/calculate'
171
+ Zold::Calculate.new(log: log).run(args)
182
172
  else
183
173
  raise "Command '#{command}' is not supported"
184
174
  end
@@ -0,0 +1,8 @@
1
+ #!/bin/bash
2
+ set -x
3
+ set -e
4
+ shopt -s expand_aliases
5
+
6
+ alias zold="$1 --ignore-global-config --trace"
7
+
8
+ zold score --host=zold.io --port=4096 --invoice=NOSUFFIX@ffffffffffffffff --strength=2 --max=5
@@ -3,7 +3,7 @@ set -x
3
3
  set -e
4
4
  shopt -s expand_aliases
5
5
 
6
- alias zold="$1"
6
+ alias zold="$1 --ignore-global-config --trace"
7
7
 
8
8
  zold --help
9
9
  declare -a commands=(node create invoice remote pay show fetch clean diff merge propagate pull push)
@@ -0,0 +1,84 @@
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 'slop'
22
+ require_relative '../log'
23
+ require_relative '../score'
24
+
25
+ # SCORE command.
26
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
27
+ # Copyright:: Copyright (c) 2018 Yegor Bugayenko
28
+ # License:: MIT
29
+ module Zold
30
+ # Calculate score
31
+ class Calculate
32
+ def initialize(log: Log::Quiet.new)
33
+ @log = log
34
+ end
35
+
36
+ def run(args = [])
37
+ opts = Slop.parse(args, help: true, suppress_errors: true) do |o|
38
+ o.banner = "Usage: zold push [ID...] [options]
39
+ Available options:"
40
+ o.string '--invoice',
41
+ 'The invoice you want to collect money to'
42
+ o.integer '--port',
43
+ "TCP port to open for the Net (default: #{Remotes::PORT})",
44
+ default: Remotes::PORT
45
+ o.string '--host', 'Host name (default: 127.0.0.1)',
46
+ default: '127.0.0.1'
47
+ o.integer '--strength',
48
+ "The strength of the score (default: #{Score::STRENGTH})",
49
+ default: Score::STRENGTH
50
+ o.integer '--max',
51
+ 'Maximum value to find and then stop (default: 8)',
52
+ default: 8
53
+ o.bool '--hide-hash', 'Don\'t print hash',
54
+ default: false
55
+ o.bool '--help', 'Print instructions'
56
+ end
57
+ if opts.help?
58
+ @log.info(opts.to_s)
59
+ return
60
+ end
61
+ calculate(opts)
62
+ end
63
+
64
+ def calculate(opts)
65
+ start = Time.now
66
+ strength = opts[:strength]
67
+ raise "Invalid strength: #{strength}" if strength <= 0 || strength > 8
68
+ score = Zold::Score.new(
69
+ Time.now, opts[:host], opts[:port].to_i,
70
+ opts[:invoice], strength: strength
71
+ )
72
+ loop do
73
+ msg = score.to_s
74
+ msg += (score.value > 0 ? ' ' + score.hash : '') unless opts['hide-hash']
75
+ @log.info(msg)
76
+ break if score.value >= opts[:max].to_i
77
+ score = score.next
78
+ end
79
+ seconds = (Time.now - start).round(2)
80
+ @log.info("Took #{seconds} seconds, #{seconds / score.value} per value")
81
+ score
82
+ end
83
+ end
84
+ end
@@ -66,20 +66,24 @@ Available options:"
66
66
  next
67
67
  end
68
68
  unless response.code == '200'
69
+ @remotes.error(r[:host], r[:port])
69
70
  @log.error("#{uri} failed as #{response.code}/#{response.message}")
70
71
  next
71
72
  end
72
73
  json = JSON.parse(response.body)['score']
73
74
  score = Score.parse_json(json)
74
75
  unless score.valid?
76
+ @remotes.error(r[:host], r[:port])
75
77
  @log.error("#{uri} invalid score: #{score}")
76
78
  next
77
79
  end
78
80
  if score.expired?
81
+ @remotes.error(r[:host], r[:port])
79
82
  @log.error("#{uri} expired score: #{score}")
80
83
  next
81
84
  end
82
85
  if score.strength < Score::STRENGTH
86
+ @remotes.error(r[:host], r[:port])
83
87
  @log.error("#{uri} score is too weak")
84
88
  next
85
89
  end
data/lib/zold/score.rb CHANGED
@@ -96,13 +96,20 @@ module Zold
96
96
  )
97
97
  end
98
98
 
99
+ def hash
100
+ raise 'Score has zero value, there is no hash' if @suffixes.empty?
101
+ @suffixes.reduce(prefix) do |pfx, suffix|
102
+ Digest::SHA256.hexdigest(pfx + ' ' + suffix)[0, 63]
103
+ end
104
+ end
105
+
99
106
  def to_text
100
- prefix, bnf = @invoice.split('@')
107
+ pfx, bnf = @invoice.split('@')
101
108
  [
102
109
  @time.to_i.to_s(16),
103
110
  @host,
104
111
  @port.to_s(16),
105
- prefix,
112
+ pfx,
106
113
  bnf,
107
114
  @suffixes.join(' ')
108
115
  ].join(' ')
@@ -127,7 +134,8 @@ module Zold
127
134
  invoice: @invoice,
128
135
  time: @time.utc.iso8601,
129
136
  suffixes: @suffixes,
130
- strength: @strength
137
+ strength: @strength,
138
+ hash: value.zero? ? nil : hash
131
139
  }
132
140
  end
133
141
 
@@ -160,14 +168,12 @@ module Zold
160
168
  @time < Time.now - 24 * 60
161
169
  end
162
170
 
171
+ def prefix
172
+ "#{@time.utc.iso8601} #{@host} #{@port} #{@invoice}"
173
+ end
174
+
163
175
  def valid?
164
- start = "#{@time.utc.iso8601} #{@host} #{@port} #{@invoice}"
165
- @suffixes.reduce(start) do |prefix, suffix|
166
- hex = Digest::SHA256.hexdigest(prefix + ' ' + suffix)
167
- return false unless hex.end_with?('0' * @strength)
168
- hex[0, 63]
169
- end
170
- true
176
+ @suffixes.empty? || hash.end_with?('0' * @strength)
171
177
  end
172
178
 
173
179
  def value
@@ -42,7 +42,7 @@ module Zold
42
42
  private
43
43
 
44
44
  def body(id, t)
45
- [id, t.id, t.amount.to_i, t.prefix, t.bnf, t.details].join(' ')
45
+ [id, t.id, t.date.utc.iso8601, t.amount.to_i, t.prefix, t.bnf, t.details].join(' ')
46
46
  end
47
47
  end
48
48
  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.6.2'.freeze
26
+ VERSION = '0.6.3'.freeze
27
27
  end
@@ -0,0 +1,37 @@
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/log'
23
+ require_relative '../../lib/zold/commands/calculate'
24
+
25
+ # SCORE test.
26
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
27
+ # Copyright:: Copyright (c) 2018 Yegor Bugayenko
28
+ # License:: MIT
29
+ class TestCalculate < Minitest::Test
30
+ def test_calculates_score
31
+ score = Zold::Calculate.new.run(
32
+ ['score', '--strength=2', '--max=8', '--invoice=NOSUFFIX@ffffffffffffffff']
33
+ )
34
+ assert(score.valid?)
35
+ assert_equal(8, score.value)
36
+ end
37
+ end
data/test/test_score.rb CHANGED
@@ -95,4 +95,12 @@ class TestScore < Minitest::Test
95
95
  assert(score.valid?)
96
96
  assert(!score.expired?)
97
97
  end
98
+
99
+ def test_correct_number_of_zeroes
100
+ score = Zold::Score.new(
101
+ Time.now, 'localhost', 443,
102
+ 'NOPREFIX@ffffffffffffffff', strength: 3
103
+ ).next
104
+ assert(score.hash.end_with?('000'))
105
+ end
98
106
  end
data/wp/.gitignore CHANGED
@@ -1,3 +1,4 @@
1
+ _minted-wp
1
2
  wp.aux
2
3
  wp.bcf
3
4
  wp.log
data/wp/logo.png ADDED
Binary file
data/wp/wp.tex CHANGED
@@ -1,22 +1,28 @@
1
1
  \documentclass[11pt,oneside]{article}
2
2
  \usepackage[utf8]{inputenc}
3
3
  \usepackage[american]{babel}
4
- % \usepackage[
5
- % paperwidth=6in, paperheight=9in,
6
- % bindingoffset=0.25in, left=0.75in, right=0.75in, top=0.75in, bottom=1.25in
7
- % ]{geometry}
8
4
  \usepackage{setspace}
9
5
  \usepackage{microtype}
10
6
  \usepackage{mathpazo} % Palantino font
7
+ \usepackage{mdframed}
11
8
  \usepackage{minted}
12
- \setminted{fontsize=\footnotesize}
9
+ \setminted{fontsize=\small}
13
10
  \setminted{breaklines}
14
11
  \usemintedstyle{bw}
12
+ \BeforeBeginEnvironment{minted}{\vspace{6pt}\begin{mdframed}[topline=false,rightline=false,bottomline=false,linecolor=black,linewidth=2pt]}
13
+ \AfterEndEnvironment{minted}{\end{mdframed}}
14
+ \usepackage{xcolor}
15
+ \usepackage{graphicx}
16
+ \newcommand\dd[1]{\colorbox{gray!30}{\texttt{#1}}}
15
17
  \usepackage{hyperref}
18
+ \hypersetup{colorlinks=true,allcolors=blue!40!black}
16
19
  \pagestyle{empty}
17
20
  \setstretch{1.2}
21
+ \setlength{\topskip}{6pt}
22
+ \setlength{\parindent}{0pt} % indent first line
23
+ \setlength{\parskip}{6pt} % before par
18
24
 
19
- \title{Zold, Lightweight Crypto Currency}
25
+ \title{\includegraphics[scale=0.05]{logo.png}\\Zold: Lightweight Crypto Currency}
20
26
  \author{Yegor Bugayenko\\\texttt{yegor@zold.io}}
21
27
 
22
28
  \begin{document}
@@ -49,69 +55,101 @@ of existing digital currencies.
49
55
 
50
56
  \section{Principles}
51
57
 
52
- \textbf{Open source}.
53
- Zold is a command line tool. Its entire code base is open source.
58
+ \textbf{Open Source}.
59
+ Zold is a command line tool. Its entire code base is open source
60
+ and hosted at the GitHub \href{https://github.com/yegor256/zold}{yegor256/zold}
61
+ repository.
62
+
63
+ \textbf{No Trust}.
64
+ The network of communicating nodes maintains wallets of users.
65
+ Anyone can add a node to the network.
66
+ It is assumed that any node may contain corrupted data, either by mistake or intentionally.
67
+
68
+ \textbf{Proof of work}.
69
+ Each node, in order to earn trust, must invest its CPU power
70
+ and find hash suffixes, performing certain calculations.
71
+
72
+ \textbf{No General Ledger}.
73
+ There is no central ledger, each wallet has its own personal ledger.
74
+ All transactions in each ledger are confirmed by
75
+ \href{https://en.wikipedia.org/wiki/RSA_(cryptosystem)}{RSA signatures}
76
+ of their owners;
54
77
 
55
78
  \textbf{Capacity}.
56
79
  One currency unit is called ZLD.
57
- One ZLD by convention equals to $2^24$ (16,777,216) \emph{zents}.
80
+ One ZLD by convention equals to $2^{24}$ \emph{zents} (16,777,216).
58
81
  All amounts are stored as signed 64-bit integers.
59
82
  Thus, the technical capacity of the currency is 549,755,813,888 ZLD (half a trillion).
60
83
 
61
- \textbf{Zero wallet}.
62
- There is no mining, the only way to get ZLD is to receive it from someone else.
63
- The wallet with the \texttt{0x00} ID belongs to the
84
+ \textbf{Zero Wallet}.
85
+ There is no ``mining,'' the only way to get ZLD is to receive it from someone else.
86
+ The wallet with the \dd{0x00} ID belongs to the
64
87
  issuer and may have a negative balance. All other wallets
65
- may have only positive balances.
66
-
67
- \textbf{No general ledger}.
68
- There is no central ledger, each wallet has its own personal ledger.
69
- Each transaction in the ledger is confirmed by RSA signature;
70
-
71
- \textbf{No trust}.
72
- The network of communicating nodes maintains wallets of users.
73
- Anyone can add a node to the network.
74
- It is assumed that any node may contain corrupted data, either by mistake or intentionally.
88
+ may only have positive balances.
75
89
 
76
90
  \section{Proof of Work}
77
91
 
78
- Each node calculates its own score.
79
- First, it builds the initial text body, which consists of four parts,
92
+ The system consists of nodes (server machines), which maintain the data.
93
+ In order to guarantee data consistency among all distributed nodes
94
+ there has to be an algorithm of data segregation.
95
+ Corrupted data must be detected earlier and filtered out as quickly as possible.
96
+ Bitcoin introduced such an algorithm and called it \emph{proof of work}.
97
+
98
+ Its fundamental principle is that each block of data must have a special
99
+ number attached to it, known as \emph{nonce}, which is rather difficult to calculate,
100
+ because it requires a lot of CPU power. It is assumed that at any moment
101
+ of time the majority of nodes in the network invest their CPU power into
102
+ calculating the nonces for the data that is not corrupted. If and when for any reason
103
+ some data gets corrupted, the amount of CPU power a part of the network
104
+ decides to invest into its nonces calculation would be smaller than what
105
+ the other part of the network invests into legal data. The latter part
106
+ will quickly dominate the former and the nodes with corrupted data will
107
+ be ostracized and eventually ignored.
108
+
109
+ Zold has borrowed this principle, although modified it. We also require
110
+ our nodes to invest their CPU power into meaninless and repetative
111
+ calculations just to help us identify which part of the network they belong to:
112
+ corrupted or not. Each Zold node has to calculate its \emph{trust score},
113
+ which is as big as much CPU power the node has invested into its calculation.
114
+
115
+ Similar to Bitcoin nonces we repetatively calculate cryptographic hashes,
116
+ looking for consecutive zeros inside them. First, in order to calculate a score,
117
+ a node makes the \emph{prefix}, which consists of four parts,
80
118
  separated by spaces:
81
119
 
82
- \begin{itemize}
83
- \item The current timestamp in UTC ISO 8601,
84
- \item The host name or IP address, e.g. \texttf{b2.zold.io},
85
- \item The TCP port number,
120
+ \begin{enumerate}
121
+ \item The current timestamp in UTC, in \href{https://en.wikipedia.org/wiki/ISO_8601}{ISO 8601},
122
+ \item The host name or IP address, e.g. \dd{b2.zold.io},
123
+ \item The \href{https://en.wikipedia.org/wiki/Port_(computer_networking)}{TCP port} number,
86
124
  \item The invoice.
87
- \end{itemize}
125
+ \end{enumerate}
88
126
 
89
- For example, the body may look like this:
127
+ For example, the prefix may look like this:
90
128
 
91
129
  \begin{minted}{text}
92
- 2017-07-19T21:24:51Z b2.zold.io 4096 Yt0lOy6Rgf@0000000000000000
130
+ 2018-05-17T03:50:59Z b2.zold.io 4096 THdonv1E@0000000000000000
93
131
  \end{minted}
94
132
 
95
- Then, it attempts to append any
96
- arbitrary text (has to match \texttt{[a-zA-Z0-9]+} regular expression)
97
- to the end of it and to calculate SHA-256 of the text
98
- in the hexadecimal format. For example, this would be the body
99
- with \texttt{abcdef} suffix:
133
+ Then, the node attempts to append any arbitrary text, which has to match
134
+ \dd{/[a-zA-Z0-9]+/} regular expression, to the end of the prefix and calculates
135
+ \href{https://en.wikipedia.org/wiki/SHA-2}{SHA-256 hash}
136
+ of the text in the hexadecimal format. For example, this would be the prefix
137
+ with the attached \dd{117b1f} suffix:
100
138
 
101
139
  \begin{minted}{text}
102
- 2017-07-19T21:24:51Z b2.zold.io 4096 Yt0lOy6Rgf@0000000000000000 abcdef
140
+ 2018-05-17T03:50:59Z b2.zold.io 4096 THdonv1E@0000000000000000 117b1f
103
141
  \end{minted}
104
142
 
105
- The SHA-256 of this body will be:
143
+ The hash of this text will be:
106
144
 
107
145
  \begin{minted}{text}
108
- 2017-07-19T21:24:51Z b2.zold.io 4096 Yt0lOy6Rgf@0000000000000000 abcdef
146
+ 670baa704726fe2c837c5ca764202adca5ab12c9b90c94d9fb1b8d629000000
109
147
  \end{minted}
110
148
 
111
149
  The node attempts to try different sufficies until one of them produces
112
- SHA-256 hash that ends with \texttt{000000} (six zeros). For example, this
113
- suffix \texttt{...} works
114
- (it took about an hour to find it on 2.3GHz Intel Core i7):
150
+ a hash that ends with a few tailing zeroes. The one above ends
151
+ with six zeroes
152
+ (it took three minutes to find it on 2.3GHz Intel Core i7):
115
153
 
116
154
  When the first suffix is found, the score is 1. Then, to
117
155
  increase the score by one, the next suffix has to be found, which
@@ -119,18 +157,82 @@ can be added to the first 64 characters of the previous hash
119
157
  in order to obtain a new hash with trailing zeros, for example:
120
158
 
121
159
  \begin{minted}{text}
122
- 2017-07-19T21:24:51Z b2.zold.io 4096 Yt0lOy6Rgf@0000000000000000 abcdef abcdef
160
+ 2018-05-17T03:50:59Z b2.zold.io 4096 THdonv1E@0000000000000000 117b1f 1546e35
161
+ \end{minted}
162
+
163
+ Produces:
164
+
165
+ \begin{minted}{text}
166
+ 99dcd18e4bd03004e1205437866b5b68035cc8985240ae52cbd37640a000000
123
167
  \end{minted}
124
168
 
125
169
  And so on.
126
170
 
127
171
  The score is valid only when the starting time point is earlier than
128
- current time, but not earlier than 24 hours ago. The strength of the score
172
+ the current time, but not earlier than 24 hours ago. The strength of the score
129
173
  is the amount of the trailing zeros in the hash. In the example above the
130
- strength was equal to six.
174
+ strength is six.
131
175
 
132
176
  \section{Wallets}
133
177
 
178
+ There is no central ledger in Zold.
179
+ Each user has \emph{wallets} (any number of them).
180
+ Each wallet is an ASCII-text file with the name equal to the wallet ID.
181
+ For example, the wallet in the file \dd{12345678abcdef} may include:
182
+
183
+ \begin{minted}{text}
184
+ 12345678abcdef
185
+ AAAAB3NzaC1yc2EAAAADAQABAAABAQCuLuVr4Tl2sXoN5Zb7b6SKMPrVjLxb...
186
+
187
+ 34;2017-07-19T21:24:51Z;-560700;Ui0wpLu7;98bb82c81735c4ee;For services;SKMPrVjLxbM5oDm0IhniQQy3shF...
188
+ 35;2017-07-19T21:25:07Z;-56990;xksQuJa9;98bb82c81735c4ee;For food;QCuLuVr4Tl2sXoN5Zb7b6SKMPrVjLxb...
189
+ 134;2017-07-19T21:29:11Z;647388;kkIZo09s;18bb82dd1735b6e9;-;
190
+ 36;2017-07-19T22:18:43Z;-884733;pplIe28s;38ab8fc8e735c4fc;For programming;2sXoN5Zb7b6SKMPrVjLxb7b6SKMPrVjLx...
191
+ \end{minted}
192
+
193
+ Lines are separated by either CR or CRLF.
194
+ There is a header and a ledger, separated by an empty line.
195
+ The header includes two lines:
196
+
197
+ \begin{enumerate}
198
+ \item Wallet ID, a 64-bit unsigned integer in hexadecimal format;
199
+ \item Public \href{https://en.wikipedia.org/wiki/RSA_(cryptosystem)}{RSA}
200
+ key of the wallet owner, in \href{https://en.wikipedia.org/wiki/Base64}{Base64}.
201
+ \end{enumerate}
202
+
203
+ The ledger includes transactions, one per line. Each transaction line
204
+ contains fields separated by a semi-colon:
205
+
206
+ \begin{enumerate}
207
+ \item Transaction ID, an unsigned 16-bit integer;
208
+ \item Date and time, in \href{https://en.wikipedia.org/wiki/ISO_8601}{ISO 8601} format;
209
+ \item Amount, a signed 64-bit integer;
210
+ \item Payment prefix, 8-32 symbols;
211
+ \item Wallet ID of the beneficiary;
212
+ \item Details, matching \dd{/[a-zA-Z0-9 -.]\{1,128\}/};
213
+ \item \href{https://en.wikipedia.org/wiki/RSA_(cryptosystem)}{RSA} signature,
214
+ 684 symbols in \href{https://en.wikipedia.org/wiki/Base64}{Base64}.
215
+ \end{enumerate}
216
+
217
+ Transactions with positive amount don't have signatures.
218
+ Their IDs point to ID fields of corresponding beneficiaries' wallets.
219
+
220
+ The combination \dd{ID+Beneficiary} is unique in the entire wallet.
221
+
222
+ The \href{https://en.wikipedia.org/wiki/RSA_(cryptosystem)}{RSA}
223
+ signature is calculated using the private RSA key of the
224
+ wallet and the following fields of transaction, separated by spaces:
225
+
226
+ \begin{enumerate}
227
+ \item Wallet ID;
228
+ \item Transaction ID, an unsigned 16-bit integer;
229
+ \item Date and time, in ISO 8601 format;
230
+ \item Amount, a signed 64-bit integer;
231
+ \item Payment prefix;
232
+ \item Wallet ID of the beneficiary;
233
+ \item Details, matching \dd{/[a-zA-Z0-9 -.]{1,128}/}.
234
+ \end{enumerate}
235
+
134
236
  \section{Push}
135
237
 
136
238
  \section{Fetch and Merge}
data/zold.gemspec CHANGED
@@ -39,7 +39,7 @@ Gem::Specification.new do |s|
39
39
  s.homepage = 'http://github.com/zerocracy/zold'
40
40
  s.files = `git ls-files`.split($RS)
41
41
  s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
42
- s.test_files = s.files.grep(%r{^(test|spec|features)/})
42
+ s.test_files = s.files.grep(%r{^(test|spec|features|wp)/})
43
43
  s.rdoc_options = ['--charset=UTF-8']
44
44
  s.extra_rdoc_files = ['README.md', 'LICENSE.txt']
45
45
  s.add_runtime_dependency 'concurrent-ruby', '1.0.5'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zold
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.2
4
+ version: 0.6.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yegor Bugayenko
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-05-16 00:00:00.000000000 Z
11
+ date: 2018-05-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -271,10 +271,12 @@ files:
271
271
  - fixtures/keys/1.pub
272
272
  - fixtures/keys/2
273
273
  - fixtures/keys/2.pub
274
+ - fixtures/scripts/calculate-scores.sh
274
275
  - fixtures/scripts/print-helps.sh
275
276
  - fixtures/scripts/push-and-pull.sh
276
277
  - lib/zold.rb
277
278
  - lib/zold/amount.rb
279
+ - lib/zold/commands/calculate.rb
278
280
  - lib/zold/commands/clean.rb
279
281
  - lib/zold/commands/create.rb
280
282
  - lib/zold/commands/diff.rb
@@ -308,6 +310,7 @@ files:
308
310
  - lib/zold/wallet.rb
309
311
  - lib/zold/wallets.rb
310
312
  - resources/remotes
313
+ - test/commands/test_calculate.rb
311
314
  - test/commands/test_clean.rb
312
315
  - test/commands/test_create.rb
313
316
  - test/commands/test_diff.rb
@@ -341,6 +344,7 @@ files:
341
344
  - test/test_zold.rb
342
345
  - wp/.gitignore
343
346
  - wp/Makefile
347
+ - wp/logo.png
344
348
  - wp/wp.tex
345
349
  - zold.gemspec
346
350
  homepage: http://github.com/zerocracy/zold
@@ -373,6 +377,7 @@ test_files:
373
377
  - features/gem_package.feature
374
378
  - features/step_definitions/steps.rb
375
379
  - features/support/env.rb
380
+ - test/commands/test_calculate.rb
376
381
  - test/commands/test_clean.rb
377
382
  - test/commands/test_create.rb
378
383
  - test/commands/test_diff.rb
@@ -404,3 +409,7 @@ test_files:
404
409
  - test/test_wallet.rb
405
410
  - test/test_wallets.rb
406
411
  - test/test_zold.rb
412
+ - wp/.gitignore
413
+ - wp/Makefile
414
+ - wp/logo.png
415
+ - wp/wp.tex