Change:
This PR attempts to implement the "non-destructive add" proposal discussed at IETF 105. Instead of blanking nodes on add, we keep track of "unmerged leaves" below each intermediate node. This involves a bit more complexity in the tree state that is passed around, but avoids unnecessary blank nodes.
As discussed in the interim: Remove processing should be updated such that for each node in the removed node's direct path: If the removed leaf is in for the node, then just remove it from that list Otherwise, blank the node
Here's the Weekly Digest for : - - Last week 9 issues were created. Of these, 6 issues have been closed and 3 issues are still open. :greenheart: , by :greenheart: , by :greenheart: , by :heart: , by :heart: , by :heart: , by :heart: , by :heart: , by :heart: , by :speaker: , by It received 2 comments. - - Last week, 13 pull requests were created, updated or merged. Last week, 3 pull requests were updated. :yellowheart: , by :yellowheart: , by :yellowheart: , by Last week, 10 pull requests were merged. :purpleheart: , by :purpleheart: , by :purpleheart: , by :purpleheart: , by :purpleheart: , by :purpleheart: , by :purpleheart: , by :purpleheart: , by :purpleheart: , by :purpleheart: , by - - Last week there were 38 commits. :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by - - Last week there were 2 contributors. :bustinsilhouette: :bustin_silhouette: - - Last week there was 1 stargazer. :star: You are the star! :star2: - - Last week there were no releases. - - That's all for last week, please :eyes: Watch and :star: Star the repository to receive next weekly updates. :smiley: You can also .*
Here's the Weekly Digest for : - - Last week, no issues were created. - - Last week, 5 pull requests were created, updated or merged. Last week, 3 pull requests were updated. :yellowheart: , by :yellowheart: , by :yellowheart: , by Last week, 2 pull requests were merged. :purpleheart: , by :purpleheart: , by - - Last week there were 2 commits. :hammerandwrench: by :hammerandwrench: by - - Last week there was 1 contributor. :bustin_silhouette: - - Last week there were no stargazers. - - Last week there were no releases. - - That's all for last week, please :eyes: Watch and :star: Star the repository to receive next weekly updates. :smiley: You can also .
Here's the Weekly Digest for : - - Last week 18 issues were created. Of these, 3 issues have been closed and 15 issues are still open. :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :greenheart: , by :heart: , by :heart: , by :heart: , by :speaker: , by It received 5 comments. - - Last week, 10 pull requests were created, updated or merged. Last week, 1 pull request was opened. :greenheart: , by Last week, 7 pull requests were updated. :yellowheart: , by :yellowheart: , by :yellowheart: , by :yellowheart: , by :yellowheart: , by :yellowheart: , by :yellowheart: , by Last week, 2 pull requests were merged. :purpleheart: , by :purpleheart: , by - - Last week there were 4 commits. :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by :hammerandwrench: by - - Last week there were 4 contributors. :bustinsilhouette: :bustinsilhouette: :bustinsilhouette: :bustin_silhouette: - - Last week there were no stargazers. - - Last week there were no releases. - - That's all for last week, please :eyes: Watch and :star: Star the repository to receive next weekly updates. :smiley: You can also .
Here's the Weekly Digest for : - - Last week 2 issues were created. Of these, 0 issues have been closed and 2 issues are still open. :greenheart: , by :greenheart: , by - - Last week, 8 pull requests were created, updated or merged. Last week, 1 pull request was opened. :greenheart: , by Last week, 5 pull requests were updated. :yellowheart: , by :yellowheart: , by :yellowheart: , by :yellowheart: , by :yellowheart: , by Last week, 2 pull requests were merged. :purpleheart: , by :purpleheart: , by - - Last week there were 2 commits. :hammerandwrench: by :hammerandwrench: by - - Last week there was 1 contributor. :bustinsilhouette: - - Last week there was 1 stargazer. :star: You are the star! :star2: - - Last week there were no releases. - - That's all for last week, please :eyes: Watch and :star: Star the repository to receive next weekly updates. :smiley: You can also .

Discussion:
A public key <ins> An ordered list of leaf indices for "unmerged" leaves (see views) </ins> A credential (only for leaf nodes) The conditions under which each of these values must or must not be

A node in the tree may also be _blank_, indicating that no value is present at that node.  The _resolution_ of a node is an ordered list of non-blank nodes that collectively cover all non-blank descendants <del> of the node.  The nodes in a resolution are ordered according to their indices. </del> <ins> of the node. </ins> <del> The resolution of a non-blank node is a one element list containing the node itself </del> <ins> The resolution of a non-blank node comprises the node itself, followed by its list of unmerged leaves, if any </ins> The resolution of a blank leaf node is the empty list

For example, consider the following tree, where the "_" character represents a blank node: <del> In this tree, we can see all three of the above rules in play: </del> <ins> In this tree, we can see all of the above rules in play: </ins> <del> The resolution of node 5 is the list [CD] </del> <ins> The resolution of node 5 is the list [CD, C] </ins> The resolution of node 2 is the empty list [] <del> The resolution of node 3 is the list [A, CD] </del> <ins> The resolution of node 3 is the list [A, CD, C] </ins> <del> Every node, regardless of whether a node is blank or populated, has a corresponding _hash_ that summarizes the contents of the subtree </del> <ins> Every node, regardless of whether the node is blank or populated, has a corresponding _hash_ that summarizes the contents of the subtree </ins> below that node.  The rules for computing these hashes are described in tree-hashes.

In particular, MLS maintains the members' views of the tree in such a way as to maintain the _tree invariant_: <del> In other words, each member holds the private keys for nodes in its direct path, and no others. </del> <ins> In other words, if node is not blank, then it holds a key pair, and the private key of that key pair is known only to members holding leaves below that node. The reverse implication is not true: A leaf below an intermediate node might not hold the private key for the node.  Such a leaf is called an _unmerged_ leaf, since encrypting to the subtree below the node requires encrypting to the node's public key as well as the unmerged leaves below it.  A leaf is unmerged when it is first added, because the process of adding the leaf does not give it access to all of the nodes above it in the tree.  Leaves are "merged" as they receive the private keys for nodes, as described in ratchet-tree- updates. </ins> 5.4.

compute the corresponding node secret and node key pair and replace the values stored at the node with the computed values. <ins> For all updated nodes, set the list of unmerged leaves to the empty list. </ins> For example, in order to communicate the example update described in the previous section, the sender would transmit the following values:

If necessary, extend the tree to the right until it has at least index + 1 leaves <ins> For each intermediate node along the path from the leaf at position "index" to the root, add "index" to the "unmerged_leaves" list for the node. </ins> Blank the path from the leaf at position "index" to the root Set the leaf node in the tree at position "index" to a new node