zold 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +105 -71
- data/bin/zold +65 -9
- data/fixtures/id_rsa +51 -0
- data/fixtures/id_rsa.pub +1 -0
- data/lib/zold/commands/init.rb +44 -0
- data/lib/zold/commands/send.rb +45 -0
- data/lib/zold/key.rb +152 -0
- data/lib/zold/log.rb +36 -0
- data/lib/zold/version.rb +1 -1
- data/lib/zold/wallet.rb +97 -0
- data/test/commands/test_init.rb +45 -0
- data/test/commands/test_send.rb +50 -0
- data/test/test_key.rb +43 -0
- data/test/test_wallet.rb +43 -0
- data/zold.gemspec +1 -1
- metadata +18 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7bb038912f96db88c1268faf5d5a30f310af4cac
|
4
|
+
data.tar.gz: 9505bbb9a1bc261b644b9f5aa81e43cbedab3aa8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0b222bbd35b0dd243c6f40e3143ee1c2603567f7920db1aa540d298524dd6c239e6e8f8af8834980f55c5b077cc5a8b2d847e1a51176dd25191d3f9813573de5
|
7
|
+
data.tar.gz: a7f4dc09dc1c4df5833af8d479b02c14c8befb8253c20a59a6b8f9aacf86ea39c5744f6cc5e4ad970a233d2141cb77fe53918a9296b87cf6ccc88c5c2ee13dff
|
data/README.md
CHANGED
@@ -1,5 +1,18 @@
|
|
1
1
|
<img src="http://www.zold.io/logo.svg" width="64px" height="64px"/>
|
2
2
|
|
3
|
+
[![Managed by Zerocracy](http://www.0crat.com/badge/C91QJT4CF.svg)](http://www.0crat.com/p/C91QJT4CF)
|
4
|
+
[![DevOps By Rultor.com](http://www.rultor.com/b/yegor256/Zold)](http://www.rultor.com/p/yegor256/Zold)
|
5
|
+
[![We recommend RubyMine](http://img.teamed.io/rubymine-recommend.svg)](https://www.jetbrains.com/ruby/)
|
6
|
+
|
7
|
+
[![Build Status](https://travis-ci.org/zerocracy/zold.svg)](https://travis-ci.org/zerocracy/zold)
|
8
|
+
[![Build status](https://ci.appveyor.com/api/projects/status/orvfo2qgmd1d7a2i?svg=true)](https://ci.appveyor.com/project/zerocracy/zold)
|
9
|
+
[![PDD status](http://www.0pdd.com/svg?name=zerocracy/zold)](http://www.0pdd.com/p?name=zerocracy/zold)
|
10
|
+
[![Gem Version](https://badge.fury.io/rb/zold.svg)](http://badge.fury.io/rb/zold)
|
11
|
+
[![Test Coverage](https://img.shields.io/codecov/c/github/zerocracy/zold.svg)](https://codecov.io/github/zerocracy/zold?branch=master)
|
12
|
+
|
13
|
+
[![Dependency Status](https://gemnasium.com/zerocracy/zold.svg)](https://gemnasium.com/zerocracy/zold)
|
14
|
+
[![Maintainability](https://api.codeclimate.com/v1/badges/7489c1d2bacde40ffc09/maintainability)](https://codeclimate.com/github/zerocracy/zold/maintainability)
|
15
|
+
|
3
16
|
**NOTICE**: It's an experiment and a very early draft! Please, feel free to
|
4
17
|
submit your ideas or pull requests.
|
5
18
|
|
@@ -8,123 +21,144 @@ ZOLD is a crypto currency.
|
|
8
21
|
ZOLD is going to solve these problems:
|
9
22
|
|
10
23
|
* Blockchain is slow and [doesn't scale](https://en.wikipedia.org/wiki/Bitcoin_scalability_problem)
|
11
|
-
* Crypto mining makes strangers rich
|
12
|
-
* High volatility makes cryptos suitable
|
24
|
+
* Crypto mining makes irrelevant strangers rich
|
25
|
+
* High volatility makes cryptos suitable mostly for the black market
|
13
26
|
|
14
27
|
ZOLD is:
|
15
28
|
|
16
29
|
* Fast
|
17
30
|
* Scalable
|
18
31
|
* Anonymous
|
19
|
-
* As stable as USD
|
20
32
|
|
21
33
|
ZOLD principles include:
|
22
34
|
|
23
|
-
* There is only one issuer: [Zerocracy, Inc.](http://www.zerocracy.com)
|
24
|
-
* The only way to get ZOLD is to earn it (or to buy from someone)
|
25
|
-
* [Zerocracy](http://www.zerocracy.com) guarantees to buy back for $1/ZOLD
|
26
|
-
* No history of transactions
|
27
|
-
* Consistency is guaranteed by protocols, not data
|
28
35
|
* The entire code base is open source
|
36
|
+
* There is no mining; the only way to get ZOLD is to receive it from someone else
|
37
|
+
* Only 2<sup>63</sup> numerals (no fractions) can technically be issued
|
38
|
+
* The first wallet belongs to the issuer and may have a negative balance
|
39
|
+
* A wallet is an XML file
|
40
|
+
* There is no central ledger, each wallet has its own personal ledger
|
41
|
+
* Each transaction in the ledger is confirmed by [RSA](https://simple.wikipedia.org/wiki/RSA_%28algorithm%29) encryption
|
29
42
|
* The network of communicating nodes maintains wallets of users
|
30
|
-
*
|
31
|
-
* Each node has a trust level, as an integer (negatives mean no trust)
|
32
|
-
* Each node earns 0.16% of each transaction it processes
|
33
|
-
* Nodes lose trust when the information they provide can't be proven by other nodes
|
34
|
-
* The list of 16 highly trusted "backbone" nodes is hardcoded in this Git repository
|
35
|
-
* The wallet no.0 belongs to [Zerocracy](http://www.zerocracy.com) and may have a negative balance
|
43
|
+
* Anyone can add a node to the network
|
36
44
|
|
37
45
|
## How to Use
|
38
46
|
|
39
|
-
Install [Rubygems](https://rubygems.org/pages/download) and then run:
|
47
|
+
Install Ruby 2.2+, [Rubygems](https://rubygems.org/pages/download), and then run:
|
40
48
|
|
41
49
|
```bash
|
42
|
-
gem install zold
|
50
|
+
$ gem install zold
|
43
51
|
```
|
44
52
|
|
45
53
|
Then, either run it as a node:
|
46
54
|
|
47
55
|
```bash
|
48
|
-
zold
|
56
|
+
$ zold start
|
49
57
|
```
|
50
58
|
|
51
59
|
Or do one of the following:
|
52
60
|
|
53
|
-
* `zold
|
54
|
-
* `zold
|
55
|
-
* `zold
|
61
|
+
* `zold init` creates a new wallet (you have to provide PGP keys)
|
62
|
+
* `zold pull` pulls a wallet from the network
|
63
|
+
* `zold send` creates a new transaction
|
64
|
+
* `zold push` pushes a wallet to the network
|
56
65
|
|
57
66
|
For more options just run:
|
58
67
|
|
59
68
|
```bash
|
60
|
-
zold --help
|
69
|
+
$ zold --help
|
61
70
|
```
|
62
71
|
|
63
|
-
##
|
64
|
-
|
65
|
-
Each running node contains a list of wallets; each wallet contains:
|
66
|
-
|
67
|
-
* ID: unsigned 64-bit integer
|
68
|
-
* Public PGP key of the owner: 256 bytes (2048 bits)
|
69
|
-
* Balance: signed 128-bit integer (in 10<sup>-12</sup>)
|
70
|
-
* Version: unsigned 64-bit integer
|
72
|
+
## Glossary
|
71
73
|
|
72
|
-
|
74
|
+
A **node** is an HTTP server with a RESTful API, a maintainer of wallets.
|
73
75
|
|
74
|
-
|
75
|
-
protocol to make payments:
|
76
|
+
A **client** is a command line Ruby gem [`zold`](https://rubygems.org/gems/zold).
|
76
77
|
|
77
|
-
|
78
|
+
A **wallet** is an XML file with a ledger of all transactions inside.
|
78
79
|
|
79
|
-
|
80
|
+
A **transaction** is a money transferring operation between two wallets.
|
80
81
|
|
81
|
-
|
82
|
+
## Data
|
82
83
|
|
83
|
-
|
84
|
-
Each node maintains a queue of payments, where each payment includes:
|
84
|
+
A wallet may look like this:
|
85
85
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
**Phase II**.
|
102
|
-
The node sends a confirmation request to its friends, which includes
|
103
|
-
their payment IDs.
|
86
|
+
```xml
|
87
|
+
<wallet>
|
88
|
+
<id>123456</id>
|
89
|
+
<pkey><!-- public RSA key, 256 bytes --></pkey>
|
90
|
+
<ledger>
|
91
|
+
[...]
|
92
|
+
<txn id="35">
|
93
|
+
<date>2017-07-19T21:24:51.136Z</date>
|
94
|
+
<beneficiary>927284</beneficiary>
|
95
|
+
<amount>-560</amount>
|
96
|
+
<sign><!-- RSA signature of the payer --></sign>
|
97
|
+
</txn>
|
98
|
+
</ledger>
|
99
|
+
</wallet>
|
100
|
+
```
|
104
101
|
|
105
|
-
|
106
|
-
Each node modifies the balances in its local list of wallets and responds
|
107
|
-
with a payment confirmation status. The payment gets removed from the queue.
|
102
|
+
Wallet `<id>` is an unsigned 32-bit integer.
|
108
103
|
|
109
|
-
|
104
|
+
Transaction `id` is an unsigned 16-bit integer.
|
110
105
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
nodes.
|
106
|
+
Transaction `date` is an unsigned 32-bit integer, meaning
|
107
|
+
milliseconds since
|
108
|
+
[epoch](https://en.wikipedia.org/wiki/Epoch_%28reference_date%29).
|
115
109
|
|
116
|
-
|
117
|
-
|
110
|
+
All amounts are signed 64-bit integers, where 1ZLD by convention equals to
|
111
|
+
2<sup>24</sup> (16,777,216). Thus, the technical capacity
|
112
|
+
of the currency is 549,755,813,888 (half a trillion).
|
118
113
|
|
119
|
-
|
120
|
-
|
114
|
+
The `<sign>` exists only in transactions with negative `amount`.
|
115
|
+
It contains an RSA signature of a data block, created by the wallet owner:
|
116
|
+
`date`, `amount`, `beneficiary` and
|
117
|
+
64 bytes of [salt](https://en.wikipedia.org/wiki/Salt_%28cryptography%29).
|
121
118
|
|
122
|
-
|
119
|
+
The list of a few backbone nodes is hard-coded in this Git repository.
|
123
120
|
|
124
|
-
|
121
|
+
## Architecture
|
125
122
|
|
126
|
-
|
127
|
-
|
123
|
+
**Pull**.
|
124
|
+
The client connects to a random closest node and pulls a wallet. If the node
|
125
|
+
doesn't have the wallet, it tries to find it in the network.
|
126
|
+
Then, it calculates and prints the balance to the user.
|
127
|
+
|
128
|
+
**Commit**.
|
129
|
+
The user provides the amount and the destination wallet name. The client
|
130
|
+
finds the mediator node in the network. The client
|
131
|
+
pulls the destination wallet and adds
|
132
|
+
a new XML element `<txn>` to both wallets.
|
133
|
+
|
134
|
+
**Push**.
|
135
|
+
The client sends two wallets to the mediator, which checks
|
136
|
+
the validity of the deduction and propagates
|
137
|
+
both wallets to other nodes in a [2PC](https://en.wikipedia.org/wiki/Two-phase_commit_protocol)
|
138
|
+
manner: acknowledgment first, commit next.
|
139
|
+
If a node receives a wallet that contains transactions that are younger
|
140
|
+
than transactions in its local copy, a merge operation is
|
141
|
+
performed. If the balance after the merge is negative, the push is rejected.
|
142
|
+
|
143
|
+
**Init**.
|
144
|
+
The client creates an empty wallet XML and asks one of the backbone
|
145
|
+
nodes to generate a new `id` for it.
|
146
|
+
|
147
|
+
**Start**.
|
148
|
+
The node manifests itself to one of the backbone nodes, which
|
149
|
+
propagates the manifestation to other nodes, they propagate further.
|
150
|
+
When any node goes down, the node that detected such a situation,
|
151
|
+
notifies other nodes and they exlude the failed node from the list.
|
152
|
+
|
153
|
+
## Corner Cases
|
154
|
+
|
155
|
+
**Too long wallet**.
|
156
|
+
If a wallet has too many transactions, its validation will take too long, since
|
157
|
+
will require many cross-wallet checks. How to solve this?
|
158
|
+
|
159
|
+
**DDoS**.
|
160
|
+
We may have too many simultaneous `push` operations to the network,
|
161
|
+
which may/will cause troubles. What to do?
|
128
162
|
|
129
163
|
## License (MIT)
|
130
164
|
|
data/bin/zold
CHANGED
@@ -24,26 +24,82 @@
|
|
24
24
|
STDOUT.sync = true
|
25
25
|
|
26
26
|
require 'slop'
|
27
|
+
require 'rainbow'
|
27
28
|
require_relative '../lib/zold'
|
28
29
|
require_relative '../lib/zold/version'
|
30
|
+
require_relative '../lib/zold/wallet'
|
31
|
+
require_relative '../lib/zold/log'
|
32
|
+
require_relative '../lib/zold/key'
|
33
|
+
require_relative '../lib/zold/commands/init'
|
34
|
+
require_relative '../lib/zold/commands/send'
|
29
35
|
|
30
36
|
opts = Slop.parse(ARGV, strict: true, help: true) do |o|
|
31
|
-
o.banner = "Usage
|
37
|
+
o.banner = "Usage: zold [options] command [arguments]
|
38
|
+
Available commands:
|
39
|
+
#{Rainbow('init').green} [id]
|
40
|
+
Creates a new wallet with the required ID or a random one
|
41
|
+
#{Rainbow('pull').green} [id...]
|
42
|
+
Pulls all local wallets and new ones explicitly required
|
43
|
+
#{Rainbow('send').green} source target amount
|
44
|
+
Send ZOLD from one wallet to another
|
45
|
+
#{Rainbow('push').green} [id...]
|
46
|
+
Push all local wallets or the ones required
|
47
|
+
Available options:"
|
48
|
+
o.string '-d', '--dir',
|
49
|
+
'The directory where wallets are stored (default: current directory)',
|
50
|
+
default: '.'
|
51
|
+
o.string '-p', '--private-key',
|
52
|
+
'The location of RSA private key (default: ~/.ssh/id_rsa)',
|
53
|
+
default: '~/.ssh/id_rsa'
|
54
|
+
o.string '-u', '--public-key',
|
55
|
+
'The location of RSA public key (default: ~/.ssh/id_rsa.pub)',
|
56
|
+
default: '~/.ssh/id_rsa.pub'
|
32
57
|
o.bool '-h', '--help', 'Show these instructions'
|
33
|
-
o.
|
58
|
+
o.on '-v', '--version', 'Show current version' do
|
59
|
+
puts Zold::VERSION
|
60
|
+
exit
|
61
|
+
end
|
34
62
|
end
|
35
63
|
|
36
|
-
|
37
|
-
puts opts
|
38
|
-
exit
|
39
|
-
end
|
64
|
+
log = Zold::Log.new
|
40
65
|
|
41
|
-
if opts.
|
42
|
-
|
66
|
+
if opts.help?
|
67
|
+
log.info(opts.to_s)
|
43
68
|
exit
|
44
69
|
end
|
45
70
|
|
46
71
|
Encoding.default_external = Encoding::UTF_8
|
47
72
|
Encoding.default_internal = Encoding::UTF_8
|
48
73
|
|
49
|
-
|
74
|
+
raise 'Command is required' if opts.arguments.empty?
|
75
|
+
|
76
|
+
command = opts.arguments[0]
|
77
|
+
|
78
|
+
case command
|
79
|
+
when 'init'
|
80
|
+
id = opts.arguments[1] ? opts.arguments[1] : SecureRandom.uuid
|
81
|
+
Zold::Init.new(
|
82
|
+
wallet: Zold::Wallet.new(File.join(opts['dir'], "#{id}.xml")),
|
83
|
+
id: id,
|
84
|
+
pubkey: Zold::Key.new(opts['public-key']),
|
85
|
+
log: log
|
86
|
+
).run
|
87
|
+
when 'send'
|
88
|
+
Zold::Send.new(
|
89
|
+
payer: Zold::Wallet.new(
|
90
|
+
File.join(opts['dir'], "#{opts.arguments[1]}.xml")
|
91
|
+
),
|
92
|
+
receiver: Zold::Wallet.new(
|
93
|
+
File.join(opts['dir'], "#{opts.arguments[2]}.xml")
|
94
|
+
),
|
95
|
+
amount: opts.arguments[3].to_f * 2 ** 24,
|
96
|
+
pvtkey: Zold::Key.new(opts['private-key']),
|
97
|
+
log: log
|
98
|
+
).run
|
99
|
+
when 'pull'
|
100
|
+
raise 'PULL is not implemented yet'
|
101
|
+
when 'push'
|
102
|
+
raise 'PUSH is not implemented yet'
|
103
|
+
else
|
104
|
+
raise "Command '#{command}' is not supported"
|
105
|
+
end
|
data/fixtures/id_rsa
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
-----BEGIN RSA PRIVATE KEY-----
|
2
|
+
MIIJJwIBAAKCAgEA1w5FGfMDNWYpgjHsIOGQyXUpfjjoxszPIkmqkiTQr6gvqN5P
|
3
|
+
gYfPwOOFesQV4rrnbttofNkqpYZTB+XIfjbf41IGodvT11MeUIbQJDqiXcGpaxvk
|
4
|
+
wf1zmMn1KceUqQjTDuvk5LLFFvFLBkKjJEfaCn2fDz2W4CuKllp45eW/oBN8LjMJ
|
5
|
+
VfRjlq1n4n54aAPhW/wIg+PfN6kLA35GADSBcQmPanfCxaFbunMmLHhGcYBoDxHr
|
6
|
+
zW09z2/+e0vqPrQusfNtllkDw2GxR0gTjFDcl+MRgsyWv3CQ1mJ5wXfPD6PJ5Ztj
|
7
|
+
POJRq9hk7iZFueR/CGa1UF94vz/WLsQ4ohzGpeA4rywvWLe1sZQkV1gwG675IOpR
|
8
|
+
AjCcmhpb/MohJQMOVnAkAyyxMfSTzVX3oNymCAvrtqGkQ621P/jNFwBsWY9KUN/f
|
9
|
+
Pp3uAXoK/iwoBRYCkGrz+d3cT7qf57wvglamQFwOCpODGCeLGo1oeWMEz/MsPgqT
|
10
|
+
ezebYoL8WpaYHkScrQE+UGP2mtpvT4fx/L6jsQfVKddAKrGSI8vstCkmunQSbcTb
|
11
|
+
atZOEa+SIw2g5/H2cdnO4yIoDa57JaEVMlqfOOGsXn3gpxB0CfgmDKI9eudt7yXH
|
12
|
+
d+nsEc+elN6n6g1kcp+ugkmT8ZindQYcggWMxo1dYEjnQje4/C0+jsBsB10CAwEA
|
13
|
+
AQKCAgASk4P6ithDG5EIUwGfkXxtOnacFZRd38EgqBZYy19PXQrI3nMlsDKM6dpU
|
14
|
+
0W1GiXiGReOPrT6Wz7SKYRnhdSH/w80Y3CE/X0mmEQ8Xogz2Zk0ZGG65Jwh+MSvB
|
15
|
+
MSExPLbmeg/qhVqq8arWXpkzABXghBtiOKK4uGofNK9uxFq6HBTE9NmgmBymHlJz
|
16
|
+
6RLDgVpNFMczhVJ5v1tZMOYhDGgF+JpvyuqDIb4Hq/ynKLiFA195tcWVmBMXwQfN
|
17
|
+
ZLBWPEAwVOOpcgT2MpEapCo0G6QCZrXTg5Kd9L4+FoGH6a50HmTJNZPr5WzCmE2X
|
18
|
+
mKy7MvaaJi0RRT3r3zrEDWUK88tgziAxP2F3KG+8cXUPqt0tOs4pugCjxMHVv/KJ
|
19
|
+
GF+0icZXzccNK27bjshd/T9kwj7wG6xA6IHZU+hbv5hSAt8W+I6afIg5LqA+B6GO
|
20
|
+
apM61iFPeSa4Fjkeunl0HGPBKYDrKkDpI9f9vI5nVblUznWgk5be/1TmhqqfvMNF
|
21
|
+
S8MRIg9qajM37ppwiSsf/XM0S+iaaSkEC92SizYKSwn+F8y/4VPa+YwNCwZyzRnC
|
22
|
+
7jx4jGrXTmBCyXzOpNY6cNa9NWO6+HOODQGLZFZ3AWjs4xIgukIkfDzIFiC0U2eU
|
23
|
+
5zDAjnr2uk+y8jeY795WHRMv6WFPYxOqDnIEXgGz5ixKng47IQKCAQEA8h2329oA
|
24
|
+
RiZm4dF2KgoE90b8z9uKdysFUPnFBz0M8iwa97vJr4wxzwilLV2YwZW+Fsu+vksy
|
25
|
+
+HsyufKjNUB60p0i1i8ILQgWUcZY6tLAaJ99yTO0FJtvIIAhXXeaOqOoKThVtSWV
|
26
|
+
HEYiHQnjxlVdAn4T7CB//vaXC/sBOFeYnaIRtwwK4jQ3IG4+u0FRYG8c2eHY+90l
|
27
|
+
MmNZZywlOfwy9cYPCaT2l5AO5kOYmIrlyezM+Abp0HSrZgJDG/H7Sx69gETjbnG1
|
28
|
+
5+YvL0MJ6FLVfTukjTMlXFx6Fiq9WCK5ggkgNcLk+KaRnbNhEJHOTdRU8/3KzBAh
|
29
|
+
RMdjlnRXrtz1tQKCAQEA42NNzAcWbKKm8KliEMMA93xkw0zS35VftMt98w+lf2kx
|
30
|
+
YWVVMBXlnic6LJvuQVW7wL3mwocnVGvbO4D59S2BUzGKsOLUIsfzwVErd513/NW6
|
31
|
+
SwHVUomBbcDfkMjuKE6JZz5JV7BsF4SlxJZdL1HWpOnry1YXUtH/ivKaqrScZJ0o
|
32
|
+
N87HHswmsezBAKQb9wOW27fXCPzNS8jWjftACCK4a3Ps492oPyCC9wuzp4kEVQQA
|
33
|
+
/R1YV18s2N7wCc9TooU2xV2Zg6viA7R1W63zwg5KOv2qOQONndmlMhAdOO941+S9
|
34
|
+
wfKcu2ZWAqyJvjjZ8xYnU92FM/CNQP5DK73VduhUCQKCAQAf2VLvQ70XfUO5XuFp
|
35
|
+
ZEoE8TyeZyXOyUT4wvJtIlXKoYymm/hK9Gk079Eyp4ZJqNYJj6G2zJOW5jXlCgr4
|
36
|
+
HVRK0krb2/H6Yn71IN9ffHu9B4X3aqq8rzmuD8zTy8DpB9A+I9/6ZUg5IOyp3zws
|
37
|
+
QdxrUIR0Yk4UDwINnGYrsDIuQjyMVLQ1z2KVDIuJ/Gyk/9jOvIvbjdqvxyvii4cW
|
38
|
+
GpvlgrlFroKVq2iaV7gCEPtrVZAc7GPjfQVy9Mc5LNq+pfuNnQJB7AleyQPZ9rqd
|
39
|
+
6g+VWrwpqtm2TZ/tvI+NwXufpG2tRMb0Ao1TLl6NXHDEAjNuqSr9Lv4BWy05hHJo
|
40
|
+
WT6lAoIBADef80gV88Zfg7cbuIGhMntYUs3z3SIUyHTR0t3C1hl1Aj9xKoW41ZL6
|
41
|
+
xaBkBMS21FcyHWE47sYYHGlSA9OWbiyL0gGze3GGuHpyANAiFVgkcI4oxKaMPL08
|
42
|
+
kXQ5swjpLXO0KPzqi4a1TFfq8KDCxF9TWftD9DCubnTvJCbeR+PVDiGY090U0+Jy
|
43
|
+
qEQf4TdsCVt2fYQVU6NWXiYdcGyNEdA3a5vSfXXz3hXRJwG04vppIFTK+PFmtvHW
|
44
|
+
l6HOtgbrz5o4a3Vqdr+xRYRH6XlvRXlo1FteIyaaN28nwf5LlqQ5sLHhR7YQMro0
|
45
|
+
uv1tquNsZ/J8Hjm2fteHW6c3qSCNdQECggEACgb3Q0rWvxlXoUIEudaG/4X3riQI
|
46
|
+
Mpj7nqUxB5VD2oX3iwcP23eKdUXOI3LCUIECJaKwT6H9cZXawoyn0Fj0ORCqtGoj
|
47
|
+
UC2497Z2BukP+acIlPWv+B4F83UgxSnvkq44PZjDCuxh5rgr/28QJlc+Gr8i2EHW
|
48
|
+
pQjUPXWStfAmIOz1SSM4VMphVgyxxfqvGyfkh6pzRNwl3vJ9hgbMV/4Q2ix4+qNl
|
49
|
+
K/gplWUJWnNtgsYTQU1RnDi9GGVG5ePJs2c2//5PzkrGoqxqrEAHDeOWZnOvkh/A
|
50
|
+
EBXJzfA/DzrnLLF6J7nEh6WqtlOSQ7ZI3PgqW7SA78LtJr4DQTy9FFd8Sg==
|
51
|
+
-----END RSA PRIVATE KEY-----
|
data/fixtures/id_rsa.pub
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDXDkUZ8wM1ZimCMewg4ZDJdSl+OOjGzM8iSaqSJNCvqC+o3k+Bh8/A44V6xBXiuudu22h82SqlhlMH5ch+Nt/jUgah29PXUx5QhtAkOqJdwalrG+TB/XOYyfUpx5SpCNMO6+TkssUW8UsGQqMkR9oKfZ8PPZbgK4qWWnjl5b+gE3wuMwlV9GOWrWfifnhoA+Fb/AiD4983qQsDfkYANIFxCY9qd8LFoVu6cyYseEZxgGgPEevNbT3Pb/57S+o+tC6x822WWQPDYbFHSBOMUNyX4xGCzJa/cJDWYnnBd88Po8nlm2M84lGr2GTuJkW55H8IZrVQX3i/P9YuxDiiHMal4DivLC9Yt7WxlCRXWDAbrvkg6lECMJyaGlv8yiElAw5WcCQDLLEx9JPNVfeg3KYIC+u2oaRDrbU/+M0XAGxZj0pQ398+ne4Begr+LCgFFgKQavP53dxPup/nvC+CVqZAXA4Kk4MYJ4sajWh5YwTP8yw+CpN7N5tigvxalpgeRJytAT5QY/aa2m9Ph/H8vqOxB9Up10AqsZIjy+y0KSa6dBJtxNtq1k4Rr5IjDaDn8fZx2c7jIigNrnsloRUyWp844axefeCnEHQJ+CYMoj16523vJcd36ewRz56U3qfqDWRyn66CSZPxmKd1BhyCBYzGjV1gSOdCN7j8LT6OwGwHXQ== test@zold.io
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# Copyright (c) 2018 Zerocracy, Inc.
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
# of this software and associated documentation files (the 'Software'), to deal
|
7
|
+
# in the Software without restriction, including without limitation the rights
|
8
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
# copies of the Software, and to permit persons to whom the Software is
|
10
|
+
# furnished to do so, subject to the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be included in all
|
13
|
+
# copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
# SOFTWARE.
|
22
|
+
|
23
|
+
require_relative '../log.rb'
|
24
|
+
|
25
|
+
# INIT command.
|
26
|
+
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
27
|
+
# Copyright:: Copyright (c) 2018 Zerocracy, Inc.
|
28
|
+
# License:: MIT
|
29
|
+
module Zold
|
30
|
+
# Init command
|
31
|
+
class Init
|
32
|
+
def initialize(wallet:, id:, pubkey:, log: Log.new)
|
33
|
+
@wallet = wallet
|
34
|
+
@id = id
|
35
|
+
@pubkey = pubkey
|
36
|
+
@log = log
|
37
|
+
end
|
38
|
+
|
39
|
+
def run
|
40
|
+
@wallet.init(@id, @pubkey)
|
41
|
+
@log.info("#{@wallet} initialized as #{@id}")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# Copyright (c) 2018 Zerocracy, Inc.
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
# of this software and associated documentation files (the 'Software'), to deal
|
7
|
+
# in the Software without restriction, including without limitation the rights
|
8
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
# copies of the Software, and to permit persons to whom the Software is
|
10
|
+
# furnished to do so, subject to the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be included in all
|
13
|
+
# copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
# SOFTWARE.
|
22
|
+
|
23
|
+
require_relative '../log.rb'
|
24
|
+
|
25
|
+
# SEND command.
|
26
|
+
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
27
|
+
# Copyright:: Copyright (c) 2018 Zerocracy, Inc.
|
28
|
+
# License:: MIT
|
29
|
+
module Zold
|
30
|
+
# Money sending command
|
31
|
+
class Send
|
32
|
+
def initialize(payer:, receiver:, amount:, pvtkey:, log: Log.new)
|
33
|
+
@payer = payer
|
34
|
+
@receiver = receiver
|
35
|
+
@amount = amount
|
36
|
+
@pvtkey = pvtkey
|
37
|
+
@log = log
|
38
|
+
end
|
39
|
+
|
40
|
+
def run
|
41
|
+
@receiver.add(@payer.sub(@amount, @receiver.id, @pvtkey))
|
42
|
+
@log.info("#{@amount} sent from #{@payer} to #{@receiver}")
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/zold/key.rb
ADDED
@@ -0,0 +1,152 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# Copyright (c) 2018 Zerocracy, Inc.
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
# of this software and associated documentation files (the 'Software'), to deal
|
7
|
+
# in the Software without restriction, including without limitation the rights
|
8
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
# copies of the Software, and to permit persons to whom the Software is
|
10
|
+
# furnished to do so, subject to the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be included in all
|
13
|
+
# copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
# SOFTWARE.
|
22
|
+
|
23
|
+
require 'openssl'
|
24
|
+
require 'base64'
|
25
|
+
|
26
|
+
# The RSA key (either private or public).
|
27
|
+
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
28
|
+
# Copyright:: Copyright (c) 2018 Zerocracy, Inc.
|
29
|
+
# License:: MIT
|
30
|
+
module Zold
|
31
|
+
# A key
|
32
|
+
class Key
|
33
|
+
def initialize(file)
|
34
|
+
@file = file
|
35
|
+
end
|
36
|
+
|
37
|
+
def to_s
|
38
|
+
rsa.to_s.strip
|
39
|
+
end
|
40
|
+
|
41
|
+
def encrypt(text)
|
42
|
+
Base64.encode64(rsa.private_encrypt(text))
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def rsa
|
48
|
+
raise "Can't find RSA key at #{@file}" unless File.exist?(@file)
|
49
|
+
text = File.read(File.expand_path(@file)).strip
|
50
|
+
unless text.start_with?('-----BEGIN')
|
51
|
+
text = OpenSSHKeyConverter.decode_pubkey(text.split[1])
|
52
|
+
end
|
53
|
+
OpenSSL::PKey::RSA.new(text)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Stolen from: https://gist.github.com/tombh/f66de84fd3a63e670ad9
|
59
|
+
module OpenSSHKeyConverter
|
60
|
+
# The components in a openssh .pub / known_host RSA public key.
|
61
|
+
RSA_COMPONENTS = ['ssh-rsa', :e, :n].freeze
|
62
|
+
# The components in a openssh .pub / known_host DSA public key.
|
63
|
+
DSA_COMPONENTS = ['ssh-dss', :p, :q, :g, :pub_key].freeze
|
64
|
+
|
65
|
+
# Encodes a key's public part in the format found in .pub & known_hosts files.
|
66
|
+
def self.encode_pubkey(key)
|
67
|
+
case key
|
68
|
+
when OpenSSL::PKey::RSA
|
69
|
+
components = RSA_COMPONENTS
|
70
|
+
when OpenSSL::PKey::DSA
|
71
|
+
components = DSA_COMPONENTS
|
72
|
+
else
|
73
|
+
raise "Unsupported key type #{key.class.name}"
|
74
|
+
end
|
75
|
+
components.map! { |c| c.is_a?(Symbol) ? encode_mpi(key.send(c)) : c }
|
76
|
+
# ruby tries to be helpful and adds new lines every 60 bytes :(
|
77
|
+
[pack_pubkey_components(components)].pack('m').delete("\n")
|
78
|
+
end
|
79
|
+
|
80
|
+
# Decodes an openssh public key from the format of .pub & known_hosts files.
|
81
|
+
def self.decode_pubkey(string)
|
82
|
+
components = unpack_pubkey_components Base64.decode64(string)
|
83
|
+
case components.first
|
84
|
+
when RSA_COMPONENTS.first
|
85
|
+
ops = RSA_COMPONENTS.zip components
|
86
|
+
key = OpenSSL::PKey::RSA.new
|
87
|
+
when DSA_COMPONENTS.first
|
88
|
+
ops = DSA_COMPONENTS.zip components
|
89
|
+
key = OpenSSL::PKey::DSA.new
|
90
|
+
else
|
91
|
+
raise "Unsupported key type #{components.first}"
|
92
|
+
end
|
93
|
+
ops.each do |o|
|
94
|
+
next unless o.first.is_a? Symbol
|
95
|
+
key.send "#{o.first}=", decode_mpi(o.last)
|
96
|
+
end
|
97
|
+
key
|
98
|
+
end
|
99
|
+
|
100
|
+
# Loads a serialized key from an IO instance (File, StringIO).
|
101
|
+
def self.load_key(io)
|
102
|
+
key_from_string io.read
|
103
|
+
end
|
104
|
+
|
105
|
+
# Reads a serialized key from a string.
|
106
|
+
def self.key_from_string(serialized_key)
|
107
|
+
header = first_line serialized_key
|
108
|
+
if header.index 'RSA'
|
109
|
+
OpenSSL::PKey::RSA.new serialized_key
|
110
|
+
elsif header.index 'DSA'
|
111
|
+
OpenSSL::PKey::DSA.new serialized_key
|
112
|
+
else
|
113
|
+
raise 'Unknown key type'
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
# Extracts the first line of a string.
|
118
|
+
def self.first_line(string)
|
119
|
+
string[0, string.index(/\r|\n/) || string.len]
|
120
|
+
end
|
121
|
+
|
122
|
+
# Unpacks the string components in an openssh-encoded pubkey.
|
123
|
+
def self.unpack_pubkey_components(str)
|
124
|
+
cs = []
|
125
|
+
i = 0
|
126
|
+
while i < str.length
|
127
|
+
len = str[i, 4].unpack('N').first
|
128
|
+
cs << str[i + 4, len]
|
129
|
+
i += 4 + len
|
130
|
+
end
|
131
|
+
cs
|
132
|
+
end
|
133
|
+
|
134
|
+
# Packs string components into an openssh-encoded pubkey.
|
135
|
+
def self.pack_pubkey_components(strings)
|
136
|
+
(strings.map { |s| [s.length].pack('N') }).zip(strings).flatten.join
|
137
|
+
end
|
138
|
+
|
139
|
+
# Decodes an openssh-mpi-encoded integer.
|
140
|
+
def self.decode_mpi(mpi_str)
|
141
|
+
mpi_str.unpack('C*').inject(0) { |a, e| (a << 8) | e }
|
142
|
+
end
|
143
|
+
|
144
|
+
# Encodes an openssh-mpi-encoded integer.
|
145
|
+
def self.encode_mpi(n)
|
146
|
+
chars = []
|
147
|
+
n = n.to_i
|
148
|
+
chars << (n & 0xff) && n >>= 8 while n != 0
|
149
|
+
chars << 0 if chars.empty? || chars.last >= 0x80
|
150
|
+
chars.reverse.pack('C*')
|
151
|
+
end
|
152
|
+
end
|
data/lib/zold/log.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# Copyright (c) 2018 Zerocracy, Inc.
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
# of this software and associated documentation files (the 'Software'), to deal
|
7
|
+
# in the Software without restriction, including without limitation the rights
|
8
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
# copies of the Software, and to permit persons to whom the Software is
|
10
|
+
# furnished to do so, subject to the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be included in all
|
13
|
+
# copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
# SOFTWARE.
|
22
|
+
|
23
|
+
require 'rainbow'
|
24
|
+
|
25
|
+
# The log.
|
26
|
+
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
27
|
+
# Copyright:: Copyright (c) 2018 Zerocracy, Inc.
|
28
|
+
# License:: MIT
|
29
|
+
module Zold
|
30
|
+
# Logging
|
31
|
+
class Log
|
32
|
+
def info(msg)
|
33
|
+
puts msg
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/lib/zold/version.rb
CHANGED
data/lib/zold/wallet.rb
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# Copyright (c) 2018 Zerocracy, Inc.
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
# of this software and associated documentation files (the 'Software'), to deal
|
7
|
+
# in the Software without restriction, including without limitation the rights
|
8
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
# copies of the Software, and to permit persons to whom the Software is
|
10
|
+
# furnished to do so, subject to the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be included in all
|
13
|
+
# copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
# SOFTWARE.
|
22
|
+
|
23
|
+
require 'nokogiri'
|
24
|
+
require 'time'
|
25
|
+
|
26
|
+
# The wallet.
|
27
|
+
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
28
|
+
# Copyright:: Copyright (c) 2018 Zerocracy, Inc.
|
29
|
+
# License:: MIT
|
30
|
+
module Zold
|
31
|
+
# A single wallet
|
32
|
+
class Wallet
|
33
|
+
def initialize(file)
|
34
|
+
@file = file
|
35
|
+
end
|
36
|
+
|
37
|
+
def to_s
|
38
|
+
"Z#{id}"
|
39
|
+
end
|
40
|
+
|
41
|
+
def init(id, pubkey)
|
42
|
+
File.write(
|
43
|
+
@file,
|
44
|
+
Nokogiri::XML::Builder.new do |xml|
|
45
|
+
xml.wallet do
|
46
|
+
xml.id_ id
|
47
|
+
xml.pkey pubkey.to_s
|
48
|
+
xml.ledger {}
|
49
|
+
end
|
50
|
+
end.to_xml
|
51
|
+
)
|
52
|
+
end
|
53
|
+
|
54
|
+
def id
|
55
|
+
xml.xpath('/wallet/id/text()').to_s.to_i
|
56
|
+
end
|
57
|
+
|
58
|
+
def balance
|
59
|
+
xml.xpath('/wallet/ledger/txn/amount/text()')
|
60
|
+
.map(&:to_s)
|
61
|
+
.map(&:to_i)
|
62
|
+
.inject(0) { |sum, n| sum + n }
|
63
|
+
end
|
64
|
+
|
65
|
+
def sub(amount, target, pvtkey)
|
66
|
+
txn = 1
|
67
|
+
date = Time.now.iso8601
|
68
|
+
doc = xml
|
69
|
+
t = doc.xpath('/wallet/ledger')[0].add_child('<txn/>')[0]
|
70
|
+
t['id'] = txn
|
71
|
+
t.add_child('<date/>')[0].content = date
|
72
|
+
t.add_child('<amount/>')[0].content = -amount
|
73
|
+
t.add_child('<beneficiary/>')[0].content = target
|
74
|
+
t.add_child('<sign/>')[0].content = pvtkey.encrypt(
|
75
|
+
"#{date} #{amount} #{target}"
|
76
|
+
)
|
77
|
+
File.write(@file, doc.to_s)
|
78
|
+
{ id: txn, date: date, amount: amount, beneficiary: id }
|
79
|
+
end
|
80
|
+
|
81
|
+
def add(txn)
|
82
|
+
doc = xml
|
83
|
+
t = doc.xpath('/wallet/ledger')[0].add_child('<txn/>')[0]
|
84
|
+
t['id'] = "/#{txn[:id]}"
|
85
|
+
t.add_child('<date/>')[0].content = txn[:date]
|
86
|
+
t.add_child('<amount/>')[0].content = txn[:amount]
|
87
|
+
t.add_child('<beneficiary/>')[0].content = txn[:beneficiary]
|
88
|
+
File.write(@file, doc.to_s)
|
89
|
+
end
|
90
|
+
|
91
|
+
private
|
92
|
+
|
93
|
+
def xml
|
94
|
+
Nokogiri::XML(File.read(@file))
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# Copyright (c) 2018 Zerocracy, Inc.
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
# of this software and associated documentation files (the 'Software'), to deal
|
7
|
+
# in the Software without restriction, including without limitation the rights
|
8
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
# copies of the Software, and to permit persons to whom the Software is
|
10
|
+
# furnished to do so, subject to the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be included in all
|
13
|
+
# copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
# SOFTWARE.
|
22
|
+
|
23
|
+
require 'minitest/autorun'
|
24
|
+
require 'tmpdir'
|
25
|
+
require_relative '../../lib/zold/wallet.rb'
|
26
|
+
require_relative '../../lib/zold/key.rb'
|
27
|
+
require_relative '../../lib/zold/commands/init.rb'
|
28
|
+
|
29
|
+
# INIT test.
|
30
|
+
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
31
|
+
# Copyright:: Copyright (c) 2018 Zerocracy, Inc.
|
32
|
+
# License:: MIT
|
33
|
+
class TestInit < Minitest::Test
|
34
|
+
def test_initializes_wallet
|
35
|
+
Dir.mktmpdir 'test' do |dir|
|
36
|
+
wallet = Zold::Wallet.new(File.join(dir, 'source.xml'))
|
37
|
+
Zold::Init.new(
|
38
|
+
wallet: wallet,
|
39
|
+
id: 1,
|
40
|
+
pubkey: Zold::Key.new('fixtures/id_rsa.pub')
|
41
|
+
).run
|
42
|
+
assert wallet.balance.zero?
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# Copyright (c) 2018 Zerocracy, Inc.
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
# of this software and associated documentation files (the 'Software'), to deal
|
7
|
+
# in the Software without restriction, including without limitation the rights
|
8
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
# copies of the Software, and to permit persons to whom the Software is
|
10
|
+
# furnished to do so, subject to the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be included in all
|
13
|
+
# copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
# SOFTWARE.
|
22
|
+
|
23
|
+
require 'minitest/autorun'
|
24
|
+
require 'tmpdir'
|
25
|
+
require_relative '../../lib/zold/wallet.rb'
|
26
|
+
require_relative '../../lib/zold/key.rb'
|
27
|
+
require_relative '../../lib/zold/commands/send.rb'
|
28
|
+
|
29
|
+
# SEND test.
|
30
|
+
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
31
|
+
# Copyright:: Copyright (c) 2018 Zerocracy, Inc.
|
32
|
+
# License:: MIT
|
33
|
+
class TestSend < Minitest::Test
|
34
|
+
def test_sends_from_wallet_to_wallet
|
35
|
+
Dir.mktmpdir 'test' do |dir|
|
36
|
+
source = Zold::Wallet.new(File.join(dir, 'source.xml'))
|
37
|
+
source.init(1, Zold::Key.new('fixtures/id_rsa.pub'))
|
38
|
+
target = Zold::Wallet.new(File.join(dir, 'target.xml'))
|
39
|
+
target.init(2, Zold::Key.new('fixtures/id_rsa.pub'))
|
40
|
+
Zold::Send.new(
|
41
|
+
payer: source,
|
42
|
+
receiver: target,
|
43
|
+
amount: 100,
|
44
|
+
pvtkey: Zold::Key.new('fixtures/id_rsa')
|
45
|
+
).run
|
46
|
+
assert source.balance == -100
|
47
|
+
assert target.balance == 100
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
data/test/test_key.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# Copyright (c) 2018 Zerocracy, Inc.
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
# of this software and associated documentation files (the 'Software'), to deal
|
7
|
+
# in the Software without restriction, including without limitation the rights
|
8
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
# copies of the Software, and to permit persons to whom the Software is
|
10
|
+
# furnished to do so, subject to the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be included in all
|
13
|
+
# copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
# SOFTWARE.
|
22
|
+
|
23
|
+
require 'minitest/autorun'
|
24
|
+
require 'tmpdir'
|
25
|
+
require_relative '../lib/zold/key.rb'
|
26
|
+
|
27
|
+
# Key test.
|
28
|
+
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
29
|
+
# Copyright:: Copyright (c) 2018 Zerocracy, Inc.
|
30
|
+
# License:: MIT
|
31
|
+
class TestKey < Minitest::Test
|
32
|
+
def test_reads_public_rsa
|
33
|
+
key = Zold::Key.new('fixtures/id_rsa.pub')
|
34
|
+
assert key.to_s.start_with?("-----BEGIN PUBLIC KEY-----\nMIICI")
|
35
|
+
assert key.to_s.end_with?("EAAQ==\n-----END PUBLIC KEY-----")
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_reads_private_rsa
|
39
|
+
key = Zold::Key.new('fixtures/id_rsa')
|
40
|
+
assert key.to_s.start_with?("-----BEGIN RSA PRIVATE KEY-----\nMIIJJ")
|
41
|
+
assert key.to_s.end_with?("Sg==\n-----END RSA PRIVATE KEY-----")
|
42
|
+
end
|
43
|
+
end
|
data/test/test_wallet.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# Copyright (c) 2018 Zerocracy, Inc.
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
# of this software and associated documentation files (the 'Software'), to deal
|
7
|
+
# in the Software without restriction, including without limitation the rights
|
8
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
# copies of the Software, and to permit persons to whom the Software is
|
10
|
+
# furnished to do so, subject to the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be included in all
|
13
|
+
# copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
# SOFTWARE.
|
22
|
+
|
23
|
+
require 'minitest/autorun'
|
24
|
+
require 'tmpdir'
|
25
|
+
require_relative '../lib/zold/key.rb'
|
26
|
+
require_relative '../lib/zold/wallet.rb'
|
27
|
+
|
28
|
+
# Wallet test.
|
29
|
+
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
30
|
+
# Copyright:: Copyright (c) 2018 Zerocracy, Inc.
|
31
|
+
# License:: MIT
|
32
|
+
class TestWallet < Minitest::Test
|
33
|
+
def test_adds_transaction
|
34
|
+
Dir.mktmpdir 'test' do |dir|
|
35
|
+
file = File.join(dir, 'source.xml')
|
36
|
+
wallet = Zold::Wallet.new(file)
|
37
|
+
wallet.init(1, Zold::Key.new('fixtures/id_rsa.pub'))
|
38
|
+
amount = 123
|
39
|
+
wallet.sub(amount, 100, Zold::Key.new('fixtures/id_rsa'))
|
40
|
+
assert wallet.balance == -amount
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/zold.gemspec
CHANGED
@@ -40,7 +40,7 @@ Gem::Specification.new do |s|
|
|
40
40
|
s.description = 'Non-blockchain cryptocurrency'
|
41
41
|
s.authors = ['Yegor Bugayenko']
|
42
42
|
s.email = 'yegor256@gmail.com'
|
43
|
-
s.homepage = 'http://github.com/
|
43
|
+
s.homepage = 'http://github.com/zerocracy/zold'
|
44
44
|
s.files = `git ls-files`.split($RS)
|
45
45
|
s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
46
46
|
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
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.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yegor Bugayenko
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-02-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nokogiri
|
@@ -193,12 +193,23 @@ files:
|
|
193
193
|
- features/gem_package.feature
|
194
194
|
- features/step_definitions/steps.rb
|
195
195
|
- features/support/env.rb
|
196
|
+
- fixtures/id_rsa
|
197
|
+
- fixtures/id_rsa.pub
|
196
198
|
- lib/zold.rb
|
199
|
+
- lib/zold/commands/init.rb
|
200
|
+
- lib/zold/commands/send.rb
|
201
|
+
- lib/zold/key.rb
|
202
|
+
- lib/zold/log.rb
|
197
203
|
- lib/zold/version.rb
|
204
|
+
- lib/zold/wallet.rb
|
205
|
+
- test/commands/test_init.rb
|
206
|
+
- test/commands/test_send.rb
|
198
207
|
- test/test__helper.rb
|
208
|
+
- test/test_key.rb
|
209
|
+
- test/test_wallet.rb
|
199
210
|
- test/test_zold.rb
|
200
211
|
- zold.gemspec
|
201
|
-
homepage: http://github.com/
|
212
|
+
homepage: http://github.com/zerocracy/zold
|
202
213
|
licenses:
|
203
214
|
- MIT
|
204
215
|
metadata: {}
|
@@ -228,5 +239,9 @@ test_files:
|
|
228
239
|
- features/gem_package.feature
|
229
240
|
- features/step_definitions/steps.rb
|
230
241
|
- features/support/env.rb
|
242
|
+
- test/commands/test_init.rb
|
243
|
+
- test/commands/test_send.rb
|
231
244
|
- test/test__helper.rb
|
245
|
+
- test/test_key.rb
|
246
|
+
- test/test_wallet.rb
|
232
247
|
- test/test_zold.rb
|