merkle_tree 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -1
- data/LICENSE.txt +1 -1
- data/README.md +4 -2
- data/lib/merkle_tree.rb +6 -6
- data/lib/merkle_tree/leaf.rb +1 -1
- data/lib/merkle_tree/node.rb +4 -4
- data/lib/merkle_tree/version.rb +1 -1
- metadata +18 -67
- data/Rakefile +0 -8
- data/bin/console +0 -14
- data/bin/setup +0 -8
- data/merkle_tree.gemspec +0 -33
- data/spec/perf/speed_spec.rb +0 -26
- data/spec/spec_helper.rb +0 -34
- data/spec/unit/add_spec.rb +0 -36
- data/spec/unit/auth_path_spec.rb +0 -18
- data/spec/unit/empty_spec.rb +0 -15
- data/spec/unit/height_spec.rb +0 -15
- data/spec/unit/include_spec.rb +0 -27
- data/spec/unit/leaf/build_spec.rb +0 -9
- data/spec/unit/leaf/eql_spec.rb +0 -16
- data/spec/unit/leaves_spec.rb +0 -16
- data/spec/unit/new_spec.rb +0 -80
- data/spec/unit/node/build_spec.rb +0 -56
- data/spec/unit/node/eql_spec.rb +0 -31
- data/spec/unit/root_spec.rb +0 -15
- data/spec/unit/size_spec.rb +0 -15
- data/spec/unit/subtree_spec.rb +0 -35
- data/spec/unit/to_s_spec.rb +0 -17
- data/spec/unit/update_spec.rb +0 -25
- data/tasks/console.rake +0 -9
- data/tasks/coverage.rake +0 -9
- data/tasks/spec.rake +0 -32
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ec49337a87e559e775e365bdbb2ebb20233846e2ee6d35c11350a83c7c7c70c0
|
4
|
+
data.tar.gz: 66540e38039f3ad8351c2b6565431fa173c6a1dc157033e1efa1e8fdf060fbe7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a8f0ad9244ccb004d87f33c366be56866fba373b827fbeeb1edd3f6ecccfbbac6788157ed537bdd475279912e898aa5c372781d666196781a13abef2216b4811
|
7
|
+
data.tar.gz: d1fd3c6f36b173efa437ccdb525ee76357335eb751d2dbbb31012904d6bce4cce71901431d2e450aad54067ce236cb0621837b5e063262a227ce2a0dd117f8e2
|
data/CHANGELOG.md
CHANGED
@@ -1,7 +1,14 @@
|
|
1
1
|
# Change log
|
2
2
|
|
3
|
+
## [v0.2.0] - 2021-03-20
|
4
|
+
|
5
|
+
### Changed
|
6
|
+
* Change gemspec to remove test and rake task files to reduce gem size
|
7
|
+
* Change to require Ruby 2.0 or higher
|
8
|
+
|
3
9
|
## [v0.1.0] - 2019-03-16
|
4
10
|
|
5
11
|
* Initial implementation and release
|
6
12
|
|
7
|
-
[v0.
|
13
|
+
[v0.2.0]: https://github.com/piotrmurach/merkle_tree/compare/v0.1.0...v0.2.0
|
14
|
+
[v0.1.0]: https://github.com/piotrmurach/merkle_tree/compare/d18e34c...v0.1.0
|
data/LICENSE.txt
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
The MIT License (MIT)
|
2
2
|
|
3
|
-
Copyright (c) 2019 Piotr Murach
|
3
|
+
Copyright (c) 2019 Piotr Murach (piotrmurach.com)
|
4
4
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
data/README.md
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
# MerkleTree
|
2
2
|
|
3
3
|
[![Gem Version](https://badge.fury.io/rb/merkle_tree.svg)][gem]
|
4
|
-
[![
|
4
|
+
[![Actions CI](https://github.com/piotrmurach/merkle_tree/workflows/CI/badge.svg?branch=master)][gh_actions_ci]
|
5
5
|
[![Build status](https://ci.appveyor.com/api/projects/status/kcbi55cyq2wlfuhc?svg=true)][appveyor]
|
6
6
|
[![Maintainability](https://api.codeclimate.com/v1/badges/ce00667c8785a62cd892/maintainability)][codeclimate]
|
7
7
|
[![Coverage Status](https://coveralls.io/repos/piotrmurach/merkle_tree/badge.svg)][coverage]
|
8
8
|
[![Inline docs](http://inch-ci.org/github/piotrmurach/merkle_tree.svg?branch=master)][inchpages]
|
9
9
|
|
10
10
|
[gem]: http://badge.fury.io/rb/merkle_tree
|
11
|
-
[
|
11
|
+
[gh_actions_ci]: https://github.com/piotrmurach/merkle_tree/actions?query=workflow%3ACI
|
12
12
|
[appveyor]: https://ci.appveyor.com/project/piotrmurach/merkle-tree
|
13
13
|
[codeclimate]: https://codeclimate.com/github/piotrmurach/merkle_tree/maintainability
|
14
14
|
[coverage]: https://coveralls.io/r/piotrmurach/merkle_tree
|
@@ -16,6 +16,8 @@
|
|
16
16
|
|
17
17
|
> 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.
|
18
18
|
|
19
|
+
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.
|
20
|
+
|
19
21
|
## Installation
|
20
22
|
|
21
23
|
Add this line to your application's Gemfile:
|
data/lib/merkle_tree.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require "English"
|
4
|
+
require "openssl"
|
5
5
|
|
6
|
-
require_relative
|
7
|
-
require_relative
|
8
|
-
require_relative
|
6
|
+
require_relative "merkle_tree/leaf"
|
7
|
+
require_relative "merkle_tree/node"
|
8
|
+
require_relative "merkle_tree/version"
|
9
9
|
|
10
10
|
# A binary tree of one-time signatures known as merkle tree.
|
11
11
|
class MerkleTree
|
@@ -252,7 +252,7 @@ class MerkleTree
|
|
252
252
|
# String representation of this tree
|
253
253
|
#
|
254
254
|
# @api public
|
255
|
-
def to_s(indent =
|
255
|
+
def to_s(indent = "")
|
256
256
|
root.to_s(indent)
|
257
257
|
end
|
258
258
|
end # MerkleTree
|
data/lib/merkle_tree/leaf.rb
CHANGED
data/lib/merkle_tree/node.rb
CHANGED
@@ -95,17 +95,17 @@ class MerkleTree
|
|
95
95
|
{ value: value, left: left.to_h, right: right.to_h }
|
96
96
|
end
|
97
97
|
|
98
|
-
def to_s(indent =
|
98
|
+
def to_s(indent = "")
|
99
99
|
indent + value.to_s + $RS +
|
100
|
-
left.to_s(indent +
|
101
|
-
right.to_s(indent +
|
100
|
+
left.to_s(indent + " ") + $RS +
|
101
|
+
right.to_s(indent + " ")
|
102
102
|
end
|
103
103
|
|
104
104
|
# An empty node used as placeholder
|
105
105
|
# @api private
|
106
106
|
class EmptyNode < Node
|
107
107
|
def initialize
|
108
|
-
@value =
|
108
|
+
@value = ""
|
109
109
|
@height = 0
|
110
110
|
@left = UNDEFINED
|
111
111
|
@right = UNDEFINED
|
data/lib/merkle_tree/version.rb
CHANGED
metadata
CHANGED
@@ -1,119 +1,71 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: merkle_tree
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Piotr Murach
|
8
8
|
autorequire:
|
9
|
-
bindir:
|
9
|
+
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-03-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: rake
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '0'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: rake
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - "~>"
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '10.0'
|
34
|
-
type: :development
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - "~>"
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: '10.0'
|
26
|
+
version: '0'
|
41
27
|
- !ruby/object:Gem::Dependency
|
42
28
|
name: rspec
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - "~>"
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '3.0'
|
48
|
-
type: :development
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - "~>"
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: '3.0'
|
55
|
-
- !ruby/object:Gem::Dependency
|
56
|
-
name: rspec-benchmark
|
57
29
|
requirement: !ruby/object:Gem::Requirement
|
58
30
|
requirements:
|
59
31
|
- - ">="
|
60
32
|
- !ruby/object:Gem::Version
|
61
|
-
version: '0'
|
33
|
+
version: '3.0'
|
62
34
|
type: :development
|
63
35
|
prerelease: false
|
64
36
|
version_requirements: !ruby/object:Gem::Requirement
|
65
37
|
requirements:
|
66
38
|
- - ">="
|
67
39
|
- !ruby/object:Gem::Version
|
68
|
-
version: '0'
|
40
|
+
version: '3.0'
|
69
41
|
description: A binary tree of one-time singatures known as a merkle tree. Often used
|
70
42
|
in distributed systems such as Git, Cassandra or Bitcoin for efficiently summarizing
|
71
43
|
sets of data.
|
72
44
|
email:
|
73
|
-
-
|
45
|
+
- piotr@piotrmurach.com
|
74
46
|
executables: []
|
75
47
|
extensions: []
|
76
|
-
extra_rdoc_files:
|
48
|
+
extra_rdoc_files:
|
49
|
+
- README.md
|
50
|
+
- CHANGELOG.md
|
51
|
+
- LICENSE.txt
|
77
52
|
files:
|
78
53
|
- CHANGELOG.md
|
79
54
|
- LICENSE.txt
|
80
55
|
- README.md
|
81
|
-
- Rakefile
|
82
|
-
- bin/console
|
83
|
-
- bin/setup
|
84
56
|
- lib/merkle_tree.rb
|
85
57
|
- lib/merkle_tree/leaf.rb
|
86
58
|
- lib/merkle_tree/node.rb
|
87
59
|
- lib/merkle_tree/version.rb
|
88
|
-
- merkle_tree.gemspec
|
89
|
-
- spec/perf/speed_spec.rb
|
90
|
-
- spec/spec_helper.rb
|
91
|
-
- spec/unit/add_spec.rb
|
92
|
-
- spec/unit/auth_path_spec.rb
|
93
|
-
- spec/unit/empty_spec.rb
|
94
|
-
- spec/unit/height_spec.rb
|
95
|
-
- spec/unit/include_spec.rb
|
96
|
-
- spec/unit/leaf/build_spec.rb
|
97
|
-
- spec/unit/leaf/eql_spec.rb
|
98
|
-
- spec/unit/leaves_spec.rb
|
99
|
-
- spec/unit/new_spec.rb
|
100
|
-
- spec/unit/node/build_spec.rb
|
101
|
-
- spec/unit/node/eql_spec.rb
|
102
|
-
- spec/unit/root_spec.rb
|
103
|
-
- spec/unit/size_spec.rb
|
104
|
-
- spec/unit/subtree_spec.rb
|
105
|
-
- spec/unit/to_s_spec.rb
|
106
|
-
- spec/unit/update_spec.rb
|
107
|
-
- tasks/console.rake
|
108
|
-
- tasks/coverage.rake
|
109
|
-
- tasks/spec.rake
|
110
60
|
homepage: https://github.com/piotrmurach/merkle_tree
|
111
61
|
licenses:
|
112
62
|
- MIT
|
113
63
|
metadata:
|
64
|
+
bug_tracker_uri: https://github.com/piotrmurach/merkle_tree/issues
|
65
|
+
changelog_uri: https://github.com/piotrmurach/merkle_tree/blob/master/CHANGELOG.md
|
66
|
+
documentation_uri: https://www.rubydoc.info/gems/merkle_tree
|
114
67
|
homepage_uri: https://github.com/piotrmurach/merkle_tree
|
115
68
|
source_code_uri: https://github.com/piotrmurach/merkle_tree
|
116
|
-
changelog_uri: https://github.com/piotrmurach/merkle_tree/blob/master/CHANGELOG.md
|
117
69
|
post_install_message:
|
118
70
|
rdoc_options: []
|
119
71
|
require_paths:
|
@@ -122,15 +74,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
122
74
|
requirements:
|
123
75
|
- - ">="
|
124
76
|
- !ruby/object:Gem::Version
|
125
|
-
version:
|
77
|
+
version: 2.0.0
|
126
78
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
127
79
|
requirements:
|
128
80
|
- - ">="
|
129
81
|
- !ruby/object:Gem::Version
|
130
82
|
version: '0'
|
131
83
|
requirements: []
|
132
|
-
|
133
|
-
rubygems_version: 2.7.3
|
84
|
+
rubygems_version: 3.1.2
|
134
85
|
signing_key:
|
135
86
|
specification_version: 4
|
136
87
|
summary: A binary tree of one-time signatures known as a merkle tree.
|
data/Rakefile
DELETED
data/bin/console
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require "bundler/setup"
|
4
|
-
require "merkle_tree"
|
5
|
-
|
6
|
-
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
-
# with your gem easier. You can also use a different console, if you like.
|
8
|
-
|
9
|
-
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
-
# require "pry"
|
11
|
-
# Pry.start
|
12
|
-
|
13
|
-
require "irb"
|
14
|
-
IRB.start(__FILE__)
|
data/bin/setup
DELETED
data/merkle_tree.gemspec
DELETED
@@ -1,33 +0,0 @@
|
|
1
|
-
lib = File.expand_path("../lib", __FILE__)
|
2
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
-
require "merkle_tree/version"
|
4
|
-
|
5
|
-
Gem::Specification.new do |spec|
|
6
|
-
spec.name = "merkle_tree"
|
7
|
-
spec.version = MerkleTree::VERSION
|
8
|
-
spec.authors = ["Piotr Murach"]
|
9
|
-
spec.email = ["me@piotrmurach.com"]
|
10
|
-
|
11
|
-
spec.summary = %q{A binary tree of one-time signatures known as a merkle tree.}
|
12
|
-
spec.description = %q{A binary tree of one-time singatures known as a merkle tree. Often used in distributed systems such as Git, Cassandra or Bitcoin for efficiently summarizing sets of data.}
|
13
|
-
spec.homepage = "https://github.com/piotrmurach/merkle_tree"
|
14
|
-
spec.license = "MIT"
|
15
|
-
|
16
|
-
if spec.respond_to?(:metadata)
|
17
|
-
spec.metadata["homepage_uri"] = spec.homepage
|
18
|
-
spec.metadata["source_code_uri"] = "https://github.com/piotrmurach/merkle_tree"
|
19
|
-
spec.metadata["changelog_uri"] = "https://github.com/piotrmurach/merkle_tree/blob/master/CHANGELOG.md"
|
20
|
-
end
|
21
|
-
|
22
|
-
spec.files = Dir['{lib,spec,examples}/**/*.rb']
|
23
|
-
spec.files += Dir['{bin,tasks}/*', 'merkle_tree.gemspec']
|
24
|
-
spec.files += Dir['README.md', 'CHANGELOG.md', 'LICENSE.txt', 'Rakefile']
|
25
|
-
spec.bindir = "exe"
|
26
|
-
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
27
|
-
spec.require_paths = ["lib"]
|
28
|
-
|
29
|
-
spec.add_development_dependency "bundler", ">= 1.17"
|
30
|
-
spec.add_development_dependency "rake", "~> 10.0"
|
31
|
-
spec.add_development_dependency "rspec", "~> 3.0"
|
32
|
-
spec.add_development_dependency "rspec-benchmark"
|
33
|
-
end
|
data/spec/perf/speed_spec.rb
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RSpec.describe 'speed performance' do
|
4
|
-
it "creates merkle trees in linear time" do
|
5
|
-
messages = bench_range(8, 8 << 12).map do |n|
|
6
|
-
Array.new(n) { "L#{n}" }
|
7
|
-
end
|
8
|
-
|
9
|
-
expect { |n, i|
|
10
|
-
MerkleTree.new(*messages[i])
|
11
|
-
}.to perform_linear.in_range(8, 8 << 12)
|
12
|
-
end
|
13
|
-
|
14
|
-
it "checks if a message belongs in logarithmic time" do
|
15
|
-
trees = []
|
16
|
-
bench_range(8, 8 << 12).each do |n|
|
17
|
-
messages = []
|
18
|
-
n.times { |i| messages << "L#{i}" }
|
19
|
-
trees << MerkleTree.new(*messages)
|
20
|
-
end
|
21
|
-
|
22
|
-
expect { |n, i|
|
23
|
-
trees[i].include?("L#{n/2}", n/2)
|
24
|
-
}.to perform_logarithmic.in_range(8, 8 << 12).sample(100).times
|
25
|
-
end
|
26
|
-
end
|
data/spec/spec_helper.rb
DELETED
@@ -1,34 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
if ENV['COVERAGE'] || ENV['TRAVIS']
|
4
|
-
require 'simplecov'
|
5
|
-
require 'coveralls'
|
6
|
-
|
7
|
-
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
|
8
|
-
SimpleCov::Formatter::HTMLFormatter,
|
9
|
-
Coveralls::SimpleCov::Formatter
|
10
|
-
]
|
11
|
-
|
12
|
-
SimpleCov.start do
|
13
|
-
command_name 'spec'
|
14
|
-
add_filter 'spec'
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
require "bundler/setup"
|
19
|
-
require "rspec-benchmark"
|
20
|
-
require "merkle_tree"
|
21
|
-
|
22
|
-
RSpec.configure do |config|
|
23
|
-
config.include RSpec::Benchmark::Matchers
|
24
|
-
|
25
|
-
# Enable flags like --only-failures and --next-failure
|
26
|
-
# config.example_status_persistence_file_path = ".rspec_status"
|
27
|
-
|
28
|
-
# Disable RSpec exposing methods globally on `Module` and `main`
|
29
|
-
config.disable_monkey_patching!
|
30
|
-
|
31
|
-
config.expect_with :rspec do |c|
|
32
|
-
c.syntax = :expect
|
33
|
-
end
|
34
|
-
end
|
data/spec/unit/add_spec.rb
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RSpec.describe MerkleTree, '#add' do
|
4
|
-
it "adds one message" do
|
5
|
-
merkle_tree = MerkleTree.new("L1", "L2", "L3", "L4")
|
6
|
-
expanded_tree = MerkleTree.new("L1", "L2", "L3", "L4", "L5")
|
7
|
-
|
8
|
-
merkle_tree << "L5"
|
9
|
-
|
10
|
-
expect(merkle_tree.leaves.size).to eq(expanded_tree.leaves.size)
|
11
|
-
expect(merkle_tree.size).to eq(expanded_tree.size)
|
12
|
-
expect(merkle_tree.root.value).to eq(expanded_tree.root.value)
|
13
|
-
end
|
14
|
-
|
15
|
-
it "adds even messages" do
|
16
|
-
merkle_tree = MerkleTree.new("L1", "L2", "L3", "L4")
|
17
|
-
expanded_tree = MerkleTree.new("L1", "L2", "L3", "L4", "L5", "L6")
|
18
|
-
|
19
|
-
merkle_tree.add("L5", "L6")
|
20
|
-
|
21
|
-
expect(merkle_tree.leaves.size).to eq(expanded_tree.leaves.size)
|
22
|
-
expect(merkle_tree.size).to eq(expanded_tree.size)
|
23
|
-
expect(merkle_tree.root.value).to eq(expanded_tree.root.value)
|
24
|
-
end
|
25
|
-
|
26
|
-
it "adds messages double the size" do
|
27
|
-
merkle_tree = MerkleTree.new("L1", "L2", "L3", "L4")
|
28
|
-
expanded_tree = MerkleTree.new("L1", "L2", "L3", "L4", "L5", "L6", "L7", "L8")
|
29
|
-
|
30
|
-
merkle_tree.add("L5", "L6", "L7", "L8")
|
31
|
-
|
32
|
-
expect(merkle_tree.leaves.size).to eq(expanded_tree.leaves.size)
|
33
|
-
expect(merkle_tree.root.value).to eq(expanded_tree.root.value)
|
34
|
-
expect(merkle_tree.size).to eq(expanded_tree.size)
|
35
|
-
end
|
36
|
-
end
|
data/spec/unit/auth_path_spec.rb
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RSpec.describe MerkleTree, '#auth_path' do
|
4
|
-
it "fails to find authentication path for an index" do
|
5
|
-
merkle_tree = MerkleTree.new("L1", "L2", "L3", "L4")
|
6
|
-
|
7
|
-
expect(merkle_tree.auth_path(100)).to eq([MerkleTree::Node::EMPTY])
|
8
|
-
end
|
9
|
-
|
10
|
-
it "finds authentication path for an index" do
|
11
|
-
merkle_tree = MerkleTree.new("L1", "L2", "L3", "L4")
|
12
|
-
|
13
|
-
expect(merkle_tree.auth_path(2)).to eq([
|
14
|
-
[:left,"f2b92f33b56466fce14bc2ccf6a92f6edfcd8111446644c20221d6ae831dd67c"],
|
15
|
-
[:right,"4a5a97c6433c4c062457e9335709d57493e75527809d8a9586c141e591ac9f2c"]
|
16
|
-
])
|
17
|
-
end
|
18
|
-
end
|
data/spec/unit/empty_spec.rb
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RSpec.describe MerkleTree, '#empty?' do
|
4
|
-
it "returns true when tree has no messages" do
|
5
|
-
merkle_tree = MerkleTree.new
|
6
|
-
|
7
|
-
expect(merkle_tree.empty?).to eq(true)
|
8
|
-
end
|
9
|
-
|
10
|
-
it "returns false when tree has messages" do
|
11
|
-
merkle_tree = MerkleTree.new("L1", "L2", "L3", "L4", "L5", "L6", "L7", "L8")
|
12
|
-
|
13
|
-
expect(merkle_tree.empty?).to eq(false)
|
14
|
-
end
|
15
|
-
end
|
data/spec/unit/height_spec.rb
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RSpec.describe MerkleTree, '#height' do
|
4
|
-
it "has no messages" do
|
5
|
-
merkle_tree = MerkleTree.new
|
6
|
-
|
7
|
-
expect(merkle_tree.height).to eq(0)
|
8
|
-
end
|
9
|
-
|
10
|
-
it "calculates tree height" do
|
11
|
-
merkle_tree = MerkleTree.new("L1", "L2", "L3", "L4", "L5", "L6")
|
12
|
-
|
13
|
-
expect(merkle_tree.height).to eq(3)
|
14
|
-
end
|
15
|
-
end
|
data/spec/unit/include_spec.rb
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RSpec.describe MerkleTree, '#include?' do
|
4
|
-
it "checks message inclusion in an empty tree" do
|
5
|
-
merkle_tree = MerkleTree.new
|
6
|
-
|
7
|
-
expect(merkle_tree.include?("L3", 2)).to eq(false)
|
8
|
-
end
|
9
|
-
|
10
|
-
it "checks valid message inclusion in 4 signatures tree" do
|
11
|
-
merkle_tree = MerkleTree.new("L1", "L2", "L3", "L4")
|
12
|
-
|
13
|
-
expect(merkle_tree.include?("L3", 2)).to eq(true)
|
14
|
-
end
|
15
|
-
|
16
|
-
it "checks valid message inclusion in 8 signatures tree" do
|
17
|
-
merkle_tree = MerkleTree.new("L1", "L2", "L3", "L4", "L5", "L6", "L7", "L8")
|
18
|
-
|
19
|
-
expect(merkle_tree.include?("L5", 4)).to eq(true)
|
20
|
-
end
|
21
|
-
|
22
|
-
it "checks invalid message inclusion in 8 signatures tree" do
|
23
|
-
merkle_tree = MerkleTree.new("L1", "L2", "L3", "L4", "L5", "L6", "L7", "L8")
|
24
|
-
|
25
|
-
expect(merkle_tree.include?("invalid", 4)).to eq(false)
|
26
|
-
end
|
27
|
-
end
|
@@ -1,9 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RSpec.describe MerkleTree::Leaf, '::build' do
|
4
|
-
it "creates a leaf node" do
|
5
|
-
leaf_node = MerkleTree::Leaf.build("L1", 0)
|
6
|
-
|
7
|
-
expect(leaf_node.value).to eq("dffe8596427fc50e8f64654a609af134d45552f18bbecef90b31135a9e7acaa0")
|
8
|
-
end
|
9
|
-
end
|
data/spec/unit/leaf/eql_spec.rb
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RSpec.describe MerkleTree::Leaf, '#==' do
|
4
|
-
it "compares two different leaves with the same message" do
|
5
|
-
leaf_a = MerkleTree::Leaf.build("L1", 0)
|
6
|
-
leaf_b = MerkleTree::Leaf.build("L1", 1)
|
7
|
-
|
8
|
-
expect(leaf_a).to_not eq(leaf_b)
|
9
|
-
end
|
10
|
-
|
11
|
-
it "compares successfully only with the same leaf" do
|
12
|
-
leaf = MerkleTree::Leaf.build("L1", 0)
|
13
|
-
|
14
|
-
expect(leaf).to eq(leaf)
|
15
|
-
end
|
16
|
-
end
|
data/spec/unit/leaves_spec.rb
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RSpec.describe MerkleTree, '#leaves' do
|
4
|
-
it "returns empty array when tree has no leaves" do
|
5
|
-
merkle_tree = MerkleTree.new
|
6
|
-
|
7
|
-
expect(merkle_tree.leaves).to be_empty
|
8
|
-
end
|
9
|
-
|
10
|
-
it "returns all leaves" do
|
11
|
-
leaves = ["L1", "L2", "L3", "L4", "L5", "L6", "L7", "L8"]
|
12
|
-
merkle_tree = MerkleTree.new(*leaves)
|
13
|
-
|
14
|
-
expect(merkle_tree.leaves.size).to eq(leaves.size)
|
15
|
-
end
|
16
|
-
end
|
data/spec/unit/new_spec.rb
DELETED
@@ -1,80 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RSpec.describe MerkleTree, '#new' do
|
4
|
-
it "creates tree from even number of messages" do
|
5
|
-
merkle_tree = MerkleTree.new("L1", "L2", "L3", "L4")
|
6
|
-
|
7
|
-
expect(merkle_tree.to_h).to eq({
|
8
|
-
root: {
|
9
|
-
value: "63442ffc2d48a92c8ba746659331f273748ccede648b27f4eacf00cb0786c439",
|
10
|
-
left: {
|
11
|
-
value: "f2b92f33b56466fce14bc2ccf6a92f6edfcd8111446644c20221d6ae831dd67c",
|
12
|
-
left: {
|
13
|
-
value: "dffe8596427fc50e8f64654a609af134d45552f18bbecef90b31135a9e7acaa0"
|
14
|
-
},
|
15
|
-
right: {
|
16
|
-
value: "d76354d8457898445bb69e0dc0dc95fb74cc3cf334f8c1859162a16ad0041f8d"
|
17
|
-
}
|
18
|
-
},
|
19
|
-
right: {
|
20
|
-
value: "8f75b0c1b3d1c0bb2eda264a43f8fdc5c72c853c95fbf2b01c1d5a3e12c6fe9a",
|
21
|
-
left: {
|
22
|
-
value: "842983de8fb1d277a3fad5c8295c7a14317c458718a10c5a35b23e7f992a5c80"
|
23
|
-
},
|
24
|
-
right: {
|
25
|
-
value: "4a5a97c6433c4c062457e9335709d57493e75527809d8a9586c141e591ac9f2c"
|
26
|
-
}
|
27
|
-
}
|
28
|
-
}
|
29
|
-
})
|
30
|
-
end
|
31
|
-
|
32
|
-
it "creates tree from odd number of messages by duplicating the last message" do
|
33
|
-
merkle_tree = MerkleTree.new("L1", "L2", "L3")
|
34
|
-
|
35
|
-
expect(merkle_tree.to_h).to eq({
|
36
|
-
root: {
|
37
|
-
value: "bdb1b6778b2923c883a078a6d8dbf40f99bb1a58bf5f650349f965bd8a222f43",
|
38
|
-
left: {
|
39
|
-
value: "f2b92f33b56466fce14bc2ccf6a92f6edfcd8111446644c20221d6ae831dd67c",
|
40
|
-
left: {
|
41
|
-
value: "dffe8596427fc50e8f64654a609af134d45552f18bbecef90b31135a9e7acaa0"
|
42
|
-
},
|
43
|
-
right: {
|
44
|
-
value: "d76354d8457898445bb69e0dc0dc95fb74cc3cf334f8c1859162a16ad0041f8d"
|
45
|
-
}
|
46
|
-
},
|
47
|
-
right: {
|
48
|
-
value: "5ca8ce04894dcfaacfe7b77d5f003b355ca0df2e0055d6c9fa3b006a8e56a2ba",
|
49
|
-
left: {
|
50
|
-
value: "842983de8fb1d277a3fad5c8295c7a14317c458718a10c5a35b23e7f992a5c80"
|
51
|
-
},
|
52
|
-
right: {
|
53
|
-
value: "842983de8fb1d277a3fad5c8295c7a14317c458718a10c5a35b23e7f992a5c80"
|
54
|
-
}
|
55
|
-
}
|
56
|
-
}
|
57
|
-
})
|
58
|
-
end
|
59
|
-
|
60
|
-
it "changes hashing function" do
|
61
|
-
merkle_tree = MerkleTree.new("L1", "L2", "L3", "L4",
|
62
|
-
digest: -> (val) { "(#{val}h)"})
|
63
|
-
|
64
|
-
expect(merkle_tree.to_h).to eq({
|
65
|
-
root: {
|
66
|
-
value: "(((L1h)(L2h)h)((L3h)(L4h)h)h)",
|
67
|
-
left: {
|
68
|
-
value: "((L1h)(L2h)h)",
|
69
|
-
left: { value: "(L1h)" },
|
70
|
-
right: { value: "(L2h)" },
|
71
|
-
},
|
72
|
-
right: {
|
73
|
-
value: "((L3h)(L4h)h)",
|
74
|
-
left: { value: "(L3h)" },
|
75
|
-
right: { value: "(L4h)" }
|
76
|
-
}
|
77
|
-
}
|
78
|
-
})
|
79
|
-
end
|
80
|
-
end
|
@@ -1,56 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RSpec.describe MerkleTree::Node, '::build' do
|
4
|
-
it "combines two leaf nodes" do
|
5
|
-
nodes = [
|
6
|
-
MerkleTree::Leaf.build("L1", 0),
|
7
|
-
MerkleTree::Leaf.build("L2", 1)
|
8
|
-
]
|
9
|
-
|
10
|
-
node = MerkleTree::Node.build(*nodes)
|
11
|
-
|
12
|
-
expect(node.value).to eq('f2b92f33b56466fce14bc2ccf6a92f6edfcd8111446644c20221d6ae831dd67c')
|
13
|
-
expect(node.left).to eq(nodes[0])
|
14
|
-
expect(node.right).to eq(nodes[1])
|
15
|
-
expect(node.left_index).to eq(0)
|
16
|
-
expect(node.right_index).to eq(1)
|
17
|
-
end
|
18
|
-
|
19
|
-
it "combines leaf node with empty node" do
|
20
|
-
leaf = MerkleTree::Leaf.build("L1", 0)
|
21
|
-
nodes = [
|
22
|
-
leaf,
|
23
|
-
MerkleTree::Node::EMPTY
|
24
|
-
]
|
25
|
-
|
26
|
-
node = MerkleTree::Node.build(*nodes)
|
27
|
-
|
28
|
-
expect(node.value).to eq("15253c068a787616f4a6580d34a099f5bde3991f771a5c8a7841638db7e69e24")
|
29
|
-
|
30
|
-
expect(node.left_index).to eq(0)
|
31
|
-
expect(node.right_index).to eq(MerkleTree::Node::UNDEFINED)
|
32
|
-
end
|
33
|
-
|
34
|
-
it "combines 2 nodes" do
|
35
|
-
nodes_left = [
|
36
|
-
MerkleTree::Leaf.build("L1", 0),
|
37
|
-
MerkleTree::Leaf.build("L2", 1)
|
38
|
-
]
|
39
|
-
|
40
|
-
nodes_right = [
|
41
|
-
MerkleTree::Leaf.build("L3", 2),
|
42
|
-
MerkleTree::Leaf.build("L4", 3)
|
43
|
-
]
|
44
|
-
|
45
|
-
node_left = MerkleTree::Node.build(*nodes_left)
|
46
|
-
node_right = MerkleTree::Node.build(*nodes_right)
|
47
|
-
|
48
|
-
node = MerkleTree::Node.build(node_left, node_right)
|
49
|
-
|
50
|
-
expect(node.value).to eq("63442ffc2d48a92c8ba746659331f273748ccede648b27f4eacf00cb0786c439")
|
51
|
-
expect(node.left).to eq(node_left)
|
52
|
-
expect(node.right).to eq(node_right)
|
53
|
-
expect(node.left_index).to eq(0)
|
54
|
-
expect(node.right_index).to eq(3)
|
55
|
-
end
|
56
|
-
end
|
data/spec/unit/node/eql_spec.rb
DELETED
@@ -1,31 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RSpec.describe MerkleTree::Node, '#==' do
|
4
|
-
it "compares two different nodes" do
|
5
|
-
nodes_left = [
|
6
|
-
MerkleTree::Leaf.build("L1", 0),
|
7
|
-
MerkleTree::Leaf.build("L2", 1)
|
8
|
-
]
|
9
|
-
|
10
|
-
nodes_right = [
|
11
|
-
MerkleTree::Leaf.build("L3", 2),
|
12
|
-
MerkleTree::Leaf.build("L4", 3)
|
13
|
-
]
|
14
|
-
|
15
|
-
node_left = MerkleTree::Node.build(*nodes_left)
|
16
|
-
node_right = MerkleTree::Node.build(*nodes_right)
|
17
|
-
|
18
|
-
expect(node_left).to_not eq(node_right)
|
19
|
-
end
|
20
|
-
|
21
|
-
it "compares same node" do
|
22
|
-
nodes = [
|
23
|
-
MerkleTree::Leaf.build("L1", 0),
|
24
|
-
MerkleTree::Leaf.build("L2", 1)
|
25
|
-
]
|
26
|
-
|
27
|
-
node = MerkleTree::Node.build(*nodes)
|
28
|
-
|
29
|
-
expect(node).to eq(node)
|
30
|
-
end
|
31
|
-
end
|
data/spec/unit/root_spec.rb
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RSpec.describe MerkleTree, '#root' do
|
4
|
-
it "returns empty root when no messages" do
|
5
|
-
merkle_tree = MerkleTree.new
|
6
|
-
|
7
|
-
expect(merkle_tree.root).to eq(MerkleTree::Node::EMPTY)
|
8
|
-
end
|
9
|
-
|
10
|
-
it "calculates root signature" do
|
11
|
-
merkle_tree = MerkleTree.new("L1", "L2", "L3", "L4")
|
12
|
-
|
13
|
-
expect(merkle_tree.root.value).to eq("63442ffc2d48a92c8ba746659331f273748ccede648b27f4eacf00cb0786c439")
|
14
|
-
end
|
15
|
-
end
|
data/spec/unit/size_spec.rb
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RSpec.describe MerkleTree, '#size' do
|
4
|
-
it "returns 0 when tree has no messages" do
|
5
|
-
merkle_tree = MerkleTree.new
|
6
|
-
|
7
|
-
expect(merkle_tree.size).to eq(0)
|
8
|
-
end
|
9
|
-
|
10
|
-
it "returns 15 when tree has 8 messages" do
|
11
|
-
merkle_tree = MerkleTree.new("L1", "L2", "L3", "L4", "L5", "L6", "L7", "L8")
|
12
|
-
|
13
|
-
expect(merkle_tree.size).to eq(15)
|
14
|
-
end
|
15
|
-
end
|
data/spec/unit/subtree_spec.rb
DELETED
@@ -1,35 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RSpec.describe MerkleTree, '#subtree' do
|
4
|
-
it "return empty node for non existent index" do
|
5
|
-
merkle_tree = MerkleTree.new("L1", "L2", "L3", "L4")
|
6
|
-
|
7
|
-
expect(merkle_tree.subtree(10)).to eq(MerkleTree::Node::EMPTY)
|
8
|
-
end
|
9
|
-
|
10
|
-
it "extracts subtree for a given index" do
|
11
|
-
merkle_tree = MerkleTree.new("L1", "L2", "L3", "L4", "L5", "L6", "L7", "L8")
|
12
|
-
|
13
|
-
expect(merkle_tree.subtree(2).to_h).to eq({
|
14
|
-
value: "63442ffc2d48a92c8ba746659331f273748ccede648b27f4eacf00cb0786c439",
|
15
|
-
left: {
|
16
|
-
value: "f2b92f33b56466fce14bc2ccf6a92f6edfcd8111446644c20221d6ae831dd67c",
|
17
|
-
left: {
|
18
|
-
value: "dffe8596427fc50e8f64654a609af134d45552f18bbecef90b31135a9e7acaa0",
|
19
|
-
},
|
20
|
-
right: {
|
21
|
-
value: "d76354d8457898445bb69e0dc0dc95fb74cc3cf334f8c1859162a16ad0041f8d",
|
22
|
-
}
|
23
|
-
},
|
24
|
-
right: {
|
25
|
-
value: "8f75b0c1b3d1c0bb2eda264a43f8fdc5c72c853c95fbf2b01c1d5a3e12c6fe9a",
|
26
|
-
left: {
|
27
|
-
value: "842983de8fb1d277a3fad5c8295c7a14317c458718a10c5a35b23e7f992a5c80",
|
28
|
-
},
|
29
|
-
right: {
|
30
|
-
value: "4a5a97c6433c4c062457e9335709d57493e75527809d8a9586c141e591ac9f2c"
|
31
|
-
}
|
32
|
-
}
|
33
|
-
})
|
34
|
-
end
|
35
|
-
end
|
data/spec/unit/to_s_spec.rb
DELETED
@@ -1,17 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RSpec.describe MerkleTree, '#to_s' do
|
4
|
-
it "prints all tree signatures indented by 2 spaces" do
|
5
|
-
merkle_tree = MerkleTree.new("L1", "L2", "L3", "L4")
|
6
|
-
|
7
|
-
expect(merkle_tree.to_s).to eq([
|
8
|
-
"63442ffc2d48a92c8ba746659331f273748ccede648b27f4eacf00cb0786c439",
|
9
|
-
" f2b92f33b56466fce14bc2ccf6a92f6edfcd8111446644c20221d6ae831dd67c",
|
10
|
-
" dffe8596427fc50e8f64654a609af134d45552f18bbecef90b31135a9e7acaa0",
|
11
|
-
" d76354d8457898445bb69e0dc0dc95fb74cc3cf334f8c1859162a16ad0041f8d",
|
12
|
-
" 8f75b0c1b3d1c0bb2eda264a43f8fdc5c72c853c95fbf2b01c1d5a3e12c6fe9a",
|
13
|
-
" 842983de8fb1d277a3fad5c8295c7a14317c458718a10c5a35b23e7f992a5c80",
|
14
|
-
" 4a5a97c6433c4c062457e9335709d57493e75527809d8a9586c141e591ac9f2c"
|
15
|
-
].join("\n"))
|
16
|
-
end
|
17
|
-
end
|
data/spec/unit/update_spec.rb
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RSpec.describe MerkleTree, '#update' do
|
4
|
-
it "updates a leaf at index position with a new message" do
|
5
|
-
merkle_tree = MerkleTree.new("L1", "L2", "L3", "L4")
|
6
|
-
updated_merkle_tree = MerkleTree.new("L1", "L2", "L3*", "L4")
|
7
|
-
expected_leaf = MerkleTree::Leaf.build("L3*", 2)
|
8
|
-
|
9
|
-
updated_leaf = merkle_tree.update("L3*", 2)
|
10
|
-
|
11
|
-
expect(updated_leaf.value).to eq(expected_leaf.value)
|
12
|
-
expect(merkle_tree.root.value).to eq(updated_merkle_tree.root.value)
|
13
|
-
end
|
14
|
-
|
15
|
-
it "updates a leaf in tree with 8 messages with a new message" do
|
16
|
-
merkle_tree = MerkleTree.new("L1", "L2", "L3", "L4", "L5", "L6", "L7", "L8")
|
17
|
-
updated_merkle_tree = MerkleTree.new("L1", "L2", "L3*", "L4", "L5", "L6", "L7", "L8")
|
18
|
-
expected_leaf = MerkleTree::Leaf.build("L3*", 2)
|
19
|
-
|
20
|
-
updated_leaf = merkle_tree.update("L3*", 2)
|
21
|
-
|
22
|
-
expect(updated_leaf.value).to eq(expected_leaf.value)
|
23
|
-
expect(merkle_tree.root.value).to eq(updated_merkle_tree.root.value)
|
24
|
-
end
|
25
|
-
end
|
data/tasks/console.rake
DELETED
data/tasks/coverage.rake
DELETED
data/tasks/spec.rake
DELETED
@@ -1,32 +0,0 @@
|
|
1
|
-
begin
|
2
|
-
require 'rspec/core/rake_task'
|
3
|
-
|
4
|
-
desc 'Run all specs'
|
5
|
-
RSpec::Core::RakeTask.new(:spec) do |task|
|
6
|
-
task.pattern = 'spec/{unit,integration}{,/*/**}/*_spec.rb'
|
7
|
-
end
|
8
|
-
|
9
|
-
namespace :spec do
|
10
|
-
desc 'Run unit specs'
|
11
|
-
RSpec::Core::RakeTask.new(:unit) do |task|
|
12
|
-
task.pattern = 'spec/unit{,/*/**}/*_spec.rb'
|
13
|
-
end
|
14
|
-
|
15
|
-
desc 'Run integration specs'
|
16
|
-
RSpec::Core::RakeTask.new(:integration) do |task|
|
17
|
-
task.pattern = 'spec/integration{,/*/**}/*_spec.rb'
|
18
|
-
end
|
19
|
-
|
20
|
-
desc 'Run integration specs'
|
21
|
-
RSpec::Core::RakeTask.new(:perf) do |task|
|
22
|
-
task.pattern = 'spec/perf{,/*/**}/*_spec.rb'
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
rescue LoadError
|
27
|
-
%w[spec spec:unit spec:integration].each do |name|
|
28
|
-
task name do
|
29
|
-
$stderr.puts "In order to run #{name}, do `gem install rspec`"
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|