zold 0.0.8 → 0.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.
Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE.md +12 -0
  3. data/.github/PULL_REQUEST_TEMPLATE.md +11 -0
  4. data/.rubocop.yml +9 -1
  5. data/.simplecov +2 -2
  6. data/.travis.yml +1 -1
  7. data/Gemfile +1 -1
  8. data/LICENSE.txt +1 -1
  9. data/Procfile +1 -1
  10. data/README.md +208 -101
  11. data/Rakefile +2 -1
  12. data/bin/zold +135 -54
  13. data/features/cli.feature +1 -1
  14. data/features/step_definitions/steps.rb +1 -1
  15. data/features/support/env.rb +1 -1
  16. data/fixtures/scripts/push-and-pull.sh +35 -0
  17. data/lib/zold.rb +2 -2
  18. data/lib/zold/amount.rb +10 -2
  19. data/lib/zold/commands/{send.rb → clean.rb} +16 -16
  20. data/lib/zold/commands/create.rb +7 -5
  21. data/lib/zold/commands/diff.rb +59 -0
  22. data/lib/zold/commands/fetch.rb +74 -0
  23. data/lib/zold/commands/{pull.rb → list.rb} +11 -17
  24. data/lib/zold/commands/merge.rb +50 -0
  25. data/lib/zold/commands/node.rb +94 -0
  26. data/lib/zold/commands/pay.rb +58 -0
  27. data/lib/zold/commands/{check.rb → propagate.rb} +19 -20
  28. data/lib/zold/commands/push.rb +12 -12
  29. data/lib/zold/commands/remote.rb +115 -0
  30. data/lib/zold/commands/{balance.rb → show.rb} +11 -7
  31. data/lib/zold/copies.rb +126 -0
  32. data/lib/zold/http.rb +70 -0
  33. data/lib/zold/id.rb +8 -3
  34. data/lib/zold/key.rb +2 -2
  35. data/lib/zold/log.rb +51 -2
  36. data/lib/zold/node/farm.rb +81 -0
  37. data/lib/zold/node/front.rb +94 -46
  38. data/lib/zold/patch.rb +58 -0
  39. data/lib/zold/remotes.rb +106 -0
  40. data/lib/zold/score.rb +101 -0
  41. data/lib/zold/signature.rb +48 -0
  42. data/lib/zold/version.rb +3 -3
  43. data/lib/zold/wallet.rb +87 -55
  44. data/lib/zold/wallets.rb +13 -6
  45. data/resources/remotes +1 -0
  46. data/test/commands/test_clean.rb +41 -0
  47. data/test/commands/test_create.rb +2 -2
  48. data/test/commands/test_diff.rb +61 -0
  49. data/test/commands/test_fetch.rb +65 -0
  50. data/test/commands/test_list.rb +42 -0
  51. data/test/commands/test_merge.rb +62 -0
  52. data/test/commands/test_node.rb +56 -0
  53. data/test/commands/{test_send.rb → test_pay.rb} +10 -11
  54. data/test/commands/test_remote.rb +60 -0
  55. data/test/commands/{test_balance.rb → test_show.rb} +6 -8
  56. data/test/node/fake_node.rb +73 -0
  57. data/test/node/test_farm.rb +34 -0
  58. data/test/node/test_front.rb +26 -57
  59. data/test/test__helper.rb +1 -1
  60. data/test/test_amount.rb +10 -2
  61. data/test/test_copies.rb +73 -0
  62. data/test/test_http.rb +42 -0
  63. data/test/test_id.rb +2 -2
  64. data/test/test_key.rb +10 -10
  65. data/test/test_patch.rb +59 -0
  66. data/test/test_remotes.rb +72 -0
  67. data/test/test_score.rb +79 -0
  68. data/test/test_signature.rb +45 -0
  69. data/test/test_wallet.rb +18 -35
  70. data/test/test_wallets.rb +14 -3
  71. data/test/test_zold.rb +52 -5
  72. data/zold.gemspec +5 -3
  73. metadata +92 -21
  74. data/CONTRIBUTING.md +0 -19
  75. data/views/index.haml +0 -6
  76. data/views/layout.haml +0 -26
  77. data/views/not_found.haml +0 -3
data/Rakefile CHANGED
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2018 Zerocracy, Inc.
1
+ # Copyright (c) 2018 Yegor Bugayenko
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  # of this software and associated documentation files (the 'Software'), to deal
@@ -40,6 +40,7 @@ Rake::TestTask.new(:test) do |test|
40
40
  test.libs << 'lib' << 'test'
