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 +4 -4
- data/Gemfile.lock +18 -18
- data/README.md +50 -1
- data/config/equestreum.yaml +1 -1
- data/config/equestreum.yml +1 -0
- data/lib/config.rb +20 -0
- data/lib/equestreum/block.rb +16 -1
- data/lib/equestreum/chain.rb +79 -9
- data/lib/equestreum/config.rb +4 -6
- data/lib/equestreum/version.rb +1 -1
- data/lib/equestreum.rb +4 -2
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9998d629961146f004cbb807abedb73aedd6ff254043c1b96cc6da40138b2e06
|
4
|
+
data.tar.gz: 783f92d5422997ba62cf3a4ed8293f0309f4b842130d36963cfed657d70a1a5e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
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.
|
10
|
+
coveralls (0.8.22)
|
11
11
|
json (>= 1.8, < 3)
|
12
|
-
simplecov (~> 0.
|
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
|
18
|
-
ffi (1.9.
|
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.
|
53
|
-
rspec-core (~> 3.
|
54
|
-
rspec-expectations (~> 3.
|
55
|
-
rspec-mocks (~> 3.
|
56
|
-
rspec-core (3.
|
57
|
-
rspec-support (~> 3.
|
58
|
-
rspec-expectations (3.
|
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.
|
61
|
-
rspec-mocks (3.
|
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.
|
64
|
-
rspec-support (3.
|
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.
|
68
|
-
docile (~> 1.1
|
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
|
+
[](https://travis-ci.org/hat-festival/equestreum)
|
1
2
|
[](https://coveralls.io/r/hat-festival/equestreum)
|
2
|
-
[](https://codeclimate.com/github/hat-festival/equestreum)
|
3
3
|
[](https://rubygems.org/gems/equestreum)
|
4
4
|
[](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
|
data/config/equestreum.yaml
CHANGED
@@ -1 +1 @@
|
|
1
|
-
chain_path:
|
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
|
data/lib/equestreum/block.rb
CHANGED
@@ -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
|
data/lib/equestreum/chain.rb
CHANGED
@@ -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
|
6
|
-
|
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
|
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 =
|
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
|
-
|
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
|
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
|
-
|
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
|
data/lib/equestreum/config.rb
CHANGED
@@ -2,9 +2,9 @@ module Equestreum
|
|
2
2
|
class Config
|
3
3
|
include Singleton
|
4
4
|
|
5
|
-
def initialize
|
6
|
-
@config = fetch_yaml File.join(File.dirname(__FILE__), '..', '..', 'config/equestreum.
|
7
|
-
@config.merge! fetch_yaml
|
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.
|
16
|
-
rescue Errno::ENOENT
|
17
|
-
{}
|
15
|
+
YAML.load_file file
|
18
16
|
end
|
19
17
|
end
|
20
18
|
end
|
data/lib/equestreum/version.rb
CHANGED
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
|
-
|
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.
|
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-
|
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
|