merkle_tree 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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]
|
4
|
-
[][gh_actions_ci]
|
5
5
|
[][appveyor]
|
6
6
|
[][codeclimate]
|
7
7
|
[][coverage]
|
8
8
|
[][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
|