rubocoin 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 23ae9a1bfaaa6ec0518f256d1649f9cba77918ea
4
+ data.tar.gz: 858b1365052751d13e841dee809c60a120653493
5
+ SHA512:
6
+ metadata.gz: 12ca76dcbbb042f28d7e30af56562304afbaa998d440b8de92d411d0628ddf4369a320802e3556f31e75f29ba391aaec806607aef798e2a3735471132924d741
7
+ data.tar.gz: e639fafe47e172fc48219b75e03fe5ed22f68d4a2bab778f1075e8b6337c83d78fdf14bf091cd3ebd907c5a25a3fafbf224b5f8449b887e302811ed15d6c8c7c
data/.gitignore ADDED
@@ -0,0 +1,11 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+
10
+ # rspec failure tracking
11
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.4.2
5
+ before_install: gem install bundler -v 1.16.0
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in rubocoin.gemspec
6
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,48 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ rubocoin (0.1.0)
5
+ colorize
6
+ sinatra
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ colorize (0.8.1)
12
+ diff-lcs (1.3)
13
+ mustermann (1.0.1)
14
+ rack (2.0.3)
15
+ rack-protection (2.0.0)
16
+ rack
17
+ rake (10.5.0)
18
+ rspec (3.7.0)
19
+ rspec-core (~> 3.7.0)
20
+ rspec-expectations (~> 3.7.0)
21
+ rspec-mocks (~> 3.7.0)
22
+ rspec-core (3.7.0)
23
+ rspec-support (~> 3.7.0)
24
+ rspec-expectations (3.7.0)
25
+ diff-lcs (>= 1.2.0, < 2.0)
26
+ rspec-support (~> 3.7.0)
27
+ rspec-mocks (3.7.0)
28
+ diff-lcs (>= 1.2.0, < 2.0)
29
+ rspec-support (~> 3.7.0)
30
+ rspec-support (3.7.0)
31
+ sinatra (2.0.0)
32
+ mustermann (~> 1.0)
33
+ rack (~> 2.0)
34
+ rack-protection (= 2.0.0)
35
+ tilt (~> 2.0)
36
+ tilt (2.0.8)
37
+
38
+ PLATFORMS
39
+ ruby
40
+
41
+ DEPENDENCIES
42
+ bundler (~> 1.16)
43
+ rake (~> 10.0)
44
+ rspec (~> 3.0)
45
+ rubocoin!
46
+
47
+ BUNDLED WITH
48
+ 1.16.0
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 Carter Brainerd
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
13
+ all 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 NONINFRINGEMENT. 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
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,45 @@
1
+ # RuboCoin
2
+
3
+ RuboCoin is my attempt of a cryptocurrency. I created it mainly just to learn more about blockchain technology.
4
+ This gem is the full node you can run on your machine to mine rubocoin and handle transactions
5
+
6
+
7
+ ## Installation
8
+
9
+ You have 2 ways to get the rubocoin node (`rubocoind`). You can grab the source code
10
+ or you can download the gem from (RubyGems)[https://rubygems.org].
11
+
12
+ #### Installing from source
13
+
14
+ ```
15
+ $ git clone https://github.com/cbrnrd/RuboCoin
16
+ $ bundle install
17
+ $ bundle exec bin/rubocoind
18
+ ```
19
+
20
+ #### Installing via `gem`
21
+
22
+ ```
23
+ $ gem install rubocoin
24
+ $ rubocoind
25
+ ```
26
+
27
+ ## Usage
28
+
29
+ All you have to do is open port 44856 and run `rubocoind`.
30
+
31
+ More command line options are coming in the near future.
32
+
33
+ ## Development
34
+
35
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
36
+
37
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
38
+
39
+ ## Contributing
40
+
41
+ Bug reports and pull requests are welcome on GitHub at https://github.com/cbrnrd/RuboCoin.
42
+
43
+ ## License
44
+
45
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "rubocoin"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/rubocoind ADDED
@@ -0,0 +1,178 @@
1
+ #!/usr/bin/env ruby
2
+ lib = File.expand_path("../../lib", __FILE__)
3
+ unless $LOAD_PATH.include?(lib)
4
+ $LOAD_PATH.unshift(lib)
5
+ require 'rubocoin'
6
+ end
7
+
8
+ def return_invalid_json
9
+ { :message => 'ERROR: Please supply valid JSON' }.to_json
10
+ end
11
+
12
+ class Rubocoind < Sinatra::Base
13
+
14
+ set :environment, :production
15
+ set :port, 44856
16
+ set :logging, true
17
+
18
+ # Create the blockchain
19
+ blockchain = Blockchain.new
20
+
21
+ pid = File.open('/tmp/rubocoind.pid', 'w') do |f|
22
+ f.print(Process.pid)
23
+ end
24
+
25
+ node_id = SecureRandom.uuid.delete('-')
26
+
27
+ # Node addresses always start in 'R'
28
+ node_id[0] = 'R'
29
+
30
+
31
+ # Lets mine!
32
+ get '/mine' do
33
+ last_block = blockchain.last_block
34
+ last_proof = last_block[:proof]
35
+ proof = blockchain.proof_of_work(last_proof)
36
+
37
+ # Distribute reward for finding the proof
38
+ blockchain.new_transaction('network', node_id, blockchain.calculate_reward_amount)
39
+
40
+ # Add a new block to the chain
41
+ block = blockchain.new_block(proof)
42
+
43
+ res = {
44
+ message: "New block forged",
45
+ index: block[:index],
46
+ transactions: block[:transactions],
47
+ proof: block[:proof],
48
+ previous_hash: block[:previous_hash]
49
+ }
50
+
51
+ status 200
52
+ res.to_json
53
+ end
54
+
55
+ # Make a new transaction and add it to the blockchain
56
+ post '/transactions/new' do
57
+ req_body = request.body.read
58
+
59
+ unless JSON.is_valid?(req_body)
60
+ status 400
61
+ return return_invalid_json
62
+ end
63
+
64
+ values = JSON.parse(req_body)
65
+
66
+ required = ['amount', 'sender', 'recipient']
67
+
68
+ unless required.all? { |e| values.key?(e) }
69
+ status 400
70
+ return { :message => 'ERROR: Missing values' }.to_json
71
+ end
72
+
73
+ # Create a new transaction
74
+ index = blockchain.new_transaction(values['sender'], values['recipient'],
75
+ values['amount'], values['others'])
76
+
77
+ res = { message: "Transaction successful. It will be added to the blockchain at block #{index}" }
78
+ status 201
79
+ res.to_json
80
+ end
81
+
82
+ # Return the current blockchain
83
+ get '/chain' do
84
+ res = {
85
+ chain: blockchain.chain,
86
+ length: blockchain.chain.size
87
+ }
88
+ res.to_json
89
+ end
90
+
91
+ post '/register_node' do
92
+ request.body.rewind
93
+ req_body = request.body.read
94
+
95
+ # Check if the json sent to us is valid
96
+ unless JSON.is_valid?(req_body)
97
+ status 400
98
+ return return_invalid_json
99
+ end
100
+
101
+ values = JSON.parse(req_body)
102
+
103
+ nodes = values[:nodes]
104
+
105
+ # Check if a list was even sent to us
106
+ if nodes.nil?
107
+ status 400
108
+ return 'ERROR: Please supply a valid node list'
109
+ end
110
+
111
+ nodes.each do |node|
112
+ blockchain.register_node(node)
113
+ end
114
+
115
+ res = { message: "Nodes have been added successfully", total_nodes: blockchain.nodes }
116
+
117
+ status 201
118
+ res.to_json
119
+ end
120
+
121
+ get '/resolve_node' do
122
+ replaced = blockchain.resolve_conflicts
123
+
124
+ if replaced
125
+ res = { message: 'Chain successfully replaced', new_chain: blockchain.chain }
126
+ else
127
+ res = { message: 'Our chain is authoritative', chain: blockchain.chain }
128
+ end
129
+
130
+ status 200
131
+ return res.to_json
132
+ end
133
+ end
134
+
135
+
136
+ daemonize = false
137
+
138
+ OptionParser.new do |opts|
139
+
140
+ opts.banner = "Usage #{File.basename($PROGRAM_NAME) [options]}"
141
+
142
+ opts.on('-d', '--daemon', 'Run the node in the background') do
143
+ daemonize = true
144
+ end
145
+
146
+ opts.on('-k', '--kill-daemon', 'Kill the rubocoind service if it\'s running') do
147
+ unless File.file?('/tmp/rubocoind.pid')
148
+ puts 'The rubocoin daemon doesn\'t seem to be running'
149
+ exit 0
150
+ end
151
+ pid = File.read('/tmp/rubocoind.pid')
152
+ # Check validity of pid file (no code injection for you)
153
+ if pid ~= /^[A-Z+$]/i
154
+ puts 'PID file is not in the correct format'
155
+ exit 0
156
+ end
157
+ system("kill #{pid}")
158
+ end
159
+
160
+ opts.on('--version', 'Show the current version and exit') do
161
+ puts Rubocoin::Version
162
+ exit 0
163
+ end
164
+
165
+ opts.on_tail('-h', '--help', 'SHow this help message and exit') do
166
+ puts opts
167
+ exit 0
168
+ end
169
+ end.parse!
170
+
171
+ if daemonize
172
+ fork do
173
+ Rubocoind.run!
174
+ end
175
+ end
176
+
177
+ # TODO add cli opts
178
+ Rubocoind.run!
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,195 @@
1
+ require 'uri'
2
+ require 'json'
3
+ require 'digest'
4
+ require 'open-uri'
5
+ require 'set'
6
+
7
+ # This class defines what our blockchain will look like as well as contain
8
+ # functoins for interacting with the chain.
9
+ class Blockchain
10
+
11
+ # The current chain being used
12
+ # @return [Array] A list of blocks
13
+ attr_accessor :chain
14
+
15
+ # We use a {Chain} instead of an {Array} here because we don't want any
16
+ # duplicate blocks in our chain. A {Set} takes care of this for us
17
+ # @return [Set] A duplicate-free list of other nodes currently registered with this node
18
+ attr_accessor :nodes
19
+
20
+ # The difficulty of this node. It's base value is 4 (meaning '0'*4)
21
+ # Each 10,000 blocks mined, the difficulty will increment by 1 (meaning '0'*5)
22
+ attr_reader :difficulty
23
+
24
+ # Initialize the chain and other variables as well
25
+ # as create the 'Genesis' block
26
+ def initialize
27
+ @current_transactions = []
28
+ @chain = []
29
+ @nodes = Set.new
30
+ @difficulty = 4
31
+ @difficulty_increment_counter = 0 # When this reaches 10000, increment difficulty by 1
32
+
33
+ # Generate the genesis block
34
+ new_block(100, 1)
35
+ end
36
+
37
+ # The reward halfs each time the difficulty increases
38
+ def calculate_reward_amount
39
+ initial_reward = 100
40
+ (@difficulty - 3).times do
41
+ initial_reward /= 2
42
+ end
43
+ return initial_reward
44
+ end
45
+
46
+ #
47
+ # Register a new node
48
+ #
49
+ def register_node(addr)
50
+ url = URI.parse(addr)
51
+ @nodes.add("#{url.host}:#{url.port}")
52
+ end
53
+
54
+ # Return the most recent block in our chain
55
+ def last_block
56
+ @chain[-1]
57
+ end
58
+
59
+ # Check whether a chain is valid
60
+ def valid_chain(chain)
61
+ last_block = chain[0]
62
+ index = 1
63
+
64
+ while index < chain.size do
65
+ block = chain[index]
66
+
67
+ # Check previous block hash is correct
68
+ if block[:previous_hash] != hash(last_block)
69
+ false
70
+ end
71
+
72
+ # Check Proof of Work
73
+ unless valid_proof(last_block[:proof], block[:proof])
74
+ false
75
+ end
76
+
77
+ last_block = block
78
+ index += 1
79
+ end
80
+ true # If we got here, all blocks are valid; therefore the chain is valid
81
+ end
82
+
83
+ def resolve_conflicts
84
+ neighbour_nodes = @nodes
85
+ new_chain = nil
86
+
87
+ # Only chains longer than ours
88
+ max_len = @chain.size
89
+
90
+ # Fetch and confirm each chain from the network
91
+ neighbour_nodes.each do |node|
92
+ response = JSON.parse(open("http://#{node}/chain").read)
93
+ response.deep_symbolize_keys!
94
+
95
+ if response[:chain]
96
+ length = response[:length]
97
+ chain = response[:chain]
98
+
99
+ # Check if the length is longer and the chain is valid
100
+ if length > max_len || valid_chain(chain)
101
+ max_len = length
102
+ new_chain = chain
103
+ end
104
+ end
105
+ end
106
+
107
+ # Replace our chain if we discovered a new, valid chain longer than ours
108
+ if new_chain
109
+ @chain = new_chain
110
+ return true
111
+ end
112
+
113
+ return false
114
+ end
115
+
116
+ def new_block(proof, previous_hash=nil)
117
+ # Define the block structure
118
+ block =
119
+ {
120
+ :index => @chain.size + 1,
121
+ :timestamp => Time.now,
122
+ :transactions => @current_transactions,
123
+ :proof => proof,
124
+ :previous_hash => previous_hash || hash(last_block)
125
+ }
126
+
127
+ # Clear transactions
128
+ @current_transactions = []
129
+ info_with_timestamp('Transaction list cleared due to new block formation')
130
+
131
+ # Append the block to the chain
132
+ @chain << block
133
+
134
+ print_new("New block added:")
135
+ puts '{'
136
+ puts "\t index: #{block[:index]}"
137
+ puts "\t timestamp: #{block[:timestamp]}"
138
+ puts "\t transactions: #{block[:transactions]}"
139
+ puts "\t proof: #{block[:proof]}"
140
+ puts "\t previous_hash: #{block[:previous_hash]}"
141
+ puts '}'
142
+
143
+ @difficulty_increment_counter += 1
144
+
145
+ info("Difficulty will increase after #{1000-@difficulty_increment_counter} more blocks")
146
+
147
+ if @difficulty_increment_counter >= 0x2710
148
+ debug_with_timestamp("Difficulty increased to #{@difficulty + 1}!")
149
+ @difficulty += 1
150
+ @difficulty_increment_counter = 0 # Reset the counter
151
+ end
152
+
153
+ block
154
+ end
155
+
156
+ def new_transaction(sender, recipient, amount, others=nil)
157
+ unless others.nil?
158
+ @current_transactions <<
159
+ {
160
+ :sender => sender,
161
+ :recipient => recipient,
162
+ :amount => amount,
163
+ :others => others
164
+ }
165
+ else
166
+ @current_transactions <<
167
+ {
168
+ :sender => sender,
169
+ :recipient => recipient,
170
+ :amount => amount
171
+ }
172
+ end
173
+
174
+ last_block[:index] + 1
175
+ end
176
+
177
+ def hash(last_block)
178
+ block_string = last_block.sort.to_h.to_json
179
+ return Digest::SHA256.hexdigest(block_string)
180
+ end
181
+
182
+ def proof_of_work(last_proof)
183
+ proof = -1
184
+ proof += 1 until valid_proof(last_proof, proof)
185
+ info("Valid proof found! #{proof}")
186
+ return proof
187
+ end
188
+
189
+ def valid_proof(last_proof, proof)
190
+ guess = "#{last_proof}#{proof}"
191
+ guess_hash = Digest::SHA256.hexdigest(guess)
192
+ return guess_hash[0..(@difficulty - 1)] == ('0' * @difficulty)
193
+ end
194
+
195
+ end
@@ -0,0 +1,37 @@
1
+ # Hash monkey patches
2
+ class Hash
3
+ def symbolize_keys!
4
+ transform_keys!{ |key| key.to_sym rescue key }
5
+ end
6
+
7
+ def deep_symbolize_keys!
8
+ deep_transform_keys!{ |key| key.to_sym rescue key }
9
+ end
10
+
11
+ def transform_keys!
12
+ return enum_for(:transform_keys!) unless block_given?
13
+ keys.each do |key|
14
+ self[yield(key)] = delete(key)
15
+ end
16
+ self
17
+ end
18
+
19
+ def deep_transform_keys!(&block)
20
+ _deep_transform_keys_in_object!(self, &block)
21
+ end
22
+
23
+ def _deep_transform_keys_in_object!(object, &block)
24
+ case object
25
+ when Hash
26
+ object.keys.each do |key|
27
+ value = object.delete(key)
28
+ object[yield(key)] = _deep_transform_keys_in_object!(value, &block)
29
+ end
30
+ object
31
+ when Array
32
+ object.map! {|e| _deep_transform_keys_in_object!(e, &block)}
33
+ else
34
+ object
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,12 @@
1
+ require 'json'
2
+
3
+ module JSON
4
+ def self.is_valid?(json)
5
+ begin
6
+ JSON.parse(json)
7
+ true
8
+ rescue JSON::ParserError
9
+ false
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,50 @@
1
+ require 'colorize'
2
+
3
+ # Prints +msg+ to the given descriptor in the form of "[INFO] - msg"
4
+ def info(msg = '', descriptor = $stdout)
5
+ descriptor.puts("[#{'INFO'.blue}] - #{msg}")
6
+ end
7
+
8
+ # @see #info
9
+ # Prints an informational message with a timestamp prepended to it
10
+ # Example: 2005-03-19 15:10:26,618 - [INFO] - msg
11
+ def info_with_timestamp(msg = '', descriptor = $stdout)
12
+ descriptor.puts("#{Time.now} - [#{'INFO'.blue}] - #{msg}")
13
+ end
14
+
15
+ # Prints +msg+ to the given descriptor in the form of "[ERROR] - msg"
16
+ def error(msg = '', descriptor = $stdout)
17
+ descriptor.puts("[#{'ERROR'.red}] - #{msg}")
18
+ end
19
+
20
+ # @see #error
21
+ # Prints an error message with a timestamp prepended to it
22
+ # Example: 2005-03-19 15:10:26,618 - [ERROR] - msg
23
+ def error_with_timestamp(msg = '', descriptor = $stdout)
24
+ descriptor.puts("#{Time.now} - [#{'ERROR'.blue}] - #{msg}")
25
+ end
26
+
27
+ # Prints +msg+ to the given descriptor in the form of "[DEBUG] - msg"
28
+ def debug(msg = '', descriptor = $stdout)
29
+ descriptor.puts("[#{'DEBUG'.yellow}] - #{msg}")
30
+ end
31
+
32
+ # @see #debug
33
+ # Prints an debug message with a timestamp prepended to it
34
+ # Example: 2005-03-19 15:10:26,618 - [DEBUG] - msg
35
+ def debug_with_timestamp(msg = '', descriptor = $stdout)
36
+ descriptor.puts("#{Time.now} - [#{'DEBUG'.yellow}] - #{msg}")
37
+ end
38
+
39
+ # Prints +msg+ to the given descriptor in the form of "[NEW] - msg"
40
+ def print_new(msg = '', descriptor = $stdout)
41
+ descriptor.puts("[#{'NEW'.green}] - #{msg}")
42
+ end
43
+
44
+ # @see #new
45
+ # Prints a 'NEW' message with a timestamp prepended to it.
46
+ # Usually used for new blocks being formed
47
+ # Example: 2005-03-19 15:10:26,618 - [NEW] - msg
48
+ def new_with_timestamp(msg = '', descriptor = $stdout)
49
+ descriptor.puts("#{Time.now} - [#{'NEW'.green}] - #{msg}")
50
+ end
@@ -0,0 +1,3 @@
1
+ module Rubocoin
2
+ VERSION = "0.1.0"
3
+ end
data/lib/rubocoin.rb ADDED
@@ -0,0 +1,17 @@
1
+ # Gems
2
+ require 'sinatra'
3
+ require 'json'
4
+ require 'securerandom'
5
+ require 'optparse'
6
+
7
+ require 'rubocoin/version'
8
+
9
+ # The lifeblood
10
+ require 'rubocoin/blockchain/blockchain'
11
+
12
+ # stdlib extensions
13
+ require 'rubocoin/core_extensions/json_ext'
14
+ require 'rubocoin/core_extensions/hash_ext'
15
+
16
+ # Useful output stuff
17
+ require 'rubocoin/text/print_utils'
data/rubocoin.gemspec ADDED
@@ -0,0 +1,27 @@
1
+
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "rubocoin"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "rubocoin"
8
+ spec.version = Rubocoin::VERSION
9
+ spec.authors = ["cbrnrd"]
10
+ spec.email = ["cbawsome77@gmail.com"]
11
+ spec.executables = %w[rubocoind]
12
+
13
+ spec.summary = ""
14
+ spec.description = ""
15
+ spec.homepage = ""
16
+ spec.license = "MIT"
17
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
18
+ f.match(%r{^(test|spec|features)/})
19
+ end
20
+
21
+
22
+ spec.add_development_dependency "bundler", "~> 1.16"
23
+ spec.add_development_dependency "rake", "~> 10.0"
24
+ spec.add_development_dependency "rspec", "~> 3.0"
25
+ spec.add_runtime_dependency "sinatra"
26
+ spec.add_runtime_dependency "colorize"
27
+ end
metadata ADDED
@@ -0,0 +1,133 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rubocoin
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - cbrnrd
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-12-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.16'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.16'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: sinatra
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: colorize
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: ''
84
+ email:
85
+ - cbawsome77@gmail.com
86
+ executables:
87
+ - rubocoind
88
+ extensions: []
89
+ extra_rdoc_files: []
90
+ files:
91
+ - ".gitignore"
92
+ - ".rspec"
93
+ - ".travis.yml"
94
+ - Gemfile
95
+ - Gemfile.lock
96
+ - LICENSE.txt
97
+ - README.md
98
+ - Rakefile
99
+ - bin/console
100
+ - bin/rubocoind
101
+ - bin/setup
102
+ - lib/rubocoin.rb
103
+ - lib/rubocoin/blockchain/blockchain.rb
104
+ - lib/rubocoin/core_extensions/hash_ext.rb
105
+ - lib/rubocoin/core_extensions/json_ext.rb
106
+ - lib/rubocoin/text/print_utils.rb
107
+ - lib/rubocoin/version.rb
108
+ - rubocoin.gemspec
109
+ homepage: ''
110
+ licenses:
111
+ - MIT
112
+ metadata: {}
113
+ post_install_message:
114
+ rdoc_options: []
115
+ require_paths:
116
+ - lib
117
+ required_ruby_version: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - ">="
120
+ - !ruby/object:Gem::Version
121
+ version: '0'
122
+ required_rubygems_version: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ version: '0'
127
+ requirements: []
128
+ rubyforge_project:
129
+ rubygems_version: 2.6.13
130
+ signing_key:
131
+ specification_version: 4
132
+ summary: ''
133
+ test_files: []