class Equestreum::Chain

Attributes

difficulty[RW]
genesis_data[RW]
path[RW]

Public Class Methods

aggregate() click to toggle source
# File lib/equestreum/chain.rb, line 72
def self.aggregate
  h = Hash.new 0
  Chain.revive[1..-1].each do |block|
    h[block.data] += 1
  end
  h
end
difficulty() click to toggle source
# File lib/equestreum/chain.rb, line 26
def self.difficulty
  self.revive.difficulty
end
difficulty=(diff) click to toggle source
# File lib/equestreum/chain.rb, line 20
def self.difficulty= diff
  c = self.revive
  c.difficulty = diff
  c.save
end
grow(data) click to toggle source
# File lib/equestreum/chain.rb, line 51
def self.grow data
  chain = self.revive
  chain.grow data
  chain.save

  chain
end
init(difficulty: 3) click to toggle source
# File lib/equestreum/chain.rb, line 30
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
new() { |self| ... } click to toggle source
# File lib/equestreum/chain.rb, line 6
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
revive() click to toggle source
# File lib/equestreum/chain.rb, line 152
def self.revive
  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

Public Instance Methods

blocks_get_newer?() click to toggle source
# File lib/equestreum/chain.rb, line 134
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
data(with_genesis: false) click to toggle source
# File lib/equestreum/chain.rb, line 59
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
grow(data, prev: nil) click to toggle source
# File lib/equestreum/chain.rb, line 40
def grow data, prev: nil
  block = Block.new do |b|
    b.data = data
    b.prev = prev ? prev : self.last.hash
    b.difficulty = @difficulty
  end

  block.mine
  push block
end
hash_ok?(index) click to toggle source
# File lib/equestreum/chain.rb, line 80
def hash_ok? index
  block = self[index]

  block.hash == (Digest::SHA256.hexdigest '%s%s%s%s%s' % [
    block.nonce,
    block.time,
    '0' * block.difficulty,
    block.prev,
    block.data
  ])
end
hashes_ok?() click to toggle source
# File lib/equestreum/chain.rb, line 92
def hashes_ok?
  self.length.times do |index|
    unless hash_ok? index
      raise EquestreumException.new "Block at #{index} tampered with"
    end
  end
  true
end
newer_than_last?(index) click to toggle source
# File lib/equestreum/chain.rb, line 127
def newer_than_last? index
  return true if index == 0
  block = self[index]
  previous = self[index - 1]
  block.time >= previous.time
end
path=(path) click to toggle source
# File lib/equestreum/chain.rb, line 16
def path= path
  Config.instance.config['chain_path'] = path
end
previous_hash_ok?(index) click to toggle source
# File lib/equestreum/chain.rb, line 113
def previous_hash_ok? index
  return true if index == 0
  block = self[index]
  previous = self[index - 1]
  block.prev == previous.hash
end
previous_hashes_ok?() click to toggle source
# File lib/equestreum/chain.rb, line 120
def previous_hashes_ok?
  self.length.times do |index|
    raise EquestreumException.new "Hash chain broken in block at #{index}" unless previous_hash_ok? index
  end
  true
end
proof_of_work_ok?(index) click to toggle source
# File lib/equestreum/chain.rb, line 101
def proof_of_work_ok? index
  block = self[index]
  block.hash.start_with? '0' * block.difficulty
end
proofs_of_work_ok?() click to toggle source
# File lib/equestreum/chain.rb, line 106
def proofs_of_work_ok?
  self.length.times do |index|
    raise EquestreumException.new "Inconsistent difficulty in block at #{index}" unless proof_of_work_ok? index
  end
  true
end
save() click to toggle source
# File lib/equestreum/chain.rb, line 145
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
verified?() click to toggle source
# File lib/equestreum/chain.rb, line 141
def verified?
  hashes_ok? && proofs_of_work_ok? && previous_hashes_ok? && blocks_get_newer?
end