41
41
  test.pattern = 'test/**/test_*.rb'
42
42
  test.verbose = false
43
+ test.warning = false
43
44
  end
44
45
 
45
46
  require 'rdoc/task'
data/bin/zold CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
  # encoding: utf-8
3
3
  #
4
- # Copyright (c) 2018 Zerocracy, Inc.
4
+ # Copyright (c) 2018 Yegor Bugayenko
5
5
  #
6
6
  # Permission is hereby granted, free of charge, to any person obtaining a copy
7
7
  # of this software and associated documentation files (the 'Software'), to deal
@@ -32,13 +32,8 @@ require_relative '../lib/zold/wallets'
32
32
  require_relative '../lib/zold/log'
33
33
  require_relative '../lib/zold/key'
34
34
  require_relative '../lib/zold/amount'
35
- require_relative '../lib/zold/commands/create'
36
- require_relative '../lib/zold/commands/send'
37
- require_relative '../lib/zold/commands/balance'
38
- require_relative '../lib/zold/commands/check'
39
- require_relative '../lib/zold/commands/pull'
40
- require_relative '../lib/zold/commands/push'
41
- require_relative '../lib/zold/node/front'
35
+ require_relative '../lib/zold/copies'
36
+ require_relative '../lib/zold/remotes'
42
37
 
43
38
  Encoding.default_external = Encoding::UTF_8
44
39
  Encoding.default_internal = Encoding::UTF_8
@@ -46,21 +41,29 @@ Encoding.default_internal = Encoding::UTF_8
46
41
  log = Zold::Log.new
47
42
 
48
43
  begin
49
- opts = Slop.parse(ARGV, strict: true, help: true) do |o|
44
+ opts = Slop.parse(ARGV, strict: false, suppress_errors: true) do |o|
50
45
  o.banner = "Usage: zold [options] command [arguments]
51
46
  Available commands:
47
+ #{Rainbow('remote').green}
48
+ Manage remote nodes
52
49
  #{Rainbow('create').green}
53
50
  Creates a new wallet with a random ID
54
- #{Rainbow('pull').green} [id...]
55
- Pulls all local wallets and new ones explicitly required
56
- #{Rainbow('check').green} id
57
- Checks the validity of the wallet
58
- #{Rainbow('balance').green} id
59
- Prints the balance of the wallet
60
- #{Rainbow('send').green} source target amount
61
- Send ZOLD from one wallet to another
62
- #{Rainbow('push').green} [id...]
63
- Push all local wallets or the ones required
51
+ #{Rainbow('fetch').green} [ID...]
52
+ Fetch wallet copies from remote nodes
53
+ #{Rainbow('clean').green} [ID...]
54
+ Remove expired local copies
55
+ #{Rainbow('merge').green} [ID...]
56
+ Merge remote copies with the HEAD
57
+ #{Rainbow('pull').green} [ID...]
58
+ Fetch and then merge
59
+ #{Rainbow('show').green} [ID...]
60
+ Show all available information about the wallet
61
+ #{Rainbow('pay').green} source target amount details
62
+ Pay ZOLD from one wallet to another
63
+ #{Rainbow('status').green}
64
+ Show status of local copies
65
+ #{Rainbow('push').green} [ID...]
66
+ Push all/some local wallets or the ones required
64
67
  #{Rainbow('node').green} port
65
68
  Run node at the given TCP port
66
69
  Available options:"
@@ -78,71 +81,149 @@ Available options:"
78
81
  o.on '--no-colors', 'Disable colors in the ouput' do
79
82
  Rainbow.enabled = false
80
83
  end
84
+ o.on '--verbose', 'Enable extra logging information' do
85
+ log = Zold::Log::Verbose.new
86
+ end
81
87
  o.on '-v', '--version', 'Show current version' do
82
- puts Zold::VERSION
88
+ log.info(Zold::VERSION)
83
89
  exit
84
90
  end
85
91
  end
86
92
 
87
- if opts.help?
93
+ raise 'Try --help' if opts.arguments.empty? && !opts.help?
94
+
95
+ if opts.help? && opts.arguments.empty?
88
96
  log.info(opts.to_s)
89
97
  exit
90
98
  end
91
99
 
92
- raise 'Command is required' if opts.arguments.empty?
93
-
94
100
  command = opts.arguments[0]
