zold 0.6 → 0.6.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +3 -3
- data/README.md +1 -81
- data/bin/zold +8 -6
- data/features/cli.feature +1 -1
- data/fixtures/scripts/print-helps.sh +1 -1
- data/fixtures/scripts/push-and-pull.sh +15 -15
- data/lib/zold/commands/clean.rb +4 -3
- data/lib/zold/commands/create.rb +3 -2
- data/lib/zold/commands/diff.rb +4 -3
- data/lib/zold/commands/fetch.rb +4 -3
- data/lib/zold/commands/invoice.rb +4 -3
- data/lib/zold/commands/merge.rb +4 -3
- data/lib/zold/commands/node.rb +1 -1
- data/lib/zold/commands/pay.rb +9 -8
- data/lib/zold/commands/propagate.rb +4 -3
- data/lib/zold/commands/push.rb +4 -3
- data/lib/zold/commands/remote.rb +10 -5
- data/lib/zold/commands/show.rb +4 -3
- data/lib/zold/commands/taxes.rb +9 -8
- data/lib/zold/node/entrance.rb +3 -3
- data/lib/zold/score.rb +1 -1
- data/lib/zold/txn.rb +6 -0
- data/lib/zold/version.rb +1 -1
- data/test/commands/test_clean.rb +1 -1
- data/test/commands/test_create.rb +1 -1
- data/test/commands/test_diff.rb +2 -2
- data/test/commands/test_fetch.rb +2 -2
- data/test/commands/test_invoice.rb +1 -1
- data/test/commands/test_merge.rb +5 -4
- data/test/commands/test_node.rb +2 -2
- data/test/commands/test_pay.rb +1 -1
- data/test/commands/test_remote.rb +4 -4
- data/test/commands/test_show.rb +1 -1
- data/test/commands/test_taxes.rb +1 -1
- data/wp/Makefile +8 -0
- data/wp/wp.tex +128 -24
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 42d45258927844c4cc2c07418af8b5077787731b
|
4
|
+
data.tar.gz: 508255ebe906bd0c4dd9fcb88ed12dee32a1973a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4783b3ade202e80fb6b252ed58cab12176a0bcb70cc4584e67e3e6fe49f1ec9fcd2fdb1df0020f7a2d13b20e865e99c591a14604e402b8725acc9168a6365b2b
|
7
|
+
data.tar.gz: c8c189ee8908b4479b3b9e71f73776995ddcfc407cb2bdb6e32b15339c63bbdfc86a6f5a49845ad064bbd92cc1f50c2da557be6ae9d3a2673dbe478f4c80c0cc
|
data/.rubocop.yml
CHANGED
@@ -6,7 +6,7 @@ AllCops:
|
|
6
6
|
TargetRubyVersion: 2.2
|
7
7
|
|
8
8
|
Metrics/CyclomaticComplexity:
|
9
|
-
Max:
|
9
|
+
Max: 25
|
10
10
|
Metrics/MethodLength:
|
11
11
|
Enabled: false
|
12
12
|
Layout/MultilineMethodCallIndentation:
|
@@ -17,13 +17,13 @@ Metrics/BlockLength:
|
|
17
17
|
Max: 100
|
18
18
|
Metrics/ClassLength:
|
19
19
|
Max: 200
|
20
|
-
|
20
|
+
Layout/EndOfLine:
|
21
21
|
EnforcedStyle: lf
|
22
22
|
Metrics/ParameterLists:
|
23
23
|
Max: 10
|
24
24
|
Layout/AlignParameters:
|
25
25
|
Enabled: false
|
26
26
|
Metrics/PerceivedComplexity:
|
27
|
-
Max:
|
27
|
+
Max: 25
|
28
28
|
Metrics/LineLength:
|
29
29
|
Max: 120
|
data/README.md
CHANGED
@@ -17,21 +17,6 @@
|
|
17
17
|
**NOTICE**: It's an experiment and a very early draft! Please, feel free to
|
18
18
|
submit your ideas or pull requests.
|
19
19
|
|
20
|
-
ZOLD principles include:
|
21
|
-
|
22
|
-
* The entire code base is open source;
|
23
|
-
* There is no mining, the only way to get ZOLD is to receive it from someone else;
|
24
|
-
* Only 2<sup>63</sup> numerals (no fractions) can technically be issued;
|
25
|
-
* The first wallet belongs to the issuer and may have a negative balance;
|
26
|
-
* A wallet is a plain text file;
|
27
|
-
* There is no central ledger, each wallet has its own personal ledger;
|
28
|
-
* Each transaction in the ledger is confirmed by [RSA](https://simple.wikipedia.org/wiki/RSA_%28algorithm%29) encryption;
|
29
|
-
* The network of communicating nodes maintains wallets of users;
|
30
|
-
* Anyone can add a node to the network.
|
31
|
-
|
32
|
-
1 ZLD by convention equals to 2<sup>24</sup> (16,777,216) _zents_.
|
33
|
-
Thus, the technical capacity of the currency is 549,755,813,888 ZLD (half a trillion).
|
34
|
-
|
35
20
|
## How to Use
|
36
21
|
|
37
22
|
Install Ruby 2.2+, [Rubygems](https://rubygems.org/pages/download), and then run:
|
@@ -44,20 +29,9 @@ $ gem install zold
|
|
44
29
|
Then, either run it as a node:
|
45
30
|
|
46
31
|
```bash
|
47
|
-
$ zold
|
32
|
+
$ zold node
|
48
33
|
```
|
49
34
|
|
50
|
-
Or do one of the following:
|
51
|
-
|
52
|
-
* `zold remote` manipulates the list off remote nodes;
|
53
|
-
* `zold create` creates a new wallet (you have to provide PGP keys);
|
54
|
-
* `zold fetch` downloads all copies of the wallet from the network;
|
55
|
-
* `zold merge` merges all copies of the wallet into the local one;
|
56
|
-
* `zold pull` first `fetch`, then `merge`;
|
57
|
-
* `zold show` prints out all known details of a wallet (incl. its balance);
|
58
|
-
* `zold pay` creates a new transaction;
|
59
|
-
* `zold push` pushes a wallet to the network.
|
60
|
-
|
61
35
|
For more options and commands just run:
|
62
36
|
|
63
37
|
```bash
|
@@ -71,60 +45,6 @@ yet, you can run:
|
|
71
45
|
$ ssh-keygen -t rsa -b 4096
|
72
46
|
```
|
73
47
|
|
74
|
-
## Glossary
|
75
|
-
|
76
|
-
**Node** is an HTTP server with a RESTful API, a maintainer of wallets
|
77
|
-
and a command line Ruby gem [`zold`](https://rubygems.org/gems/zold).
|
78
|
-
|
79
|
-
**Network** is a set of all nodes available online.
|
80
|
-
|
81
|
-
**Score** is the amount of "hash sufficies" a node has at any given moment of time.
|
82
|
-
|
83
|
-
**Wallet** is a text file with a ledger of all transactions inside.
|
84
|
-
|
85
|
-
**Transaction** is a money transferring operation between two wallets.
|
86
|
-
|
87
|
-
**MSS** (minimum summary score) is a summary of all scores required to trust a wallet.
|
88
|
-
|
89
|
-
## Score
|
90
|
-
|
91
|
-
Each node calculates its own score. First, it takes the current timestamp
|
92
|
-
in UTC [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601),
|
93
|
-
for example `2017-07-19T21:24:51Z ` (with a trailing space). Then, it appends
|
94
|
-
its own host name or IP address to it, space, TCP port number, and a space.
|
95
|
-
Then, it attempts to append any
|
96
|
-
arbitrary text (has to match `[a-zA-Z0-9]+`) to the end of it and to calculate SHA-256 of the text
|
97
|
-
in the hexadecimal format, for example:
|
98
|
-
|
99
|
-
```
|
100
|
-
Input: "2017-07-19T21:24:51Z b1.zold.io 4096 the-suffix"
|
101
|
-
SHA-256: "eba36e52e1ee674d198f486e07c8496853ffc8879e7fe25329523177646a96a0"
|
102
|
-
```
|
103
|
-
|
104
|
-
The node attempts to try different sufficies until one of them produces
|
105
|
-
SHA-256 hash that ends with `0000000` (seven zeros). For example, this
|
106
|
-
suffix `11edb424c` works (it took 212 minutes to find it on 2.3GHz Intel Core i7):
|
107
|
-
|
108
|
-
```
|
109
|
-
Input: "2017-07-19T21:24:51Z b1.zold.io 4096 11edb424c"
|
110
|
-
SHA-256: "34f48e0eee1ed12ad74cb39418f2f6e7442a776a7b6182697957650e00000000"
|
111
|
-
```
|
112
|
-
|
113
|
-
When the first suffix is found, the score of the node is 1. Then, to
|
114
|
-
increase the score by one, the node has to find the next suffix, which
|
115
|
-
can be added to the first 20 characters of the previous hash
|
116
|
-
in order to obtain a new hash with trailing zeros, for example:
|
117
|
-
|
118
|
-
```
|
119
|
-
Input: "34f48e0eee1ed12ad74c "
|
120
|
-
SHA-256: "..."
|
121
|
-
```
|
122
|
-
|
123
|
-
And so on.
|
124
|
-
|
125
|
-
The score is valid only when the starting time point is earlier than
|
126
|
-
current time, but not earlier than 24 hours ago.
|
127
|
-
|
128
48
|
## Operations
|
129
49
|
|
130
50
|
### Remote
|
data/bin/zold
CHANGED
@@ -41,7 +41,7 @@ Encoding.default_internal = Encoding::UTF_8
|
|
41
41
|
log = Zold::Log.new
|
42
42
|
|
43
43
|
args = []
|
44
|
-
unless ENV['RACK_ENV'] == 'test'
|
44
|
+
unless ENV['RACK_ENV'] == 'test' || ARGV.find { |a| a == '--ignore-global-config' }
|
45
45
|
config = File.expand_path('~/.zold')
|
46
46
|
if File.exist?(config)
|
47
47
|
body = File.read(config)
|
@@ -92,6 +92,7 @@ Available options:"
|
|
92
92
|
default: Dir.pwd
|
93
93
|
o.bool '-h', '--help', 'Show these instructions'
|
94
94
|
o.bool '--trace', 'Show full stack trace in case of a problem'
|
95
|
+
o.bool '--ignore-global-config', 'Don\'t read options from the ~/.zold file'
|
95
96
|
o.on '--no-colors', 'Disable colors in the ouput' do
|
96
97
|
Rainbow.enabled = false
|
97
98
|
end
|
@@ -104,16 +105,17 @@ Available options:"
|
|
104
105
|
end
|
105
106
|
end
|
106
107
|
|
107
|
-
|
108
|
+
commands = opts.arguments.reject { |a| a.start_with?('-') }
|
109
|
+
command = commands[0]
|
108
110
|
|
109
|
-
if
|
111
|
+
if command.nil?
|
112
|
+
raise 'A command required, try --help' unless opts.help?
|
110
113
|
log.info(opts.to_s)
|
111
114
|
exit
|
112
115
|
end
|
113
116
|
|
114
|
-
|
115
|
-
|
116
|
-
args = args[(args.index(command) + 1)..-1]
|
117
|
+
args = opts.arguments
|
118
|
+
args << '--help' if opts.help?
|
117
119
|
|
118
120
|
wallets = Zold::Wallets.new(opts['dir'])
|
119
121
|
remotes = Zold::Remotes.new(File.join(opts['dir'], '.zoldata/remotes'))
|
data/features/cli.feature
CHANGED
@@ -12,6 +12,6 @@ Feature: Command Line Processing
|
|
12
12
|
Then Exit code is zero
|
13
13
|
|
14
14
|
Scenario: Wallet can be created
|
15
|
-
When I run bin/zold with "--trace
|
15
|
+
When I run bin/zold with "--trace --public-key=id_rsa.pub create"
|
16
16
|
Then Exit code is zero
|
17
17
|
|
@@ -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
|
port=`python -c 'import socket; s=socket.socket(); s.bind(("", 0)); print(s.getsockname()[1]); s.close()'`
|
9
9
|
|
@@ -21,21 +21,21 @@ while ! nc -z localhost ${port}; do
|
|
21
21
|
((c++)) && ((c==20)) && break
|
22
22
|
done
|
23
23
|
|
24
|
-
zold
|
25
|
-
zold
|
26
|
-
zold
|
24
|
+
zold remote clean
|
25
|
+
zold remote add localhost ${port}
|
26
|
+
zold remote show
|
27
27
|
|
28
|
-
zold
|
28
|
+
zold create --public-key=id_rsa.pub 0000000000000000
|
29
29
|
target=`zold create --public-key=id_rsa.pub`
|
30
30
|
invoice=`zold invoice ${target}`
|
31
|
-
zold
|
32
|
-
zold
|
33
|
-
zold
|
34
|
-
zold
|
31
|
+
zold pay --private-key=id_rsa 0000000000000000 ${invoice} 14.99 'To save the world!'
|
32
|
+
zold propagate 0000000000000000
|
33
|
+
zold show
|
34
|
+
zold show 0000000000000000
|
35
35
|
|
36
|
-
zold
|
37
|
-
zold
|
38
|
-
zold
|
39
|
-
zold
|
40
|
-
zold
|
41
|
-
zold
|
36
|
+
zold remote show
|
37
|
+
zold push 0000000000000000
|
38
|
+
zold fetch 0000000000000000 --ignore-score-weakness
|
39
|
+
zold diff 0000000000000000
|
40
|
+
zold merge 0000000000000000
|
41
|
+
zold clean 0000000000000000
|
data/lib/zold/commands/clean.rb
CHANGED
@@ -39,7 +39,7 @@ module Zold
|
|
39
39
|
end
|
40
40
|
|
41
41
|
def run(args = [])
|
42
|
-
opts = Slop.parse(args, help: true) do |o|
|
42
|
+
opts = Slop.parse(args, help: true, suppress_errors: true) do |o|
|
43
43
|
o.banner = "Usage: zold clean [ID...] [options]
|
44
44
|
Available options:"
|
45
45
|
o.bool '--help', 'Print instructions'
|
@@ -48,8 +48,9 @@ Available options:"
|
|
48
48
|
@log.info(opts.to_s)
|
49
49
|
return
|
50
50
|
end
|
51
|
-
|
52
|
-
|
51
|
+
mine = opts.arguments[1..-1]
|
52
|
+
raise 'At least one wallet ID is required' if mine.empty?
|
53
|
+
mine.each do |id|
|
53
54
|
clean(Copies.new(File.join(@copies, id)), opts)
|
54
55
|
end
|
55
56
|
end
|
data/lib/zold/commands/create.rb
CHANGED
@@ -35,7 +35,7 @@ module Zold
|
|
35
35
|
end
|
36
36
|
|
37
37
|
def run(args = [])
|
38
|
-
opts = Slop.parse(args, help: true) do |o|
|
38
|
+
opts = Slop.parse(args, help: true, suppress_errors: true) do |o|
|
39
39
|
o.banner = "Usage: zold create [options]
|
40
40
|
Available options:"
|
41
41
|
o.string '--public-key',
|
@@ -48,7 +48,8 @@ Available options:"
|
|
48
48
|
@log.info(opts.to_s)
|
49
49
|
return
|
50
50
|
end
|
51
|
-
|
51
|
+
mine = opts.arguments[1..-1]
|
52
|
+
create(mine.empty? ? Id.new : Id.new(mine[0]), opts)
|
52
53
|
end
|
53
54
|
|
54
55
|
def create(id, opts)
|
data/lib/zold/commands/diff.rb
CHANGED
@@ -39,7 +39,7 @@ module Zold
|
|
39
39
|
end
|
40
40
|
|
41
41
|
def run(args = [])
|
42
|
-
opts = Slop.parse(args, help: true) do |o|
|
42
|
+
opts = Slop.parse(args, help: true, suppress_errors: true) do |o|
|
43
43
|
o.banner = "Usage: zold diff [ID...] [options]
|
44
44
|
Available options:"
|
45
45
|
o.bool '--help', 'Print instructions'
|
@@ -48,9 +48,10 @@ Available options:"
|
|
48
48
|
@log.info(opts.to_s)
|
49
49
|
return
|
50
50
|
end
|
51
|
-
|
51
|
+
mine = opts.arguments[1..-1]
|
52
|
+
raise 'At least one wallet ID is required' if mine.empty?
|
52
53
|
stdout = ''
|
53
|
-
|
54
|
+
mine.each do |id|
|
54
55
|
stdout += diff(
|
55
56
|
@wallets.find(Id.new(id)),
|
56
57
|
Copies.new(File.join(@copies, id)),
|
data/lib/zold/commands/fetch.rb
CHANGED
@@ -41,7 +41,7 @@ module Zold
|
|
41
41
|
end
|
42
42
|
|
43
43
|
def run(args = [])
|
44
|
-
opts = Slop.parse(args, help: true) do |o|
|
44
|
+
opts = Slop.parse(args, help: true, suppress_errors: true) do |o|
|
45
45
|
o.banner = "Usage: zold fetch [ID...] [options]
|
46
46
|
Available options:"
|
47
47
|
o.bool '--ignore-score-weakness',
|
@@ -56,8 +56,9 @@ Available options:"
|
|
56
56
|
@log.info(opts.to_s)
|
57
57
|
return
|
58
58
|
end
|
59
|
-
|
60
|
-
|
59
|
+
mine = opts.arguments[1..-1]
|
60
|
+
raise 'At least one wallet ID is required' if mine.empty?
|
61
|
+
mine.each do |id|
|
61
62
|
fetch(id, Copies.new(File.join(@copies, id)), opts)
|
62
63
|
end
|
63
64
|
end
|
@@ -35,7 +35,7 @@ module Zold
|
|
35
35
|
end
|
36
36
|
|
37
37
|
def run(args = [])
|
38
|
-
opts = Slop.parse(args, help: true) do |o|
|
38
|
+
opts = Slop.parse(args, help: true, suppress_errors: true) do |o|
|
39
39
|
o.banner = "Usage: zold invoice ID [options]
|
40
40
|
Where:
|
41
41
|
'ID' is the wallet ID of the money receiver
|
@@ -49,8 +49,9 @@ Available options:"
|
|
49
49
|
@log.info(opts.to_s)
|
50
50
|
return
|
51
51
|
end
|
52
|
-
|
53
|
-
wallet
|
52
|
+
mine = opts.arguments[1..-1]
|
53
|
+
raise 'Receiver wallet ID is required' if mine[0].nil?
|
54
|
+
wallet = @wallets.find(Zold::Id.new(mine[0]))
|
54
55
|
raise 'Wallet doesn\'t exist, do \'fetch\' first' unless wallet.exists?
|
55
56
|
invoice(wallet, opts)
|
56
57
|
end
|
data/lib/zold/commands/merge.rb
CHANGED
@@ -39,7 +39,7 @@ module Zold
|
|
39
39
|
|
40
40
|
# Returns the array of modified wallets (IDs)
|
41
41
|
def run(args = [])
|
42
|
-
opts = Slop.parse(args, help: true) do |o|
|
42
|
+
opts = Slop.parse(args, help: true, suppress_errors: true) do |o|
|
43
43
|
o.banner = "Usage: zold merge [ID...] [options]
|
44
44
|
Available options:"
|
45
45
|
o.bool '--help', 'Print instructions'
|
@@ -48,9 +48,10 @@ Available options:"
|
|
48
48
|
@log.info(opts.to_s)
|
49
49
|
return
|
50
50
|
end
|
51
|
-
|
51
|
+
mine = opts.arguments[1..-1]
|
52
|
+
raise 'At least one wallet ID is required' if mine.empty?
|
52
53
|
modified = []
|
53
|
-
|
54
|
+
mine.each do |id|
|
54
55
|
wallet = @wallets.find(Id.new(id))
|
55
56
|
next unless merge(wallet, Copies.new(File.join(@copies, id)), opts)
|
56
57
|
modified << Id.new(id)
|
data/lib/zold/commands/node.rb
CHANGED
@@ -38,7 +38,7 @@ module Zold
|
|
38
38
|
end
|
39
39
|
|
40
40
|
def run(args = [])
|
41
|
-
opts = Slop.parse(args, help: true) do |o|
|
41
|
+
opts = Slop.parse(args, help: true, suppress_errors: true) do |o|
|
42
42
|
o.banner = 'Usage: zold node [options]'
|
43
43
|
o.string '--invoice',
|
44
44
|
'The invoice you want to collect money to'
|
data/lib/zold/commands/pay.rb
CHANGED
@@ -34,7 +34,7 @@ module Zold
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def run(args = [])
|
37
|
-
opts = Slop.parse(args, help: true) do |o|
|
37
|
+
opts = Slop.parse(args, help: true, suppress_errors: true) do |o|
|
38
38
|
o.banner = "Usage: zold pay wallet invoice amount [details] [options]
|
39
39
|
Where:
|
40
40
|
'wallet' is the sender's wallet ID
|
@@ -55,14 +55,15 @@ Available options:"
|
|
55
55
|
@log.info(opts.to_s)
|
56
56
|
return
|
57
57
|
end
|
58
|
-
|
59
|
-
|
58
|
+
mine = opts.arguments[1..-1]
|
59
|
+
raise 'Payer wallet ID is required as the first argument' if mine[0].nil?
|
60
|
+
from = @wallets.find(Zold::Id.new(mine[0]))
|
60
61
|
raise 'Wallet doesn\'t exist, do \'fetch\' first' unless from.exists?
|
61
|
-
raise 'Recepient\'s invoice is required' if
|
62
|
-
invoice =
|
63
|
-
raise 'Amount is required (in ZLD)' if
|
64
|
-
amount = Zold::Amount.new(zld:
|
65
|
-
details =
|
62
|
+
raise 'Recepient\'s invoice is required as the second argument' if mine[1].nil?
|
63
|
+
invoice = mine[1]
|
64
|
+
raise 'Amount is required (in ZLD) as the third argument' if mine[2].nil?
|
65
|
+
amount = Zold::Amount.new(zld: mine[2].to_f)
|
66
|
+
details = mine[3] ? mine[3] : '-'
|
66
67
|
pay(from, invoice, amount, details, opts)
|
67
68
|
end
|
68
69
|
|
@@ -37,7 +37,7 @@ module Zold
|
|
37
37
|
|
38
38
|
# Returns list of Wallet IDs which were affected
|
39
39
|
def run(args = [])
|
40
|
-
opts = Slop.parse(args, help: true) do |o|
|
40
|
+
opts = Slop.parse(args, help: true, suppress_errors: true) do |o|
|
41
41
|
o.banner = "Usage: zold propagate [ID...] [options]
|
42
42
|
Available options:"
|
43
43
|
o.bool '--help', 'Print instructions'
|
@@ -46,9 +46,10 @@ Available options:"
|
|
46
46
|
@log.info(opts.to_s)
|
47
47
|
return
|
48
48
|
end
|
49
|
-
|
49
|
+
mine = opts.arguments[1..-1]
|
50
|
+
raise 'At least one wallet ID is required' if mine.empty?
|
50
51
|
modified = []
|
51
|
-
|
52
|
+
mine.each do |id|
|
52
53
|
modified += propagate(@wallets.find(id), opts)
|
53
54
|
end
|
54
55
|
modified
|
data/lib/zold/commands/push.rb
CHANGED
@@ -39,7 +39,7 @@ module Zold
|
|
39
39
|
end
|
40
40
|
|
41
41
|
def run(args = [])
|
42
|
-
opts = Slop.parse(args, help: true) do |o|
|
42
|
+
opts = Slop.parse(args, help: true, suppress_errors: true) do |o|
|
43
43
|
o.banner = "Usage: zold push [ID...] [options]
|
44
44
|
Available options:"
|
45
45
|
o.bool '--help', 'Print instructions'
|
@@ -48,8 +48,9 @@ Available options:"
|
|
48
48
|
@log.info(opts.to_s)
|
49
49
|
return
|
50
50
|
end
|
51
|
-
|
52
|
-
|
51
|
+
mine = opts.arguments[1..-1]
|
52
|
+
raise 'At least one wallet ID is required' if mine.empty?
|
53
|
+
mine.each do |id|
|
53
54
|
push(@wallets.find(Id.new(id)), opts)
|
54
55
|
end
|
55
56
|
end
|
data/lib/zold/commands/remote.rb
CHANGED
@@ -41,7 +41,7 @@ module Zold
|
|
41
41
|
end
|
42
42
|
|
43
43
|
def run(args = [])
|
44
|
-
opts = Slop.parse(args, help: true) do |o|
|
44
|
+
opts = Slop.parse(args, help: true, suppress_errors: true) do |o|
|
45
45
|
o.banner = "Usage: zold remote <command> [options]
|
46
46
|
Available commands:
|
47
47
|
#{Rainbow('remote show').green}
|
@@ -62,7 +62,12 @@ Available options:"
|
|
62
62
|
default: false
|
63
63
|
o.bool '--help', 'Print instructions'
|
64
64
|
end
|
65
|
-
|
65
|
+
if opts.help?
|
66
|
+
@log.info(opts.to_s)
|
67
|
+
return
|
68
|
+
end
|
69
|
+
mine = opts.arguments[1..-1]
|
70
|
+
command = mine[0]
|
66
71
|
case command
|
67
72
|
when 'show'
|
68
73
|
show
|
@@ -71,14 +76,14 @@ Available options:"
|
|
71
76
|
when 'reset'
|
72
77
|
reset
|
73
78
|
when 'add'
|
74
|
-
add(
|
79
|
+
add(mine[1], mine[2] ? mine[2].to_i : Remotes::PORT)
|
75
80
|
when 'remove'
|
76
|
-
remove(
|
81
|
+
remove(mine[1], mine[2] ? mine[2].to_i : Remotes::PORT)
|
77
82
|
when 'update'
|
78
83
|
update(opts)
|
79
84
|
update(opts, false)
|
80
85
|
else
|
81
|
-
|
86
|
+
raise "Unknown command '#{command}'"
|
82
87
|
end
|
83
88
|
end
|
84
89
|
|
data/lib/zold/commands/show.rb
CHANGED
@@ -36,7 +36,7 @@ module Zold
|
|
36
36
|
end
|
37
37
|
|
38
38
|
def run(args = [])
|
39
|
-
opts = Slop.parse(args, help: true) do |o|
|
39
|
+
opts = Slop.parse(args, help: true, suppress_errors: true) do |o|
|
40
40
|
o.banner = "Usage: zold show [ID...] [options]
|
41
41
|
Available options:"
|
42
42
|
o.bool '--help', 'Print instructions'
|
@@ -45,12 +45,13 @@ Available options:"
|
|
45
45
|
@log.info(opts.to_s)
|
46
46
|
return
|
47
47
|
end
|
48
|
-
|
48
|
+
mine = opts.arguments[1..-1]
|
49
|
+
if mine.empty?
|
49
50
|
require_relative 'list'
|
50
51
|
List.new(wallets: @wallets, log: @log).run(args)
|
51
52
|
else
|
52
53
|
total = Amount::ZERO
|
53
|
-
|
54
|
+
mine.each do |id|
|
54
55
|
total += show(@wallets.find(Id.new(id)), opts)
|
55
56
|
end
|
56
57
|
total
|
data/lib/zold/commands/taxes.rb
CHANGED
@@ -41,7 +41,7 @@ module Zold
|
|
41
41
|
end
|
42
42
|
|
43
43
|
def run(args = [])
|
44
|
-
opts = Slop.parse(args, help: true) do |o|
|
44
|
+
opts = Slop.parse(args, help: true, suppress_errors: true) do |o|
|
45
45
|
o.banner = "Usage: zold taxes command [options]
|
46
46
|
Available commands:
|
47
47
|
#{Rainbow('taxes pay').green} wallet
|
@@ -57,21 +57,22 @@ Available options:"
|
|
57
57
|
default: '~/.ssh/id_rsa'
|
58
58
|
o.bool '--help', 'Print instructions'
|
59
59
|
end
|
60
|
-
|
60
|
+
mine = opts.arguments[1..-1]
|
61
|
+
command = mine[0]
|
61
62
|
case command
|
62
63
|
when 'show'
|
63
|
-
raise 'At least one wallet ID is required' unless
|
64
|
-
|
64
|
+
raise 'At least one wallet ID is required' unless mine[1]
|
65
|
+
mine[1..-1].each do |id|
|
65
66
|
show(@wallets.find(Id.new(id), opts))
|
66
67
|
end
|
67
68
|
when 'debt'
|
68
|
-
raise 'At least one wallet ID is required' unless
|
69
|
-
|
69
|
+
raise 'At least one wallet ID is required' unless mine[1]
|
70
|
+
mine[1..-1].each do |id|
|
70
71
|
debt(@wallets.find(Id.new(id), opts))
|
71
72
|
end
|
72
73
|
when 'pay'
|
73
|
-
raise 'At least one wallet ID is required' unless
|
74
|
-
|
74
|
+
raise 'At least one wallet ID is required' unless mine[1]
|
75
|
+
mine[1..-1].each do |id|
|
75
76
|
pay(@wallets.find(Id.new(id)), opts)
|
76
77
|
end
|
77
78
|
else
|
data/lib/zold/node/entrance.rb
CHANGED
@@ -55,10 +55,10 @@ module Zold
|
|
55
55
|
copies.add(body, 'remote', Remotes::PORT, 0)
|
56
56
|
Fetch.new(
|
57
57
|
remotes: @remotes, copies: copies.root, log: @log
|
58
|
-
).run([id.to_s, "--ignore-node=#{@address}"])
|
58
|
+
).run(['fetch', id.to_s, "--ignore-node=#{@address}"])
|
59
59
|
modified = Merge.new(
|
60
60
|
wallets: @wallets, copies: copies.root, log: @log
|
61
|
-
).run([id.to_s])
|
61
|
+
).run(['merge', id.to_s])
|
62
62
|
debt = Tax.new(@wallets.find(id)).debt
|
63
63
|
if debt > Tax::TRIAL
|
64
64
|
raise "Taxes are not paid, the debt is #{debt} (#{debt.to_i} zents), won't promote the wallet"
|
@@ -67,7 +67,7 @@ module Zold
|
|
67
67
|
modified.each do |m|
|
68
68
|
Push.new(
|
69
69
|
wallets: @wallets, remotes: @remotes, log: @log
|
70
|
-
).run([m.to_s])
|
70
|
+
).run(['push', m.to_s])
|
71
71
|
end
|
72
72
|
modified
|
73
73
|
end
|
data/lib/zold/score.rb
CHANGED
data/lib/zold/txn.rb
CHANGED
@@ -34,19 +34,25 @@ module Zold
|
|
34
34
|
attr_reader :id, :date, :amount, :prefix, :bnf, :details, :sign
|
35
35
|
attr_writer :sign, :amount, :bnf
|
36
36
|
def initialize(id, date, amount, prefix, bnf, details)
|
37
|
+
raise 'The ID can\'t be NIL' if id.nil?
|
37
38
|
raise "ID of transaction can't be negative: #{id}" if id < 1
|
38
39
|
@id = id
|
40
|
+
raise 'The time can\'t be NIL' if date.nil?
|
39
41
|
raise 'Time have to be of type Time' unless date.is_a?(Time)
|
40
42
|
raise "Time can't be in the future: #{date}" if date > Time.now
|
41
43
|
@date = date
|
44
|
+
raise 'The amount can\'t be NIL' if amount.nil?
|
42
45
|
raise 'The amount has to be of type Amount' unless amount.is_a?(Amount)
|
43
46
|
raise 'The amount can\'t be zero' if amount.zero?
|
44
47
|
@amount = amount
|
48
|
+
raise 'The bnf can\'t be NIL' if bnf.nil?
|
45
49
|
raise 'The bnf has to be of type Id' unless bnf.is_a?(Id)
|
46
50
|
@bnf = bnf
|
51
|
+
raise 'Prefix can\'t be NIL' if prefix.nil?
|
47
52
|
raise "Prefix is too short: \"#{prefix}\"" if prefix.length < 8
|
48
53
|
raise "Prefix is too long: \"#{prefix}\"" if prefix.length > 32
|
49
54
|
@prefix = prefix
|
55
|
+
raise 'Details can\'t be NIL' if details.nil?
|
50
56
|
raise 'Details can\'t be empty' if details.empty?
|
51
57
|
raise "Details are too long: \"#{details}\"" if details.length > 128
|
52
58
|
raise "Details are wrong: \"#{details}\"" unless details =~ /^[a-zA-Z0-9 -\.,]{1,128}$/
|
data/lib/zold/version.rb
CHANGED
data/test/commands/test_clean.rb
CHANGED
@@ -35,7 +35,7 @@ class TestClean < Minitest::Test
|
|
35
35
|
copies = Zold::Copies.new(File.join(dir, "copies/#{id}"))
|
36
36
|
copies.add('a1', 'host-1', 80, 1, Time.now - 26 * 60)
|
37
37
|
copies.add('a2', 'host-2', 80, 2, Time.now - 26 * 60)
|
38
|
-
Zold::Clean.new(copies: copies.root).run([id.to_s])
|
38
|
+
Zold::Clean.new(copies: copies.root).run(['clean', id.to_s])
|
39
39
|
assert(copies.all.empty?)
|
40
40
|
end
|
41
41
|
end
|
@@ -32,7 +32,7 @@ class TestCreate < Minitest::Test
|
|
32
32
|
def test_creates_wallet
|
33
33
|
Dir.mktmpdir 'test' do |dir|
|
34
34
|
wallet = Zold::Create.new(wallets: Zold::Wallets.new(dir)).run(
|
35
|
-
['--public-key=fixtures/id_rsa.pub']
|
35
|
+
['create', '--public-key=fixtures/id_rsa.pub']
|
36
36
|
)
|
37
37
|
assert wallet.balance.zero?
|
38
38
|
assert(
|
data/test/commands/test_diff.rb
CHANGED
@@ -47,14 +47,14 @@ class TestDiff < Minitest::Test
|
|
47
47
|
File.write(second.path, File.read(wallet.path))
|
48
48
|
Zold::Pay.new(
|
49
49
|
wallets: Zold::Wallets.new(dir)
|
50
|
-
).run([id.to_s, second.id.to_s, '14.95', '--force', '--private-key=fixtures/id_rsa'])
|
50
|
+
).run(['pay', id.to_s, second.id.to_s, '14.95', '--force', '--private-key=fixtures/id_rsa'])
|
51
51
|
copies = Zold::Copies.new(File.join(dir, "copies/#{id}"))
|
52
52
|
copies.add(File.read(first.path), 'host-1', 80, 5)
|
53
53
|
copies.add(File.read(second.path), 'host-2', 80, 5)
|
54
54
|
diff = Zold::Diff.new(
|
55
55
|
wallets: Zold::Wallets.new(dir),
|
56
56
|
copies: copies.root
|
57
|
-
).run([id.to_s])
|
57
|
+
).run(['diff', id.to_s])
|
58
58
|
assert(diff.include?('-1;'))
|
59
59
|
end
|
60
60
|
end
|
data/test/commands/test_fetch.rb
CHANGED
@@ -58,7 +58,7 @@ class TestFetch < Minitest::Test
|
|
58
58
|
remotes.add('fake-2', 80)
|
59
59
|
copies = Zold::Copies.new(File.join(dir, "copies/#{id}"))
|
60
60
|
Zold::Fetch.new(copies: copies.root, remotes: remotes).run(
|
61
|
-
['--ignore-score-weakness', id.to_s]
|
61
|
+
['fetch', '--ignore-score-weakness', id.to_s]
|
62
62
|
)
|
63
63
|
assert_equal(copies.all[0][:name], '1')
|
64
64
|
assert_equal(copies.all[0][:score], 0)
|
@@ -79,7 +79,7 @@ class TestFetch < Minitest::Test
|
|
79
79
|
)
|
80
80
|
remotes.add('fake-1', 80)
|
81
81
|
copies = Zold::Copies.new(File.join(dir, "copies/#{id}"))
|
82
|
-
Zold::Fetch.new(copies: copies.root, remotes: remotes).run([id.to_s])
|
82
|
+
Zold::Fetch.new(copies: copies.root, remotes: remotes).run(['fetch', id.to_s])
|
83
83
|
assert_equal(copies.all[0][:name], '1')
|
84
84
|
assert_equal(copies.all[0][:score], 0)
|
85
85
|
end
|
@@ -38,7 +38,7 @@ class TestInvoice < Minitest::Test
|
|
38
38
|
source = wallets.find(id)
|
39
39
|
source.init(id, Zold::Key.new(file: 'fixtures/id_rsa.pub'))
|
40
40
|
invoice = Zold::Invoice.new(wallets: wallets).run(
|
41
|
-
[id.to_s, '--length=16']
|
41
|
+
['invoice', id.to_s, '--length=16']
|
42
42
|
)
|
43
43
|
assert_equal(33, invoice.length)
|
44
44
|
end
|
data/test/commands/test_merge.rb
CHANGED
@@ -24,6 +24,7 @@ require 'json'
|
|
24
24
|
require 'time'
|
25
25
|
require 'webmock/minitest'
|
26
26
|
require_relative '../../lib/zold/wallet'
|
27
|
+
require_relative '../../lib/zold/wallets'
|
27
28
|
require_relative '../../lib/zold/id'
|
28
29
|
require_relative '../../lib/zold/copies'
|
29
30
|
require_relative '../../lib/zold/key'
|
@@ -49,14 +50,14 @@ class TestMerge < Minitest::Test
|
|
49
50
|
File.write(second.path, File.read(wallet.path))
|
50
51
|
Zold::Pay.new(
|
51
52
|
wallets: Zold::Wallets.new(dir)
|
52
|
-
).run([id.to_s, second.id.to_s, '14.95', '--force', '--private-key=fixtures/id_rsa'])
|
53
|
+
).run(['pay', id.to_s, second.id.to_s, '14.95', '--force', '--private-key=fixtures/id_rsa'])
|
53
54
|
copies = Zold::Copies.new(File.join(dir, "copies/#{id}"))
|
54
55
|
copies.add(File.read(first.path), 'host-1', 80, 5)
|
55
56
|
copies.add(File.read(second.path), 'host-2', 80, 5)
|
56
57
|
modified = Zold::Merge.new(
|
57
58
|
wallets: Zold::Wallets.new(dir),
|
58
59
|
copies: copies.root
|
59
|
-
).run([id.to_s])
|
60
|
+
).run(['merge', id.to_s])
|
60
61
|
assert(1, modified.count)
|
61
62
|
assert(id, modified[0])
|
62
63
|
end
|
@@ -74,14 +75,14 @@ class TestMerge < Minitest::Test
|
|
74
75
|
File.write(second.path, File.read(wallet.path))
|
75
76
|
Zold::Pay.new(
|
76
77
|
wallets: Zold::Wallets.new(dir)
|
77
|
-
).run([id.to_s, second.id.to_s, '14.95', '--force', '--private-key=fixtures/id_rsa'])
|
78
|
+
).run(['pay', id.to_s, second.id.to_s, '14.95', '--force', '--private-key=fixtures/id_rsa'])
|
78
79
|
copies = Zold::Copies.new(File.join(dir, "copies/#{id}"))
|
79
80
|
copies.add(File.read(first.path), 'host-1', 80, 5)
|
80
81
|
copies.add(File.read(second.path), 'host-2', 80, 5)
|
81
82
|
modified = Zold::Merge.new(
|
82
83
|
wallets: Zold::Wallets.new(dir),
|
83
84
|
copies: copies.root
|
84
|
-
).run([id.to_s])
|
85
|
+
).run(['merge', id.to_s])
|
85
86
|
assert(1, modified.count)
|
86
87
|
assert(id, modified[0])
|
87
88
|
end
|
data/test/commands/test_node.rb
CHANGED
@@ -46,8 +46,8 @@ class TestNode < Minitest::Test
|
|
46
46
|
remotes = Zold::Remotes.new(File.join(dir, 'remotes.csv'))
|
47
47
|
remotes.clean
|
48
48
|
remotes.add('localhost', port)
|
49
|
-
Zold::Push.new(wallet: wallet, remotes: remotes).run
|
50
|
-
Zold::Fetch.new(wallet: wallet, copies: copies, remotes: remotes).run
|
49
|
+
Zold::Push.new(wallet: wallet, remotes: remotes).run(['push'])
|
50
|
+
Zold::Fetch.new(wallet: wallet, copies: copies, remotes: remotes).run(['fetch'])
|
51
51
|
assert_equal(copies.all[0][:name], '1')
|
52
52
|
assert_equal(copies.all[0][:score], 0)
|
53
53
|
end
|
data/test/commands/test_pay.rb
CHANGED
@@ -41,7 +41,7 @@ class TestPay < Minitest::Test
|
|
41
41
|
amount = Zold::Amount.new(zld: 14.95)
|
42
42
|
Zold::Pay.new(wallets: wallets).run(
|
43
43
|
[
|
44
|
-
'--force', '--private-key=fixtures/id_rsa',
|
44
|
+
'pay', '--force', '--private-key=fixtures/id_rsa',
|
45
45
|
id.to_s, target.to_s, amount.to_zld, 'For the car'
|
46
46
|
]
|
47
47
|
)
|
@@ -57,11 +57,11 @@ class TestRemote < Minitest::Test
|
|
57
57
|
status: 404
|
58
58
|
)
|
59
59
|
cmd = Zold::Remote.new(remotes: remotes)
|
60
|
-
cmd.run([
|
61
|
-
cmd.run(['add', zero.host, zero.port.to_s])
|
62
|
-
cmd.run(%w[add localhost 2])
|
60
|
+
cmd.run(%w[remote clean])
|
61
|
+
cmd.run(['remote', 'add', zero.host, zero.port.to_s])
|
62
|
+
cmd.run(%w[remote add localhost 2])
|
63
63
|
assert_equal(2, remotes.all.count)
|
64
|
-
cmd.run(['update', '--ignore-score-weakness'])
|
64
|
+
cmd.run(['remote', 'update', '--ignore-score-weakness'])
|
65
65
|
assert_equal(1, remotes.all.count)
|
66
66
|
end
|
67
67
|
end
|
data/test/commands/test_show.rb
CHANGED
@@ -37,7 +37,7 @@ class TestShow < Minitest::Test
|
|
37
37
|
wallets = Zold::Wallets.new(dir)
|
38
38
|
wallet = wallets.find(id)
|
39
39
|
wallet.init(Zold::Id.new, Zold::Key.new(file: 'fixtures/id_rsa.pub'))
|
40
|
-
balance = Zold::Show.new(wallets: wallets).run([id.to_s])
|
40
|
+
balance = Zold::Show.new(wallets: wallets).run(['show', id.to_s])
|
41
41
|
assert_equal(Zold::Amount::ZERO, balance)
|
42
42
|
end
|
43
43
|
end
|
data/test/commands/test_taxes.rb
CHANGED
@@ -59,7 +59,7 @@ class TestTaxes < Minitest::Test
|
|
59
59
|
)
|
60
60
|
Zold::Taxes.new(
|
61
61
|
wallets: wallets, remotes: remotes
|
62
|
-
).run(['
|
62
|
+
).run(['taxes', '--private-key=fixtures/id_rsa', id.to_s])
|
63
63
|
assert_equal(Zold::Amount.new(coins: 335_376_547), wallet.balance)
|
64
64
|
end
|
65
65
|
end
|
data/wp/Makefile
ADDED
data/wp/wp.tex
CHANGED
@@ -1,37 +1,141 @@
|
|
1
1
|
\documentclass[11pt,oneside]{article}
|
2
2
|
\usepackage[utf8]{inputenc}
|
3
3
|
\usepackage[american]{babel}
|
4
|
-
\usepackage[
|
5
|
-
|
6
|
-
|
7
|
-
]{geometry}
|
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
8
|
\usepackage{setspace}
|
9
|
-
\usepackage{
|
10
|
-
|
11
|
-
\pagestyle{empty}
|
12
|
-
\setlength{\topskip}{6pt}
|
13
|
-
\setlength{\parindent}{0pt} % indent first line
|
14
|
-
\setlength{\parskip}{0pt} % before par
|
15
|
-
\interfootnotelinepenalty=10000
|
16
|
-
\setstretch{1.1}
|
17
|
-
|
9
|
+
\usepackage{microtype}
|
18
10
|
\usepackage{mathpazo} % Palantino font
|
19
|
-
|
11
|
+
\usepackage{minted}
|
12
|
+
\setminted{fontsize=\footnotesize}
|
13
|
+
\setminted{breaklines}
|
14
|
+
\usemintedstyle{bw}
|
20
15
|
\usepackage{hyperref}
|
21
|
-
\
|
22
|
-
|
23
|
-
maxcitenames=1,maxbibnames=1]{biblatex}
|
24
|
-
\addbibresource{main.bib}
|
16
|
+
\pagestyle{empty}
|
17
|
+
\setstretch{1.2}
|
25
18
|
|
26
19
|
\title{Zold, Lightweight Crypto Currency}
|
27
|
-
\author{Yegor Bugayenko
|
28
|
-
CEO of Zerocracy, Inc.\\
|
29
|
-
555 Bryant, Ste 470, Palo Alto, CA 94301\\
|
30
|
-
\texttt{yegor@zerocracy.com}\\
|
31
|
-
408.692.4742}
|
32
|
-
\begin{document}
|
20
|
+
\author{Yegor Bugayenko\\\texttt{yegor@zold.io}}
|
33
21
|
|
22
|
+
\begin{document}
|
34
23
|
\raggedbottom
|
24
|
+
\maketitle
|
25
|
+
\begin{abstract}
|
26
|
+
Works for you?
|
27
|
+
\end{abstract}
|
28
|
+
|
29
|
+
\section{Motivation}
|
30
|
+
|
31
|
+
Bitcoin, the first decentralized digital currency, was released in
|
32
|
+
January 2009. Since then a number of similar Blockchain-based products have been
|
33
|
+
created, including Etherium, Litecoin, and others.
|
34
|
+
|
35
|
+
Zold is also a decentralized digital currency that maintains its transactions
|
36
|
+
in an unpredicable amount of zero-trust server nodes, trying to guarantee
|
37
|
+
data consistency. However, the architecture of Zold is not based on Blockchain
|
38
|
+
principles. The development of Zold was motivated by the desire to overcome
|
39
|
+
a few obvious disadvantages of existing solutions.
|
40
|
+
|
41
|
+
First, the speed of transaction processing is rather low.
|
42
|
+
|
43
|
+
Second, mining commissions are high.
|
44
|
+
|
45
|
+
Third, the technology is too complex.
|
46
|
+
|
47
|
+
Zold was created as an attempt to resolve these mentioned problems
|
48
|
+
of existing digital currencies.
|
49
|
+
|
50
|
+
\section{Principles}
|
51
|
+
|
52
|
+
\textbf{Open source}.
|
53
|
+
Zold is a command line tool. Its entire code base is open source.
|
54
|
+
|
55
|
+
\textbf{Capacity}.
|
56
|
+
One currency unit is called ZLD.
|
57
|
+
One ZLD by convention equals to $2^24$ (16,777,216) \emph{zents}.
|
58
|
+
All amounts are stored as signed 64-bit integers.
|
59
|
+
Thus, the technical capacity of the currency is 549,755,813,888 ZLD (half a trillion).
|
60
|
+
|
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
|
64
|
+
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.
|
75
|
+
|
76
|
+
\section{Proof of Work}
|
77
|
+
|
78
|
+
Each node calculates its own score.
|
79
|
+
First, it builds the initial text body, which consists of four parts,
|
80
|
+
separated by spaces:
|
81
|
+
|
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,
|
86
|
+
\item The invoice.
|
87
|
+
\end{itemize}
|
88
|
+
|
89
|
+
For example, the body may look like this:
|
90
|
+
|
91
|
+
\begin{minted}{text}
|
92
|
+
2017-07-19T21:24:51Z b2.zold.io 4096 Yt0lOy6Rgf@0000000000000000
|
93
|
+
\end{minted}
|
94
|
+
|
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:
|
100
|
+
|
101
|
+
\begin{minted}{text}
|
102
|
+
2017-07-19T21:24:51Z b2.zold.io 4096 Yt0lOy6Rgf@0000000000000000 abcdef
|
103
|
+
\end{minted}
|
104
|
+
|
105
|
+
The SHA-256 of this body will be:
|
106
|
+
|
107
|
+
\begin{minted}{text}
|
108
|
+
2017-07-19T21:24:51Z b2.zold.io 4096 Yt0lOy6Rgf@0000000000000000 abcdef
|
109
|
+
\end{minted}
|
110
|
+
|
111
|
+
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):
|
115
|
+
|
116
|
+
When the first suffix is found, the score is 1. Then, to
|
117
|
+
increase the score by one, the next suffix has to be found, which
|
118
|
+
can be added to the first 64 characters of the previous hash
|
119
|
+
in order to obtain a new hash with trailing zeros, for example:
|
120
|
+
|
121
|
+
\begin{minted}{text}
|
122
|
+
2017-07-19T21:24:51Z b2.zold.io 4096 Yt0lOy6Rgf@0000000000000000 abcdef abcdef
|
123
|
+
\end{minted}
|
124
|
+
|
125
|
+
And so on.
|
126
|
+
|
127
|
+
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
|
129
|
+
is the amount of the trailing zeros in the hash. In the example above the
|
130
|
+
strength was equal to six.
|
131
|
+
|
132
|
+
\section{Wallets}
|
133
|
+
|
134
|
+
\section{Push}
|
135
|
+
|
136
|
+
\section{Fetch and Merge}
|
137
|
+
|
138
|
+
\section{Threats Analysis}
|
35
139
|
|
36
140
|
how are you?
|
37
141
|
|
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:
|
4
|
+
version: 0.6.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yegor Bugayenko
|
@@ -340,6 +340,7 @@ files:
|
|
340
340
|
- test/test_wallets.rb
|
341
341
|
- test/test_zold.rb
|
342
342
|
- wp/.gitignore
|
343
|
+
- wp/Makefile
|
343
344
|
- wp/wp.tex
|
344
345
|
- zold.gemspec
|
345
346
|
homepage: http://github.com/zerocracy/zold
|