mssmt 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/README.md +2 -2
- data/lib/mssmt/branch_node.rb +5 -0
- data/lib/mssmt/leaf_node.rb +5 -0
- data/lib/mssmt/proof.rb +68 -0
- data/lib/mssmt/tree.rb +29 -26
- data/lib/mssmt/version.rb +1 -1
- data/lib/mssmt.rb +2 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bc50f962065de3f0ceaeebaa7715ab5e32d03a882d7df11022e6e4bc90b459d1
|
4
|
+
data.tar.gz: 020cb3cfedb35c8c3a6cd123d9b772e666e9b9fe19f301c07acc6ca27a193ca6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 468f823bbba1cff9549b5977a98270ec215e3ccf7b8057bcdd0642fd99da280233a0a821254fc2fb4c294d638ccaa6443cf04abd8a99fd4e61de6f2c51f169a1
|
7
|
+
data.tar.gz: 17f30d1180c82d4b4862c752b842e725e5d9527f1ad7f80b5e8eeb3e0d2573b127531afbfda474017103b97b21acbf3d1f1e891398686fdf06256dd3d246dc06
|
data/README.md
CHANGED
@@ -36,9 +36,9 @@ tree.insert(key, leaf)
|
|
36
36
|
# Get root node
|
37
37
|
root_node = tree.root_node
|
38
38
|
# Root hash
|
39
|
-
root_hash = tree.root_hash
|
39
|
+
root_hash = tree.root_hash.unpack1('H*')
|
40
40
|
# or
|
41
|
-
root_node.node_hash
|
41
|
+
root_node.node_hash.unpack1('H*')
|
42
42
|
|
43
43
|
# Get leaf node in tree
|
44
44
|
leaf = tree.get(key)
|
data/lib/mssmt/branch_node.rb
CHANGED
data/lib/mssmt/leaf_node.rb
CHANGED
data/lib/mssmt/proof.rb
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module MSSMT
|
3
|
+
# Merkle proof for MS-SMT.
|
4
|
+
class Proof
|
5
|
+
attr_reader :nodes
|
6
|
+
|
7
|
+
# Constructor
|
8
|
+
# @param [Array(MSSMT::BranchNode|MSSMT::LeafNode)] nodes Siblings that should be hashed with the leaf and
|
9
|
+
# its parents to arrive at the root of the MS-SMT.
|
10
|
+
def initialize(nodes)
|
11
|
+
@nodes = nodes
|
12
|
+
end
|
13
|
+
|
14
|
+
# Compresses a merkle proof by replacing its empty nodes with a bit vector.
|
15
|
+
# @return [MSSMT::CompressedProof]
|
16
|
+
def compress
|
17
|
+
bits = Array.new(nodes.length, false)
|
18
|
+
compact_nodes = []
|
19
|
+
nodes.each.each_with_index do |node, i|
|
20
|
+
# puts "#{node.node_hash}:#{Tree.empty_tree[Tree::MAX_LEVEL - 1].node_hash}"
|
21
|
+
if node.node_hash == Tree.empty_tree[Tree::MAX_LEVEL - 1].node_hash
|
22
|
+
bits[i] = true
|
23
|
+
else
|
24
|
+
compact_nodes << node
|
25
|
+
end
|
26
|
+
end
|
27
|
+
CompressedProof.new(compact_nodes, bits)
|
28
|
+
end
|
29
|
+
|
30
|
+
def ==(other)
|
31
|
+
return false unless other.is_a?(Proof)
|
32
|
+
nodes == other.nodes
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Compressed MS-SMT merkle proof.
|
37
|
+
# Since merkle proofs for a MS-SMT are always constant size (255 nodes),
|
38
|
+
# we replace its empty nodes by a bit vector.
|
39
|
+
class CompressedProof < Proof
|
40
|
+
attr_reader :bits
|
41
|
+
|
42
|
+
# Constructor
|
43
|
+
# @param [Array(MSSMT::BranchNode|MSSMT::LeafNode)] nodes Siblings that should be hashed with the leaf and
|
44
|
+
# its parents to arrive at the root of the MS-SMT.
|
45
|
+
# @param [Array] bits +bits+ determines whether a sibling node within a proof is part of the empty tree.
|
46
|
+
# This allows us to efficiently compress proofs by not including any pre-computed nodes.
|
47
|
+
def initialize(nodes, bits)
|
48
|
+
super(nodes)
|
49
|
+
@bits = bits
|
50
|
+
end
|
51
|
+
|
52
|
+
# Decompress a compressed merkle proof by replacing its bit vector with the empty nodes it represents.
|
53
|
+
# @return [MSSMT::Proof]
|
54
|
+
def decompress
|
55
|
+
count = 0
|
56
|
+
full_nodes = []
|
57
|
+
bits.each.with_index do |b, i|
|
58
|
+
if b
|
59
|
+
full_nodes << Tree.empty_tree[Tree::MAX_LEVEL - i]
|
60
|
+
else
|
61
|
+
full_nodes << nodes[count]
|
62
|
+
count += 1
|
63
|
+
end
|
64
|
+
end
|
65
|
+
Proof.new(full_nodes)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
data/lib/mssmt/tree.rb
CHANGED
@@ -10,10 +10,29 @@ module MSSMT
|
|
10
10
|
# Index of the last bit for MS-SMT keys
|
11
11
|
LAST_BIT_INDEX = MAX_LEVEL - 1
|
12
12
|
|
13
|
-
attr_reader :
|
13
|
+
attr_reader :store
|
14
|
+
|
15
|
+
def self.empty_tree
|
16
|
+
@empty_tree ||= build_empty_tree
|
17
|
+
end
|
18
|
+
|
19
|
+
# Generate empty tree.
|
20
|
+
# @return [Array]
|
21
|
+
def self.build_empty_tree
|
22
|
+
tree = Array.new(MSSMT::Tree::MAX_LEVEL + 1)
|
23
|
+
tree[MSSMT::Tree::MAX_LEVEL] = MSSMT::LeafNode.empty_leaf
|
24
|
+
MSSMT::Tree::MAX_LEVEL.times do |i|
|
25
|
+
branch =
|
26
|
+
MSSMT::BranchNode.new(
|
27
|
+
tree[MSSMT::Tree::MAX_LEVEL - i],
|
28
|
+
tree[MSSMT::Tree::MAX_LEVEL - i]
|
29
|
+
)
|
30
|
+
tree[MSSMT::Tree::MAX_LEVEL - (i + 1)] = branch
|
31
|
+
end
|
32
|
+
tree.freeze
|
33
|
+
end
|
14
34
|
|
15
35
|
def initialize(store: MSSMT::Store::DefaultStore.new)
|
16
|
-
@empty_tree = build_empty_tree
|
17
36
|
@store = store
|
18
37
|
end
|
19
38
|
|
@@ -26,7 +45,7 @@ module MSSMT
|
|
26
45
|
# Get root node in tree.
|
27
46
|
# @return [MSSMT::BranchNode]
|
28
47
|
def root_node
|
29
|
-
store.root.nil? ? empty_tree[0] : store.root
|
48
|
+
store.root.nil? ? Tree.empty_tree[0] : store.root
|
30
49
|
end
|
31
50
|
|
32
51
|
# Insert a leaf node at the given key within the MS-SMT.
|
@@ -49,10 +68,10 @@ module MSSMT
|
|
49
68
|
root =
|
50
69
|
walk_up(key, leaf, siblings) do |i, _, _, parent|
|
51
70
|
prev_parent = prev_parents[MSSMT::Tree::MAX_LEVEL - 1 - i]
|
52
|
-
unless prev_parent == empty_tree[i].node_hash
|
71
|
+
unless prev_parent == Tree.empty_tree[i].node_hash
|
53
72
|
store.delete_branch(prev_parent)
|
54
73
|
end
|
55
|
-
unless parent.node_hash == empty_tree[i].node_hash
|
74
|
+
unless parent.node_hash == Tree.empty_tree[i].node_hash
|
56
75
|
store.insert_branch(parent)
|
57
76
|
end
|
58
77
|
end
|
@@ -76,19 +95,19 @@ module MSSMT
|
|
76
95
|
|
77
96
|
# Generate a merkle proof for the leaf node found at the given +key+.
|
78
97
|
# @param [String] key key with hex format.
|
79
|
-
# @return [
|
98
|
+
# @return [MSSMT::Proof] merkle proof
|
80
99
|
def merkle_proof(key)
|
81
100
|
proof = Array.new(MAX_LEVEL)
|
82
101
|
walk_down(key) { |i, _, sibling, _| proof[MAX_LEVEL - 1 - i] = sibling }
|
83
|
-
proof
|
102
|
+
MSSMT::Proof.new(proof)
|
84
103
|
end
|
85
104
|
|
86
105
|
# Verify whether a merkle proof for the leaf found at the given key is valid.
|
87
106
|
# @param [String] key key with hex format.
|
88
107
|
# @param [MSSMT::LeafNode] leaf leaf node.
|
89
|
-
# @param [
|
108
|
+
# @param [MSSMT::Proof] proof merkle proof.
|
90
109
|
def valid_merkle_proof?(key, leaf, proof)
|
91
|
-
root_hash == walk_up(key, leaf, proof).node_hash
|
110
|
+
root_hash == walk_up(key, leaf, proof.nodes).node_hash
|
92
111
|
end
|
93
112
|
|
94
113
|
private
|
@@ -110,7 +129,7 @@ module MSSMT
|
|
110
129
|
end
|
111
130
|
|
112
131
|
def get_node(height, key)
|
113
|
-
return empty_tree[height] if empty_tree[height].node_hash == key
|
132
|
+
return Tree.empty_tree[height] if Tree.empty_tree[height].node_hash == key
|
114
133
|
store.branches[key] || store.leaves[key]
|
115
134
|
end
|
116
135
|
|
@@ -152,21 +171,5 @@ module MSSMT
|
|
152
171
|
value = [key].pack("H*")[idx / 8].ord
|
153
172
|
(value >> (idx % 8)) & 1
|
154
173
|
end
|
155
|
-
|
156
|
-
# Generate empty tree.
|
157
|
-
# @return [Array]
|
158
|
-
def build_empty_tree
|
159
|
-
tree = Array.new(MSSMT::Tree::MAX_LEVEL + 1)
|
160
|
-
tree[MSSMT::Tree::MAX_LEVEL] = MSSMT::LeafNode.empty_leaf
|
161
|
-
MSSMT::Tree::MAX_LEVEL.times do |i|
|
162
|
-
branch =
|
163
|
-
MSSMT::BranchNode.new(
|
164
|
-
tree[MSSMT::Tree::MAX_LEVEL - i],
|
165
|
-
tree[MSSMT::Tree::MAX_LEVEL - i]
|
166
|
-
)
|
167
|
-
tree[MSSMT::Tree::MAX_LEVEL - (i + 1)] = branch
|
168
|
-
end
|
169
|
-
tree
|
170
|
-
end
|
171
174
|
end
|
172
175
|
end
|
data/lib/mssmt/version.rb
CHANGED
data/lib/mssmt.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mssmt
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- azuchi
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-10-
|
11
|
+
date: 2022-10-26 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Ruby implementation of Merkle Sum Sparse Merkle Tree
|
14
14
|
email:
|
@@ -33,6 +33,7 @@ files:
|
|
33
33
|
- lib/mssmt.rb
|
34
34
|
- lib/mssmt/branch_node.rb
|
35
35
|
- lib/mssmt/leaf_node.rb
|
36
|
+
- lib/mssmt/proof.rb
|
36
37
|
- lib/mssmt/store.rb
|
37
38
|
- lib/mssmt/store/default_store.rb
|
38
39
|
- lib/mssmt/tree.rb
|