95
101
 
102
+ args = ARGV[(ARGV.index(command) + 1)..-1]
103
+
96
104
  wallets = Zold::Wallets.new(opts['dir'])
105
+ remotes = Zold::Remotes.new(File.join(opts['dir'], '.zold/remotes'))
106
+ copies = File.join(opts['dir'], '.zold/copies')
97
107
 
98
108
  case command
99
109
  when 'node'
100
- raise 'TCP port is required' if opts.arguments[1].nil?
101
- Zold::Front.run!(port: opts.arguments[1].to_i)
110
+ require_relative '../lib/zold/commands/node'
111
+ Zold::Node.new(log: log).run(args)
102
112
  when 'create'
113
+ require_relative '../lib/zold/commands/create'
103
114
  Zold::Create.new(
104
115
  wallets: wallets,
105
116
  pubkey: Zold::Key.new(file: opts['public-key']),
106
117
  log: log
107
- ).run
108
- when 'send'
109
- raise "Payer wallet ID is required" if opts.arguments[1].nil?
110
- raise "Recepient wallet ID is required" if opts.arguments[2].nil?
111
- Zold::Send.new(
112
- payer: wallets.find(Zold::Id.new(opts.arguments[1])),
113
- receiver: wallets.find(Zold::Id.new(opts.arguments[2])),
114
- amount: Zold::Amount.new(zld: opts.arguments[3].to_f),
115
- pvtkey: Zold::Key.new(file: opts['private-key']),
116
- log: log
117
- ).run
118
- when 'balance'
119
- raise "Wallet ID is required" if opts.arguments[1].nil?
120
- Zold::Balance.new(
121
- wallet: wallets.find(Zold::Id.new(opts.arguments[1])),
118
+ ).run(args)
119
+ when 'remote'
120
+ require_relative '../lib/zold/commands/remote'
121
+ Zold::Remote.new(
122
+ remotes: remotes,
122
123
  log: log
123
- ).run
124
- when 'check'
125
- raise "Wallet ID is required" if opts.arguments[1].nil?
126
- Zold::Check.new(
127
- wallet: wallets.find(Zold::Id.new(opts.arguments[1])),
128
- wallets: wallets,
124
+ ).run(args)
125
+ when 'pay'
126
+ raise "Payer wallet ID is required" if args[0].nil?
127
+ raise "Recepient wallet ID is required" if args[1].nil?
128
+ raise "Amount is required (in Zolds)" if args[2].nil?
129
+ require_relative '../lib/zold/commands/pay'
130
+ Zold::Pay.new(
131
+ payer: wallets.find(Zold::Id.new(args[0])),
132
+ receiver: Zold::Id.new(args[1]),
133
+ amount: Zold::Amount.new(zld: args[2].to_f),
134
+ details: opts.arguments[4] ? args[3] : '-',
135
+ pvtkey: Zold::Key.new(file: opts['private-key']),
129
136
  log: log
130
- ).run
137
+ ).run(args)
138
+ when 'show'
139
+ if args[0].nil?
140
+ require_relative '../lib/zold/commands/list'
141
+ Zold::List.new(
142
+ wallets: wallets,
143
+ log: log
144
+ ).run(args)
145
+ else
146
+ require_relative '../lib/zold/commands/show'
147
+ args.each do |id|
148
+ Zold::Show.new(
149
+ wallet: wallets.find(Zold::Id.new(id)),
150
+ log: log
151
+ ).run(args)
152
+ end
153
+ end
154
+ when 'fetch'
155
+ require_relative '../lib/zold/commands/fetch'
156
+ args.each do |id|
157
+ Zold::Fetch.new(
158
+ wallet: wallets.find(Zold::Id.new(id)),
159
+ remotes: remotes,
160
+ copies: Zold::Copies.new(File.join(copies, id)),
161
+ log: log
162
+ ).run(args)
163
+ end
164
+ when 'clean'
165
+ require_relative '../lib/zold/commands/clean'
166
+ if args.empty?
167
+ args = Dir.new(copies).select { |f| f =~ /[0-9a-fA-F]{16}/ }
168
+ end
169
+ args.each do |id|
170
+ Zold::Clean.new(
171
+ copies: Zold::Copies.new(File.join(copies, id)),
172
+ log: log
173
+ ).run(args)
174
+ end
175
+ when 'diff'
176
+ require_relative '../lib/zold/commands/diff'
177
+ args.each do |id|
178
+ Zold::Diff.new(
179
+ wallet: wallets.find(Zold::Id.new(id)),
180
+ copies: Zold::Copies.new(File.join(copies, id)),
181
+ log: log
182
+ ).run(args)
183
+ end
184
+ when 'merge'
185
+ require_relative '../lib/zold/commands/merge'
186
+ require_relative '../lib/zold/commands/propagate'
187
+ args.each do |id|
188
+ Zold::Merge.new(
189
+ wallet: wallets.find(Zold::Id.new(id)),
190
+ copies: Zold::Copies.new(File.join(copies, id)),
191
+ log: log
192
+ ).run(args)
193
+ Zold::Propagate.new(
194
+ wallet: wallets.find(Zold::Id.new(id)),
195
+ wallets: wallets,
196
+ log: log
197
+ ).run(args)
198
+ end
131
199
  when 'pull'
