rubocoin 0.1.0

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 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: []