equestreum 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 165ee5b574d1d6b256e913e0fe8e17f476105f219f50473fd45051c5343fcf9d
4
- data.tar.gz: e7a60c9d11f1e57afdb77f7511f0019f3b492d28709c2599e55975b9478523c7
3
+ metadata.gz: 9998d629961146f004cbb807abedb73aedd6ff254043c1b96cc6da40138b2e06
4
+ data.tar.gz: 783f92d5422997ba62cf3a4ed8293f0309f4b842130d36963cfed657d70a1a5e
5
5
  SHA512:
6
- metadata.gz: f92abea21333957147a923bd16a5d42c91d8dee6f49a377ffe5acc2479fbbaeb58d890f90dc748ae16b8a1a1ea46f75cc1a62a5b965d9c057c00995456d91a2b
7
- data.tar.gz: f2e1644bc5498297e54165355805a8e4bcaf8ac810c2f301811b3df927baea5198806c228255d3304ddce44ee4021612f22ce040bc3fceaac99079b78ea8d6f6
6
+ metadata.gz: 9fa81e145bf4357da2e737c29d85f7b92ee0351938363df5b3e881b7710674e42bdf27c5eee89c62d04fb1d0b15a78b3a54d676c88684e44302942bb22ce9fc2
7
+ data.tar.gz: 7bad49b5c456efe912e996791cfb33f0c33b1020f0fd775e387c6727a64bb1e5a11e008410442649b1d426e894ccf8c772545dd9be9ecd440174da1e1a02799f
data/Gemfile.lock CHANGED
@@ -1,21 +1,21 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- equestreum (0.1.1)
4
+ equestreum (0.1.2)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
9
  coderay (1.1.2)
10
- coveralls (0.8.21)
10
+ coveralls (0.8.22)
11
11
  json (>= 1.8, < 3)
12
- simplecov (~> 0.14.1)
12
+ simplecov (~> 0.16.1)
13
13
  term-ansicolor (~> 1.3)
14
14
  thor (~> 0.19.4)
15
15
  tins (~> 1.6)
16
16
  diff-lcs (1.3)
17
- docile (1.1.5)
18
- ffi (1.9.23)
17
+ docile (1.3.1)
18
+ ffi (1.9.25)
19
19
  formatador (0.2.5)
20
20
  guard (2.14.2)
21
21
  formatador (>= 0.2.4)
@@ -49,23 +49,23 @@ GEM
49
49
  rb-fsevent (0.10.3)
50
50
  rb-inotify (0.9.10)
51
51
  ffi (>= 0.5.0, < 2)
52
- rspec (3.7.0)
53
- rspec-core (~> 3.7.0)
54
- rspec-expectations (~> 3.7.0)
55
- rspec-mocks (~> 3.7.0)
56
- rspec-core (3.7.1)
57
- rspec-support (~> 3.7.0)
58
- rspec-expectations (3.7.0)
52
+ rspec (3.8.0)
53
+ rspec-core (~> 3.8.0)
54
+ rspec-expectations (~> 3.8.0)
55
+ rspec-mocks (~> 3.8.0)
56
+ rspec-core (3.8.0)
57
+ rspec-support (~> 3.8.0)
58
+ rspec-expectations (3.8.1)
59
59
  diff-lcs (>= 1.2.0, < 2.0)
60
- rspec-support (~> 3.7.0)
61
- rspec-mocks (3.7.0)
60
+ rspec-support (~> 3.8.0)
61
+ rspec-mocks (3.8.0)
62
62
  diff-lcs (>= 1.2.0, < 2.0)
63
- rspec-support (~> 3.7.0)
64
- rspec-support (3.7.1)
63
+ rspec-support (~> 3.8.0)
64
+ rspec-support (3.8.0)
65
65
  ruby_dep (1.5.0)
66
66
  shellany (0.0.1)
67
- simplecov (0.14.1)
68
- docile (~> 1.1.0)
67
+ simplecov (0.16.1)
68
+ docile (~> 1.1)
69
69
  json (>= 1.8, < 3)
70
70
  simplecov-html (~> 0.10.0)
71
71
  simplecov-html (0.10.2)
