lib/equestreum/chain.rb in equestreum-0.1.1 vs lib/equestreum/chain.rb in equestreum-0.1.2
- old
+ new
@@ -1,25 +1,84 @@
module Equestreum
class Chain < Array
private :push, :append, :<<
+ attr_accessor :genesis_data, :difficulty, :path
- def initialize genesis
- push genesis
+ def initialize
+ @genesis_data = 'genesis block'
+ @difficulty = 3
+ @path = Config.instance.config['chain_path']
+ yield self if block_given?
+
+ grow @genesis_data,
+ prev: '0000000000000000000000000000000000000000000000000000000000000000'
end
- def grow data
+ def path= path
+ Config.instance.config['chain_path'] = path
+ end
+
+ def self.difficulty= diff
+ c = self.revive
+ c.difficulty = diff
+ c.save
+ end
+
+ def self.difficulty
+ self.revive.difficulty
+ end
+
+ def self.init difficulty: 3
+ diff = Config.instance.config['difficulty'] ? Config.instance.config['difficulty'] : difficulty
+ unless File.exists? Config.instance.config['chain_path']
+ chain = Chain.new do |c|
+ c.difficulty = diff
+ end
+ chain.save
+ end
+ end
+
+ def grow data, prev: nil
block = Block.new do |b|
b.data = data
- b.prev = self.last.hash
- b.difficulty = self.last.difficulty
+ b.prev = prev ? prev : self.last.hash
+ b.difficulty = @difficulty
end
block.mine
-
push block
end
+ def self.grow data
+ chain = self.revive
+ chain.grow data
+ chain.save
+
+ chain
+ end
+
+ def data with_genesis: false
+ data = self.map do |b|
+ {
+ datetime: Time.at(b.time).iso8601,
+ data: b.data
+ }
+ end
+
+ data.shift unless with_genesis
+
+ data
+ end
+
+ def self.aggregate
+ h = Hash.new 0
+ Chain.revive[1..-1].each do |block|
+ h[block.data] += 1
+ end
+ h
+ end
+
def hash_ok? index
block = self[index]
block.hash == (Digest::SHA256.hexdigest '%s%s%s%s%s' % [
block.nonce,
@@ -30,11 +89,13 @@
])
end
def hashes_ok?
self.length.times do |index|
- raise EquestreumException.new "Block at #{index} tampered with" unless hash_ok? index
+ unless hash_ok? index
+ raise EquestreumException.new "Block at #{index} tampered with"
+ end
end
true
end
def proof_of_work_ok? index
@@ -65,26 +126,35 @@
def newer_than_last? index
return true if index == 0
block = self[index]
previous = self[index - 1]
- block.time > previous.time
+ block.time >= previous.time
end
def blocks_get_newer?
self.length.times do |index|
raise EquestreumException.new "Block at #{index} seems older than its predecessor" unless newer_than_last? index
end
true
end
+ def verified?
+ hashes_ok? && proofs_of_work_ok? && previous_hashes_ok? && blocks_get_newer?
+ end
+
def save
+ FileUtils.mkdir_p File.dirname Config.instance.config['chain_path']
File.open Config.instance.config['chain_path'], 'w' do |f|
f.write Marshal.dump self
end
end
def self.revive
- Marshal.load File.read Config.instance.config['chain_path']
+ begin
+ Marshal.load File.read Config.instance.config['chain_path']
+ rescue Errno::ENOENT
+ raise EquestreumException.new "no chain found at #{Config.instance.config['chain_path']}"
+ end
end
end
end