132
- Zold::Pull.new(
133
- wallet: wallets.find(Zold::Id.new(opts.arguments[1])),
134
- log: log
135
- ).run
200
+ require_relative '../lib/zold/commands/fetch'
201
+ require_relative '../lib/zold/commands/merge'
202
+ args.each do |id|
203
+ Zold::Fetch.new(
204
+ wallet: wallets.find(Zold::Id.new(id)),
205
+ remotes: remotes,
206
+ copies: Zold::Copies.new(File.join(copies, id)),
207
+ log: log
208
+ ).run(args)
209
+ Zold::Merge.new(
210
+ wallet: wallets.find(Zold::Id.new(id)),
211
+ copies: Zold::Copies.new(File.join(copies, id)),
212
+ log: log
213
+ ).run(args)
214
+ end
136
215
  when 'push'
216
+ require_relative '../lib/zold/commands/push'
137
217
  Zold::Push.new(
138
- wallet: wallets.find(Zold::Id.new(opts.arguments[1])),
218
+ wallet: wallets.find(Zold::Id.new(args[0])),
219
+ remotes: remotes,
139
220
  log: log
140
- ).run
221
+ ).run(args)
141
222
  else
142
223
  raise "Command '#{command}' is not supported"
143
224
  end
144
225
  rescue StandardError => ex
145
- log.error(ex.message)
226
+ log.error("#{ex.message} (#{ex.class.name})")
146
227
  puts ex.backtrace if opts['trace']
147
228
  exit -1
148
229
  end
@@ -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 "create --private-key id_rsa --public-key id_rsa.pub"
15
+ When I run bin/zold with " --private-key id_rsa --public-key id_rsa.pub --trace create"
16
16
  Then Exit code is zero
17
17
 
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2018 Zerocracy, Inc.
1
+ # Copyright (c) 2018 Yegor Bugayenko
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  # of this software and associated documentation files (the 'Software'), to deal
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2018 Zerocracy, Inc.
1
+ # Copyright (c) 2018 Yegor Bugayenko
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  # of this software and associated documentation files (the 'Software'), to deal
@@ -0,0 +1,35 @@
1
+ #!/bin/bash
2
+ set -x
3
+ set -e
4
+ shopt -s expand_aliases
5
+
6
+ alias zold="$1"
7
+
8
+ port=`python -c 'import socket; s=socket.socket(); s.bind(("", 0)); print(s.getsockname()[1]); s.close()'`
9
+
10
+ mkdir server
11
+ cd server
12
+ zold node --host=localhost --port=${port} --bind-port=${port} --threads=0 &
13
+ pid=$!
14
+ trap "kill -9 $pid" EXIT
15
+ cd ..
16
+
17
+ while ! nc -z localhost ${port}; do
18
+ sleep 0.1
19
+ done
20
+
21
+ zold remote clean
22
+ zold remote add localhost ${port}
23
+ zold remote show
24
+
25
+ zold --public-key id_rsa.pub create 0000000000000000
26
+ zold --private-key id_rsa --trace pay 0000000000000000 af5788fcadd710c5 14.99 'To save the world!'
27
+ zold show
28
+ zold show 0000000000000000
29
+
30
+ zold push 0000000000000000
31
+ zold fetch 0000000000000000
32
+ zold diff 0000000000000000
33
+ zold --trace merge 0000000000000000
34
+
35
+ echo 'DONE'
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2018 Zerocracy, Inc.
1
+ # Copyright (c) 2018 Yegor Bugayenko
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  # of this software and associated documentation files (the 'Software'), to deal
@@ -23,7 +23,7 @@ require_relative 'zold/version'
23
23
 
