All Projects → piotrmurach → Merkle_tree

piotrmurach / Merkle_tree

Licence: mit
A merkle tree is a data structure used for efficiently summarizing sets of data, often one-time signatures.

Programming Languages

ruby
36898 projects - #4 most used programming language

Projects that are alternatives of or similar to Merkle tree

Firo
The privacy-focused cryptocurrency
Stars: ✭ 528 (+676.47%)
Mutual labels:  cryptocurrency, merkle-tree
tty-tree
Print directory or structured data in a tree like format
Stars: ✭ 54 (-20.59%)
Mutual labels:  ruby-gem, tree-structure
Bitshares Core
BitShares Blockchain implementation and command-line interface
Stars: ✭ 1,096 (+1511.76%)
Mutual labels:  cryptocurrency
Ecola
Tree editor for touch screens
Stars: ✭ 64 (-5.88%)
Mutual labels:  tree-structure
Simplechain
⛓✨ Interactive blockchain built with Node.js
Stars: ✭ 61 (-10.29%)
Mutual labels:  cryptocurrency
Crypto Trading Bot
Cryptocurrency trading bot in javascript for Bitfinex, Bitmex, Binance, FTX, Bybit ... (public edition)
Stars: ✭ 1,089 (+1501.47%)
Mutual labels:  cryptocurrency
Osint Tools
OSINT tools catalog
Stars: ✭ 62 (-8.82%)
Mutual labels:  cryptocurrency
Ethsnarks Miximus
Example project for EthSnarks - Miximus coin mixer
Stars: ✭ 58 (-14.71%)
Mutual labels:  cryptocurrency
Ruby Statistics
Ruby gem for some statistical operations without any statistical language dependency
Stars: ✭ 67 (-1.47%)
Mutual labels:  ruby-gem
Mcafee Bot
buy coins based on @officialmcafee tweets
Stars: ✭ 61 (-10.29%)
Mutual labels:  cryptocurrency
Pybtc
Python bitcoin library
Stars: ✭ 64 (-5.88%)
Mutual labels:  cryptocurrency
Mobidex
Mobile trustless trading through Uniswap
Stars: ✭ 61 (-10.29%)
Mutual labels:  cryptocurrency
Crypto Whale Watcher
An app to keep a watch on big volume trades of cryptocurrecies on different exchanges by sending alerts via a Telegram Bot.
Stars: ✭ 60 (-11.76%)
Mutual labels:  cryptocurrency
The Journal Of Blockchain
区块链自媒体、专注区块链技术学习和实践、IPFS/Filecoin、Bitcoin、Ethereum、EOS、Cosmos、区块链、白皮书、Coinmarketcap、Coindesk、Safe Network、Telegram、Docker、社会治理、经济激励
Stars: ✭ 63 (-7.35%)
Mutual labels:  cryptocurrency
Coniks Java
A CONIKS implementation in Java
Stars: ✭ 58 (-14.71%)
Mutual labels:  merkle-tree
Alttracker
Alt Tracker is a beautiful, simple, cryptocurrency portfolio management tool
Stars: ✭ 65 (-4.41%)
Mutual labels:  cryptocurrency
Cryptoawesome
The most complete cryptocurrency image library to be used in your project.
Stars: ✭ 58 (-14.71%)
Mutual labels:  cryptocurrency
Ki
Go language (golang) full strength tree structures (ki in Japanese)
Stars: ✭ 61 (-10.29%)
Mutual labels:  tree-structure
Exonum Client
JavaScript client for Exonum blockchain
Stars: ✭ 62 (-8.82%)
Mutual labels:  merkle-tree
Str metrics
Ruby gem (native extension in Rust) providing implementations of various string metrics
Stars: ✭ 68 (+0%)
Mutual labels:  ruby-gem

MerkleTree

Gem Version Actions CI Build status Maintainability Coverage Status Inline docs

A binary tree of one-time signatures known as merkle tree. Often used in distributed systems such as Git, Cassandra or Bitcoin for efficiently summarizing sets of data.

A binary tree originally developed to authenticate a large number of public keys with a single value, namely the root of the tree. The merkle root is usually available publicly. Each node in the tree contains a cryptographic hash of node values of its children. The N values/messages that need to be authenticated are placed at the N leaves of the tree. A leaf can store an arbitrary value, usually a public authentication key, that is a cryptographic hash of the value that needs to be authenticated. A leaf can be then verified by publicly available merkle tree root value and its authentication path.

Installation

Add this line to your application's Gemfile:

gem 'merkle_tree'

And then execute:

$ bundle

Or install it yourself as:

$ gem install merkle_tree

Contents

1. Usage

Create a new MerkleTree by passing all the messages to be hashed:

merkle_tree = MerkleTree.new("L1", "L2", "L3", "L4")

Then you can use the tree to verify if a message belongs:

merkle_tree.include?("L3", 2) # => true

Or change the message to a new content:

merkle_tree.update("L3*", 2)

