utreexo 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 +26 -9
- data/lib/utreexo.rb +10 -0
- data/lib/utreexo/forest.rb +277 -14
- data/lib/utreexo/proof.rb +71 -3
- data/lib/utreexo/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f4df7507cb6f4a66261406b31c0b74ca81070e94fe747f328b09bbbfbf8ce38d
|
4
|
+
data.tar.gz: 275f3c81ee3acf4b1ecfd21dde961c8ac3b5f63627314268f8ef1cec45dd7d7e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 492bb3babdb31e371d615ebeafa0b25e58fc9e0d6e5a43a3aae934aa719ed580bc9d4507ec5565a65db0c246d6aa3110626f812fc76ee37512adebd1a5ed2bfb
|
7
|
+
data.tar.gz: f4b19fdf737d28475b0f6ce88f1a3f211b6ebdeb9811b391c3779aa9fc88092cb695c25d45685577d6824fbfceb1dba58b959ebf0b6b83a07e3424e90b6cf223
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Utreexorb [](https://travis-ci.org/chaintope/utreexorb) [](https://travis-ci.org/chaintope/utreexorb) [](https://badge.fury.io/rb/utreexo) [](LICENSE)
|
2
2
|
|
3
3
|
This library is a Ruby implementation of [Utreexo](https://github.com/mit-dci/utreexo/blob/master/utreexo.pdf).
|
4
4
|
|
@@ -26,15 +26,15 @@ Or install it yourself as:
|
|
26
26
|
require 'utreexo'
|
27
27
|
|
28
28
|
# initialize forest.
|
29
|
-
|
30
29
|
f = Utreexo::Forest.new
|
31
30
|
|
32
31
|
# add element to forest.
|
33
32
|
f.add('a00000aa00000000000000000000000000000000000000000000000000000000')
|
34
33
|
f.add('a00100aa00000000000000000000000000000000000000000000000000000000')
|
35
|
-
|
36
|
-
f.add('
|
37
|
-
f.add('
|
34
|
+
# if you want to tracking proof, set tracking flag to true.
|
35
|
+
f.add('a00200aa00000000000000000000000000000000000000000000000000000000', true)
|
36
|
+
f.add('a00300aa00000000000000000000000000000000000000000000000000000000', true)
|
37
|
+
f.add('a00400aa00000000000000000000000000000000000000000000000000000000', true)
|
38
38
|
|
39
39
|
# forest has 2 tree, height 2, height 0
|
40
40
|
# accumulator root for height 2 tree
|
@@ -43,14 +43,33 @@ f.acc[2]
|
|
43
43
|
# accumulator root for height 0 tree
|
44
44
|
f.acc[0]
|
45
45
|
=> 'a00400aa00000000000000000000000000000000000000000000000000000000'
|
46
|
+
|
47
|
+
# show forest.
|
48
|
+
puts f
|
49
|
+
07:2d04
|
50
|
+
|---------------\ |---------------\
|
51
|
+
05:736b 06:1a8e
|
52
|
+
|-------\ |-------\ |-------\ |-------\
|
53
|
+
00:???? 01:???? 02:a002 03:a003 04:a004
|
54
|
+
```
|
55
|
+
|
56
|
+
### Get proof
|
57
|
+
|
58
|
+
If leaf tracking enabled, you can get its proof. If you add or remove element to the forest, the position and inclusion proof of the leaf being tracked are updated.
|
59
|
+
|
60
|
+
```ruby
|
61
|
+
proof = f.proof('a00200aa00000000000000000000000000000000000000000000000000000000')
|
62
|
+
=> [2] leaf = a00200aa00000000000000000000000000000000000000000000000000000000, siblings = ["a00300aa00000000000000000000000000000000000000000000000000000000", "736b3e12120637186a0a8eef8ce45ed69b39119182cc749b793f05de3996f464"]
|
63
|
+
|
64
|
+
# get all tracking proofs
|
65
|
+
proofs = f.proofs
|
46
66
|
```
|
47
67
|
|
48
68
|
### Verify element.
|
49
69
|
|
50
70
|
```ruby
|
51
71
|
# proof for 3rd element
|
52
|
-
proof =
|
53
|
-
['a00300aa00000000000000000000000000000000000000000000000000000000', '736b3e12120637186a0a8eef8ce45ed69b39119182cc749b793f05de3996f464'])
|
72
|
+
proof = f.proof('a00200aa00000000000000000000000000000000000000000000000000000000')
|
54
73
|
|
55
74
|
f.include?(proof)
|
56
75
|
=> true
|
@@ -59,8 +78,6 @@ f.include?(proof)
|
|
59
78
|
### Remove element from forest.
|
60
79
|
|
61
80
|
```ruby
|
62
|
-
proof = Utreexo::Proof.new(2, 'a00200aa00000000000000000000000000000000000000000000000000000000',
|
63
|
-
['a00300aa00000000000000000000000000000000000000000000000000000000', '736b3e12120637186a0a8eef8ce45ed69b39119182cc749b793f05de3996f464'])
|
64
81
|
f.remove(proof)
|
65
82
|
|
66
83
|
# If delete 3rd element, last item move to 3rd element position, and root hash changed.
|
data/lib/utreexo.rb
CHANGED
@@ -8,4 +8,14 @@ module Utreexo
|
|
8
8
|
autoload :Forest, 'utreexo/forest'
|
9
9
|
autoload :Proof, 'utreexo/proof'
|
10
10
|
|
11
|
+
module_function
|
12
|
+
|
13
|
+
# Calculate parent hash
|
14
|
+
# @param [String] left left node hash with hex format.
|
15
|
+
# @param [String] right left node hash with hex format.
|
16
|
+
# @return [String] a parent hash with hex format.
|
17
|
+
def parent(left, right)
|
18
|
+
Blake2b.hex([left + right].pack('H*'))
|
19
|
+
end
|
20
|
+
|
11
21
|
end
|
data/lib/utreexo/forest.rb
CHANGED
@@ -6,23 +6,32 @@ module Utreexo
|
|
6
6
|
attr_accessor :num_leaves
|
7
7
|
|
8
8
|
# accumulator
|
9
|
-
|
9
|
+
attr_reader :acc
|
10
|
+
|
11
|
+
# tracking proofs
|
12
|
+
attr_reader :proofs
|
10
13
|
|
11
14
|
def initialize
|
12
|
-
@height = 0
|
13
15
|
@num_leaves = 0
|
14
|
-
@forest = []
|
15
16
|
@acc = []
|
17
|
+
@proofs = []
|
16
18
|
end
|
17
19
|
|
18
20
|
# Add element to forest.
|
19
21
|
# @param [String] leaf an element hash to be added with hex format.
|
20
|
-
def add(leaf)
|
22
|
+
def add(leaf, track = false)
|
21
23
|
n = leaf
|
22
24
|
h = 0
|
23
25
|
r = acc[h]
|
26
|
+
proofs << Utreexo::Proof.new(num_leaves, leaf) if track
|
24
27
|
until r.nil? do
|
25
|
-
|
28
|
+
# Update siblings for tracking proofs
|
29
|
+
p1 = find_proof(r)
|
30
|
+
p1.each{|p|p.siblings << n}
|
31
|
+
p2 = find_proof(n)
|
32
|
+
p2.each{|p|p.siblings << r}
|
33
|
+
|
34
|
+
n = Utreexo.parent(r, n)
|
26
35
|
acc[h] = nil
|
27
36
|
h += 1
|
28
37
|
r = acc[h]
|
@@ -37,19 +46,40 @@ module Utreexo
|
|
37
46
|
raise Utreexo::Error, 'The target element does not exist in the forest.' unless include?(proof)
|
38
47
|
n = nil
|
39
48
|
h = 0
|
49
|
+
@num_leaves -= 1
|
50
|
+
fl = forest_leaves
|
51
|
+
# update acc hash
|
52
|
+
is_switch = false
|
53
|
+
has_single_leaf = !acc[0].nil?
|
40
54
|
while h < proof.siblings.length do
|
41
|
-
|
55
|
+
s = proof.siblings[h]
|
42
56
|
if !n.nil?
|
43
|
-
n = parent(
|
57
|
+
n = ((1<<h) & proof.position) == 0 ? Utreexo.parent(n, s) : Utreexo.parent(s, n)
|
44
58
|
elsif acc[h].nil?
|
45
|
-
acc[h] =
|
59
|
+
acc[h] = s
|
46
60
|
else
|
47
|
-
|
61
|
+
# pickup switch pair
|
62
|
+
is_switch = true
|
63
|
+
if has_single_leaf
|
64
|
+
switch_single_leaf(proof, s)
|
65
|
+
else
|
66
|
+
switch_leaf_block(proof, fl, h)
|
67
|
+
end
|
68
|
+
n = (((1<<h) & proof.position) == 0) ? Utreexo.parent(acc[h], s) : Utreexo.parent(s, acc[h])
|
48
69
|
acc[h] = nil
|
49
70
|
end
|
50
71
|
h += 1
|
51
72
|
end
|
52
73
|
acc[h] = n
|
74
|
+
|
75
|
+
proofs.sort!{|a, b| a.position <=> b.position}
|
76
|
+
proofs.delete(proof)
|
77
|
+
|
78
|
+
# Update proofs
|
79
|
+
remove_unnecessary_siblings!(proof)
|
80
|
+
update_position!(proof) unless is_switch
|
81
|
+
|
82
|
+
proofs.sort!{|a, b| a.position <=> b.position}
|
53
83
|
end
|
54
84
|
|
55
85
|
# Whether the element exists in the forest
|
@@ -60,26 +90,259 @@ module Utreexo
|
|
60
90
|
n = proof.payload
|
61
91
|
proof.siblings.each_with_index do |sibling, height|
|
62
92
|
if ((1<<height) & proof.position) == 0
|
63
|
-
n = parent(n, sibling)
|
93
|
+
n = Utreexo.parent(n, sibling)
|
64
94
|
else
|
65
|
-
n = parent(sibling, n)
|
95
|
+
n = Utreexo.parent(sibling, n)
|
66
96
|
end
|
67
97
|
end
|
68
98
|
n == root
|
69
99
|
end
|
70
100
|
|
101
|
+
# Get the current proof being tracked specified by leaf. If not tracking, return nil.
|
102
|
+
# @param [String] leaf
|
103
|
+
# @return [Utreexo::Proof]
|
104
|
+
def proof(leaf)
|
105
|
+
proofs.find{|p|p.payload == leaf}
|
106
|
+
end
|
107
|
+
|
71
108
|
# get current height of the highest tree
|
72
109
|
# @return [Integer] current height of the highest tree
|
73
|
-
def
|
110
|
+
def highest_height
|
74
111
|
i = acc.reverse.find_index{|i|!i.nil?}
|
75
112
|
i ||= 0
|
76
113
|
acc.length - i
|
77
114
|
end
|
78
115
|
|
116
|
+
# show forest
|
117
|
+
def to_s
|
118
|
+
h = highest_height
|
119
|
+
outs = []
|
120
|
+
index = 0
|
121
|
+
h.times do |i|
|
122
|
+
diff = Math.log2(num_leaves) == (h - 1) ? i + 1 : i
|
123
|
+
row_len = 1 << (h - diff)
|
124
|
+
out = ''
|
125
|
+
line = ''
|
126
|
+
row_items = (num_leaves / (2**i))
|
127
|
+
row_len.times do |j|
|
128
|
+
out << "#{index.to_s.rjust(2, '0')}:"
|
129
|
+
node = (j.even? && (row_items - 1) == j) ? acc[i] : find_node(i, j)
|
130
|
+
out << (node ? "#{node[0..3]} " : "???? ")
|
131
|
+
out << (" " * (2 ** (3 + i)))[0...-8]
|
132
|
+
index += 1
|
133
|
+
break if (j + 2) > row_items
|
134
|
+
end
|
135
|
+
outs << out
|
136
|
+
break if i == (h - 1)
|
137
|
+
(row_len / 2).times do
|
138
|
+
line << '|'
|
139
|
+
line << ('--------' * (2 ** (i))).chop
|
140
|
+
line << "\\"
|
141
|
+
line << (" " * (2 ** (3 + i))).chop
|
142
|
+
end
|
143
|
+
outs << line
|
144
|
+
end
|
145
|
+
outs.reverse.join("\n")
|
146
|
+
end
|
147
|
+
|
79
148
|
private
|
80
149
|
|
81
|
-
def
|
82
|
-
|
150
|
+
def find_node(height, index)
|
151
|
+
return find_proof_at(index)&.payload if height == 0
|
152
|
+
return acc[self.highest_height - 1] if height == (self.highest_height - 1)
|
153
|
+
if height == 1
|
154
|
+
p1 = find_proof_at(index * 2)
|
155
|
+
return Utreexo.parent(p1.payload, p1.siblings[0]) if p1
|
156
|
+
p2 = find_proof_at(index * 2 + 1)
|
157
|
+
return Utreexo.parent(p2.siblings[0], p2.payload) if p2
|
158
|
+
end
|
159
|
+
left_pos = (2 ** height) * index
|
160
|
+
if index.even?
|
161
|
+
left_pos += (2 ** height)
|
162
|
+
else
|
163
|
+
left_pos -= (2 ** height)
|
164
|
+
end
|
165
|
+
right_pos = left_pos + (2 ** height - 1)
|
166
|
+
targets = proofs.select{|p| left_pos <= p.position && p.position <= right_pos}
|
167
|
+
p = targets.find{|p|!p.siblings[height].nil?}
|
168
|
+
p.siblings[height] if p
|
169
|
+
end
|
170
|
+
|
171
|
+
# Calculate the proof associated with the target(self or parent).
|
172
|
+
# @param [String] target a target hash.
|
173
|
+
# @return [Array[Utreexo::Proof]] target proofs.
|
174
|
+
def find_proof(target)
|
175
|
+
proofs.select do |p|
|
176
|
+
n = p.payload
|
177
|
+
p.siblings.each_with_index do|s, h|
|
178
|
+
if ((1<<h) & p.position) == 0
|
179
|
+
n = Utreexo.parent(n, s)
|
180
|
+
else
|
181
|
+
n = Utreexo.parent(s, n)
|
182
|
+
end
|
183
|
+
end
|
184
|
+
n == target
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
def find_proof_at(index)
|
189
|
+
proofs.find{|p|p.position == index}
|
190
|
+
end
|
191
|
+
|
192
|
+
def remove_unnecessary_siblings!(proof)
|
193
|
+
return unless proof.siblings.size > 0
|
194
|
+
target = proof.payload
|
195
|
+
proofs.select{|p|p.siblings.include?(target)}.each do |p|
|
196
|
+
p.siblings = p.siblings[0...p.siblings.index(target)]
|
197
|
+
end
|
198
|
+
proof.siblings.each_with_index do |s, h|
|
199
|
+
target = ((1<<h) & proof.position) == 0 ? Utreexo.parent(target, s) : Utreexo.parent(s, target)
|
200
|
+
proofs.select{|p|p.siblings.include?(target)}.each do |p|
|
201
|
+
p.siblings = p.siblings[0...p.siblings.index(target)]
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
# update position
|
207
|
+
# @param [Utreexo::Proof] proof removed proof
|
208
|
+
def update_position!(proof)
|
209
|
+
proof_pos = proof.position
|
210
|
+
start_index = 0
|
211
|
+
h = highest_height
|
212
|
+
h.times do |i|
|
213
|
+
half_pos = 2 ** (h - (i + 1))
|
214
|
+
threshold = half_pos + start_index
|
215
|
+
proofs.each do |p|
|
216
|
+
next if p.position < start_index
|
217
|
+
if (highest_height - 1) == i
|
218
|
+
p.position -= 1 if proof.left?
|
219
|
+
elsif proof_pos < threshold
|
220
|
+
if p.position >= threshold
|
221
|
+
p.position -= half_pos
|
222
|
+
else
|
223
|
+
p.position += half_pos
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
proof_pos += half_pos if proof_pos < threshold
|
228
|
+
start_index += half_pos
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
# Get the number of leaves of each tree in the forest in ascending order.
|
233
|
+
# @return [Array[Integer]] the number of leaves of each tree in the forest.
|
234
|
+
def forest_leaves
|
235
|
+
acc.map.with_index{|a, i| a.nil? ? nil : 2 ** i}.compact.reverse
|
236
|
+
end
|
237
|
+
|
238
|
+
# Get the start index and end index of the leaf of the tree with the target leaf number in the forest.
|
239
|
+
# @param [Integer] forest_trees the number of leaves of each tree in the forest.
|
240
|
+
# @param [Integer] target_tree Number of leaves in target tree.
|
241
|
+
# @return [Range] start index and end index at the target tree.
|
242
|
+
def target_tree_range(forest_trees, target_tree)
|
243
|
+
i = forest_trees.index(target_tree)
|
244
|
+
left_pos = 0
|
245
|
+
i.times do |index|
|
246
|
+
left_pos += forest_trees[index]
|
247
|
+
end
|
248
|
+
left_pos..(left_pos + target_tree - 1)
|
249
|
+
end
|
250
|
+
|
251
|
+
# Get leaf tree height at pos.
|
252
|
+
# @param [Integer] pos leaf position.
|
253
|
+
# @return [Integer] tree height.
|
254
|
+
def tree_height(pos)
|
255
|
+
r = 0..0
|
256
|
+
tree_heights = acc.map.with_index{|a, i| a ? i : nil}.reverse
|
257
|
+
tree_heights[tree_heights.index(highest_height - 1)..-1].each do |h|
|
258
|
+
next unless h
|
259
|
+
r = (r.last...(r.last + 2**h))
|
260
|
+
return h if r.include?(pos)
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
# Switch one leaf and remove leaf in the forest.
|
265
|
+
# @param [Utreexo::Proof] proof proof of removed leaf
|
266
|
+
# @param [String] s currently being processed
|
267
|
+
def switch_single_leaf(proof, s)
|
268
|
+
p0 = proof(acc[0])
|
269
|
+
if p0
|
270
|
+
p0.siblings = proof.siblings
|
271
|
+
p0.position = proof.position
|
272
|
+
end
|
273
|
+
ps = proof(s)
|
274
|
+
ps.siblings[0] = acc[0] if ps
|
275
|
+
|
276
|
+
target = proof.payload
|
277
|
+
new_target = acc[0]
|
278
|
+
proof.siblings.each_with_index do |s, h|
|
279
|
+
if ((1<<h) & proof.position) == 0
|
280
|
+
target = Utreexo.parent(target, s)
|
281
|
+
new_target = Utreexo.parent(new_target, s)
|
282
|
+
else
|
283
|
+
target = Utreexo.parent(s, target)
|
284
|
+
new_target = Utreexo.parent(s, new_target)
|
285
|
+
end
|
286
|
+
proofs.select{|p|p.siblings.include?(target)}.each do |p|
|
287
|
+
p.siblings[p.siblings.index(target)] = new_target
|
288
|
+
end
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
292
|
+
# Switch leaf blocks to be removed in the forest.
|
293
|
+
# @param [Utreexo::Proof] proof proof of removed leaf
|
294
|
+
# @param [Integer] fl leaves count in the forest.
|
295
|
+
# @param [Integer] h the height currently being processed
|
296
|
+
def switch_leaf_block(proof, fl, h)
|
297
|
+
switch_size = 2 ** h
|
298
|
+
sw_to_range = target_tree_range(fl, switch_size)
|
299
|
+
sw_to = sw_to_range.map {|pos|proofs.find{|p|p.position == pos}}
|
300
|
+
sw_from_range = proof.switch_range(switch_size)
|
301
|
+
sw_from = {}
|
302
|
+
sw_from_range.each {|pos|sw_from[pos] = proofs.find{|p|p.position == pos}}
|
303
|
+
height = proof.tree_height
|
304
|
+
# sort from tree
|
305
|
+
sorted_from = sw_from.sort{|(k1, v1), (k2, v2)| proof.same_subtree_height(k2) <=> proof.same_subtree_height(k1)}
|
306
|
+
|
307
|
+
sw_from_range.each.with_index do |pos, i|
|
308
|
+
from = sorted_from[i][1]
|
309
|
+
to = sw_to[i]
|
310
|
+
if from
|
311
|
+
from.position = sw_to_range.first + i unless proof == from
|
312
|
+
from.siblings.clear if from.payload == proof.siblings[0] # proof's sibling
|
313
|
+
end
|
314
|
+
if to
|
315
|
+
to.position = sw_from_range.first + i
|
316
|
+
to.siblings = to.siblings.slice(0, h) + proof.siblings.slice(-(height - h), height - h)
|
317
|
+
end
|
318
|
+
end
|
319
|
+
|
320
|
+
# Update another branch's siblings in the same tree as the proof
|
321
|
+
updated_parents = proof.switched_parents(acc[h], h)
|
322
|
+
# right branch
|
323
|
+
branch = (sw_from_range.last + 1)..(proof.tree_leaves - 1)
|
324
|
+
branch.each do |pos|
|
325
|
+
p = find_proof_at(pos)
|
326
|
+
next unless p
|
327
|
+
sub_h = proof.same_subtree_height(pos) - 1
|
328
|
+
p.siblings = p.siblings.slice(0, sub_h)
|
329
|
+
(height - sub_h).times do |i|
|
330
|
+
target = acc[p.siblings.size]
|
331
|
+
target = i.even? ? updated_parents[i] : proof.siblings[p.siblings.size] unless target
|
332
|
+
p.siblings << target
|
333
|
+
end
|
334
|
+
end
|
335
|
+
# left branch
|
336
|
+
branch = 0..(sw_from_range.first - 1)
|
337
|
+
branch.each do |pos|
|
338
|
+
p = find_proof_at(pos)
|
339
|
+
next unless p
|
340
|
+
branch_height = Math.log2(branch.size).to_i
|
341
|
+
p.siblings = p.siblings.slice(0, branch_height)
|
342
|
+
(height - branch_height).times do
|
343
|
+
p.siblings << (acc[p.siblings.size] ? acc[p.siblings.size] : proof.siblings[p.siblings.size])
|
344
|
+
end
|
345
|
+
end
|
83
346
|
end
|
84
347
|
|
85
348
|
end
|
data/lib/utreexo/proof.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
module Utreexo
|
2
2
|
class Proof
|
3
3
|
|
4
|
-
|
5
|
-
attr_reader :payload
|
6
|
-
|
4
|
+
attr_accessor :position # where at the bottom of the tree it sits
|
5
|
+
attr_reader :payload # hash of the thing itself (what's getting proved)
|
6
|
+
attr_accessor :siblings # hash of siblings up to a root
|
7
7
|
|
8
8
|
# initialize
|
9
9
|
# @param [Integer] position Where at the bottom of the tree it sits
|
@@ -27,5 +27,73 @@ module Utreexo
|
|
27
27
|
position.even?
|
28
28
|
end
|
29
29
|
|
30
|
+
# Show proof
|
31
|
+
def to_s
|
32
|
+
"[#{position}] leaf = #{payload}, siblings = #{siblings}"
|
33
|
+
end
|
34
|
+
|
35
|
+
# Return tree height containing this element
|
36
|
+
# @return [Integer] tree height
|
37
|
+
def tree_height
|
38
|
+
siblings.size
|
39
|
+
end
|
40
|
+
|
41
|
+
# Returns the number of leaves in the tree that contains this element.
|
42
|
+
# @return [Integer] the number of leaves in the tree
|
43
|
+
def tree_leaves
|
44
|
+
2 ** tree_height
|
45
|
+
end
|
46
|
+
|
47
|
+
# Return the position of this proof's pair leaf.
|
48
|
+
# @return [Integer] the position of this proof's pair leaf
|
49
|
+
def pair_pos
|
50
|
+
right? ? position - 1 : position + 1
|
51
|
+
end
|
52
|
+
|
53
|
+
# Returns the position of the leaf that is switched together with this proof, when switching this proof.
|
54
|
+
# @param [Integer] leaves the number of leaves to be switched.
|
55
|
+
# @return [Range] Leaf range to be switched.
|
56
|
+
def switch_range(leaves)
|
57
|
+
l = tree_leaves
|
58
|
+
unit = l / leaves
|
59
|
+
unit.times do |i|
|
60
|
+
range = ((i * leaves)...((i + 1) * leaves))
|
61
|
+
return range.first..(range.last - 1) if range.include?(position)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# When replacing the parent of +height+ of this proof with +parent+ argument, returns the list of parent nodes to be updated.
|
66
|
+
# @param [String] parent the parent value to replace
|
67
|
+
# @param [Integer] parent_height the parent height to replace
|
68
|
+
# @return [Array[String]] a list of updated parents
|
69
|
+
def switched_parents(parent, parent_height)
|
70
|
+
n = parent
|
71
|
+
(tree_height - parent_height).times.map do |i|
|
72
|
+
if ((1<<(i + parent_height)) & position) == 0
|
73
|
+
n = Utreexo.parent(n, siblings[parent_height + i])
|
74
|
+
else
|
75
|
+
n = Utreexo.parent(siblings[parent_height + i], n)
|
76
|
+
end
|
77
|
+
n
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# Get the height at which the leaves of +pos+ will be the same tree as the leaves of this proof.
|
82
|
+
# @param [Integer] pos target position
|
83
|
+
# @return [Integer] height
|
84
|
+
def same_subtree_height(pos)
|
85
|
+
raise Utreexo::Error, "pos: #{pos} does not in tree." unless (0...tree_leaves).include?(pos)
|
86
|
+
return 0 if position == pos
|
87
|
+
(tree_height + 1).times do |i|
|
88
|
+
same_group = false
|
89
|
+
groups = tree_leaves / (2 ** i)
|
90
|
+
(tree_leaves / groups).times do |j|
|
91
|
+
group = ((groups * j)...(groups * (j + 1)))
|
92
|
+
same_group = true if group.include?(position) && group.include?(pos)
|
93
|
+
end
|
94
|
+
return tree_height - (i - 1) unless same_group
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
30
98
|
end
|
31
99
|
end
|
data/lib/utreexo/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: utreexo
|
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: 2019-
|
11
|
+
date: 2019-07-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: blake2b
|