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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c2bf77bb8efa4e33fe73b3bd1b54e577e02097fadda8420924caf8df0ad9df21
4
- data.tar.gz: a5715d5289504147a0b76f8c3935910df965cae05df2a284136735389f8daa27
3
+ metadata.gz: bc50f962065de3f0ceaeebaa7715ab5e32d03a882d7df11022e6e4bc90b459d1
4
+ data.tar.gz: 020cb3cfedb35c8c3a6cd123d9b772e666e9b9fe19f301c07acc6ca27a193ca6
5
5
  SHA512:
6
- metadata.gz: 30e1c75109384039d6d87ed9702e7bfbe2848e499285460b67da66dd80668e32590ce409d5deedd64a08ed5cae6f558d40817c73275a271c0b92c6a0f1cab8e0
7
- data.tar.gz: 6231535740549dfdb317e122945464ec92789c24479f164058ebdb06a3bfb2cabd688a0b6c0eca4c48881e9a891f5b72532a7609b4ec27edf132f9986f6ad558
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)
@@ -21,5 +21,10 @@ module MSSMT
21
21
  "#{left.node_hash}#{right.node_hash}#{[@sum].pack("Q>")}"
22
22
  )
23
23
  end
24
+
25
+ def ==(other)
26
+ return false unless other.is_a?(BranchNode)
27
+ node_hash == other.node_hash
28
+ end
24
29
  end
25
30
  end
@@ -30,5 +30,10 @@ module MSSMT
30
30
  def empty?
31
31
  (value.nil? or value.empty?) && sum.zero?
32
32
  end
33
+
34
+ def ==(other)
35
+ return false unless other.is_a?(LeafNode)
36
+ node_hash == other.node_hash
37
+ end
33
38
  end
34
39
  end
@@ -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 :empty_tree, :store
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 [Array] merkle proof
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 [Array] proof merkle proof.
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MSSMT
4
- VERSION = "0.1.0"
4
+ VERSION = "0.2.0"
5
5
  end
data/lib/mssmt.rb CHANGED
@@ -12,4 +12,6 @@ module MSSMT
12
12
  autoload :LeafNode, "mssmt/leaf_node"
13
13
  autoload :BranchNode, "mssmt/branch_node"
14
14
  autoload :Tree, "mssmt/tree"
15
+ autoload :Proof, "mssmt/proof"
16
+ autoload :CompressedProof, "mssmt/proof"
15
17
  end
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.1.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-17 00:00:00.000000000 Z
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