24
24
  # Zold main module.
25
25
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
26
- # Copyright:: Copyright (c) 2018 Zerocracy, Inc.
26
+ # Copyright:: Copyright (c) 2018 Yegor Bugayenko
27
27
  # License:: MIT
28
28
  module Zold
29
29
  # to be implemented...
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2018 Zerocracy, Inc.
1
+ # Copyright (c) 2018 Yegor Bugayenko
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  # of this software and associated documentation files (the 'Software'), to deal
@@ -22,7 +22,7 @@ require 'rainbow'
22
22
 
23
23
  # The amount.
24
24
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
25
- # Copyright:: Copyright (c) 2018 Zerocracy, Inc.
25
+ # Copyright:: Copyright (c) 2018 Yegor Bugayenko
26
26
  # License:: MIT
27
27
  module Zold
28
28
  # Amount
@@ -57,6 +57,14 @@ module Zold
57
57
  @coins == other.to_i
58
58
  end
59
59
 
60
+ def >(other)
61
+ @coins > other.to_i
62
+ end
63
+
64
+ def <(other)
65
+ @coins < other.to_i
66
+ end
67
+
60
68
  def +(other)
61
69
  Amount.new(coins: @coins + other.to_i)
62
70
  end
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2018 Zerocracy, Inc.
1
+ # Copyright (c) 2018 Yegor Bugayenko
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  # of this software and associated documentation files (the 'Software'), to deal
@@ -18,29 +18,29 @@
18
18
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
19
  # SOFTWARE.
20
20
 
21
+ require 'uri'
22
+ require 'json'
23
+ require 'time'
21
24
  require_relative '../log.rb'
25
+ require_relative '../http.rb'
26
+ require_relative '../score.rb'
22
27
 
23
- # SEND command.
28
+ # CLEAN command.
24
29
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
25
- # Copyright:: Copyright (c) 2018 Zerocracy, Inc.
30
+ # Copyright:: Copyright (c) 2018 Yegor Bugayenko
26
31
  # License:: MIT
27
32
  module Zold
28
- # Money sending command
29
- class Send
30
- def initialize(payer:, receiver:, amount:, pvtkey:, log: Log::Quiet.new)
31
- @payer = payer
32
- @receiver = receiver
33
- @amount = amount
34
- @pvtkey = pvtkey
33
+ # CLEAN pulling command
34
+ class Clean
35
+ def initialize(copies:, log: Log::Quiet.new)
36
+ @copies = copies
35
37
  @log = log
36
38
  end
37
39
 
38
- def run
39
- raise "The amount can't be negative: #{@amount}" if @amount.negative?
40
- txn = @payer.sub(@amount, @receiver.id, @pvtkey)
41
- @receiver.add(txn)
42
- @log.info("#{@amount} sent from #{@payer} to #{@receiver}")
43
- txn[:id]
40
+ def run(_ = [])
41
+ @copies.clean
42
+ @log.debug("Expired local copies removed for #{@copies}, \
43
+ #{@copies.all.count} left")
44
44
  end
45
45
  end
46
46
  end
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2018 Zerocracy, Inc.
1
+ # Copyright (c) 2018 Yegor Bugayenko
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  # of this software and associated documentation files (the 'Software'), to deal
@@ -24,7 +24,7 @@ require_relative '../id.rb'
24
24
 
25
25
  # CREATE command.
26
26
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
27
- # Copyright:: Copyright (c) 2018 Zerocracy, Inc.
27
+ # Copyright:: Copyright (c) 2018 Yegor Bugayenko
28
28
  # License:: MIT
29
29
  module Zold
30
30
  # Create command
@@ -35,11 +35,13 @@ module Zold
35
35
  @log = log
36
36
  end
37
37
 
38
- def run
39
- id = Id.new
38
+ def run(args = [])
39
+ id = args.empty? ? Id.new : Id.new(args[0])
40
40
  wallet = @wallets.find(id)
41
41
  wallet.init(id, @pubkey)
42
- @log.info("#{wallet} created at #{@wallets}")
42
+ @log.info(wallet.id)
43
+ @log.debug("Wallet #{Rainbow(wallet).green} \
44
+ created at #{@wallets.path}")
43
45
  wallet
44
46
  end
45
47
  end