data/README.md CHANGED
@@ -1,6 +1,55 @@
1
+ [![Build Status](http://img.shields.io/travis/hat-festival/equestreum.svg?style=flat-square)](https://travis-ci.org/hat-festival/equestreum)
1
2
  [![Coverage Status](http://img.shields.io/coveralls/hat-festival/equestreum.svg?style=flat-square)](https://coveralls.io/r/hat-festival/equestreum)
2
- [![Code Climate](http://img.shields.io/codeclimate/github/hat-festival/equestreum.svg?style=flat-square)](https://codeclimate.com/github/hat-festival/equestreum)
3
3
  [![Gem Version](http://img.shields.io/gem/v/equestreum.svg?style=flat-square)](https://rubygems.org/gems/equestreum)
4
4
  [![License](http://img.shields.io/:license-mit-blue.svg?style=flat-square)](http://hat-festival.mit-license.org)
5
5
 
6
6
  # Equestreum
7
+
8
+ ## A blockchain for the [Voting Machine](//github.com/hat-festival/voting-machine)
9
+
10
+ We're trying to answer [one of the fundamental questions](//www.quora.com/Would-you-rather-fight-100-duck-sized-horses-or-one-horse-sized-duck), and we'd like to store the votes somewhere secure and stable. Unfortunately we don't have access to anything like that, so we built a blockchain instead
11
+
12
+ Starting with [this excellent tutorial](https://yukimotopress.github.io/programming-blockchains-step-by-step), this is about the simplest implementation of a blockchain that I could come up with
13
+
14
+ ## How do I use it?
15
+
16
+ irb(main):001:0> require 'equestreum'
17
+ => true
18
+ irb(main):002:0> chain = Equestreum::Chain.new do |c|
19
+ irb(main):003:1* c.path = '/tmp/shonky.chain'
20
+ irb(main):004:1> end
21
+ => [#<Equestreum::Block:0x00007fd33d978660 @difficulty=3, @data="genesis block", @prev="0000000000000000000000000000000000000000000000000000000000000000", @time=1533992533, @nonce=9792, @hash="000a17e993e50496da998aabb67a5d88963979fc6f7c8ce552edb36f3fb2efea">]
22
+ irb(main):005:0> chain.first.data
23
+ => "genesis block"
24
+ irb(main):006:0> chain.grow 'store this data'
25
+ => [#<Equestreum::Block:0x00007fd33d978660 @difficulty=3, @data="genesis block", @prev="0000000000000000000000000000000000000000000000000000000000000000", @time=1533992533, @nonce=9792, @hash="000a17e993e50496da998aabb67a5d88963979fc6f7c8ce552edb36f3fb2efea">, #<Equestreum::Block:0x00007fd33d21fb48 @difficulty=3, @data="store this data", @prev="000a17e993e50496da998aabb67a5d88963979fc6f7c8ce552edb36f3fb2efea", @time=1533992533, @nonce=9525, @hash="0006d5dd01dc826a9f89446b3de097dabf5cb0fcf830ed32e25b9ee92696e16a">]
26
+ irb(main):007:0> chain.count
27
+ => 2
28
+ irb(main):008:0> chain.verified?
29
+ => true
30
+ irb(main):009:0> chain.difficulty
31
+ => 3
32
+ irb(main):010:0> chain.difficulty = 4
33
+ => 4
34
+ irb(main):011:0> chain.grow 'store some more data at a higher difficulty'
35
+ => [#<Equestreum::Block:0x00007fd33d978660 @difficulty=3, @data="genesis block", @prev="0000000000000000000000000000000000000000000000000000000000000000", @time=1533992533, @nonce=9792, @hash="000a17e993e50496da998aabb67a5d88963979fc6f7c8ce552edb36f3fb2efea">, #<Equestreum::Block:0x00007fd33d21fb48 @difficulty=3, @data="store this data", @prev="000a17e993e50496da998aabb67a5d88963979fc6f7c8ce552edb36f3fb2efea", @time=1533992533, @nonce=9525, @hash="0006d5dd01dc826a9f89446b3de097dabf5cb0fcf830ed32e25b9ee92696e16a">, #<Equestreum::Block:0x00007fd33f019950 @difficulty=4, @data="store some more data at a higher difficulty", @prev="0006d5dd01dc826a9f89446b3de097dabf5cb0fcf830ed32e25b9ee92696e16a", @time=1533992534, @nonce=6484, @hash="0000bb78110c6d5d4404140fa5b64786a856485c4a98ebe0b3ff108f3c6111c8">]
36
+ irb(main):012:0> chain.save
37
+ => 614
38
+ irb(main):013:0> c = Equestreum::Chain.revive
39
+ => [#<Equestreum::Block:0x00007fd33d1a6900 @difficulty=3, @data="genesis block", @prev="0000000000000000000000000000000000000000000000000000000000000000", @time=1533992533, @nonce=9792, @hash="000a17e993e50496da998aabb67a5d88963979fc6f7c8ce552edb36f3fb2efea">, #<Equestreum::Block:0x00007fd33d1a64c8 @difficulty=3, @data="store this data", @prev="000a17e993e50496da998aabb67a5d88963979fc6f7c8ce552edb36f3fb2efea", @time=1533992533, @nonce=9525, @hash="0006d5dd01dc826a9f89446b3de097dabf5cb0fcf830ed32e25b9ee92696e16a">, #<Equestreum::Block:0x00007fd33d1a63b0 @difficulty=4, @data="store some more data at a higher difficulty", @prev="0006d5dd01dc826a9f89446b3de097dabf5cb0fcf830ed32e25b9ee92696e16a", @time=1533992534, @nonce=6484, @hash="0000bb78110c6d5d4404140fa5b64786a856485c4a98ebe0b3ff108f3c6111c8">]
40
+ irb(main):014:0> c.map { |b| b.data }
41
+ => ["genesis block", "store this data", "store some more data at a higher difficulty"]
42
+ irb(main):015:0> c[1].data = 'this should be immutable'
43
+ => "this should be immutable"
44
+ irb(main):016:0> begin
45
+ irb(main):017:1> c.verified?
46
+ irb(main):018:1> rescue Equestreum::EquestreumException => e
47
+ irb(main):019:1> puts e.text
48
+ irb(main):020:1> end
49
+ Block at 1 tampered with
50
+ => nil
51
+ irb(main):021:0>
52
+
53
+ ## Should I use it?
54
+
55
+ Fuck no
@@ -1 +1 @@
1
- chain_path: tmp/equestreum.chain
1
+ chain_path: /usr/local/etc/equestreum.chain
@@ -0,0 +1 @@
1
+ chain_path: /usr/local/etc/equestreum.chain
data/lib/config.rb ADDED
@@ -0,0 +1,20 @@
1
+ module Equestreum
2
+ class Config
3
+ include Singleton
4
+
5
+ def initialize
6
+ @config = fetch_yaml File.join(File.dirname(__FILE__), '..', '..', 'config/equestreum.yml')
7
+ @config.merge! fetch_yaml "#{ENV['HOME']}/.equestreum/config.yaml"
8
+ end
9
+
10
+ def config
11
+ @config
12
+ end
13
+
14
+ def fetch_yaml file
15
+ YAML.load_file file
16
+ rescue Errno::ENOENT
17
+ {}
18
+ end
19
+ end
20
+ end
@@ -13,7 +13,7 @@ module Equestreum
13
13
  @time = Time.now.to_i
14
14
  @nonce = 0
15
15
  loop do
16
- @hash = Equestreum.hash @nonce, @difficulty, @prev, @data
16
+ @hash = Equestreum.hash @nonce, @time, @difficulty, @prev, @data
17
17
  if Equestreum.difficulty_attained hash, @difficulty
18
18
  break
19
19
  else
@@ -21,5 +21,20 @@ module Equestreum
21
21
  end
22
22
  end
23
23
  end
24
+
25
+ def to_h
26
+ h = {}
27
+ [
28
+ :data,
29
+ :time,
30
+ :hash,
31
+ :prev,
32
+ :nonce,
33
+ :difficulty
34
+ ].each do |key|
35
+ h[key] = self.send(key)
36
+ end
37
+ h
38
+ end
24
39
  end
25
40
  end
@@ -1,23 +1,82 @@
1
1
  module Equestreum
2
2
  class Chain < Array
3
3
  private :push, :append, :<<
4
+ attr_accessor :genesis_data, :difficulty, :path
4
5
 
5
- def initialize genesis
6
- push genesis
6
+ def initialize
7
+ @genesis_data = 'genesis block'
8
+ @difficulty = 3
9
+ @path = Config.instance.config['chain_path']
10
+ yield self if block_given?
11
+
12
+ grow @genesis_data,
13
+ prev: '0000000000000000000000000000000000000000000000000000000000000000'
14
+ end
15
+
16
+ def path= path
17
+ Config.instance.config['chain_path'] = path
18
+ end
19
+
20
+ def self.difficulty= diff
21
+ c = self.revive
22
+ c.difficulty = diff
23
+ c.save
24
+ end
25
+
26
+ def self.difficulty
27
+ self.revive.difficulty
7
28
  end
8
29
 
9
- def grow data
30
+ def self.init difficulty: 3
31
+ diff = Config.instance.config['difficulty'] ? Config.instance.config['difficulty'] : difficulty
32
+ unless File.exists? Config.instance.config['chain_path']
33
+ chain = Chain.new do |c|
34
+ c.difficulty = diff
35
+ end
36
+ chain.save
37
+ end
38
+ end
39
+
40
+ def grow data, prev: nil
10
41
  block = Block.new do |b|
11
42
  b.data = data
12
- b.prev = self.last.hash
13
- b.difficulty = self.last.difficulty
43
+ b.prev = prev ? prev : self.last.hash
44
+ b.difficulty = @difficulty
14
45
  end
15
46
 
16
47
  block.mine
17
-
18
48
  push block
19
49
  end
20
50
 
51
+ def self.grow data
52
+ chain = self.revive
53
+ chain.grow data
54
+ chain.save
55
+
56
+ chain
57
+ end
58
+
59
+ def data with_genesis: false
60
+ data = self.map do |b|
61
+ {
62
+ datetime: Time.at(b.time).iso8601,
63
+ data: b.data
64
+ }
65
+ end
66
+
67
+ data.shift unless with_genesis
68
+
69
+ data
70
+ end
71
+
72
+ def self.aggregate
73
+ h = Hash.new 0
74
+ Chain.revive[1..-1].each do |block|
75
+ h[block.data] += 1
76
+ end
77
+ h
78
+ end
79
+
21
80
  def hash_ok? index
22
81
  block = self[index]
23
82
 
@@ -32,7 +91,9 @@ module Equestreum
32
91
 
33
92
  def hashes_ok?
34
93
  self.length.times do |index|
35
- raise EquestreumException.new "Block at #{index} tampered with" unless hash_ok? index
94
+ unless hash_ok? index
95
+ raise EquestreumException.new "Block at #{index} tampered with"
96
+ end
36
97
  end
37
98
  true
38
99
  end
@@ -67,7 +128,7 @@ module Equestreum
67
128
  return true if index == 0
68
129
  block = self[index]
69
130
  previous = self[index - 1]
70
- block.time > previous.time
131
+ block.time >= previous.time
71
132
  end
72
133
 
73
134
  def blocks_get_newer?
@@ -77,14 +138,23 @@ module Equestreum
77
138
  true
78
139
  end
79
140
 
141
+ def verified?
142
+ hashes_ok? && proofs_of_work_ok? && previous_hashes_ok? && blocks_get_newer?
143
+ end
144
+
80
145
  def save
146
+ FileUtils.mkdir_p File.dirname Config.instance.config['chain_path']
81
147
  File.open Config.instance.config['chain_path'], 'w' do |f|
82
148
  f.write Marshal.dump self
83
149
  end
84
150
  end
85
151
 
86
152
  def self.revive
87
- Marshal.load File.read Config.instance.config['chain_path']
153
+ begin
154
+ Marshal.load File.read Config.instance.config['chain_path']
155
+ rescue Errno::ENOENT
156
+ raise EquestreumException.new "no chain found at #{Config.instance.config['chain_path']}"
157
+ end
88
158
  end
89
159
  end
90
160
  end
@@ -2,9 +2,9 @@ module Equestreum
2
2
  class Config
3
3
  include Singleton
4
4
 
5
- def initialize custom = "#{ENV['HOME']}/.equestreum/config.yaml"
6
- @config = fetch_yaml File.join(File.dirname(__FILE__), '..', '..', 'config/equestreum.yaml')
7
- @config.merge! fetch_yaml custom
5
+ def initialize
6
+ @config = fetch_yaml File.join(File.dirname(__FILE__), '..', '..', 'config/equestreum.yml')
7
+ @config.merge! fetch_yaml 'config/equestreum.yml' if File.exists? 'config/equestreum.yml'
8
8
  end
9
9
 
10
10
  def config
@@ -12,9 +12,7 @@ module Equestreum
12
12
  end
13
13
 
14
14
  def fetch_yaml file
15
- YAML.load File.open file
16
- rescue Errno::ENOENT
17
- {}
15
+ YAML.load_file file
18
16
  end
19
17
  end
20
18
  end
@@ -1,3 +1,3 @@
1
1
  module Equestreum
2
- VERSION = '0.1.1'
2
+ VERSION = '0.1.2'
3
3
  end
data/lib/equestreum.rb CHANGED
@@ -1,4 +1,6 @@
1
1
  require 'digest'
2
+ require 'singleton'
3
+ require 'yaml'
2
4
 
3
5
  require 'equestreum/version'
4
6
  require 'equestreum/config'
@@ -6,10 +8,10 @@ require 'equestreum/block'
6
8
  require 'equestreum/chain'
7
9
 
8
10
  module Equestreum
9
- def self.hash nonce, difficulty, prev, data
11
+ def self.hash nonce, time, difficulty, prev, data
10
12
  string = '%s%s%s%s%s' % [
11
13
  nonce,
12
- Time.now.to_i,
14
+ time,
13
15
  '0' * difficulty,
14
16
  prev,
15
17
  data
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: equestreum
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - pikesley
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-05-28 00:00:00.000000000 Z
11
+ date: 2018-08-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -114,7 +114,9 @@ files:
114
114
  - bin/console
115
115
  - bin/setup
116
116
  - config/equestreum.yaml
117
+ - config/equestreum.yml
117
118
  - equestreum.gemspec
119
+ - lib/config.rb
118
120
  - lib/equestreum.rb
119
121
  - lib/equestreum/block.rb
120
122
  - lib/equestreum/chain.rb