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