mssmt 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/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
|