merkle_tree 0.1.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 +7 -0
- data/CHANGELOG.md +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +361 -0
- data/Rakefile +8 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/merkle_tree.rb +258 -0
- data/lib/merkle_tree/leaf.rb +57 -0
- data/lib/merkle_tree/node.rb +137 -0
- data/lib/merkle_tree/version.rb +5 -0
- data/merkle_tree.gemspec +33 -0
- data/spec/perf/speed_spec.rb +26 -0
- data/spec/spec_helper.rb +34 -0
- data/spec/unit/add_spec.rb +36 -0
- data/spec/unit/auth_path_spec.rb +18 -0
- data/spec/unit/empty_spec.rb +15 -0
- data/spec/unit/height_spec.rb +15 -0
- data/spec/unit/include_spec.rb +27 -0
- data/spec/unit/leaf/build_spec.rb +9 -0
- data/spec/unit/leaf/eql_spec.rb +16 -0
- data/spec/unit/leaves_spec.rb +16 -0
- data/spec/unit/new_spec.rb +80 -0
- data/spec/unit/node/build_spec.rb +56 -0
- data/spec/unit/node/eql_spec.rb +31 -0
- data/spec/unit/root_spec.rb +15 -0
- data/spec/unit/size_spec.rb +15 -0
- data/spec/unit/subtree_spec.rb +35 -0
- data/spec/unit/to_s_spec.rb +17 -0
- data/spec/unit/update_spec.rb +25 -0
- data/tasks/console.rake +9 -0
- data/tasks/coverage.rake +9 -0
- data/tasks/spec.rake +32 -0
- metadata +137 -0
@@ -0,0 +1,16 @@
|
|
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
|
@@ -0,0 +1,80 @@
|
|
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
|
@@ -0,0 +1,56 @@
|
|
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
|
@@ -0,0 +1,31 @@
|
|
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
|
@@ -0,0 +1,15 @@
|
|
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
|
@@ -0,0 +1,15 @@
|
|
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
|
@@ -0,0 +1,35 @@
|
|
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
|
@@ -0,0 +1,17 @@
|
|
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
|
@@ -0,0 +1,25 @@
|
|
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
ADDED
data/tasks/coverage.rake
ADDED
data/tasks/spec.rake
ADDED
@@ -0,0 +1,32 @@
|
|
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
|
metadata
ADDED
@@ -0,0 +1,137 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: merkle_tree
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Piotr Murach
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-03-16 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.17'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.17'
|
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'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
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
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description: A binary tree of one-time singatures known as a merkle tree. Often used
|
70
|
+
in distributed systems such as Git, Cassandra or Bitcoin for efficiently summarizing
|
71
|
+
sets of data.
|
72
|
+
email:
|
73
|
+
- me@piotrmurach.com
|
74
|
+
executables: []
|
75
|
+
extensions: []
|
76
|
+
extra_rdoc_files: []
|
77
|
+
files:
|
78
|
+
- CHANGELOG.md
|
79
|
+
- LICENSE.txt
|
80
|
+
- README.md
|
81
|
+
- Rakefile
|
82
|
+
- bin/console
|
83
|
+
- bin/setup
|
84
|
+
- lib/merkle_tree.rb
|
85
|
+
- lib/merkle_tree/leaf.rb
|
86
|
+
- lib/merkle_tree/node.rb
|
87
|
+
- 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
|
+
homepage: https://github.com/piotrmurach/merkle_tree
|
111
|
+
licenses:
|
112
|
+
- MIT
|
113
|
+
metadata:
|
114
|
+
homepage_uri: https://github.com/piotrmurach/merkle_tree
|
115
|
+
source_code_uri: https://github.com/piotrmurach/merkle_tree
|
116
|
+
changelog_uri: https://github.com/piotrmurach/merkle_tree/blob/master/CHANGELOG.md
|
117
|
+
post_install_message:
|
118
|
+
rdoc_options: []
|
119
|
+
require_paths:
|
120
|
+
- lib
|
121
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
122
|
+
requirements:
|
123
|
+
- - ">="
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0'
|
126
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
127
|
+
requirements:
|
128
|
+
- - ">="
|
129
|
+
- !ruby/object:Gem::Version
|
130
|
+
version: '0'
|
131
|
+
requirements: []
|
132
|
+
rubyforge_project:
|
133
|
+
rubygems_version: 2.7.3
|
134
|
+
signing_key:
|
135
|
+
specification_version: 4
|
136
|
+
summary: A binary tree of one-time signatures known as a merkle tree.
|
137
|
+
test_files: []
|