Packages
elixium_core
0.2.10
0.6.3
0.6.2
0.6.1
0.6.0
0.5.4
0.5.3
0.5.2
0.5.1
0.5.0
0.4.12
0.4.11
0.4.10
0.4.9
0.4.8
0.4.7
0.4.6
0.4.5
0.4.4
0.4.3
0.4.2
0.4.1
0.4.0
0.3.19
0.3.18
0.3.17
0.3.16
0.3.15
0.3.14
0.3.13
0.3.12
0.3.11
0.3.10
0.3.9
0.3.8
0.3.7
0.3.6
0.3.5
0.3.4
0.3.3
0.3.1
0.2.13
0.2.12
0.2.11
0.2.10
0.2.9
0.2.8
0.2.7
0.2.6
0.2.5
0.2.4
0.2.3
0.2.2
0.2.1
0.2.0
0.1.4
0.1.3
The core package for the Elixium blockchain, containing all the modules needed to run the chain
Current section
Files
Jump to
Current section
Files
lib/store/ledger.ex
defmodule Elixium.Store.Ledger do
alias Elixium.Blockchain.Block
use Elixium.Store
@moduledoc """
Provides an interface for interacting with the blockchain stored within LevelDB. This
is where blocks are stored and fetched
"""
@store_dir ".chaindata"
@ets_name :chaindata
def initialize do
initialize(@store_dir)
:ets.new(@ets_name, [:ordered_set, :public, :named_table])
end
@doc """
Add a block to leveldb, indexing it by its hash (this is the most likely piece of data to be unique)
"""
def append_block(block) do
transact @store_dir do
&Exleveldb.put(&1, String.to_atom(block.hash), :erlang.term_to_binary(block))
end
:ets.insert(@ets_name, {block.index, block.hash, block})
end
@doc """
Given a block hash, return its contents
"""
@spec retrieve_block(String.t()) :: Block
def retrieve_block(hash) do
# Only check the store if we don't have this hash in our ETS cache
case :ets.match(@ets_name, {'_', hash, '$1'}) do
[] ->
transact @store_dir do
fn ref ->
case Exleveldb.get(ref, hash) do
{:ok, block} -> :erlang.binary_to_term(block)
err -> err
end
end
end
[block] -> block
end
end
@doc """
Return the whole chain from leveldb
"""
def retrieve_chain do
chain =
transact @store_dir do
fn ref ->
ref
|> Exleveldb.map(fn {_, block} -> :erlang.binary_to_term(block) end)
|> Enum.sort_by(& &1.index, &>=/2)
end
end
ets_hydrate = Enum.map(chain, &({&1.index, String.to_atom(&1.hash), &1}))
:ets.insert(@ets_name, ets_hydrate)
chain
end
@doc """
Returns the most recent block on the chain
"""
@spec last_block :: Block
def last_block do
case :ets.last(@ets_name) do
[] ->
transact @store_dir do
fn ref ->
:err
# TODO
# {:ok, block} = Exleveldb.get()
end
end
key ->
[{_index, _key, block}] = :ets.lookup(@ets_name, key)
block
end
end
@doc """
Returns the block at a given index
"""
@spec block_at_height(integer) :: Block
def block_at_height(height) do
case :ets.lookup(@ets_name, height) do
[] -> :none
[{_index, _key, block}] -> block
end
end
@doc """
Returns the number of blocks in the chain
"""
@spec count_blocks :: integer
def count_blocks, do: :ets.info(@ets_name, :size)
def empty? do
empty?(@store_dir)
end
end