equestreum 0.1.1 → 0.1.2

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 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