zold 0.0.2 → 0.0.3
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/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
|
+
[](http://www.0crat.com/p/C91QJT4CF)
|
4
|
+
[](http://www.rultor.com/p/yegor256/Zold)
|
5
|
+
[](https://www.jetbrains.com/ruby/)
|
6
|
+
|
7
|
+
[](https://travis-ci.org/zerocracy/zold)
|
8
|
+
[](https://ci.appveyor.com/project/zerocracy/zold)
|
9
|
+
[](http://www.0pdd.com/p?name=zerocracy/zold)
|
10
|
+
[](http://badge.fury.io/rb/zold)
|
11
|
+
[](https://codecov.io/github/zerocracy/zold?branch=master)
|
12
|
+
|
13
|
+
[](https://gemnasium.com/zerocracy/zold)
|
14
|
+
[](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
|
+
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
|
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
|