Change:
Conflicts with (in derivation of ) This is intended just to move around the required steps and give them clearer labels. Please keep an eye out for things that might have accidentally been added or dropped.
Interim 2022-06-02: NAME to review, then clear to merge
Currently, we only have explicit algorithm steps for validating an UpdatePath. We should have a similar level of concreteness for the process of creating an UpdatePath.

Discussion:
path secret to each public key in the resolution of the non-updated child. <del> The recipient of an UpdatePath processes it with the following steps: </del> <ins> A member of the group _updates their direct path_ by computing new values for their leaf node and the nodes along their filtered direct path: </ins> <del> Compute the updated path secrets. </del> <ins> Blank all nodes along the direct path of the sender's leaf. </ins> <del> Identify a node in the filtered direct path for which the recipient is in the subtree of the non-updated child. </del> <ins> Compute updated path secrets and public keys for the nodes on the sender's filtered direct path. </ins> <del> Identify a node in the resolution of the copath node for which the recipient has a private key. </del> <ins> Generate a sequence of path secrets of the same length as the filtered direct path, as defined in </ins> <del> Decrypt the path secret for the parent of the copath node using the private key from the resolution node. </del> <ins> For each node in the filtered direct path, replace the node's public key with the "node_pub[n]" value derived from the corresponding path secret "path_secret[n]". </ins> <del> Derive path secrets for ancestors of that node using the algorithm described above. </del> <ins> Compute the new parent hashes for the nodes along the filtered direct path and the sender's leaf node. </ins> <del> The recipient SHOULD verify that the received public keys agree with the public keys derived from the new path_secret values. </del> <ins> Update the leaf node for the sender. </ins> <del> Merge the updated path secrets into the tree. </del> <ins> Set the "leaf_node_source" to "commit". </ins> <del> Blank all nodes on the direct path of the sender's leaf. </del> <ins> Set the "encryption_key" to the public key of a freshly sampled key pair </ins> <del> For all nodes on the filtered direct path of the sender's leaf, </del> <ins> Set the parent hash to the parent hash for the leaf. </ins> <del> Set the public key to the received public key. </del> <ins> Re-sign the leaf node with its new contents </ins> <del> Set the list of unmerged leaves to the empty list. </del> <ins> Since the new leaf node effectively updates an existing leaf node in the group, it MUST adhere to the same restrictions as LeafNodes used in "Update" proposals (aside from "leaf_node_source").  The application MAY specify other changes to the leaf node, e.g., providing a new signature key, updated capabilities, or different extensions. </ins> <del> Store the updated hash of the next node on the filtered direct path (represented as a ParentNode struct), going from root to leaf, so that each hash incorporates all the non- blank nodes above it.  The root node always has a zero- length hash for this value. </del> <ins> The member then _encrypts path secrets to the group_.  For each node in the member's filtered direct path, the member takes the following steps: Compute the resolution of the node's child that is on the copath of the sender (the child that is not in the direct path of the sender).  Any new member (from an Add proposal) added in the same Commit MUST be excluded from this resolution. For each node in the resolution, encrypt the path secret for the direct path node using the public key of the resolution node, as defined in The recipient of an UpdatePath performs the corresponding steps. First, the recipient _merges UpdatePath into the tree_: Blank all nodes on the direct path of the sender's leaf. For all nodes on the filtered direct path of the sender's leaf, Set the public key to the public key in the UpdatePath. Set the list of unmerged leaves to the empty list. Compute parent hashes for the nodes in the sender's filtered direct path, and verify that the "parent_hash" field of the leaf node matches the parent hash for the first node in its filtered direct path. Note that these hashes are computed from root to leaf, so that each hash incorporates all the non-blank nodes above it.  The root node always has a zero-length hash for its parent hash. Second, the recipient _decrypts the path secrets_: Identify a node in the filtered direct path for which the recipient is in the subtree of the non-updated child. </ins> <del> For nodes where a path secret was recovered in step 1 ("Compute the updated path secrets"), compute and store the node's updated private key. </del> <ins> Identify a node in the resolution of the copath node for which the recipient has a private key. Decrypt the path secret for the parent of the copath node using the private key from the resolution node. Derive path secrets for ancestors of that node in the sender's filtered direct path using the algorithm described above. Derive the node secrets and node key pairs from the path secrets. Verify that the derived public keys are the same as the corresponding public keys sent in the UpdatePath. Store the derived private keys in the corresponding ratchet tree nodes. </ins> For example, in order to communicate the example update described in <del> ratchet-tree-evolution, the sender would transmit the following values: </del> <ins> ratchet-tree-evolution, the member at node B would transmit the following values: </ins> In this table, the value node_pub[i] represents the public key derived from node_secret[i], pk(X) represents the current public key of node X, and E(K, S) represents the public-key encryption of the path secret S to the public key K (using HPKE). <ins> A recipient at node A would decrypt "E(pk(A), path_secret[0])" to obtain "path_secret[0]", then use it to derive "path_secret[1]" and the resulting node secrets and key pairs.  Thus A would have the private keys to nodes X' and Y', in accordance with the tree invariant. Similarly, a recipient at node D would decrypt "E(pk(Z), path_secret[1])" to obtain "path_secret[1]", then use it to derive the node secret and and key pair for the node Y'.  As required to maintain the tree invariant, node D does not receive the private key for the node X', since X' is not an ancestor of D. </ins> After processing the update, each recipient MUST delete outdated key material, specifically: <del> The path secrets used to derive each updated node key pair. </del> <ins> The path secrets and node secrets used to derive each updated node key pair. </ins> Each outdated node key pair that was replaced by the update.

