zold 0.6.3 → 0.6.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +35 -116
- data/fixtures/scripts/push-and-pull.sh +2 -2
- data/lib/zold/amount.rb +9 -4
- data/lib/zold/commands/args.rb +50 -0
- data/lib/zold/commands/clean.rb +5 -6
- data/lib/zold/commands/create.rb +4 -5
- data/lib/zold/commands/diff.rb +3 -5
- data/lib/zold/commands/fetch.rb +4 -6
- data/lib/zold/commands/invoice.rb +2 -5
- data/lib/zold/commands/merge.rb +4 -6
- data/lib/zold/commands/node.rb +9 -3
- data/lib/zold/commands/pay.rb +10 -8
- data/lib/zold/commands/propagate.rb +5 -6
- data/lib/zold/commands/push.rb +4 -6
- data/lib/zold/commands/remote.rb +2 -5
- data/lib/zold/commands/show.rb +3 -5
- data/lib/zold/commands/taxes.rb +3 -1
- data/lib/zold/hexnum.rb +51 -0
- data/lib/zold/remotes.rb +2 -2
- data/lib/zold/tax.rb +11 -13
- data/lib/zold/txn.rb +8 -7
- data/lib/zold/version.rb +1 -1
- data/lib/zold/wallets.rb +1 -0
- data/test/commands/test_diff.rb +1 -1
- data/test/commands/test_pay.rb +7 -5
- data/test/commands/test_push.rb +52 -0
- data/test/test_hexnum.rb +34 -0
- data/test/test_patch.rb +6 -6
- data/test/test_txn.rb +2 -2
- data/wp/wp.tex +287 -26
- metadata +8 -2
data/wp/wp.tex
CHANGED
@@ -17,26 +17,34 @@
|
|
17
17
|
\usepackage{hyperref}
|
18
18
|
\hypersetup{colorlinks=true,allcolors=blue!40!black}
|
19
19
|
\pagestyle{empty}
|
20
|
-
\setstretch{1.
|
20
|
+
\setstretch{1.1}
|
21
21
|
\setlength{\topskip}{6pt}
|
22
22
|
\setlength{\parindent}{0pt} % indent first line
|
23
23
|
\setlength{\parskip}{6pt} % before par
|
24
24
|
|
25
|
-
\title{\includegraphics[scale=0.05]{logo.png}\\Zold:
|
25
|
+
\title{\includegraphics[scale=0.05]{logo.png}\\Zold: a Light-Weight Crypto Currency}
|
26
26
|
\author{Yegor Bugayenko\\\texttt{yegor@zold.io}}
|
27
27
|
|
28
28
|
\begin{document}
|
29
29
|
\raggedbottom
|
30
|
+
|
30
31
|
\maketitle
|
31
32
|
\begin{abstract}
|
32
|
-
|
33
|
+
The world is hyped about digital currencies now. Why not create a new one,
|
34
|
+
which will implement a different set of architectural principles? Zold is
|
35
|
+
an \emph{experimental} solution that enables distributed transactions between
|
36
|
+
anonymous users. Its core ``proof of work'' principle is borrowed from Bitcoin's Blockchain,
|
37
|
+
while the rest of the architecture is new.
|
33
38
|
\end{abstract}
|
34
39
|
|
40
|
+
\colorbox{yellow}{It's a draft! Don't show it to anyone yet.}
|
41
|
+
|
35
42
|
\section{Motivation}
|
36
43
|
|
37
44
|
Bitcoin, the first decentralized digital currency, was released in
|
38
45
|
January 2009. Since then a number of similar Blockchain-based products have been
|
39
|
-
created, including Etherium, Litecoin, and others.
|
46
|
+
created, including Etherium, Litecoin, and others. \colorbox{yellow}{links} There were other solutions,
|
47
|
+
not based on Blockchain, including IOTA, and others. \colorbox{yellow}{links}
|
40
48
|
|
41
49
|
Zold is also a decentralized digital currency that maintains its transactions
|
42
50
|
in an unpredicable amount of zero-trust server nodes, trying to guarantee
|
@@ -44,15 +52,18 @@ data consistency. However, the architecture of Zold is not based on Blockchain
|
|
44
52
|
principles. The development of Zold was motivated by the desire to overcome
|
45
53
|
a few obvious disadvantages of existing solutions.
|
46
54
|
|
47
|
-
First, the speed of transaction processing is rather low.
|
55
|
+
First, the speed of transaction processing is rather low. \colorbox{yellow}{proof?}
|
48
56
|
|
49
|
-
Second, mining commissions are high.
|
57
|
+
Second, mining commissions are high. \colorbox{yellow}{proof?}
|
50
58
|
|
51
|
-
Third, the technology is too complex.
|
59
|
+
Third, the technology is too complex. \colorbox{yellow}{proof?}
|
52
60
|
|
53
61
|
Zold was created as an attempt to resolve these mentioned problems
|
54
62
|
of existing digital currencies.
|
55
63
|
|
64
|
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
65
|
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
66
|
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
56
67
|
\section{Principles}
|
57
68
|
|
58
69
|
\textbf{Open Source}.
|
@@ -67,7 +78,7 @@ It is assumed that any node may contain corrupted data, either by mistake or int
|
|
67
78
|
|
68
79
|
\textbf{Proof of work}.
|
69
80
|
Each node, in order to earn trust, must invest its CPU power
|
70
|
-
and find hash suffixes, performing certain calculations.
|
81
|
+
and find hash suffixes, performing certain expensive and meaningless calculations.
|
71
82
|
|
72
83
|
\textbf{No General Ledger}.
|
73
84
|
There is no central ledger, each wallet has its own personal ledger.
|
@@ -87,6 +98,11 @@ The wallet with the \dd{0x00} ID belongs to the
|
|
87
98
|
issuer and may have a negative balance. All other wallets
|
88
99
|
may only have positive balances.
|
89
100
|
|
101
|
+
\colorbox{yellow}{Let's compare each of these principles with other currencies and highlight similarities.}
|
102
|
+
|
103
|
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
104
|
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
105
|
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
90
106
|
\section{Proof of Work}
|
91
107
|
|
92
108
|
The system consists of nodes (server machines), which maintain the data.
|
@@ -94,6 +110,7 @@ In order to guarantee data consistency among all distributed nodes
|
|
94
110
|
there has to be an algorithm of data segregation.
|
95
111
|
Corrupted data must be detected earlier and filtered out as quickly as possible.
|
96
112
|
Bitcoin introduced such an algorithm and called it \emph{proof of work}.
|
113
|
+
\colorbox{yellow}{link}
|
97
114
|
|
98
115
|
Its fundamental principle is that each block of data must have a special
|
99
116
|
number attached to it, known as \emph{nonce}, which is rather difficult to calculate,
|
@@ -105,9 +122,10 @@ decides to invest into its nonces calculation would be smaller than what
|
|
105
122
|
the other part of the network invests into legal data. The latter part
|
106
123
|
will quickly dominate the former and the nodes with corrupted data will
|
107
124
|
be ostracized and eventually ignored.
|
125
|
+
\colorbox{yellow}{let's make sure this text is correct and add a link}
|
108
126
|
|
109
|
-
Zold has borrowed this principle, although modified it.
|
110
|
-
|
127
|
+
Zold has borrowed this principle, although modified it. It also requires
|
128
|
+
its nodes to invest their CPU power into meaninless and repetative
|
111
129
|
calculations just to help us identify which part of the network they belong to:
|
112
130
|
corrupted or not. Each Zold node has to calculate its \emph{trust score},
|
113
131
|
which is as big as much CPU power the node has invested into its calculation.
|
@@ -173,10 +191,13 @@ the current time, but not earlier than 24 hours ago. The strength of the score
|
|
173
191
|
is the amount of the trailing zeros in the hash. In the example above the
|
174
192
|
strength is six.
|
175
193
|
|
194
|
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
195
|
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
196
|
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
176
197
|
\section{Wallets}
|
177
198
|
|
178
|
-
There is no central ledger in Zold.
|
179
|
-
|
199
|
+
There is no central ledger in Zold, like many other digital currencies.
|
200
|
+
Instead, each user has their own \emph{wallets} (any number of them) with their own ledgers inside.
|
180
201
|
Each wallet is an ASCII-text file with the name equal to the wallet ID.
|
181
202
|
For example, the wallet in the file \dd{12345678abcdef} may include:
|
182
203
|
|
@@ -184,10 +205,10 @@ For example, the wallet in the file \dd{12345678abcdef} may include:
|
|
184
205
|
12345678abcdef
|
185
206
|
AAAAB3NzaC1yc2EAAAADAQABAAABAQCuLuVr4Tl2sXoN5Zb7b6SKMPrVjLxb...
|
186
207
|
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
208
|
+
003a;2017-07-19T21:24:51Z;ffffffff9c0ccccd;Ui0wpLu7;98bb82c81735c4ee;For services;SKMPrVj...
|
209
|
+
003b;2017-07-19T21:25:07Z;ffffffffffa72367;xksQuJa9;98bb82c81735c4ee;For food;QCuLuVr4...
|
210
|
+
0f34;2017-07-19T21:29:11Z;0000000000647388;kkIZo09s;18bb82dd1735b6e9;-;
|
211
|
+
003c;2017-07-19T22:18:43Z;ffffffffff884733;pplIe28s;38ab8fc8e735c4fc;For programming;2sXoN5...
|
191
212
|
\end{minted}
|
192
213
|
|
193
214
|
Lines are separated by either CR or CRLF.
|
@@ -204,11 +225,11 @@ The ledger includes transactions, one per line. Each transaction line
|
|
204
225
|
contains fields separated by a semi-colon:
|
205
226
|
|
206
227
|
\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;
|
228
|
+
\item Transaction ID, an unsigned 16-bit integer, 4-symbols hex;
|
229
|
+
\item Date and time, in \href{https://en.wikipedia.org/wiki/ISO_8601}{ISO 8601} format, 20 symbols;
|
230
|
+
\item Amount, a signed 64-bit integer, 16-symbols hex;
|
210
231
|
\item Payment prefix, 8-32 symbols;
|
211
|
-
\item Wallet ID of the beneficiary;
|
232
|
+
\item Wallet ID of the beneficiary, 16-symbols hex;
|
212
233
|
\item Details, matching \dd{/[a-zA-Z0-9 -.]\{1,128\}/};
|
213
234
|
\item \href{https://en.wikipedia.org/wiki/RSA_(cryptosystem)}{RSA} signature,
|
214
235
|
684 symbols in \href{https://en.wikipedia.org/wiki/Base64}{Base64}.
|
@@ -217,10 +238,10 @@ contains fields separated by a semi-colon:
|
|
217
238
|
Transactions with positive amount don't have signatures.
|
218
239
|
Their IDs point to ID fields of corresponding beneficiaries' wallets.
|
219
240
|
|
220
|
-
The combination
|
241
|
+
The combination ``ID'' + ``Beneficiary'' is unique in the entire wallet.
|
221
242
|
|
222
243
|
The \href{https://en.wikipedia.org/wiki/RSA_(cryptosystem)}{RSA}
|
223
|
-
signature is calculated using the private
|
244
|
+
signature is calculated using the private key of the
|
224
245
|
wallet and the following fields of transaction, separated by spaces:
|
225
246
|
|
226
247
|
\begin{enumerate}
|
@@ -233,12 +254,252 @@ wallet and the following fields of transaction, separated by spaces:
|
|
233
254
|
\item Details, matching \dd{/[a-zA-Z0-9 -.]{1,128}/}.
|
234
255
|
\end{enumerate}
|
235
256
|
|
236
|
-
|
257
|
+
For example, this text may be used as a signing input:
|
237
258
|
|
238
|
-
\
|
259
|
+
\begin{minted}{text}
|
260
|
+
12345678abcdef 003a 2017-07-19T21:24:51Z ffffffff9c0ccccd Ui0wpLu7 98bb82c81735c4ee For services
|
261
|
+
\end{minted}
|
262
|
+
|
263
|
+
Each transaction takes 900 symbols at most.
|
264
|
+
The maximum amount of transactions in one wallet is 65536.
|
265
|
+
Thus, a single wallet may be as big as a 59Mb text file, at most.
|
266
|
+
|
267
|
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
268
|
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
269
|
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
270
|
+
\section{Taxes}
|
271
|
+
|
272
|
+
Each wallet must have to pay \emph{taxes} in order to be promoted by nodes.
|
273
|
+
The maximum amount of tax debt a node can tolerate is 1 ZLD. This means
|
274
|
+
that if the debt is smaller, all nodes must promote the wallet to their
|
275
|
+
remote nodes. If the debt is bigger, a node will accept the wallet but won't
|
276
|
+
promote it further, which will seriously decrease wallet's visibility in
|
277
|
+
the network---only a limited amount of nodes will see it, unless the owner
|
278
|
+
manually pushes it to many nodes, which is an expensive operation.
|
279
|
+
|
280
|
+
The amount of taxes to be paid is calculated by the following formula:
|
281
|
+
|
282
|
+
$$X = A \times F \times T.$$
|
283
|
+
|
284
|
+
$A$ is the total age of the wallet,
|
285
|
+
which is calculated as the difference in hours between the current time
|
286
|
+
and the time of the oldest transaction in the wallet.
|
287
|
+
$T$ is the total number of transactions in the wallet.
|
288
|
+
$F$ is the fee per transaction/hour, which is equal to 7.48 zents
|
289
|
+
(a one-year-old wallet with 4096 transactions inside must pay approximately 16 ZLD taxes annually).
|
290
|
+
|
291
|
+
In order to pay taxes the owner of the wallet has to select any remote
|
292
|
+
node from the network, which has a score of 16 or more. Then, it has to
|
293
|
+
take the invoice from the score and send the payment of 1 ZLD or less
|
294
|
+
to that node. The score has to be placed into the details of the transaction,
|
295
|
+
prefixed by \dd{TAXES }. All tax payments inside a wallet must
|
296
|
+
have unique scores.
|
297
|
+
|
298
|
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
299
|
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
300
|
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
301
|
+
\section{Fetch, Merge, and Propagate}
|
302
|
+
|
303
|
+
Each node maintains a list of \emph{remote nodes} (their host names and TCP port numbers),
|
304
|
+
their scores and their availability information. When the node is just installed,
|
305
|
+
the list contains a limited amount of pre-defined addresses. The list is
|
306
|
+
updated both by user request and automatically in order to give priority
|
307
|
+
to high-score nodes and the nodes with the highest availability.
|
308
|
+
Moreover, the node adds new elements to the list retrieving them from all
|
309
|
+
available remote nodes.
|
310
|
+
|
311
|
+
First, to see a wallet, it has to be \emph{fetched} from a number of remote
|
312
|
+
nodes. The nodes may provide different versions of the same wallet, either
|
313
|
+
because some data is corrupted or because modifications were made to the same
|
314
|
+
wallet from different parts of the network. Each version retrieved from the
|
315
|
+
network is stored in a local \emph{copy} and gets a score assigned to it.
|
316
|
+
The score of the local copy is a summary of all scores of the nodes that
|
317
|
+
provided that copy. Let's say, there are 17 nodes in the network and they
|
318
|
+
provided three different copies of the wallet:
|
319
|
+
|
320
|
+
\begin{minted}{text}
|
321
|
+
copy-1: 78,090 bytes, 11 servers, 177 score
|
322
|
+
copy-2: 56,113 bytes, 4 servers, 69 score
|
323
|
+
copy-3: 97,132 bytes, 2 servers, 37 score
|
324
|
+
\end{minted}
|
239
325
|
|
240
|
-
\
|
326
|
+
The fetch operation ends at this point. The next step is to \emph{merge}
|
327
|
+
all three copies into the local one, if it exists. The algorithm of merging
|
328
|
+
is the following.
|
329
|
+
|
330
|
+
First, the copy of the wallet we are merging into, is added to the list,
|
331
|
+
with the score zero:
|
332
|
+
|
333
|
+
\begin{minted}{text}
|
334
|
+
copy-0: 55,991 bytes, 0 servers, 0 score
|
335
|
+
copy-1: 78,090 bytes, 11 servers, 177 score
|
336
|
+
copy-2: 56,113 bytes, 4 servers, 69 score
|
337
|
+
copy-3: 97,132 bytes, 2 servers, 37 score
|
338
|
+
\end{minted}
|
339
|
+
|
340
|
+
Then, the copy with the highest score is assumed to be the correct one,
|
341
|
+
which is the \dd{copy-1} in this example.
|
342
|
+
|
343
|
+
Then, all other copies, in the order of their scores, are merged into the
|
344
|
+
correct one, transaction by transaction, applied the following rules
|
345
|
+
consequently:
|
346
|
+
|
347
|
+
\begin{enumerate}
|
348
|
+
\item If the transaction already exists, it's ignored;
|
349
|
+
\item If the transaction is negative (spending money) and its ID is lower than
|
350
|
+
the maximum ID in the ledger, it gets ignored as a fraudulent one (``double spending'');
|
351
|
+
\item If the transaction makes the balance of the wallet negative, it is ignored;
|
352
|
+
\item If the transaction is positive and its signature is not valid, it is ignored;
|
353
|
+
\item If the transaction is negative and it's absent in the paying wallet
|
354
|
+
(which is fetched and merged first), it's ignored;
|
355
|
+
\item Otherwise, it gets added to the end of the ledger.
|
356
|
+
\end{enumerate}
|
357
|
+
|
358
|
+
When merge is done, the modifications get \emph{propagated} to other wallets
|
359
|
+
available locally. Each transaction that has a negative amount is
|
360
|
+
copied to the ledger of their receiving wallets (with a reversed sign),
|
361
|
+
if it doesn't yet exist there.
|
362
|
+
|
363
|
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
364
|
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
365
|
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
366
|
+
\section{Pay and Push}
|
367
|
+
|
368
|
+
To send money from one wallet to another, the owner of the sending wallet
|
369
|
+
has to add a negative transaction to it, signing it with the private RSA key.
|
370
|
+
|
371
|
+
At any moment of time any node may decide to push a wallet to another node.
|
372
|
+
The accepts it, merges with the local version, and keeps locally. Then, it
|
373
|
+
\emph{promotes} the wallet to all known remote nodes.
|
374
|
+
|
375
|
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
376
|
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
377
|
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
378
|
+
\section{RESTful API}
|
379
|
+
|
380
|
+
There is a limited set of RESTful API entry points in each node.
|
381
|
+
Each response has \dd{Content-Type},
|
382
|
+
\dd{Content-Length}, and \dd{X-Zold-Version}
|
383
|
+
HTTP headers.
|
384
|
+
|
385
|
+
\dd{GET /} is a home page of a node that returns JSON response with the
|
386
|
+
information about the node, for example (other details may be added in
|
387
|
+
further versions):
|
388
|
+
|
389
|
+
\begin{minted}{json}
|
390
|
+
{
|
391
|
+
"version": "0.6.1",
|
392
|
+
"score": {
|
393
|
+
"value": 3,
|
394
|
+
"host": "b2.zold.io",
|
395
|
+
"port": 4096,
|
396
|
+
"invoice": "THdonv1E@0000000000000000",
|
397
|
+
"suffixes": [ "4f9c38", "49c074", "24829a" ],
|
398
|
+
"strength": 6
|
399
|
+
}
|
400
|
+
}
|
401
|
+
\end{minted}
|
241
402
|
|
242
|
-
|
403
|
+
\dd{GET /remotes} returns the list of remote nodes known by the node, in JSON:
|
404
|
+
|
405
|
+
\begin{minted}{json}
|
406
|
+
{
|
407
|
+
"version": "0.6.1",
|
408
|
+
"all": [
|
409
|
+
{ "host": "b2.zold.io", "port": 4096 },
|
410
|
+
{ "host": "b1.zold.io", "port": 80 }
|
411
|
+
]
|
412
|
+
}\end{minted}
|
413
|
+
|
414
|
+
\dd{GET /wallet/<ID>} returns the content of the wallet:
|
415
|
+
|
416
|
+
\begin{minted}{json}
|
417
|
+
{
|
418
|
+
"version": "0.6.1",
|
419
|
+
"body": "..."
|
420
|
+
}\end{minted}
|
421
|
+
|
422
|
+
If the wallet is not found, a
|
423
|
+
\href{https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.5}{404}
|
424
|
+
HTTP response is returned.
|
425
|
+
|
426
|
+
If the client provided the MD5 hash of the wallet content in the
|
427
|
+
\href{https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.26}{\dd{If-None-Match}}
|
428
|
+
HTTP header and it matches with the hash of the
|
429
|
+
content the node contains, a
|
430
|
+
\href{https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.5}{304} HTTP response is returned.
|
431
|
+
|
432
|
+
\dd{PUT /wallet/<ID>} pushes the content of the wallet to the node. The
|
433
|
+
node responds either with
|
434
|
+
\href{https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.3}{202} (if accepted),
|
435
|
+
\href{https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.1}{400} (if the data is corrupted),
|
436
|
+
or
|
437
|
+
\href{https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.5}{304}
|
438
|
+
(if the content is the same as the one the node already has).
|
439
|
+
|
440
|
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
441
|
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
442
|
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
443
|
+
\section{Incentives}
|
444
|
+
|
445
|
+
It is obvious that anonymous users will participate in Zold and maintain
|
446
|
+
their nodes only if they have enough financial motivation to do that. Simply
|
447
|
+
put, their expenses must be lower than the income they are getting in
|
448
|
+
form of taxes. This Section analyzes the most obvious questions users
|
449
|
+
may have, regarding their motivation.
|
450
|
+
|
451
|
+
\subsection{To Stay Online}
|
452
|
+
|
453
|
+
What is the reason for a node to stay online and spend its CPU power
|
454
|
+
and network traffic? Each node is insterested in doing that because it
|
455
|
+
hopes that wallet owners will pay taxes to its invoices. The software
|
456
|
+
automatically decides which node to pay taxes to and the selection is
|
457
|
+
made by the availability criteria. The node which is the most available
|
458
|
+
and visible will get the majority of tax payments.
|
459
|
+
|
460
|
+
\subsection{To Accept Wallets}
|
461
|
+
|
462
|
+
Why a node would accept push requests and spend its storage space
|
463
|
+
on the wallets coming in? If the node doesn't accept a push request,
|
464
|
+
its availability rating decreases and other nodes will stop paying
|
465
|
+
taxes to it.
|
466
|
+
|
467
|
+
\subsection{To Promote Other Nodes}
|
468
|
+
|
469
|
+
What is the incentive to promote other remote nodes via the \dd{/remotes} RESTful
|
470
|
+
entry point and why can't a node always return an empty list, expecting its clients
|
471
|
+
to always pay taxes to it? The software automatically prioritizes remote
|
472
|
+
nodes by the amount of remote nodes it promotes. The longer the list a node
|
473
|
+
returns, the higher its chance to be at the top of the list.
|
474
|
+
|
475
|
+
\colorbox{yellow}{We need more here}
|
476
|
+
|
477
|
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
478
|
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
479
|
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
480
|
+
\section{Threats}
|
481
|
+
|
482
|
+
It is obvious that a distributed system that consists of anonymous nodes
|
483
|
+
even theorecially can't be 100\% safe, reliable, secure and trustworthy.
|
484
|
+
Zold is not an exception. However, it's designed in an honest attempt
|
485
|
+
to mitigate all critical threats and make the system ``reliable enough.''
|
486
|
+
This Section summarizes the most import of those threads and explains
|
487
|
+
how Zold responds to them.
|
488
|
+
|
489
|
+
\subsection{Double Spending}
|
490
|
+
|
491
|
+
It is possible to submit the same spending transaction to the same wallet
|
492
|
+
and then push it to two different nodes in different parts of the network.
|
493
|
+
They won't know about each other and will propagate those spending
|
494
|
+
transactions to other wallets. Both two owners of those money receiving
|
495
|
+
wallets will think that their money arrived, while only one of them is
|
496
|
+
a legit receiver, the other transaction is fraudulent.
|
497
|
+
|
498
|
+
This will happen, but very soon one part of the network will dominate the other
|
499
|
+
one, and one of the transactions will be rejected from the wallet, after
|
500
|
+
a number of merge operations in all nodes of the network. The receiver of the
|
501
|
+
money must be careful and always to the full fetch (from as many
|
502
|
+
|
503
|
+
\colorbox{yellow}{We need more here}
|
243
504
|
|
244
505
|
\end{document}
|
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.
|
4
|
+
version: 0.6.4
|
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-
|
11
|
+
date: 2018-05-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: concurrent-ruby
|
@@ -276,6 +276,7 @@ files:
|
|
276
276
|
- fixtures/scripts/push-and-pull.sh
|
277
277
|
- lib/zold.rb
|
278
278
|
- lib/zold/amount.rb
|
279
|
+
- lib/zold/commands/args.rb
|
279
280
|
- lib/zold/commands/calculate.rb
|
280
281
|
- lib/zold/commands/clean.rb
|
281
282
|
- lib/zold/commands/create.rb
|
@@ -292,6 +293,7 @@ files:
|
|
292
293
|
- lib/zold/commands/show.rb
|
293
294
|
- lib/zold/commands/taxes.rb
|
294
295
|
- lib/zold/copies.rb
|
296
|
+
- lib/zold/hexnum.rb
|
295
297
|
- lib/zold/http.rb
|
296
298
|
- lib/zold/id.rb
|
297
299
|
- lib/zold/key.rb
|
@@ -320,6 +322,7 @@ files:
|
|
320
322
|
- test/commands/test_merge.rb
|
321
323
|
- test/commands/test_node.rb
|
322
324
|
- test/commands/test_pay.rb
|
325
|
+
- test/commands/test_push.rb
|
323
326
|
- test/commands/test_remote.rb
|
324
327
|
- test/commands/test_show.rb
|
325
328
|
- test/commands/test_taxes.rb
|
@@ -329,6 +332,7 @@ files:
|
|
329
332
|
- test/test__helper.rb
|
330
333
|
- test/test_amount.rb
|
331
334
|
- test/test_copies.rb
|
335
|
+
- test/test_hexnum.rb
|
332
336
|
- test/test_http.rb
|
333
337
|
- test/test_id.rb
|
334
338
|
- test/test_key.rb
|
@@ -387,6 +391,7 @@ test_files:
|
|
387
391
|
- test/commands/test_merge.rb
|
388
392
|
- test/commands/test_node.rb
|
389
393
|
- test/commands/test_pay.rb
|
394
|
+
- test/commands/test_push.rb
|
390
395
|
- test/commands/test_remote.rb
|
391
396
|
- test/commands/test_show.rb
|
392
397
|
- test/commands/test_taxes.rb
|
@@ -396,6 +401,7 @@ test_files:
|
|
396
401
|
- test/test__helper.rb
|
397
402
|
- test/test_amount.rb
|
398
403
|
- test/test_copies.rb
|
404
|
+
- test/test_hexnum.rb
|
399
405
|
- test/test_http.rb
|
400
406
|
- test/test_id.rb
|
401
407
|
- test/test_key.rb
|