zold 0.6 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +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
|