merklecpp Documentation#
merklecpp is a header-only C++ library for creation and manipulation of Merkle
trees. The main entry-point is the merkle::TreeT template, which
allows us to create a Merkle tree with a compile-time configurable hash size
and function.
A default implementation without further dependencies is provided as
merkle::Tree, which uses the built-in SHA256 function
(merkle::sha256()). merklecpp also provides bindings for the
respective OpenSSL functions (see Hash functions),
which can be specified as a template parameter as illustrated by the following
example:
merkle::TreeT<32, merkle::sha256_openssl> tree;
for (auto h : hashes)
{
tree.insert(h);
}
auto root = tree.root();
auto path = tree.path(hashes.size() - 1);
assert(path->verify(root));
Trees#
-
template<size_t HASH_SIZE, void HASH_FUNCTION>
class TreeT# Template for Merkle trees.
- Template Parameters:
HASH_SIZE – Size of each hash in number of bytes
HASH_FUNCTION – The hash function
Public Types
-
using Path = PathT<HASH_SIZE, HASH_FUNCTION>#
The type of paths in the tree.
-
using Tree = TreeT<HASH_SIZE, HASH_FUNCTION>#
The type of the tree.
Public Functions
-
TreeT() = default#
Constructs an empty tree.
-
inline TreeT(const std::vector<uint8_t> &bytes)#
Deserialises a tree.
- Parameters:
bytes – Byte buffer containing a serialised tree
-
inline TreeT(const std::vector<uint8_t> &bytes, size_t &position)#
Deserialises a tree.
- Parameters:
bytes – Byte buffer containing a serialised tree
position – Position of the first byte within
bytes
-
inline TreeT(const Hash &root)#
Constructs a tree containing one root hash.
- Parameters:
root – Root hash of the tree
-
inline ~TreeT()#
Deconstructor.
-
inline bool invariant()#
Invariant of the tree.
-
inline void insert(const uint8_t *hash)#
Inserts a hash into the tree.
- Parameters:
hash – Hash to insert
-
inline void insert(const Hash &hash)#
Inserts a hash into the tree.
- Parameters:
hash – Hash to insert
-
inline void insert(const std::vector<Hash> &hashes)#
Inserts multiple hashes into the tree.
- Parameters:
hashes – Vector of hashes to insert
-
inline void insert(const std::list<Hash> &hashes)#
Inserts multiple hashes into the tree.
- Parameters:
hashes – List of hashes to insert
-
inline void flush_to(size_t index)#
Flush the tree to some leaf.
Note
This invalidates all indicies smaller than
indexand no paths from them to the root can be extracted anymore.- Parameters:
index – Leaf index to flush the tree to
-
inline void retract_to(size_t index)#
Retracts a tree up to some leaf index.
Note
This invalidates all indicies greater than
indexand no paths from them to the root can be extracted anymore.- Parameters:
index – Leaf index to retract the tree to
-
inline Tree &operator=(const Tree &other)#
Assigns a tree.
- Parameters:
other – The tree to assign
- Returns:
The tree
-
inline Tree &operator=(Tree &&other) noexcept#
Assigns a tree by move.
- Parameters:
other – The tree to assign
- Returns:
The tree
-
inline std::shared_ptr<Hash> past_root(size_t index)#
Extracts a past root hash.
Note
This extracts the root hash of the tree at a past state, when
indexwas the last, right-most leaf index in the tree. It is equivalent to retracting the tree toindexand then extracting the root.- Parameters:
index – The last leaf index to consider
- Returns:
The root hash
-
inline Node *walk_to(size_t index, bool update, const std::function<bool(Node*&, bool)> &&f)#
Walks along the path from the root of a tree to a leaf.
- Parameters:
index – The leaf index to walk to
update – Flag to enable re-computation of node fields (like subtree size) while walking
f – Function to call for each node on the path; the Boolean indicates whether the current step is a right or left turn.
- Returns:
The final leaf node in the walk
-
inline std::shared_ptr<Path> path(size_t index)#
Extracts the path from a leaf index to the root of the tree.
- Parameters:
index – The leaf index of the path to extract
- Returns:
The path
-
inline std::shared_ptr<Path> past_path(size_t index, size_t as_of)#
Extracts a past path from a leaf index to the root of the tree.
Note
This extracts a path at a past state, when
as_ofwas the last, right-most leaf index in the tree. It is equivalent to retracting the tree toas_ofand then extracting the path ofindex.- Parameters:
index – The leaf index of the path to extract
as_of – The maximum leaf index to consider
- Returns:
The past path
-
inline std::optional<Hash> subtree_root(uint8_t level, size_t index)#
Extracts the root hash of a complete subtree resident in memory.
Note
Like root() and path(), it may materialize pending nodes and compute dirty hashes, but does not change logical leaf contents or hashing semantics. It returns std::nullopt if any leaf of the subtree has been flushed, if the subtree extends past the last leaf, or if the node at that position is not a full subtree. The subtree spans leaf indices [index << level, (index + 1) << level).
- Parameters:
level – The height of the subtree (it spans 2**level leaves)
index – The index of the subtree at that height
- Returns:
The subtree root hash if the subtree is complete (balanced) and fully resident in memory; otherwise, std::nullopt
-
inline void serialise(std::vector<uint8_t> &bytes)#
Serialises the tree.
- Parameters:
bytes – The vector of bytes to serialise to
-
inline void serialise(size_t from, size_t to, std::vector<uint8_t> &bytes)#
Serialises a segment of the tree.
- Parameters:
from – Smalles leaf index to include
to – Greatest leaf index to include
bytes – The vector of bytes to serialise to
-
inline void deserialise(const std::vector<uint8_t> &bytes)#
Deserialises a tree.
- Parameters:
bytes – The vector of bytes to deserialise from
-
inline void deserialise(const std::vector<uint8_t> &bytes, size_t &position)#
Deserialises a tree.
- Parameters:
bytes – The vector of bytes to deserialise from
position – Position of the first byte in
bytes
-
inline operator std::vector<uint8_t>() const#
Operator to serialise the tree.
-
inline const Hash &operator[](size_t index) const#
Operator to extract a leaf hash from the tree.
- Parameters:
index – Leaf index of the leaf to extract
- Returns:
The leaf hash
-
inline const Hash &leaf(size_t index) const#
Extract a leaf hash from the tree.
- Parameters:
index – Leaf index of the leaf to extract
- Returns:
The leaf hash
-
inline size_t num_leaves() const#
Number of leaves in the tree.
Note
This is the abstract number of leaves in the tree (including flushed leaves), not the number of nodes in memory.
- Returns:
The number of leaves in the tree
-
inline size_t min_index() const#
Minimum leaf index.
Note
The smallest leaf index for which it is safe to extract roots and paths.
- Returns:
The minumum leaf index
-
inline size_t max_index() const#
Maximum leaf index.
Note
The greatest leaf index for which it is safe to extract roots and paths.
- Returns:
The maximum leaf index
-
inline bool empty() const#
Indicates whether the tree is empty.
- Returns:
Boolean that indicates whether the tree is empty
-
inline size_t size()#
Computes the size of the tree.
Note
This is the number of nodes in the tree, including leaves and internal nodes.
- Returns:
The size of the tree
-
inline size_t serialised_size()#
Computes the minumal number of bytes required to serialise the tree.
- Returns:
The number of bytes required to serialise the tree
-
inline size_t serialised_size(size_t from, size_t to)#
The number of bytes required to serialise a segment of the tree.
- Parameters:
from – The smallest leaf index to include
to – The greatest leaf index to include
- Returns:
The number of bytes required to serialise the tree segment
Public Members
-
struct merkle::TreeT::Statistics statistics#
Public Static Attributes
-
static constexpr auto hash_function = HASH_FUNCTION#
Hash function used to combine tree nodes.
-
struct Statistics#
Structure to hold statistical information.
Public Functions
-
inline std::string to_string() const#
String representation of the statistics.
Public Members
-
size_t num_hash = 0#
The number of hashes taken by the tree via hash()
-
size_t num_past_root = 0#
The number of past_root() opertations performed on the tree.
-
size_t num_flush = 0#
The number of flush_to() opertations performed on the tree.
-
size_t num_retract = 0#
The number of retract_to() opertations performed on the tree.
-
size_t num_past_paths = 0#
The number of past paths extracted from the tree via past_path()
-
inline std::string to_string() const#
Hashes#
-
template<size_t SIZE>
struct HashT# Template for fixed-size hashes.
- Template Parameters:
SIZE – Size of the hash in number of bytes
Public Functions
-
inline HashT()#
Constructs a Hash with all bytes set to zero.
-
inline HashT(const uint8_t *bytes)#
Constructs a Hash from a byte buffer.
- Parameters:
bytes – Buffer with hash value
-
inline HashT(const std::string &s)#
Constructs a Hash from a string.
- Parameters:
s – String to read the hash value from
-
inline HashT(const std::vector<uint8_t> &bytes)#
Deserialises a Hash from a vector of bytes.
- Parameters:
bytes – Vector to read the hash value from
-
inline HashT(const std::vector<uint8_t> &bytes, size_t &position)#
Deserialises a Hash from a vector of bytes.
- Parameters:
bytes – Vector to read the hash value from
position – Position of the first byte in
bytes
-
inline HashT(const std::array<uint8_t, SIZE> &bytes)#
Deserialises a Hash from an array of bytes.
- Parameters:
bytes – Array to read the hash value from
-
inline size_t size() const#
The size of the hash (in number of bytes)
-
inline void zero()#
zeros out all bytes in the hash
-
inline size_t serialised_size() const#
The size of the serialisation of the hash (in number of bytes)
-
inline std::string to_string(size_t num_bytes = size_bytes, bool lower_case = true) const#
Convert a hash to a hex-encoded string.
- Parameters:
num_bytes – The number of bytes to convert
lower_case – Enables lower-case hex characters
- Throws:
std::out_of_range – if
num_bytesexceeds the hash size
-
inline void serialise(std::vector<uint8_t> &buffer) const#
Serialises a hash.
- Parameters:
buffer – Buffer to serialise to
-
inline void deserialise(const std::vector<uint8_t> &buffer, size_t &position)#
Deserialises a hash.
- Parameters:
buffer – Buffer to read the hash from
position – Position of the first byte in
bytes
-
inline void deserialise(const std::vector<uint8_t> &buffer)#
Deserialises a hash.
- Parameters:
buffer – Buffer to read the hash from
-
inline operator std::vector<uint8_t>() const#
Conversion operator to vector of bytes.
Paths#
-
template<size_t HASH_SIZE, void HASH_FUNCTION>
class PathT# Template for Merkle paths.
- Template Parameters:
HASH_SIZE – Size of each hash in number of bytes
HASH_FUNCTION – The hash function
Public Types
- Direction = enum { PATH_LEFT, PATH_RIGHT }
Path direction.
- Element = struct { HashT< HASH_SIZE > hash
Path element.
-
using const_iterator = typename std::list<Element>::const_iterator#
Iterator for path elements.
Public Functions
-
inline PathT(const HashT<HASH_SIZE> &leaf, size_t leaf_index, std::list<Element> &&elements, size_t max_index)#
Path constructor.
- Parameters:
leaf –
leaf_index –
elements –
max_index –
-
inline PathT(const std::vector<uint8_t> &bytes)#
Deserialises a path.
- Parameters:
bytes – Vector to deserialise from
-
inline PathT(const std::vector<uint8_t> &bytes, size_t &position)#
Deserialises a path.
- Parameters:
bytes – Vector to deserialise from
position – Position of the first byte in
bytes
-
inline std::shared_ptr<HashT<HASH_SIZE>> root() const#
Computes the root at the end of the path.
Note
This (re-)computes the root by hashing the path elements, it does not return a previously saved root hash.
-
inline bool verify(const HashT<HASH_SIZE> &expected_root) const#
Verifies that the root at the end of the path is expected.
- Parameters:
expected_root – The root hash that the elements on the path are expected to hash to.
-
inline void serialise(std::vector<uint8_t> &bytes) const#
Serialises a path.
- Parameters:
bytes – Vector of bytes to serialise to
-
inline void deserialise(const std::vector<uint8_t> &bytes, size_t &position)#
Deserialises a path.
- Parameters:
bytes – Vector of bytes to serialise from
position – Position of the first byte in
bytes
-
inline void deserialise(const std::vector<uint8_t> &bytes)#
Deserialises a path.
- Parameters:
bytes – Vector of bytes to serialise from
-
inline operator std::vector<uint8_t>() const#
Conversion operator to vector of bytes.
-
inline size_t size() const#
The number of elements on the path.
-
inline size_t serialised_size() const#
The size of the serialised path in number of bytes.
-
inline size_t leaf_index() const#
Index of the leaf of the path.
-
inline size_t max_index() const#
Maximum index of the tree at the time the path was extracted.
-
inline const HashT<HASH_SIZE> &operator[](size_t i) const#
Operator to extract the hash of a given path element.
- Parameters:
i – Index of the path element
-
inline const_iterator begin() const#
Start iterator for path elements.
-
inline const_iterator end() const#
End iterator for path elements.
-
inline std::string to_string(size_t num_bytes = HASH_SIZE, bool lower_case = true) const#
Convert a path to a string.
- Parameters:
num_bytes – The maximum number of bytes to convert
lower_case – Enables lower-case hex characters
-
inline bool operator==(const PathT<HASH_SIZE, HASH_FUNCTION> &other) const#
Equality operator for paths.
-
inline bool operator!=(const PathT<HASH_SIZE, HASH_FUNCTION> &other) const#
Inequality operator for paths.
Public Members
-
Direction direction#
The direction at which
hashjoins at this path element.Note
If
direction== PATH_LEFT,hashjoins at the left, i.e. if t is the current hash, e.g. a leaf, then t’ = Hash(hash, t );
Hash functions#
By default, merklecpp uses its built-in SHA256 function
(merkle::sha256()) for node hashes. For convenience, merklecpp also
provides bindings to the SHA256 implementation in OpenSSL.
To enable these bindings, merklecpp requires the compiler macro
HAVE_OPENSSL to be defined.
-
static inline void merkle::sha256(const HashT<32> &l, const HashT<32> &r, HashT<32> &out)#
Built-in SHA256 function for tree node hashes.
Computes SHA256 over the 64-byte concatenation of
landr, including standard SHA256 message padding.- Parameters:
l – Left node hash
r – Right node hash
out – Output node hash
-
static inline void merkle::sha256_openssl(const merkle::HashT<32> &l, const merkle::HashT<32> &r, merkle::HashT<32> &out)#
OpenSSL SHA256.
- Parameters:
l – Left node hash
r – Right node hash
out – Output node hash