You can also check the tree height:

merkle_tree.height # => 2

And how many nodes it has:

merkle_tree.size # => 7

Finally, you can print the contents of the tree to see all the signatures:

merkle_tree.to_s
# =>
# 63442ffc2d48a92c8ba746659331f273748ccede648b27f4eacf00cb0786c439
#   f2b92f33b56466fce14bc2ccf6a92f6edfcd8111446644c20221d6ae831dd67c
#     dffe8596427fc50e8f64654a609af134d45552f18bbecef90b31135a9e7acaa0
#     d76354d8457898445bb69e0dc0dc95fb74cc3cf334f8c1859162a16ad0041f8d
#   8f75b0c1b3d1c0bb2eda264a43f8fdc5c72c853c95fbf2b01c1d5a3e12c6fe9a
#     842983de8fb1d277a3fad5c8295c7a14317c458718a10c5a35b23e7f992a5c80
#     4a5a97c6433c4c062457e9335709d57493e75527809d8a9586c141e591ac9f2c

2. API

2.1 root

To access the root node of the merkle tree use the root method that will return the tree structure with all its children and their signatures.

For example, given a tree with 4 messages

merkle_tree = MerkleTree.new("L1", "L2", "L3", "L4")

A full tree of one-time signatures will be available:

merkle_tree.root
# =>
# MerkleTree::Node
#  @value="63442ffc2d48a92c8ba746659331f273748ccede648b27f4eacf00cb0786c439"
#  @left=MerkleTree::Node
#    @value="f2b92f33b56466fce14bc2ccf6a92f6edfcd8111446644c20221d6ae831dd67c"
#    @left=MerkleTree::Leaf
#      @value="dffe8596427fc50e8f64654a609af134d45552f18bbecef90b31135a9e7acaa0"
#    @right=MerkleTree::Leaf
#      @value="d76354d8457898445bb69e0dc0dc95fb74cc3cf334f8c1859162a16ad0041f8d"
#  @right=MerkleTree::Node
#    @value="8f75b0c1b3d1c0bb2eda264a43f8fdc5c72c853c95fbf2b01c1d5a3e12c6fe9a"
#    @left=
#     MerkleTree::Leaf
#      @value="842983de8fb1d277a3fad5c8295c7a14317c458718a10c5a35b23e7f992a5c80"
#   @right=MerkleTree::Leaf
#     @value="4a5a97c6433c4c062457e9335709d57493e75527809d8a9586c141e591ac9f2c"

Since the root is a node you can retrieve it's signature using the value call:

merkle_tree.root.value
# => "63442ffc2d48a92c8ba746659331f273748ccede648b27f4eacf00cb0786c439"

2.2 leaves

You can access all the leaves and their one-time signatures using the leaves method:

merkle_tree = MerkleTree.new("L1", "L2", "L3", "L4")

merkle_tree.leaves
# =>
# [
# <MerkleTree::Leaf @value="dffe8596...", @left_index=0, @right_index=0, @height=0>,
# <MerkleTree::Leaf @value="d76354d8...", @left_index=1, @right_index=1, @height=0>,
# <MerkleTree::Leaf @value="842983de...", @left_index=2, @right_index=2, @height=0>,
# <MerkleTree::Leaf @value="4a5a97c6...", @left_index=3, @right_index=3, @height=0>
# ]

2.3 subtree

To access a part of Merkle tree use subtree with the index of the one-time signature:

merkle_tree = MerkleTree.new("L1", "L2", "L3", "L4", "L5", "L6", "L7", "L8")

merkle_tree.subtree(2).to_h
# =>
# {
#   value: "63442ffc2d48a92c8ba746659331f273748ccede648b27f4eacf00cb0786c439",
#   left: {
#     value: "f2b92f33b56466fce14bc2ccf6a92f6edfcd8111446644c20221d6ae831dd67c",
#     left: { value: "dffe8596427fc50e8f64654a609af134d45552f18bbecef90b31135a9e7acaa0" },
#     right: { value: "d76354d8457898445bb69e0dc0dc95fb74cc3cf334f8c1859162a16ad0041f8d" }
#   },
#   right: {
#     value: "8f75b0c1b3d1c0bb2eda264a43f8fdc5c72c853c95fbf2b01c1d5a3e12c6fe9a",
#     left: { value: "842983de8fb1d277a3fad5c8295c7a14317c458718a10c5a35b23e7f992a5c80" },
#     right: { value: "4a5a97c6433c4c062457e9335709d57493e75527809d8a9586c141e591ac9f2c" }
#   }
# }

2.4 height

Every leaf in the tree has height 0 and the hash function of two leaves has height 1. So the tree has a total height of H if there is N leaves so that N = 2^H.

merkle_tree = MerkleTree.new("L1", "L2", "L3", "L4", "L5", "L6", "L7", "L8")

And since 8 = 2^3 then the height:

merkle_tree.height # => 3

2.5 size

