You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: draft-davidben-tls-merkle-tree-certs.md
+36-13Lines changed: 36 additions & 13 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -430,14 +430,44 @@ Given a Merkle Tree over `n` elements, a subtree defined by `[start, end)`, a co
430
430
431
431
## Arbitrary Intervals
432
432
433
-
Not all `[start, end)` intervals of a Merkle tree are valid subtrees. This section describes how, for any `start < end`, to determine up to two subtrees that efficiently cover the interval. The subtrees are determined by the following Python procedure:
433
+
Not all `[start, end)` intervals of a Merkle tree are valid subtrees. This section describes how, for any `start < end`, to determine up to two subtrees that efficiently cover the interval. The subtrees are determined by the following procedure:
434
+
435
+
1. If `end - start` is one, return a single subtree, `[start, end)`.
436
+
437
+
2. Otherwise, run the following to return a pair of subtrees:
438
+
439
+
1. Let `last` be `end - 1`, the last index in `[start, end)`.
440
+
441
+
2. Let `split` be the bit index of the most significant bit where `start` and `last` differ. Bits are numbered from the least significant bit, starting at zero. `split` is the height at which `start` and `last`'s paths in the tree diverge.
442
+
443
+
3. Let `mid` be `last` with the least significant `split` bits set to zero. `mid` is the leftmost leaf node in the above divergence point's right branch.
444
+
445
+
4. Within the least significant `split` bits of `left`, let `b` be the bit index of the most significant bit with value zero, if any:
446
+
447
+
1. If there is such a bit, let `left_split` be `b + 1`.
448
+
2. Otherwise, let `left_split` be zero.
449
+
450
+
`left_split`is the height of the lowest common ancestor of the nodes in `[start, mid)`.
451
+
452
+
5. Let `left_start` be `start` with the least significant `left_split` bits set to zero. `left_start` is the above lowest common ancestor's leftmost leaf node.
453
+
454
+
6. Return the subtrees `[left_start, mid)` and `[mid, end)`.
455
+
456
+
When the procedure returns a single subtree, the subtree is `[start, start+1)`. When it returns two subtrees, `left` and `right`, the subtrees satisfy the following properties:
457
+
458
+
* `left.end = right.start`. That is, the two subtrees cover adjacent intervals.
459
+
* `left.start <= start` and `end = right.end`. That is, the two subtrees together cover the entire target interval, possibly with some extra entries before `start` left, but not after `end`.
460
+
* `left.end - left.start < 2 * (end - start)` and `right.end - right.start <= end - start`. That is, the two subtrees efficiently cover the interval.
461
+
* `left` is full, while `right` may be partial.
462
+
463
+
The following Python code implements this procedure:
434
464
435
465
~~~python
436
466
def find_subtrees(start, end):
437
467
""" Returns a list of one or two subtrees that efficiently
438
468
cover [start, end). """
439
469
assert start < end
440
-
if end - start < 2:
470
+
if end - start == 1:
441
471
return [(start, end),]
442
472
last = end - 1
443
473
# Find where start and last's tree paths diverge. The two
# Maximize the left endpoint. This is just before start's
449
479
# path leaves the right edge of its new subtree.
450
480
left_split = (~start & mask).bit_length()
451
-
left = start & ~((1 << left_split) - 1)
452
-
return [(left, mid), (mid, end)]
481
+
left_start = start & ~((1 << left_split) - 1)
482
+
return [(left_start, mid), (mid, end)]
453
483
~~~
454
484
455
-
[[TODO: Write this up in prose too.]]
456
-
457
-
When the procedure returns a single subtree, the subtree is `[start, end)`. When it returns two subtrees, `left` and `right`, the subtrees satisfy the following properties:
458
-
459
-
1. `left.end = right.start`. That is, the two subtrees cover adjacent intervals.
460
-
2. `left.start <= start` and `end = right.end`. That is, the two subtrees together cover the entire target interval, possibly with some extra entries before `start` left, but not after `end`.
461
-
3. `left.end - left.start < 2 * (end - start)` and `right.end - right.start <= end - start`. That is, the two subtrees efficiently cover the interval.
462
-
4. `left` is full, while `right` may be partial.
463
-
464
485
{{fig-subtree-example}} shows the subtrees which cover `[5, 13)` in a Merkle Tree of 13 elements. The two subtrees selected are `[4, 8)` and `[8, 13)`. Note that the subtrees cover a slightly larger interval than `[5, 13)`.
465
486
466
487
<!-- Ideally we'd use the Unicode box-drawing characters for the text form, but aasvg doesn't support them: https://github.com/martinthomson/aasvg/issues/9 -->
@@ -1436,3 +1457,5 @@ In draft-04, there is no fast issuance mode. In draft-05, frequent, non-landmark
1436
1457
- Removed now unnecessary placeholder text
1437
1458
1438
1459
- First draft at IANA registration and ASN.1 module
1460
+
1461
+
- Added a prose version of the procedure to select subtrees
0 commit comments