Change:
used for the Merkle trees in the Certificate Transparency protocol I- D.ietf-trans-rfc6962-bis.) <del> The _direct path_ of a root is the empty list, and of any other node is the concatenation of that node's parent along with the parent's direct path.  The _copath_ of a node is the node's sibling concatenated with the list of siblings of all the nodes in its direct path, excluding the root. For example, in the below tree: The direct path of C is (W, V, X) The copath of C is (D, U, Z) A tree with "n" leaves has "2*n - 1" nodes.  For example, the above tree has 7 leaves (A, B, C, D, E, F, G) and 13 nodes. Each leaf is given an _index_ (or _leaf index_), starting at "0" from the left to "n-1" at the right. Finally, a node in the tree may also be _blank_, indicating that no value is present at that node (i.e. no keying material).  This is often the case when a leaf was recently removed from the tree. </del> There are multiple ways that an implementation might represent a ratchet tree in memory.  For example, left-balanced binary trees can be represented as an array of nodes, with node relationships computed

Discussion:
This PR reorganizes the exposition of tree concept to make them read more clearly. A new Paths through the Ratchet Tree section is introduced, which covers direct paths, copaths, and filtered direct paths The Ratchet Tree Nodes section is moved forward, so that the definition of filtered direct paths can refer to the notion of resolutions (see NAME note on ) The path example expanded so that there are blanks in the tree, and so that it shows all three path types (direct, copath, and filtered direct) for every leaf. The section on verifying parent hashes uses the example tree from the path section to illustrate the concepts noted in
Latest commit adds coverage for the last part of . In addition to moving the figure forward, it refactors the explanation to be even more explicit about what must be consumed and what may be kept.
Currently defined only briefly in "RatchetTree Evolution". While that's where it's primarily used, it would fit better in the terminology section, especially if we expand it a little and add an illustration.
The problem here is that the definition of "filtered direct path" depends on the definition of "resolution" which isn't defined until a later section.
Indeed, so proposes moving up the definition of resolution as well.
Add illustration of filtered direct path Add illustration of parent hash validation, including: Leaves with no parent hash Nodes with invalid parent hash Skipping blank nodes Add corresponding derivations to Appendix A Move figure in Section 10.2 up to Section 10 as an overview
NAME Note that I have taken a stab at parts of this in because it came along with some other tree stuff.
Duplicate
Regarding the Tree Hash Including the parentnode in the tree hash which is supposed to be computed from the leaves, makes the definition appear circular to a new reader. Since the situation when you have blank nodes in the middle of a tree but not at the root is a rather complicated, the situation when you could calculate a tree hash using the parentnode is non-obvious. In the description of Tree Hash the document says that the ParentNode object is optional "depending on whether the node is blank or not." This isn't clear specification language. Saying the parentnode object is present if the node is blank or present if the node is not blank would be clear. What if the parent node is also blank? What if the root is blank?

I think an example with and without blank nodes would be appropriate. Explaining the reason why the parentnode is included will help the reader establish a better mental model. Regarding the Parent Hash I still find this section super confusing. A few points Using a tree hash (siblingtreehash) inside the parent hash is non-obvious. There should be some explanation about what property this is providing and that it is a tree hash and not a parent hash. (Honestly it was the third time I read the section that I realized that it was really the tree hash and not the parent hash of the sibling.) Using P, V, and S for Parent, target node, and sibling node is introduced here and never used anywhere else in the document. P for parent and S for sibling make sense. I can't tell what V is supposed to stand for, and it unfortunately could cause people to confuse the vector notation used throughout, but shortly after introducing V for the target node. I propose using "N" for node or "X" instead. There is one reference to the filtered direct path of U. Perhaps this is V, or a child of V? The calculations are sufficiently complicated that I think this warrants a complete, non-trivial, worked example (possibly in an appendix). At some point we should consider providing test vectors in a future document, and this would be an ideal candidate.
Regarding the Tree Hash To be clear, the that is included in the tree hash is the node whose subtree is being hashed. The tree hash doesn't include only the leaves, it includes all the nodes in the tree. If you mean , then yes, I agree the connection is a little subtle. I've tried to explain this a little better. Updated this to be clear that the ParentNode is omitted if and only if the node is blank. Not clear what situation you mean here. I think the specific computations are pretty clearly specified for these cases. Something like this was added in : URL I extended the example and put it in an appendix. Assuming you mean here, hopefully this is addressed by the above notes. Added a note to clarify that this is the tree hash and why. Changed to "D" for "direct path", and explained the semantics. Actually it's the leaf, which is now called "L".

I think the example linked above does a pretty good job. Feedback obviously welcome. Agreed that a test vectors document will be a useful follow-on.
In order to use tree hashes to represent siblings in parent hashes, we had to compute a different tree hash on the right edge of the tree, pretending that the tree is full, in the sense of having leaves. Thus we actually have two tree hashes in play, one used for group agreement on the tree and one used for parent hash inputs. We should consider specifying that the logical tree used by MLS is always full. This change to the specification would not change the computations done by the protocol much, if at all. Thanks to the fact that we no longer generate redundant nodes (), there is never anything non-blank to the right of the rightmost non-blank leaf anyway. So the main impact is to insert some blank nodes between a parent node on the right edge of the tree and its right child -- and all of the algorithms in the specification already skip over such nodes. Likewise, implementations' internal represntations of the tree wouldn't have to change much, since the extra nodes could be "virtual". The only time they would be noticed is when computing tree hashes. We would have to update the description of the extension to say that it only covers the tree up to the rightmost non-blank leaf. It would simplify the specification in a few ways, for example: The "original sibling tree hash" would just entail blanking unmerged leaves, not structure changes. The description of extending and truncating the tree would be much simpler. The main cost would be extra hashes when joining, or when updating a member close to the right edge of the tree. If you have a tree with leaves, then you have to compute tree hashes over blank leaves and their blank parents.
Thanks to NAME and NAME for helping inspire and develop this idea in discussions around
Virtual interim 2022-05-19 NAME notes that the current tree hash is quite tricky to implement, so this would be a useful simplification Doubling the hashes on a fresh tree doesn't sound too intimidating Folks would find more concreteness useful here, interested in PR Could we phrase this as only a change to TreeKEM?

Would be premised on the equivalence of the hashed tree an the tree you operate on
Discussed at 19 May interim: NAME to draft a PR.
Holding a PR until after lands. Some notes on what would need to change: {{ratchet-tree-terminology}} would change from "the unique left-balanced tree with N leaves" to "the unique balanced binary tree with depth , where is the smallest number such that ". {{adding-and-removing-leaves}} would either be removed, or updated so that it talks about increasing or decreasing the depth of the tree (equivalently, doubling or halving the number of leaves). {{add}} would talk about increasing depth instead of adding leaves. {{remove}} would talk about decreasing depth instead of removing leaves. {{ratchet-tree-extension}} would be explicit that it only carries nodes up to the rightmost non-blank leaf. The encoding/decoding algorithms would have to be updated. {{array-based-trees}} and {{link-based-trees}} could probably be simplified. We would need to make sure all figures showed full trees.
I went ahead and filed for this, based on top of . Once that merges, we can update the PR to be a little easier to read. The changes are basically as described above. One additional note: We have actually already incurred the cost to a new joiner of hashing all the extra nodes, because they have to do it for parent hash verification anyway. So this approach is actually a net reduction in the amount of hashing that has to be done, since they don't have to also compute the non-full-tree hashes.
In , we introduced the idea of a "filtered direct path". It would be helpful to have an illustration of how a filtered direct path differs from a direct path.