You can check total number of tree nodes with size or length calls:

merkle_tree = MerkleTree.new("L1", "L2", "L3", "L4", "L5", "L6", "L7", "L8")
merkle_tree.size
# => 15

2.6 include?

You can verify that a leaf belongs to merkle tree, namely, there is an authentication path or merkle path from the leaf to the root. This operation is log2N where N is number of leaves.

Given a tree with 4 messages:

merkle_tree = MerkleTree.new("L1", "L2", "L3", "L4")

To check if a message L3 is contained in one of the one-time signatures, use the include? or member? method passing the message and position index:

merkle_tree.include?("L3", 2) # => true

Conversely, if the message is not part of one-time signature at position indexed:

merkle_tree.include?("invalid", 2) # => false

2.7 add

To add new messages to already existing tree use add or << method. This action will create a new merkle root and increase tree height.

A merkle tree with 4 messages:

merkle_tree = MerkleTree.new("L1", "L2", "L3", "L4")

Will have the following properties:

merkle_tree.leaves.size
# => 4
merkle_tree.height
# => 2
merkle_tree.size
# => 7

To add L5 and L6 messages do:

merkle_tree.add("L5", "L6")

This will expand tree to have:

merkle_tree.leaves.size
# => 6
merkle_tree.height
# => 3
merkle_tree.size
# => 15

2.8 update

You can replace any merkle tree message with a new one using the update call, which accepts a new message as a first argument and the index of the message to replace.

For example, given the tree:

merkle_tree = MerkleTree.new("L1", "L2", "L3", "L4")

To update message from L3 to L3* do:

merkle_tree.update("L3*", 2)
# =>
# #<MerkleTree::Leaf @value="e9a1dd00f5c5e848f6ca6d8660c5191d76ac5dd8867b7a8b08fb59c5ed2806db" ... >

2.9 to_h

You can dump the whole structure of the tree with to_h method:

merkle_tree = MerkleTree.new("L1", "L2", "L3", "L4")

merkle_tree.to_h
# =>
# root: {
#   value: "63442ffc2d48a92c8ba746659331f273748ccede648b27f4eacf00cb0786c439",
#   left: {
#     value: "f2b92f33b56466fce14bc2ccf6a92f6edfcd8111446644c20221d6ae831dd67c",
#     left: { value: "dffe8596427fc50e8f64654a609af134d45552f18bbecef90b31135a9e7acaa0" },
#     right: { value: "d76354d8457898445bb69e0dc0dc95fb74cc3cf334f8c1859162a16ad0041f8d" }
#   },
#   right: {
#     value: "8f75b0c1b3d1c0bb2eda264a43f8fdc5c72c853c95fbf2b01c1d5a3e12c6fe9a",
#     left: { value: "842983de8fb1d277a3fad5c8295c7a14317c458718a10c5a35b23e7f992a5c80" },
#     right: { value: "4a5a97c6433c4c062457e9335709d57493e75527809d8a9586c141e591ac9f2c" }
#   }
# }

2.10 to_s

merkle_tree = MerkleTree.new("L1", "L2", "L3", "L4")

You can print merkle tree out to string:

merkle_tree.to_s
# =>
# 63442ffc2d48a92c8ba746659331f273748ccede648b27f4eacf00cb0786c439
#   f2b92f33b56466fce14bc2ccf6a92f6edfcd8111446644c20221d6ae831dd67c
#     dffe8596427fc50e8f64654a609af134d45552f18bbecef90b31135a9e7acaa0
#     d76354d8457898445bb69e0dc0dc95fb74cc3cf334f8c1859162a16ad0041f8d
#   8f75b0c1b3d1c0bb2eda264a43f8fdc5c72c853c95fbf2b01c1d5a3e12c6fe9a
#     842983de8fb1d277a3fad5c8295c7a14317c458718a10c5a35b23e7f992a5c80
#     4a5a97c6433c4c062457e9335709d57493e75527809d8a9586c141e591ac9f2c

2.11 :digest

By default the SHA-256 is used to create one-time signatures using Ruby's openssl package. You can see different OpenSSl::Digest.

To provide your own algorithm use the :digest keyword and as value a lambda that will produce message hash. For example, to use SHA-512 message digest algorithm do:

MerkleTree.new("L1",..., digest: -> (val) { OpenSSL::Digest::SHA256.hexdigest(val) })

3. See Also

  • splay_tree – A self-balancing binary tree with amortised access.

Development

After checking out the repo, run bin/setup to install dependencies. Then, run rake spec to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.

To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the version number in version.rb, and then run bundle exec rake release, which will create a git tag for the version, push git commits and tags, and push the .gem file to rubygems.org.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/piotrmurach/merkle_tree. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.

License

The gem is available as open source under the terms of the MIT License.

Code of Conduct

Everyone interacting in the MerkleTree project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.

Copyright

Copyright (c) 2019 Piotr Murach. See LICENSE.txt for further details.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].