leaf nodes in the new ratchet tree, add a blank leaf to the right side of the new ratchet tree and assign it to the sender. <del> Generate path secrets for the parent nodes along the sender's filtered direct path, as described in synchronizing-views-of- the-tree.  Define "commit_secret" as the value "path_secret[n+1]" derived from the last path secret value ("path_secret[n]") derived for the UpdatePath. Update the new ratchet tree by setting the parent nodes on the sender's filtered direct path based on the path secrets. Compute parent hashes for these nodes.  Set the sender's leaf node in the new tree to a new leaf node including the resulting parent hash for its nearest ancestor. The new leaf node MUST have "leaf_node_source" set to "commit". Since the new leaf node effectively updates an existing leaf node in the group, it MUST adhere to the same restrictions as LeafNodes used in "Update" proposals (aside from "leaf_node_source"). The application MAY specify other changes to the leaf node, e.g., providing a new signature key, updated capabilities, or different extensions. </del> <ins> Update the sender's direct path in the ratchet tree as described in synchronizing-views-of-the-tree.  Define "commit_secret" as the value "path_secret[n+1]" derived from the last path secret value ("path_secret[n]") derived for the UpdatePath. </ins> Construct a provisional GroupContext object containing the following values:

"extensions": The new GroupContext extensions (possibly updated by a GroupContextExtensions proposal) <del> Create an UpdatePath that encrypts the path secrets for the nodes along the sender's filtered direct path to the new ratchet tree, using the provisional GroupContext as context. Any new member (from an Add proposal) MUST be excluded from the resolution during the computation of the UpdatePath. </del> <ins> Encrypt the path secrets resulting from the tree update to the group as described in synchronizing-views-of-the-tree, using the provisional group context as the context for HPKE encryption. </ins> <del> Assign this UpdatePath to the "path" field in the Commit. </del> <ins> Create an UpdatePath containing the sender's new leaf node and the new public keys and encrypted path secrets along the sender's filtered direct path.  Assign this UpdatePath to the "path" field in the Commit. </ins> If not populating the "path" field: Set the "path" field in the Commit to the null optional.  Define "commit_secret" as the all-

Verify that the "encryption_key" value in the LeafNode is different from the committer's current leaf node. <del> Compute parent hashes for the parent nodes in the UpdatePath (relative to the new ratchet tree) and verify that the "parent_hash" field of the leaf node matches the parent hash for the first node its filtered direct path. </del> <ins> Merge the UpdatePath into the new ratchet tree as described in synchronizing-views-of-the-tree. </ins> Construct a provisional GroupContext object containing the following values:

"extensions": The new GroupContext extensions (possibly updated by a GroupContextExtensions proposal) <del> Apply the UpdatePath to the tree, as described in </del> <ins> Decrypt the path secrets for UpdatePath as described in </ins> synchronizing-views-of-the-tree, using the provisional <del> GroupContext when decrypting the path secret and storing "leaf_node" at the committer's leaf. </del> <ins> GroupContext as the context for HPKE decryption. </ins> Define "commit_secret" as the value "path_secret[n+1]" derived from the last path secret value ("path_secret[n]") derived for