Packages
elixium_core
0.6.2
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/encoding/block_encoder.ex
defmodule Elixium.BlockEncoder do
alias Elixium.Block
@moduledoc """
Provides functionality for encoding and decoding blocks
"""
@encoding_order [
:index, :hash, :previous_hash,
:merkle_root, :timestamp, :nonce,
:difficulty, :version, :transactions
]
@doc """
Encode a block to a binary representation based on the encoding order:
@encoding_order
"""
@spec encode(Block) :: binary
def encode(block) do
block = Map.delete(block, :__struct__)
Enum.reduce(@encoding_order, <<>>, fn attr, bin -> encode(attr, bin, block[attr]) end)
end
defp encode(:difficulty, bin, value) do
# Convert to binary and strip out ETF bytes (we dont need them for storage,
# we can add them back in when we need to read)
<<131, 70, difficulty::binary>> = :erlang.term_to_binary(value)
bin <> difficulty
end
defp encode(:transactions, bin, value) do
# Add transactions in as raw ETF encoding for easy decoding later
bin <> :erlang.term_to_binary(value)
end
defp encode(:hash, bin, value), do: b16encode(bin, value)
defp encode(:previous_hash, bin, value), do: b16encode(bin, value)
defp encode(:merkle_root, bin, value), do: b16encode(bin, value)
defp encode(_attr, bin, value) when is_binary(value) do
bin <> value
end
defp encode(_attr, bin, value) when is_number(value) do
bin <> :binary.encode_unsigned(value)
end
defp b16encode(bin, value), do: bin <> Base.decode16!(value)
@doc """
Decode a block from binary that was previously encoded by encode/1
"""
@spec decode(binary) :: Block
def decode(block_binary) do
<<index::bytes-size(4),
hash::bytes-size(32),
previous_hash::bytes-size(32),
merkle_root::bytes-size(32),
timestamp::bytes-size(4),
nonce::bytes-size(8),
difficulty::bytes-size(8),
version::bytes-size(2),
transactions::binary
>> = block_binary
%Block{
index: index,
hash: Base.encode16(hash),
previous_hash: Base.encode16(previous_hash),
merkle_root: Base.encode16(merkle_root),
timestamp: :binary.decode_unsigned(timestamp),
nonce: nonce,
difficulty: :erlang.binary_to_term(<<131, 70>> <> difficulty),
version: version,
transactions: :erlang.binary_to_term(transactions)
}
end
end