zold 0.0.8 → 0.1

Sign up to get free protection for your applications and to get access to all the features.
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