class Hashtastic::MerkleTree

Attributes

layers[R]
leafs[R]

Public Class Methods

new(leafs, hashfunc = EthereumSHA3) click to toggle source
# File lib/hashtastic/merkle_tree/merkle_tree.rb, line 26
def initialize(leafs, hashfunc = EthereumSHA3)
  leafs.each { |leaf| self.class.validate_hex(leaf) }
  @hashfunc = hashfunc
  @leafs = leafs.sort.uniq
  @layers = LayersCreator.call(@leafs, hashfunc)
end
validate_hex(hex) click to toggle source
# File lib/hashtastic/merkle_tree/merkle_tree.rb, line 19
def validate_hex(hex)
  raise ArgumentError, hex unless Utils.hex?(hex)
end
verify(proof:, root:, leaf:, hashfunc: EthereumSHA3) click to toggle source
# File lib/hashtastic/merkle_tree/merkle_tree.rb, line 6
def verify(proof:, root:, leaf:, hashfunc: EthereumSHA3)
  proof.each { |hex| validate_hex(hex) }

  computed_hash =
    proof.reduce(leaf) do |acc, element|
      combined = [acc, element].map { |h| Utils.hex_to_ascii(h) }.sort.join

      hashfunc.call(combined)
    end

  computed_hash == root
end

Public Instance Methods

proof(leaf) click to toggle source
# File lib/hashtastic/merkle_tree/merkle_tree.rb, line 37
def proof(leaf)
  index = leafs.index(leaf)
  raise LeafNotFoundError, leaf unless index

  layers.each_with_object([]) do |layer, accumulator|
    pair_element = pair_element(index, layer)

    accumulator.push(pair_element) if pair_element

    index = (index / 2).floor
  end
end
root() click to toggle source
# File lib/hashtastic/merkle_tree/merkle_tree.rb, line 33
def root
  layers[layers.length - 1][0]
end

Private Instance Methods

pair_element(index, layer) click to toggle source
# File lib/hashtastic/merkle_tree/merkle_tree.rb, line 52
def pair_element(index, layer)
  pair_index = index.even? ? index + 1 : index - 1

  return layer[pair_index] if pair_index < layer.length
end