<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE rfc [
  <!ENTITY nbsp    "&#160;">
  <!ENTITY zwsp   "&#8203;">
  <!ENTITY nbhy   "&#8209;">
  <!ENTITY wj     "&#8288;">
]>
<?xml-stylesheet type="text/xsl" href="rfc2629.xslt" ?>
<!-- generated by https://github.com/cabo/kramdown-rfc version 1.7.29 (Ruby 3.4.4) -->
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" ipr="trust200902" docName="draft-ietf-keytrans-protocol-02" category="std" consensus="true" submissionType="IETF" tocInclude="true" sortRefs="true" symRefs="true" version="3">
  <!-- xml2rfc v2v3 conversion 3.29.0 -->
  <front>
    <title>Key Transparency Protocol</title>
    <seriesInfo name="Internet-Draft" value="draft-ietf-keytrans-protocol-02"/>
    <author fullname="Brendan McMillion">
      <organization/>
      <address>
        <email>brendanmcmillion@gmail.com</email>
      </address>
    </author>
    <author fullname="Felix Linker">
      <organization/>
      <address>
        <email>linkerfelix@gmail.com</email>
      </address>
    </author>
    <date year="2025" month="July" day="07"/>
    <area>SEC</area>
    <workgroup>KEYTRANS Working Group</workgroup>
    <keyword>key transparency</keyword>
    <abstract>
      <?line 73?>

<t>While there are several established protocols for end-to-end encryption,
relatively little attention has been given to securely distributing the end-user
public keys for such encryption. As a result, these protocols are often still
vulnerable to eavesdropping by active attackers. Key Transparency is a protocol
for distributing sensitive cryptographic information, such as public keys, in a
way that reliably either prevents interference or detects that it occurred in a
timely manner.</t>
    </abstract>
    <note removeInRFC="true">
      <name>About This Document</name>
      <t>
        The latest revision of this draft can be found at <eref target="https://ietf-wg-keytrans.github.io/draft-protocol/draft-ietf-keytrans-protocol.html"/>.
        Status information for this document may be found at <eref target="https://datatracker.ietf.org/doc/draft-ietf-keytrans-protocol/"/>.
      </t>
      <t>
        Discussion of this document takes place on the
        Key Transparency Working Group mailing list (<eref target="mailto:keytrans@ietf.org"/>),
        which is archived at <eref target="https://mailarchive.ietf.org/arch/browse/keytrans/"/>.
        Subscribe at <eref target="https://www.ietf.org/mailman/listinfo/keytrans/"/>.
      </t>
      <t>Source for this draft and an issue tracker can be found at
        <eref target="https://github.com/ietf-wg-keytrans/draft-protocol"/>.</t>
    </note>
  </front>
  <middle>
    <?line 83?>

<section anchor="introduction">
      <name>Introduction</name>
      <t>End-to-end encrypted communication services rely on the secure exchange of
public keys to ensure that messages remain confidential. It is typically assumed
that service providers correctly manage the public keys associated with each
user's account. However, this is not always true. A service provider that is
compromised or malicious can change the public keys associated with a user's
account without their knowledge, thereby allowing the provider to eavesdrop on
and impersonate that user.</t>
      <t>This document describes a protocol that enables a group of users to ensure that
they all have the same view of the public keys associated with each other's
accounts. Ensuring a consistent view allows users to detect when unauthorized
public keys have been associated with their account, indicating a potential
compromise.</t>
      <t>More detailed information about the protocol participants and the ways the
protocol can be deployed can be found in <xref target="ARCH"/>.</t>
    </section>
    <section anchor="conventions-and-definitions">
      <name>Conventions and Definitions</name>
      <t>The key words "<bcp14>MUST</bcp14>", "<bcp14>MUST NOT</bcp14>", "<bcp14>REQUIRED</bcp14>", "<bcp14>SHALL</bcp14>", "<bcp14>SHALL
NOT</bcp14>", "<bcp14>SHOULD</bcp14>", "<bcp14>SHOULD NOT</bcp14>", "<bcp14>RECOMMENDED</bcp14>", "<bcp14>NOT RECOMMENDED</bcp14>",
"<bcp14>MAY</bcp14>", and "<bcp14>OPTIONAL</bcp14>" in this document are to be interpreted as
described in BCP 14 <xref target="RFC2119"/> <xref target="RFC8174"/> when, and only when, they
appear in all capitals, as shown here.</t>
      <?line -18?>

<t>This document uses the TLS presentation language <xref target="RFC8446"/> to describe the
structure of protocol messages, but does not require the use of a specific
transport protocol. As such, implementations do not necessarily need to transmit
messages according to the TLS format and can choose whichever encoding method
best suits their application. However, cryptographic computations <bcp14>MUST</bcp14> be done
with the TLS presentation language format to ensure the protocol's security
properties are maintained.</t>
    </section>
    <section anchor="tree-construction">
      <name>Tree Construction</name>
      <t>A Transparency Log is a verifiable data structure that maps a <em>label-version
pair</em> to some unstructured data such as a cryptographic public key. Labels
correspond to user identifiers, and a new version of a label is created each
time the label's associated value changes.</t>
      <t>KT uses a <em>prefix tree</em> to store a mapping from each label-version pair
to a commitment to the label's value at that version. Every time the prefix
tree changes, its new root hash and the current timestamp are stored in a <em>log
tree</em>. The benefit of the prefix tree is that it is easily searchable and the
benefit of the log tree is that it can easily be verified to be append-only. The
data structure powering KT combines a log tree and a prefix tree, and is called
the <em>combined tree</em>.</t>
      <t>This section describes the operation of prefix trees, log trees, and the
combined tree structure, at a high level. More precise algorithms for computing
the intermediate and root values of the trees are given in
<xref target="cryptographic-computations"/>.</t>
      <section anchor="terminology">
        <name>Terminology</name>
        <t>Trees consist of <em>nodes</em>, which have a byte string as their <em>value</em>. A node is
either a <em>leaf</em> if it has no children, or a <em>parent</em> if it has either a <em>left
child</em> or a <em>right child</em>. A node is the <em>root</em> of a tree if it has no parents,
and an <em>intermediate</em> if it has both children and parents. Nodes are <em>siblings</em>
if they share the same parent.</t>
        <t>The <em>descendants</em> of a node are that node, its children, and the descendants of
its children. A <em>subtree</em> of a tree is the tree given by the descendants of a
particular node, called the <em>head</em> of the subtree.</t>
        <t>The <em>direct path</em> of a root node 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
<em>copath</em> 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.</t>
        <t>The <em>size</em> of a tree or subtree is defined as the number of leaf nodes it
contains.</t>
      </section>
      <section anchor="log-tree">
        <name>Log Tree</name>
        <t>Log trees store information in the chronological order that it was added, and
are constructed as <em>left-balanced</em> binary trees.</t>
        <t>A binary tree is <em>balanced</em> if its size is a power of two and for any parent
node in the tree, its left and right subtrees have the same size. A binary tree
is <em>left-balanced</em> if for every parent, either the parent is balanced, or the
left subtree of that parent is the largest balanced subtree that could be
constructed from the leaves present in the parent's own subtree. Given a list of
<tt>n</tt> items, there is a unique left-balanced binary tree structure with these
elements as leaves. Note also that every parent always has both a left and right
child.</t>
        <figure>
          <name>A log tree containing five leaves.</name>
          <artset>
            <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="256" width="272" viewBox="0 0 272 256" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                <path d="M 144,112 L 144,128" fill="none" stroke="black"/>
                <path d="M 240,48 L 240,64" fill="none" stroke="black"/>
                <path d="M 264,96 L 264,192" fill="none" stroke="black"/>
                <path d="M 160,64 L 248,64" fill="none" stroke="black"/>
                <path d="M 112,128 L 176,128" fill="none" stroke="black"/>
                <path d="M 104,176 L 112,192" fill="none" stroke="black"/>
                <path d="M 176,128 L 184,144" fill="none" stroke="black"/>
                <path d="M 200,176 L 208,192" fill="none" stroke="black"/>
                <path d="M 248,64 L 264,96" fill="none" stroke="black"/>
                <path d="M 80,192 L 88,176" fill="none" stroke="black"/>
                <path d="M 104,144 L 112,128" fill="none" stroke="black"/>
                <path d="M 152,80 L 160,64" fill="none" stroke="black"/>
                <path d="M 176,192 L 184,176" fill="none" stroke="black"/>
                <g class="text">
                  <text x="240" y="36">X</text>
                  <text x="144" y="100">X</text>
                  <text x="96" y="164">X</text>
                  <text x="192" y="164">X</text>
                  <text x="72" y="212">X</text>
                  <text x="120" y="212">X</text>
                  <text x="168" y="212">X</text>
                  <text x="216" y="212">X</text>
                  <text x="264" y="212">X</text>
                  <text x="28" y="244">Index:</text>
                  <text x="72" y="244">0</text>
                  <text x="120" y="244">1</text>
                  <text x="168" y="244">2</text>
                  <text x="216" y="244">3</text>
                  <text x="264" y="244">4</text>
                </g>
              </svg>
            </artwork>
            <artwork type="ascii-art"><![CDATA[
                             X
                             |
                   .---------+.
                  /            \
                 X              |
                 |              |
             .---+---.          |
            /         \         |
           X           X        |
          / \         / \       |
         /   \       /   \      |
        X     X     X     X     X

Index:  0     1     2     3     4
]]></artwork>
          </artset>
        </figure>
        <t>Log trees initially consist of a single leaf node. New leaves are
added to the right-most edge of the tree along with a single parent node to
construct the left-balanced binary tree with <tt>n+1</tt> leaves.</t>
        <figure>
          <name>Example of inserting a new leaf with index 5 into the previously depicted log tree. Observe that only the nodes on the path from the new root to the new leaf change.</name>
          <artset>
            <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="256" width="320" viewBox="0 0 320 256" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                <path d="M 144,112 L 144,128" fill="none" stroke="black"/>
                <path d="M 240,48 L 240,64" fill="none" stroke="black"/>
                <path d="M 288,96 L 288,144" fill="none" stroke="black"/>
                <path d="M 160,64 L 272,64" fill="none" stroke="black"/>
                <path d="M 112,128 L 176,128" fill="none" stroke="black"/>
                <path d="M 104,176 L 112,192" fill="none" stroke="black"/>
                <path d="M 176,128 L 184,144" fill="none" stroke="black"/>
                <path d="M 200,176 L 208,192" fill="none" stroke="black"/>
                <path d="M 296,176 L 304,192" fill="none" stroke="black"/>
                <path d="M 272,64 L 288,96" fill="none" stroke="black"/>
                <path d="M 80,192 L 88,176" fill="none" stroke="black"/>
                <path d="M 104,144 L 112,128" fill="none" stroke="black"/>
                <path d="M 152,80 L 160,64" fill="none" stroke="black"/>
                <path d="M 176,192 L 184,176" fill="none" stroke="black"/>
                <path d="M 272,192 L 280,176" fill="none" stroke="black"/>
                <g class="text">
                  <text x="240" y="36">X</text>
                  <text x="144" y="100">X</text>
                  <text x="96" y="164">X</text>
                  <text x="192" y="164">X</text>
                  <text x="288" y="164">X</text>
                  <text x="72" y="212">X</text>
                  <text x="120" y="212">X</text>
                  <text x="168" y="212">X</text>
                  <text x="216" y="212">X</text>
                  <text x="264" y="212">X</text>
                  <text x="312" y="212">X</text>
                  <text x="28" y="244">Index:</text>
                  <text x="72" y="244">0</text>
                  <text x="120" y="244">1</text>
                  <text x="168" y="244">2</text>
                  <text x="216" y="244">3</text>
                  <text x="264" y="244">4</text>
                  <text x="312" y="244">5</text>
                </g>
              </svg>
            </artwork>
            <artwork type="ascii-art"><![CDATA[
                             X
                             |
                   .---------+---.
                  /               \
                 X                 |
                 |                 |
             .---+---.             |
            /         \            |
           X           X           X
          / \         / \         / \
         /   \       /   \       /   \
        X     X     X     X     X     X

Index:  0     1     2     3     4     5
]]></artwork>
          </artset>
        </figure>
        <t>Leaves can have arbitrary data as their value, and are frequently referred to as
"log entries" later in the document. The value of a parent node is always the
hash of the combined values of its left and right children.</t>
        <t>Log trees are powerful in that they can provide both <em>inclusion proofs</em>, which
demonstrate that a leaf is included in a log, and <em>consistency proofs</em>, which
demonstrate that a new version of a log is an extension of a previous version.</t>
        <t>Inclusion and consistency proofs in KT differ from similar protocols in that
proofs only ever contain the values of nodes that are the head of a balanced
subtree. Whenever the value of the head of a non-balanced subtree is needed by a
verifier, the prover breaks down the non-balanced subtree into the
smallest-possible number of balanced subtrees and provides the value of the head
of each. This allows verifiers to cache a larger number of intermediate values
than would otherwise be possible, reducing the size of subsequent responses.</t>
        <t>As a result, an inclusion proof for a leaf is given by providing the copath
values of the leaf with any non-balanced subtrees broken down as mentioned. The
proof is verified by hashing the leaf value together with the copath values,
re-computing the head values of non-balanced subtrees where needed, and checking
that the result equals the root value of the log.</t>
        <figure>
          <name>Illustration of an inclusion proof. To verify that leaf 2 is included in the tree, the prover provides the verifier with the values of leaf 2's copath. These nodes are marked by (X).</name>
          <artset>
            <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="256" width="320" viewBox="0 0 320 256" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                <path d="M 144,112 L 144,128" fill="none" stroke="black"/>
                <path d="M 240,48 L 240,64" fill="none" stroke="black"/>
                <path d="M 288,96 L 288,144" fill="none" stroke="black"/>
                <path d="M 160,64 L 272,64" fill="none" stroke="black"/>
                <path d="M 112,128 L 176,128" fill="none" stroke="black"/>
                <path d="M 104,176 L 112,192" fill="none" stroke="black"/>
                <path d="M 176,128 L 184,144" fill="none" stroke="black"/>
                <path d="M 200,176 L 208,192" fill="none" stroke="black"/>
                <path d="M 296,176 L 304,192" fill="none" stroke="black"/>
                <path d="M 272,64 L 288,96" fill="none" stroke="black"/>
                <path d="M 80,192 L 88,176" fill="none" stroke="black"/>
                <path d="M 104,144 L 112,128" fill="none" stroke="black"/>
                <path d="M 152,80 L 160,64" fill="none" stroke="black"/>
                <path d="M 176,192 L 184,176" fill="none" stroke="black"/>
                <path d="M 272,192 L 280,176" fill="none" stroke="black"/>
                <g class="text">
                  <text x="240" y="36">X</text>
                  <text x="144" y="100">X</text>
                  <text x="96" y="164">(X)</text>
                  <text x="192" y="164">X</text>
                  <text x="288" y="164">(X)</text>
                  <text x="72" y="212">X</text>
                  <text x="120" y="212">X</text>
                  <text x="168" y="212">X</text>
                  <text x="216" y="212">(X)</text>
                  <text x="264" y="212">X</text>
                  <text x="312" y="212">X</text>
                  <text x="28" y="244">Index:</text>
                  <text x="72" y="244">0</text>
                  <text x="120" y="244">1</text>
                  <text x="168" y="244">2</text>
                  <text x="216" y="244">3</text>
                  <text x="264" y="244">4</text>
                  <text x="312" y="244">5</text>
                </g>
              </svg>
            </artwork>
            <artwork type="ascii-art"><![CDATA[
                             X
                             |
                   .---------+---.
                  /               \
                 X                 |
                 |                 |
             .---+---.             |
            /         \            |
          (X)          X          (X)
          / \         / \         / \
         /   \       /   \       /   \
        X     X     X    (X)    X     X

Index:  0     1     2     3     4     5
]]></artwork>
          </artset>
        </figure>
        <t>When requesting a consistency proof, verifiers are expected to have retained the
head values of the largest-possible balanced subtrees (these will later be
defined as the "full subtrees") of the previous version of the log. A
consistency proof then consists of the minimum set of node values that are
necessary to compute the root value of the new version of the log from the
values that the verifier retained.</t>
        <figure>
          <name>Illustration of a consistency proof between a log with 4 and with 6 leaves respectively. The verifier is expected to already have the values (X), so the prover provides the verifier with the values of the nodes marked [X]. By combining these, the verifier is able to compute the new root value of the log.</name>
          <artset>
            <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="256" width="376" viewBox="0 0 376 256" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                <path d="M 144,112 L 144,128" fill="none" stroke="black"/>
                <path d="M 240,48 L 240,64" fill="none" stroke="black"/>
                <path d="M 336,112 L 336,128" fill="none" stroke="black"/>
                <path d="M 360,160 L 360,192" fill="none" stroke="black"/>
                <path d="M 160,64 L 320,64" fill="none" stroke="black"/>
                <path d="M 112,128 L 176,128" fill="none" stroke="black"/>
                <path d="M 304,128 L 344,128" fill="none" stroke="black"/>
                <path d="M 104,176 L 112,192" fill="none" stroke="black"/>
                <path d="M 176,128 L 184,144" fill="none" stroke="black"/>
                <path d="M 200,176 L 208,192" fill="none" stroke="black"/>
                <path d="M 296,176 L 304,192" fill="none" stroke="black"/>
                <path d="M 344,128 L 360,160" fill="none" stroke="black"/>
                <path d="M 320,64 L 328,80" fill="none" stroke="black"/>
                <path d="M 80,192 L 88,176" fill="none" stroke="black"/>
                <path d="M 104,144 L 112,128" fill="none" stroke="black"/>
                <path d="M 152,80 L 160,64" fill="none" stroke="black"/>
                <path d="M 176,192 L 184,176" fill="none" stroke="black"/>
                <path d="M 272,192 L 280,176" fill="none" stroke="black"/>
                <path d="M 296,144 L 304,128" fill="none" stroke="black"/>
                <g class="text">
                  <text x="240" y="36">X</text>
                  <text x="144" y="100">(X)</text>
                  <text x="336" y="100">X</text>
                  <text x="96" y="164">X</text>
                  <text x="192" y="164">X</text>
                  <text x="288" y="164">X</text>
                  <text x="72" y="212">X</text>
                  <text x="120" y="212">X</text>
                  <text x="168" y="212">X</text>
                  <text x="216" y="212">X</text>
                  <text x="264" y="212">(X)</text>
                  <text x="312" y="212">[X]</text>
                  <text x="360" y="212">[X]</text>
                  <text x="28" y="244">Index:</text>
                  <text x="72" y="244">0</text>
                  <text x="120" y="244">1</text>
                  <text x="168" y="244">2</text>
                  <text x="216" y="244">3</text>
                  <text x="264" y="244">4</text>
                  <text x="312" y="244">5</text>
                  <text x="360" y="244">6</text>
                </g>
              </svg>
            </artwork>
            <artwork type="ascii-art"><![CDATA[
                             X
                             |
                   .---------+---------.
                  /                     \
                (X)                      X
                 |                       |
             .---+---.               .---+.
            /         \             /      \
           X           X           X        |
          / \         / \         / \       |
         /   \       /   \       /   \      |
        X     X     X     X    (X)   [X]   [X]

Index:  0     1     2     3     4     5     6
]]></artwork>
          </artset>
        </figure>
      </section>
      <section anchor="prefix-tree">
        <name>Prefix Tree</name>
        <t>Prefix trees store a mapping between search keys and their corresponding values,
with the ability to efficiently prove that a search key's value was looked up
correctly.</t>
        <t>Each leaf node in a prefix tree represents a specific mapping from search key to
value, while each parent node represents some prefix which all search keys in
the subtree headed by that node have in common. The subtree headed by a parent's
left child contains all search keys that share its prefix followed by an
additional 0 bit, while the subtree headed by a parent's right child contains
all search keys that share its prefix followed by an additional 1 bit.</t>
        <t>The root node, in particular, represents the empty string as a prefix. The
root's left child contains all search keys that begin with a 0 bit, while the right
child contains all search keys that begin with a 1 bit.</t>
        <t>A prefix tree can be searched by starting at the root node and moving to the
left child if the first bit of a search key is 0, or the right child if the first bit
is 1. This is then repeated for the second bit, third bit, and so on until the
search either terminates at a leaf node (which may or may not be for the desired
value), or a parent node that lacks the desired child.</t>
        <figure>
          <name>A prefix tree containing five entries.</name>
          <artset>
            <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="240" width="296" viewBox="0 0 296 240" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                <path d="M 104,112 L 104,144" fill="none" stroke="black"/>
                <path d="M 176,48 L 176,64" fill="none" stroke="black"/>
                <path d="M 240,112 L 240,128" fill="none" stroke="black"/>
                <path d="M 272,160 L 272,192" fill="none" stroke="black"/>
                <path d="M 112,64 L 224,64" fill="none" stroke="black"/>
                <path d="M 216,128 L 256,128" fill="none" stroke="black"/>
                <path d="M 112,176 L 120,192" fill="none" stroke="black"/>
                <path d="M 208,176 L 216,192" fill="none" stroke="black"/>
                <path d="M 224,64 L 232,80" fill="none" stroke="black"/>
                <path d="M 256,128 L 272,160" fill="none" stroke="black"/>
                <path d="M 104,80 L 112,64" fill="none" stroke="black"/>
                <path d="M 88,192 L 96,176" fill="none" stroke="black"/>
                <path d="M 184,192 L 192,176" fill="none" stroke="black"/>
                <path d="M 208,144 L 216,128" fill="none" stroke="black"/>
                <g class="text">
                  <text x="176" y="36">X</text>
                  <text x="104" y="100">0</text>
                  <text x="240" y="100">1</text>
                  <text x="104" y="164">0</text>
                  <text x="200" y="164">0</text>
                  <text x="20" y="212">Key:</text>
                  <text x="80" y="212">00010</text>
                  <text x="128" y="212">00101</text>
                  <text x="176" y="212">10001</text>
                  <text x="224" y="212">10111</text>
                  <text x="272" y="212">11011</text>
                  <text x="28" y="228">Value:</text>
                  <text x="96" y="228">A</text>
                  <text x="144" y="228">B</text>
                  <text x="192" y="228">C</text>
                  <text x="240" y="228">D</text>
                  <text x="288" y="228">E</text>
                </g>
              </svg>
            </artwork>
            <artwork type="ascii-art"><![CDATA[
                     X
                     |
             .-------+-----.
            /               \
            0                1
            |                |
            |             .--+-.
            |            /      \
            0           0        |
           / \         / \       |
          /   \       /   \      |
Key:   00010 00101 10001 10111 11011
Value:     A     B     C     D     E
]]></artwork>
          </artset>
        </figure>
        <t>New key-value pairs are added to the tree by searching it according to the same process.
If the search terminates at a parent without a left or right child, a new leaf
is simply added as the parent's missing child. If the search terminates at a
leaf for the wrong search key, one or more intermediate nodes are added until the new
leaf and the existing leaf would no longer reside in the same place. That is,
until we reach the first bit that differs between the new search key and the existing
search key.</t>
        <figure>
          <name>The previous prefix tree after adding the key-value pair: 01101 -&gt; F.</name>
          <artset>
            <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="240" width="344" viewBox="0 0 344 240" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                <path d="M 144,112 L 144,128" fill="none" stroke="black"/>
                <path d="M 176,160 L 176,192" fill="none" stroke="black"/>
                <path d="M 216,48 L 216,64" fill="none" stroke="black"/>
                <path d="M 288,112 L 288,128" fill="none" stroke="black"/>
                <path d="M 320,160 L 320,192" fill="none" stroke="black"/>
                <path d="M 160,64 L 272,64" fill="none" stroke="black"/>
                <path d="M 120,128 L 160,128" fill="none" stroke="black"/>
                <path d="M 264,128 L 304,128" fill="none" stroke="black"/>
                <path d="M 112,176 L 120,192" fill="none" stroke="black"/>
                <path d="M 160,128 L 176,160" fill="none" stroke="black"/>
                <path d="M 256,176 L 264,192" fill="none" stroke="black"/>
                <path d="M 272,64 L 280,80" fill="none" stroke="black"/>
                <path d="M 304,128 L 320,160" fill="none" stroke="black"/>
                <path d="M 88,192 L 96,176" fill="none" stroke="black"/>
                <path d="M 112,144 L 120,128" fill="none" stroke="black"/>
                <path d="M 152,80 L 160,64" fill="none" stroke="black"/>
                <path d="M 232,192 L 240,176" fill="none" stroke="black"/>
                <path d="M 256,144 L 264,128" fill="none" stroke="black"/>
                <g class="text">
                  <text x="216" y="36">X</text>
                  <text x="144" y="100">0</text>
                  <text x="288" y="100">1</text>
                  <text x="104" y="164">0</text>
                  <text x="248" y="164">0</text>
                  <text x="28" y="212">Index:</text>
                  <text x="80" y="212">00010</text>
                  <text x="128" y="212">00101</text>
                  <text x="176" y="212">01101</text>
                  <text x="224" y="212">10001</text>
                  <text x="272" y="212">10111</text>
                  <text x="320" y="212">11011</text>
                  <text x="28" y="228">Value:</text>
                  <text x="96" y="228">A</text>
                  <text x="144" y="228">B</text>
                  <text x="192" y="228">F</text>
                  <text x="240" y="228">C</text>
                  <text x="288" y="228">D</text>
                  <text x="336" y="228">E</text>
                </g>
              </svg>
            </artwork>
            <artwork type="ascii-art"><![CDATA[
                          X
                          |
                   .------+------.
                  /               \
                 0                 1
                 |                 |
              .--+-.            .--+-.
             /      \          /      \
            0        |        0        |
           / \       |       / \       |
          /   \      |      /   \      |
Index: 00010 00101 01101 10001 10111 11011
Value:     A     B     F     C     D     E
]]></artwork>
          </artset>
        </figure>
        <t>The value of a leaf node is the encoded key-value pair, while the value of a
parent node is the hash of the combined values of its left and right children
(or a stand-in value when one of the children doesn't exist).</t>
        <t>A proof of membership is given by providing the leaf value, along with the
value of each copath entry along the search path. A proof of non-membership
is given by providing an abridged proof of membership that follows the
path for the intended search key, but ends either at a stand-in node or a leaf for a
different search key. In either case, the proof is verified by hashing together the
leaf with the copath hash values and checking that the result equals the root
hash value of the tree.</t>
      </section>
      <section anchor="combined-tree">
        <name>Combined Tree</name>
        <t>Log trees are desirable because they can provide efficient consistency proofs to
convince verifiers that nothing has been removed from a log that was present in a
previous version. However, log trees can't be efficiently searched without
downloading the entire log. Prefix trees are efficient to search and can provide
inclusion proofs to convince verifiers that the returned search results are
correct. However, it's not possible to efficiently prove that a new version of a
prefix tree contains the same data as a previous version with only new values
added.</t>
        <t>In the combined tree structure, based on <xref target="Merkle2"/>, each label-version pair
stored by a Transparency Log corresponds to a search key in a prefix tree. This
prefix tree maps the label-version pair's search key to a commitment to the
label's contents at that version. To allow users to track changes to the prefix
tree, a log tree contains a record of each version of the prefix tree along with
the timestamp of when it was published. With some caveats, this combined
structure supports both efficient consistency proofs and can be efficiently
searched.</t>
        <t>Note that, although the Transparency Log maintains a single logical prefix tree,
each modification of the prefix tree results in a new root value which is then
stored in the log tree. As part of the protocol, the Transparency Log is often
required to perform lookups in different versions of the prefix tree. Different
versions of the prefix tree are identified by the log entry where their root
value was stored.</t>
        <figure>
          <name>An example evolution of the combined tree structure. Every new log entry added contains the timestamp T_n of when it was created and the new prefix tree root hash PT_n.</name>
          <artset>
            <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="112" width="560" viewBox="0 0 560 112" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                <path d="M 72,32 L 72,48" fill="none" stroke="black"/>
                <path d="M 360,32 L 360,48" fill="none" stroke="black"/>
                <path d="M 440,48 L 440,64" fill="none" stroke="black"/>
                <path d="M 40,48 L 112,48" fill="none" stroke="black"/>
                <path d="M 280,48 L 432,48" fill="none" stroke="black"/>
                <path d="M 200,62 L 216,62" fill="none" stroke="black"/>
                <path d="M 200,66 L 216,66" fill="none" stroke="black"/>
                <path d="M 384,64 L 480,64" fill="none" stroke="black"/>
                <path d="M 32,48 L 60,104" fill="none" stroke="black"/>
                <path d="M 112,48 L 128,80" fill="none" stroke="black"/>
                <path d="M 272,48 L 300,104" fill="none" stroke="black"/>
                <path d="M 480,64 L 488,80" fill="none" stroke="black"/>
                <path d="M 4,104 L 32,48" fill="none" stroke="black"/>
                <path d="M 244,104 L 272,48" fill="none" stroke="black"/>
                <path d="M 376,80 L 384,64" fill="none" stroke="black"/>
                <path d="M 4,104 L 60,104" fill="none" stroke="black"/>
                <path d="M 244,104 L 300,104" fill="none" stroke="black"/>
                <polygon class="arrowhead" points="224,64 212,58.4 212,69.6" fill="black" transform="rotate(0,216,64)"/>
                <circle cx="32" cy="48" r="6" class="opendot" fill="white" stroke="black"/>
                <circle cx="72" cy="32" r="6" class="opendot" fill="white" stroke="black"/>
                <circle cx="272" cy="48" r="6" class="opendot" fill="white" stroke="black"/>
                <circle cx="360" cy="32" r="6" class="opendot" fill="white" stroke="black"/>
                <circle cx="440" cy="48" r="6" class="opendot" fill="white" stroke="black"/>
                <g class="text">
                  <text x="104" y="100">(T_n,</text>
                  <text x="152" y="100">PT_n)</text>
                  <text x="344" y="100">(T_n,</text>
                  <text x="392" y="100">PT_n)</text>
                  <text x="464" y="100">(T_n+1,</text>
                  <text x="528" y="100">PT_n+1)</text>
                </g>
              </svg>
            </artwork>
            <artwork type="ascii-art"><![CDATA[
        o                                   o
   o----+----.                   o----------+---------o
  / \         \         ==>     / \            .------+----.
 /   \         |               /   \          /             \
/_____\   (T_n, PT_n)         /_____\   (T_n, PT_n)   (T_n+1, PT_n+1)
]]></artwork>
          </artset>
        </figure>
      </section>
    </section>
    <section anchor="updating-views-of-the-tree">
      <name>Updating Views of the Tree</name>
      <t>As users interact with the Transparency Log over time, they will see many
different root hashes as the contents of the log changes. It's necessary for
users to guarantee that the root hashes they observe are consistent with respect
to two important properties:</t>
      <ul spacing="normal">
        <li>
          <t>If root hash B is shown after root hash A, then root hash B contains all the
same log entries as A with any new log entries added to the rightmost edge of
A.</t>
        </li>
        <li>
          <t>All log entries in the range starting from the rightmost log entry of A and
ending at the rightmost log entry of B, have monotonically increasing
timestamps.</t>
        </li>
      </ul>
      <t>The first property is necessary to ensure that the Transparency Log never
removes a log entry after showing it to a user, as this would allow the
Transparency Log to remove evidence of its own misbehavior. The second property
ensures that all users have a consistent view of when each portion of the tree
was created. As will be discussed in later sections, users rely on log entry
timestamps to decide whether to continue monitoring certain labels and which
portions of the tree to skip when searching. Disagreement on when portions of
the tree were created can cause users to disagree on the value of a
label-version pair, introducing the same security issues as a fork.</t>
      <t>Proving the first property, that the log tree is append-only, can be done by
providing a consistency proof from the log tree. Proving the second property,
that newly added log entries have monotonically increasing timestamps, requires
establishing some additional structure on the log's contents.</t>
      <section anchor="implicit-binary-search-tree">
        <name>Implicit Binary Search Tree</name>
        <t>Intuitively, the leaves of the log tree can be considered a flat array
representation of a binary tree. This structure is similar to the log tree, but
distinguished by the fact that not all parent nodes have two children.</t>
        <figure>
          <name>A binary tree constructed from 14 entries in a log</name>
          <artset>
            <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="256" width="392" viewBox="0 0 392 256" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
                <path d="M 144,112 L 144,128" fill="none" stroke="black"/>
                <path d="M 240,48 L 240,64" fill="none" stroke="black"/>
                <path d="M 336,112 L 336,128" fill="none" stroke="black"/>
                <path d="M 160,64 L 320,64" fill="none" stroke="black"/>
                <path d="M 112,128 L 176,128" fill="none" stroke="black"/>
                <path d="M 304,128 L 368,128" fill="none" stroke="black"/>
                <path d="M 104,176 L 112,192" fill="none" stroke="black"/>
                <path d="M 176,128 L 184,144" fill="none" stroke="black"/>
                <path d="M 200,176 L 208,192" fill="none" stroke="black"/>
                <path d="M 296,176 L 304,192" fill="none" stroke="black"/>
                <path d="M 320,64 L 328,80" fill="none" stroke="black"/>
                <path d="M 368,128 L 376,144" fill="none" stroke="black"/>
                <path d="M 80,192 L 88,176" fill="none" stroke="black"/>
                <path d="M 104,144 L 112,128" fill="none" stroke="black"/>
                <path d="M 152,80 L 160,64" fill="none" stroke="black"/>
                <path d="M 176,192 L 184,176" fill="none" stroke="black"/>
                <path d="M 272,192 L 280,176" fill="none" stroke="black"/>
                <path d="M 296,144 L 304,128" fill="none" stroke="black"/>
                <path d="M 368,192 L 376,176" fill="none" stroke="black"/>
                <g class="text">
                  <text x="240" y="36">X</text>
                  <text x="144" y="100">X</text>
                  <text x="336" y="100">X</text>
                  <text x="96" y="164">X</text>
                  <text x="192" y="164">X</text>
                  <text x="288" y="164">X</text>
                  <text x="384" y="164">X</text>
                  <text x="72" y="212">X</text>
                  <text x="120" y="212">X</text>
                  <text x="168" y="212">X</text>
                  <text x="216" y="212">X</text>
                  <text x="264" y="212">X</text>
                  <text x="312" y="212">X</text>
                  <text x="360" y="212">X</text>
                  <text x="28" y="244">Index:</text>
                  <text x="72" y="244">0</text>
                  <text x="96" y="244">1</text>
                  <text x="120" y="244">2</text>
                  <text x="144" y="244">3</text>
                  <text x="168" y="244">4</text>
                  <text x="192" y="244">5</text>
                  <text x="216" y="244">6</text>
                  <text x="240" y="244">7</text>
                  <text x="264" y="244">8</text>
                  <text x="288" y="244">9</text>
                  <text x="308" y="244">10</text>
                  <text x="332" y="244">11</text>
                  <text x="356" y="244">12</text>
                  <text x="380" y="244">13</text>
                </g>
              </svg>
            </artwork>
            <artwork type="ascii-art"><![CDATA[
                             X
                             |
                   .---------+---------.
                  /                     \
                 X                       X
                 |                       |
             .---+---.               .---+---.
            /         \             /         \
           X           X           X           X
          / \         / \         / \         /
         /   \       /   \       /   \       /
        X     X     X     X     X     X     X

Index:  0  1  2  3  4  5  6  7  8  9 10 11 12 13
]]></artwork>
          </artset>
        </figure>
        <t>The implicit binary search tree containing <tt>n</tt> entries can be defined
inductively. The index of the root log entry in the implicit binary search tree
is the greatest power of two, minus one, that is less than the size of the
implicit binary search tree. That is <tt>i_root = 2^floor(log2(n)) - 1</tt>. The left
subtree is the implicit binary search tree of size <tt>i_root</tt>, i.e., the implicit
binary search tree for all elements with a smaller index than the root. The
right subtree is the implicit binary search tree of size <tt>n-i_root-1</tt>, but
offset with <tt>i_root+1</tt>. Initially, these will be all indices larger than the
root.</t>
        <t>Users ensure that log entry timestamps are monotonic by enforcing that the
structure of this search tree holds. That is, users check that any timestamp
they observe in the root's left subtree is less than or equal to the root's
timestamp, and that any timestamp they observe in the root's right subtree is
greater than or equal to the root's timestamp, and so on recursively. Following
this tree structure ensures that users can detect misbehavior quickly while
minimizing the number of log entries that need to be checked.</t>
        <t>As an example, consider a log with 50 entries. Instead of having the root be the
typical "middle" entry of <tt>50/2 = 25</tt>, the root would be entry 31. As new log
entries are added to the tree's right edge, all users that interact with the
Transparency Log will require log entries to the right of entry 31 to have
timestamps that are greater than or equal to that of entry 31, regardless of how
much or how little the tree grows.</t>
        <t>Because we are often looking at the rightmost log entry, it is frequently useful
to refer to the <strong>frontier</strong> of the log. The frontier consists of the root log
entry, followed by the entries produced by repeatedly moving right until
reaching the last entry of the log. Using the same example of a log with 50
entries, the frontier would be entries: <tt>31, 47, 49</tt>.</t>
        <t>Example code for efficiently navigating the implicit binary search tree is
provided in <xref target="appendix-implicit-search-tree"/>.</t>
      </section>
      <section anchor="update-algorithm">
        <name>Algorithm</name>
        <t>Users retain the following information about the last tree head they've
observed:</t>
        <ol spacing="normal" type="1"><li>
            <t>The size of the log tree (that is, the number of leaves it contained).</t>
          </li>
          <li>
            <t>The head values of the log tree's <strong>full subtrees</strong>. The full subtrees are
the balanced subtrees which are as large as possible, meaning that they do
not have another balanced subtree as their parent.</t>
          </li>
          <li>
            <t>The timestamps of the log entries along the frontier.</t>
          </li>
        </ol>
        <t>When users make queries to the Transparency Log, they advertise the size of the
last tree head they observed. If the Transparency Log responds with an
updated tree head, it first provides a consistency proof to show that the new
tree head is an extension of the previous one. It then also provides the
following:</t>
        <ul spacing="normal">
          <li>
            <t>In the new implicit binary search tree, compute the direct path of the log
entry with index <tt>size-1</tt>, where <tt>size</tt> is the tree size advertised by the
user. Provide the timestamp of each log entry in the direct path whose index
is greater than or equal to <tt>size</tt>.</t>
          </li>
          <li>
            <t>Exactly one of these log entries will lie on the new tree's frontier. From
this log entry, compute the remainder of the frontier. That is, compute the
log entry's right child, the right child's right child, and so on. Provide
the timestamps for these log entries as well.</t>
          </li>
        </ul>
        <t>Users verify that the first timestamp is greater than or equal to the timestamp
of the rightmost log entry they retained, and that each subsequent timestamp is
greater than or equal to the one prior. While this only requires users to verify
a logarithmic number of the newly added log entries' timestamps, it guarantees
that two users with overlapping views of the tree will detect any violations.
While retaining only the rightmost log entry's timestamp would be sufficient for
this purpose, users retain the timestamps of all log entries along the frontier.
The additional timestamps are retained to make later parts of the protocol more
efficient.</t>
        <t>Additionally, the Transparency Log defines two durations: how far ahead and how
far behind the current time the rightmost log entry's timestamp may be. Users
verify this against their local clock.</t>
        <t>For users which have never interacted with the Transparency Log before and don't
have a previous tree head to advertise, the Transparency Log simply provides the
timestamps of the log entries on the frontier. The user verifies each timestamp
is greater than or equal to the one prior, as above.</t>
      </section>
    </section>
    <section anchor="binary-ladder">
      <name>Binary Ladder</name>
      <t>A <strong>binary ladder</strong> is a series of lookups, producing a series of inclusion and
non-inclusion proofs, from a single log entry's prefix tree. The purpose of a
binary ladder varies depending on the exact context in which it is provided, but
it is generally to establish some bound on the greatest version of a label that
existed as of a particular log entry. All binary ladders are variants of the
following series of lookups, which exactly determines the greatest version of a
label that exists:</t>
      <ol spacing="normal" type="1"><li>
          <t>First, version <tt>x</tt> of the label is looked up, where <tt>x</tt> is a consecutively
higher power of two minus one (0, 1, 3, 7, ...). This is repeated until the
first non-inclusion proof is produced.</t>
        </li>
        <li>
          <t>Once the first non-inclusion proof is produced, a binary search is conducted
between the greatest version that was proved to be included, and the version
that was proved to not be included. Each step of the binary search produces
either an inclusion or non-inclusion proof, which guides the search left or
right until it terminates.</t>
        </li>
      </ol>
      <t>As an example, if the greatest version of a label that existed in a particular
log entry was version 6, that would be established by the following: inclusion
proofs for versions 0, 1, 3, a non-inclusion proof for version 7, then followed
by inclusion proofs for versions 5 and 6. This series of lookups uniquely
identifies 6 as the greatest version that exists, in the sense that the
Transparency Log would be unable to prove a different greatest version to any
user.</t>
      <t>While the description above may imply that the series of lookups is interactive,
this is not the case in practice. Users may receive one or more binary ladders,
corresponding to the same or different log entries, in a single query response.
The Transparency Log's query response always contains sufficient information to
allow users to predict the outcome of each lookup (inclusion or non-inclusion of
a particular version) in the binary ladder.</t>
      <t>Example code for computing the versions of a label that go in a binary ladder is
provided in <xref target="appendix-binary-ladder"/>.</t>
    </section>
    <section anchor="fixed-version-searches">
      <name>Fixed-Version Searches</name>
      <t>When searching the combined tree structure described in <xref target="combined-tree"/>, users
perform a binary search for the first log entry where the prefix tree at that
entry contains the target label-version pair. Users reuse the implicit binary
search tree from <xref target="implicit-binary-search-tree"/> for this purpose. This ensures
that all users will check the same or similar entries when searching for the
same label, allowing for efficient user monitoring of the Transparency Log.</t>
      <section anchor="fv-binary-ladder">
        <name>Binary Ladder</name>
        <t>To perform a binary search, users need to be able to inspect individual log
entries and determine whether their search should continue to the left of the
current log entry or the right. Specifically, they need to be able to determine
if the greatest version of their label that was present in some version of the
prefix tree was greater than, equal to, or less than their <strong>target version</strong>.</t>
        <t>This is accomplished by having the Transparency Log provide a binary ladder from
each log entry in the user's search path. Binary ladders provided for the
purpose of a fixed-version search follow the series of lookups described in
<xref target="binary-ladder"/>, but with two optimizations:</t>
        <t>First, the series of lookups ends after the first inclusion proof for a version
greater than or equal to the target version, or the first non-inclusion proof
for a version less than the target version. The additional lookups are
unnecessary, since the user only needs to know whether the greatest version of
the label that existed as of a particular log entry is greater than or less than
their target version -- not its exact value.</t>
        <t>Second, the Transparency Log omits inclusion proofs for any versions of the
label where another inclusion proof for the same version was already provided in
the same query response for a log entry to the left. Similarly, the Transparency
Log omits non-inclusion proofs for any versions of the label where another
non-inclusion proof for the same version was already provided in the same query
response for a log entry to the right. Providing these proofs is unnecessary
since the only possible outcome they could have on the user's binary search
would be to cause it to fail.</t>
      </section>
      <section anchor="maximum-lifetime">
        <name>Maximum Lifetime</name>
        <t>A Transparency Log operator <bcp14>MAY</bcp14> define a maximum lifetime for log entries. If
defined, it <bcp14>MUST</bcp14> be greater than zero milliseconds. Whether a log entry has surpassed
its maximum lifetime is determined by subtracting the timestamp of the rightmost
log entry from the timestamp of the log entry in question and checking if the
result is greater than or equal to the defined duration.</t>
        <t>A user executing a search may arrive at a log entry which is past its maximum
lifetime by either of two ways: The user may have inspected a log entry which is
<strong>not</strong> expired and decided to recurse to the log entry's left child, which is
expired. Alternatively, the root log entry may be expired, in which case the
user would've started their search at an expired root log entry.</t>
        <t>When a user's search proceeds from a log entry which is not expired to a log
entry which is expired, the user is provided with a binary ladder from the
expired log entry as usual. If the user's search would recurse further into the
expired portion of the tree (to the log entry's left child), the search is
aborted. If the user's search would recurse away from the expired portion of the
tree (to the log entry's right child), the user continues as normal.</t>
        <t>When the root and potentially multiple frontier log entries are expired, the
user skips to the furthest-right expired frontier log entry without receiving
binary ladders from any of its parents. Similar to the previous case,
the user is provided with a binary ladder from this log entry. If the user
determines that its search would recurse to the left (further into the expired
portion of the tree), it aborts; to the right (into the unexpired portion of the
tree), it continues.</t>
        <t>This allows the Transparency Log to prune data which is sufficiently old, as
only a small amount of the log tree and prefix tree outside of the maximum
lifetime need to be retained. Specifically, users will still need only a
logarithmic number of log entries that have passed their maximum lifetime,
meaning the rest can be discarded. Pruning is explained in more detail in
<xref target="ARCH"/>.</t>
      </section>
      <section anchor="fv-algorithm">
        <name>Algorithm</name>
        <t>The algorithm for performing a fixed-version search (a search for a specific
version of a label) is described below as a recursive algorithm. It starts with
the root log entry, as defined by the implicit binary search tree, and then
recurses to left or right children, each time starting back at step 1.</t>
        <ol spacing="normal" type="1"><li>
            <t>Verify that the log entry's timestamp is consistent with the timestamps of
all ancestor log entries. That is, if the log entry is in the ancestor's left
subtree, then its timestamp is less than or equal to the ancestor's. If the
log entry is in the ancestor's right subtree, then its timestamp is greater
than or equal to the ancestor's.</t>
          </li>
          <li>
            <t>If the log entry has surpassed its maximum lifetime and is on the frontier,
determine whether its right child has also surpassed its maximum lifetime. If
so, recurse to the right child; otherwise, continue to step 3. Note that a
right child always exists, as the rightmost log entry cannot exceed its
maximum lifetime by definition.</t>
          </li>
          <li>
            <t>Obtain a binary ladder from the current log entry for the target version.
Verify that the binary ladder terminates in a way that is consistent with
previously inspected log entries. Specifically, verify that it indicates a
maximum version greater than or equal to any log entries to the left, and
less than or equal to any log entries to the right.</t>
          </li>
          <li>
            <t>If the binary ladder was terminated early due to a non-inclusion proof for a
version less than or equal the target version, recurse to the log entry's right child.
Otherwise, check if the log entry has surpassed its maximum lifetime. If so,
abort the search with an error indicating that the desired version of the
label has expired and is no longer available. If not, recurse to the log
entry's left child. If, in either case, recursion isn't possible because the
search is at a leaf node:</t>
          </li>
          <li>
            <t>This largely concludes the search. However, there are some additional
technicalities to address. First, it's possible for the binary search to
conclude even if the label-version pair that the user is interested in
doesn't exist or is expired. Out of the log entries touched by the binary
search, identify which log entry was first to contain the desired
label-version pair. If there is no such log entry, or if it is past its
maximum lifetime, abort the search and return an error to the user.</t>
          </li>
          <li>
            <t>It's also possible at this point that a commitment to the contents of the
desired label-version pair has not been provided by the Transparency Log.
This can happen, for example, if multiple versions of a label were inserted
in the same log entry and the binary ladder was terminated early due to an
inclusion proof for a version greater than the target version. If this has
happened, obtain a search proof for the target label-version pair from the
prefix tree in the first log entry to contain it (identified in step 5). If
the search proof shows non-inclusion rather than inclusion, return an error
to the user.</t>
          </li>
        </ol>
        <t>The most important goal of this algorithm is correctly identifying the first log
entry that contains the target label-version pair. The purpose of
doing this is to make monitoring more efficient for the label owner. If a label
has a large number of versions, it can become prohibitively expensive for its
owner to repeatedly check that every single version is represented correctly in
multiple log entries. Instead, the label owner can check that the version was
created correctly in the one log entry where it was first added and then enforce
that binary searches for that version always converge back to that same log
entry.</t>
      </section>
    </section>
    <section anchor="monitoring-the-tree">
      <name>Monitoring the Tree</name>
      <t>As new entries are added to the log tree, the search path that's traversed to
find a specific version of a label may change. New intermediate nodes may be
established between the search root and the log entry, or a new search root may be
created. The goal of monitoring a label is to efficiently ensure that, when
these new parent nodes are created, they're created correctly such that searches
for the same versions of a label continue converging to the same entries in the log.</t>
      <t>Monitoring is performed both by the users that own a label, meaning they are the
authoritative source for the label's content, and the users that lookup a label.
Owners monitor their labels to ensure that past (expected) versions of a label
are still correctly stored in the log and that no new (unexpected) versions have
been added. Users that looked up a label may sometimes need to monitor it
afterwards to ensure that the version they observed isn't later concealed by the
Transparency Log.</t>
      <section anchor="reasonable-monitoring-window">
        <name>Reasonable Monitoring Window</name>
        <t>Label owners <bcp14>MUST</bcp14> monitor their labels regularly, ensuring that past versions of
the label are still correctly represented in the log and that any new versions
of the label are permissible (alerting the user if not). Transparency Logs
define a duration, referred to as the <strong>Reasonable Monitoring
Window</strong> (RMW), which is the frequency with which the Transparency Log generally
expects label owners to perform monitoring. The log entry maximum lifetime, if
defined, <bcp14>MUST</bcp14> be greater than the RMW.</t>
        <t><strong>Distinguished</strong> log entries are chosen according to the algorithm below, such
that there is roughly one per every interval of the RMW. If a user looks up a
label (either through a fixed-version or greatest-version search) and finds that
the first log entry that contains the desired label-version pair is to the right
of the rightmost distinguished log entry, and the Transparency Log is deployed
in Contact Monitoring mode, the user <bcp14>MUST</bcp14> regularly monitor the label-version
pair until its monitoring path intersects a distinguished log entry. That is,
until a new distinguished log entry is established to its right and the two log
entries are verified to be consistent. The purpose of this monitoring is to
ensure that the label-version pair is not removed or obscured by the
Transparency Log before the label owner has had an opportunity to detect it. If
the Transparency Log is deployed with a Third-Party Auditor or Third-Party
Manager, this monitoring is not necessary if the third party is honest. However,
the user <bcp14>MAY</bcp14> still perform it to detect collusion between the Transparency Log
and the third party.</t>
        <t>If a user looks up a label and finds that the first log entry
containing the label-version pair is either a distinguished log entry or to the
left of any distinguished log entry, they do not need to monitor it
afterwards. The only state that would be retained from the query would be the
tree head, as discussed in <xref target="updating-views-of-the-tree"/>.</t>
        <t>"Regular" monitoring <bcp14>SHOULD</bcp14> be performed at least as frequently as the RMW and
<bcp14>MUST</bcp14>, if at all possible, happen more frequently than the log entry maximum
lifetime.</t>
      </section>
      <section anchor="distinguished-log-entries">
        <name>Distinguished Log Entries</name>
        <t>Distinguished log entries are chosen according to the following recursive
algorithm:</t>
        <ol spacing="normal" type="1"><li>
            <t>Take as input: a log entry, the timestamp of a log entry to its left, and the
timestamp of a log entry to its right.</t>
          </li>
          <li>
            <t>If the right timestamp minus the left timestamp is less than the Reasonable
Monitoring Window, terminate the algorithm. Otherwise, declare that the given
log entry is distinguished.</t>
          </li>
          <li>
            <t>If the given log entry has a left child in the implicit binary search tree,
then recurse to its subtree by executing this algorithm with: the given log
entry's left child, the given left timestamp, and the timestamp of the given
log entry.</t>
          </li>
          <li>
            <t>If the given log entry has a right child, then recurse to its right subtree
by executing this algorithm with: the given log entry's right child, the
timestamp of the given log entry, and the given right timestamp.</t>
          </li>
        </ol>
        <t>The algorithm is initialized with these parameters: the
root node in the implicit binary search tree, the timestamp 0, and the timestamp
of the rightmost log entry. Note that step 2 is specifically "less than" and not
"less than or equal to"; this ensures correct behavior when the RMW is zero.</t>
        <t>This process for choosing distinguished log entries ensures that they are
<strong>regularly spaced</strong>. Having irregularly spaced distinguished log entries risks
either overwhelming label owners with a large number of them, or delaying
consensus between users by having arbitrarily few. Distinguished log entries
must reliably occur at roughly the same interval as the Reasonable Monitoring
Window regardless of variations in how quickly new log entries are added.</t>
        <t>This process also ensures that distinguished log entries are <strong>stable</strong>. Once a
log entry is chosen to be distinguished, it will never stop being distinguished.
This is important because it means that, if a user looks up a label and checks
consistency with some distinguished log entry, this log entry can't later avoid
inspection by the label owner by losing its distinguished status.</t>
      </section>
      <section anchor="monitor-binary-ladder">
        <name>Binary Ladder</name>
        <t>Similar to the algorithm for searching the tree, the algorithm for monitoring
the tree requires a way to prove that the greatest version of a label stored in
a particular log entry's prefix tree is greater than or equal to a <strong>target
version</strong>. The target version in this case is the version of the label that the
user is monitoring. Unlike in a search though, users already know that the
target version of the label exists and only need proof that there has not been
an unexpected downgrade.</t>
        <t>Binary ladders provided for the purpose of monitoring follow the series of
lookups that would be made by the algorithm in <xref target="binary-ladder"/> if the target
version of the label was the greatest that existed. Note that this means the
series of lookups performed is always the same for the same target version,
regardless of whatever the actual greatest version of the label is. From this
series of lookups, two optimizations are made:</t>
        <t>First, any lookup for a version greater than the target version is omitted. As a
result, all lookups in the binary ladder will result in an inclusion proof if
the Transparency Log is behaving honestly.</t>
        <t>Second, any lookup that would be omitted from a binary ladder for the log entry
when executing a fixed-version or greatest-version search for the label-version
pair is also omitted here. That is, when preparing a binary ladder for a log
entry, the Transparency Log considers the log entries that are in its direct
path and to its left. If, during a search for the label-version pair being
monitored, the user would receive an inclusion proof for some version <tt>v</tt> from
one of these log entries, then the lookup for version <tt>v</tt> is omitted.</t>
      </section>
      <section anchor="m-algorithm">
        <name>Algorithm</name>
        <t>To monitor a given label, users maintain a small amount of state: a map from a
position in the log to a version counter. The version counter is the greatest
version of the label that's been proved to exist at that log position. Users
initially populate this map by setting the position of the first log entry to
contain the label-version pair they've looked up to map to that version. A map
may track several different versions of a label simultaneously if a user has
been shown different versions of the same label.</t>
        <t>To update this map, users receive the most recent tree head from the server and
follow these steps for each entry in the map, from rightmost to leftmost log
entry:</t>
        <ol spacing="normal" type="1"><li>
            <t>Determine if the log entry is distinguished. If so, leave
the position-version pair in the map and move on to the next map entry.</t>
          </li>
          <li>
            <t>Compute the ordered list of log entries to inspect:
            </t>
            <ol spacing="normal" type="1"><li>
                <t>Initialize the list by setting it to be the log entry's direct path in the
implicit binary search tree based on the current tree size.</t>
              </li>
              <li>
                <t>Remove all entries that are to the left of the log entry.</t>
              </li>
              <li>
                <t>If any of the remaining log entries are distinguished, terminate the list
just after the first distinguished log entry.</t>
              </li>
            </ol>
          </li>
          <li>
            <t>If the computed list is empty, leave the position-version pair in the map
and move on to the next map entry.</t>
          </li>
          <li>
            <t>For each log entry in the computed list, from left to right:
            </t>
            <ol spacing="normal" type="1"><li>
                <t>Check if a binary ladder for this log entry was already provided in the
same query response. If so:
                </t>
                <ol spacing="normal" type="1"><li>
                    <t>If the previously provided binary ladder had a greater target version
than the current map entry, then this version of the label no longer
needs to be monitored. Remove the position-version pair with the
the lesser version from the map and move on to the next map
entry.</t>
                  </li>
                  <li>
                    <t>If it had a version less than or equal to that of the current map
entry, terminate and return an error to the user.</t>
                  </li>
                </ol>
              </li>
              <li>
                <t>Receive and verify a binary ladder from this log entry where the target
version is the version currently in the map. This proves that, at the
indicated log entry, the greatest version present is greater than or equal
to the previously observed version.</t>
              </li>
              <li>
                <t>If the above check fails, terminate and return an error to the user.
Otherwise, remove the current position-version pair from the map and
replace it with a new one for the position of the log entry that the
binary ladder came from.</t>
              </li>
            </ol>
          </li>
        </ol>
        <t>Once the map entries are updated according to this process, the final step of
monitoring is to remove all mappings where the position corresponds to a
distinguished log entry. All remaining entries will be non-distinguished log
entries lying on the log's frontier.</t>
        <t>In summary, monitoring works by progressively moving up the tree as new
intermediate/root nodes are established and verifying that they're constructed
correctly. Once a distinguished log entry is reached and successfully verified,
monitoring is no longer necessary and the relevant entry is removed from the
map.</t>
        <t>Users will often be able to execute the monitoring process, at least partially,
with the output of a fixed-version or greatest-version search for the label.
This may reduce the need for monitoring-specific requests. It is also worth
noting that the work required to monitor several versions of the same label
scales sublinearly because the direct paths of the different versions will often
intersect. Intersections reduce the total number of entries in the map and
therefore the amount of work that will be needed to monitor the label from then
on.</t>
        <section anchor="owner-algorithm">
          <name>Owner Algorithm</name>
          <t>If the user owns the label being monitored, they will additionally need to
retain the rightmost distinguished log entry where they've verified that the
greatest version of the label is correct. Users advertise this log entry's
position in their Monitor request. For a number of subsequent distinguished log
entries, the Transparency Log provides the greatest version of the label that
the log entry's prefix tree contains, along with a binary ladder (according to
the rules stated in <xref target="gv-binary-ladder"/>) to prove that this is correct.</t>
          <t>Users verify that the version has not unexpectedly increased or decreased.
Importantly, users also verify that they receive a binary ladder for the
distinguished log entry immediately following the one they've advertised, the
distinguished log entry immediately following that one, and so on. The
Transparency Log provides whichever intermediate timestamps are necessary to
demonstrate that this is the case. To avoid excessive load, the Transparency Log
<bcp14>SHOULD</bcp14> limit the number of distinguished log entries it provides binary ladders
for in a single response.</t>
          <t>If a user is monitoring the label for the first time since it was created, they
advertise the first log entry to contain the label even if it is not known to be
distinguished. The Transparency Log provides binary ladders for subsequent
distinguished log entries.</t>
        </section>
      </section>
    </section>
    <section anchor="greatest-version-searches">
      <name>Greatest-Version Searches</name>
      <t>Users often wish to search for the "most recent" version, or the greatest
version, of a label. Unlike searches for a specific version, label owners
regularly verify that the greatest version is correctly represented in the
log. This enables a simpler, more efficient approach to searching.</t>
      <t><xref target="distinguished-log-entries"/> defines the
concept of a distinguished log entry, which is any log entry that label owners
are required to check for correctness. As a result, users can start their search
at the rightmost distinguished log entry and only consider new versions which
have been created since then. The rightmost distinguished log entry will always
be on the frontier of the log and will never be past its maximum lifetime.</t>
      <section anchor="gv-binary-ladder">
        <name>Binary Ladder</name>
        <t>One special consideration for a greatest-version search is that the Transparency
Log must prove that it is revealing the absolute greatest version of a label
that exists, referred to as the <strong>target version</strong>. This differs from the binary
ladders described for fixed-version searches (<xref target="fv-binary-ladder"/>) and
monitoring (<xref target="monitor-binary-ladder"/>), which only aim to prove a lower
bound on the greatest version.</t>
        <t>Binary ladders provided for the purpose of a greatest-version search follow the
series of lookups described in <xref target="binary-ladder"/>, with two optimizations:</t>
        <t>First, the series of lookups ends after the first non-inclusion proof for a
version less than the target version. This differs from <xref target="fv-binary-ladder"/> in
that the binary ladder algorithm will continue even after receiving an inclusion
proof for a version equal to the target version. This is often necessary to
demonstrate that there are no versions greater than the target version.</t>
        <t>Second, depending on whether the binary ladder is for a distinguished or
non-distinguished log entry:</t>
        <ul spacing="normal">
          <li>
            <t>If the log entry is non-distinguished:
            </t>
            <ul spacing="normal">
              <li>
                <t>An inclusion proof for a version is omitted if an inclusion proof for the
same version has already been provided in the same query response from a log
entry to the left.</t>
              </li>
              <li>
                <t>A non-inclusion proof for a version is omitted if a non-inclusion proof for
the same version has already been provided in the same query response from a
log entry to the right.</t>
              </li>
            </ul>
          </li>
          <li>
            <t>If the log entry is distinguished:
            </t>
            <ul spacing="normal">
              <li>
                <t>An inclusion or non-inclusion proof for a version is omitted only if it has
previously been provided in the same query response for the same log entry.
This may happen if the binary ladder is provided in a Monitor query response
and the user owns the label being monitored.</t>
              </li>
            </ul>
          </li>
        </ul>
      </section>
      <section anchor="algorithm">
        <name>Algorithm</name>
        <t>The algorithm for performing a greatest-version search (a search for the
greatest version of a label) is described below as a recursive algorithm. It
starts at the rightmost distinguished log entry, or the root of the implicit
binary search tree if there are no distinguished log entries, and then recurses
down the remainder of the frontier, each time starting back at step 1:</t>
        <ol spacing="normal" type="1"><li>
            <t>Obtain a binary ladder from the current log entry for the target version. If
this is not the starting log entry, verify that the binary ladder indicates a
maximum version greater than or equal to that of its parent log entry.</t>
          </li>
          <li>
            <t>If this is the rightmost log entry, verify the binary ladder terminates in a
way that proves the target version to be the greatest that exists. This means
that it does not terminate early, all lookups for versions less than or equal
to the target version produce inclusion proofs, and all lookups for versions
greater than the target version produce non-inclusion proofs.</t>
          </li>
          <li>
            <t>If this is not the rightmost log entry, recurse to the current log entry's
right child.</t>
          </li>
        </ol>
        <t>If the starting log entry was not distinguished or if the starting log entry did
not contain the greatest version of the label, note that the user may be
obligated to monitor the label in the future per
<xref target="reasonable-monitoring-window"/>.</t>
      </section>
    </section>
    <section anchor="cryptographic-computations">
      <name>Cryptographic Computations</name>
      <section anchor="cipher-suites">
        <name>Cipher Suites</name>
        <t>Each Transparency Log uses a single fixed cipher suite, chosen when it is
initially created, that specifies the following primitives and parameters for
cryptographic computations:</t>
        <ul spacing="normal">
          <li>
            <t>A hash algorithm</t>
          </li>
          <li>
            <t>A signature algorithm</t>
          </li>
          <li>
            <t>A Verifiable Random Function (VRF) algorithm</t>
          </li>
          <li>
            <t><tt>Nc</tt>: The size in bytes of commitment openings</t>
          </li>
          <li>
            <t><tt>Kc</tt>: A fixed string of bytes used in the computation of commitments</t>
          </li>
        </ul>
        <t>The hash algorithm is used to calculate intermediate and root values of
hash trees. The signature algorithm is used for signatures from both the service
operator and the third party, if one is present. The VRF is used for preserving
the privacy of labels. One of the VRF algorithms from <xref target="RFC9381"/> must be
used.</t>
        <t>Cipher suites are represented with the CipherSuite type. The cipher suites are
defined in <xref target="kt-cipher-suites"/>.</t>
      </section>
      <section anchor="tree-head-signature">
        <name>Tree Head Signature</name>
        <t>The head of a Transparency Log, which represents its most recent state, is
encoded as:</t>
        <sourcecode type="tls-presentation"><![CDATA[
struct {
  uint64 tree_size;
  opaque signature<0..2^16-1>;
} TreeHead;
]]></sourcecode>
        <t>where <tt>tree_size</tt> is the number of log entries. If the
Transparency Log is deployed with Third-Party Management, then the public key
used to verify the signature belongs to the Third-Party Manager; otherwise the
public key used belongs to the Service Operator.</t>
        <t>The signature itself is computed over a <tt>TreeHeadTBS</tt> structure, which
incorporates the log's current state as well as long-term log configuration:</t>
        <sourcecode type="tls-presentation"><![CDATA[
enum {
  reserved(0),
  contactMonitoring(1),
  thirdPartyManagement(2),
  thirdPartyAuditing(3),
  (255)
} DeploymentMode;

struct {
  CipherSuite ciphersuite;
  DeploymentMode mode;
  opaque signature_public_key<0..2^16-1>;
  opaque vrf_public_key<0..2^16-1>;

  select (Configuration.mode) {
    case contactMonitoring:
    case thirdPartyManagement:
      opaque leaf_public_key<0..2^16-1>;
    case thirdPartyAuditing:
      uint64 max_auditor_lag;
      uint64 auditor_start_pos;
      opaque auditor_public_key<0..2^16-1>;
  };

  uint64 max_ahead;
  uint64 max_behind;
  uint64 reasonable_monitoring_window;
  optional<uint64> maximum_lifetime;
} Configuration;

struct {
  Configuration config;
  uint64 tree_size;
  opaque root[Hash.Nh];
} TreeHeadTBS;
]]></sourcecode>
        <t>The <tt>ciphersuite</tt> field contains the cipher suite for the Transparency Log,
chosen from the registry in <xref target="kt-cipher-suites"/>. The <tt>mode</tt> field specifies
whether the Transparency Log is deployed in Contact Monitoring mode or with a
Third-Party Manager or Auditor. The <tt>signature_public_key</tt> field contains the
public key to use for verifying signatures on the <tt>TreeHeadTBS</tt> structure. The
<tt>vrf_public_key</tt> field contains the VRF public key to use for evaluating the VRF
proofs provided in the <tt>BinaryLadderStep.proof</tt> field described in <xref target="search"/>.</t>
        <t>If the deployment mode specifies a Third-Party Manager, a public key is provided
in <tt>leaf_public_key</tt>. This public key is used to verify the Service Operator's
signature on modifications to the Transparency Log, as described in
<xref target="update-format"/>.</t>
        <t>If the deployment mode specifies a Third-Party Auditor, the maximum amount of
time in milliseconds that the auditor may lag behind the most recent version of
the Transparency Log is provided in <tt>max_auditor_lag</tt>. The position of the first
log entry that the auditor started processing is provided in
<tt>auditor_start_pos</tt>. A public key for verifying the auditor's signature on views
of the Transparency Log is provided in <tt>auditor_public_key</tt>.</t>
        <t>The <tt>max_ahead</tt> and <tt>max_behind</tt> fields contain the maximum amount of time in
milliseconds that a tree head may be ahead of or behind the user's local clock
without being rejected. The <tt>reasonable_monitoring_window</tt> contains the
Reasonable Monitoring Window, defined in <xref target="reasonable-monitoring-window"/>, in
milliseconds. If the Transparency Log has chosen to define a maximum lifetime
for log entries, per <xref target="maximum-lifetime"/>, this duration in milliseconds is
stored in the <tt>maximum_lifetime</tt> field.</t>
        <t>Finally, the <tt>root</tt> field contains the root value of the log tree with
<tt>tree_size</tt> leaves. <tt>Hash.Nh</tt> is the output size of the cipher suite's
hash function in bytes.</t>
      </section>
      <section anchor="auditor-tree-head-signature">
        <name>Auditor Tree Head Signature</name>
        <t>In deployment scenarios where a Third-Party Auditor is present, the auditor's
view of the Transparency Log is presented to users with an <tt>AuditorTreeHead</tt>
structure:</t>
        <sourcecode type="tls-presentation"><![CDATA[
struct {
  uint64 timestamp;
  uint64 tree_size;
  opaque signature<0..2^16-1>;
} AuditorTreeHead;
]]></sourcecode>
        <t>Users verify an <tt>AuditorTreeHead</tt> with the following steps:</t>
        <ol spacing="normal" type="1"><li>
            <t>If the user advertised a previously observed tree size in their request,
verify that the advertised tree size is greater than or equal to
<tt>Configuration.auditor_start_pos</tt>.</t>
          </li>
          <li>
            <t>Verify that the timestamp of the rightmost log entry is greater than or equal
to <tt>timestamp</tt>, and that the difference between the two is less than or equal
to <tt>Configuration.max_auditor_lag</tt>.</t>
          </li>
          <li>
            <t>Verify that <tt>tree_size</tt> is less than or equal to that of the <tt>TreeHead</tt>
provided by the Transparency Log.</t>
          </li>
          <li>
            <t>Verify <tt>signature</tt> as a signature over the <tt>AuditorTreeHeadTBS</tt> structure:</t>
          </li>
        </ol>
        <sourcecode type="tls-presentation"><![CDATA[
struct {
  Configuration config;
  uint64 timestamp;
  uint64 tree_size;
  opaque root[Hash.Nh];
} AuditorTreeHeadTBS;
]]></sourcecode>
        <t>The <tt>config</tt> field contains the long-term configuration for the Transparency
Log. The <tt>timestamp</tt> and <tt>tree_size</tt> fields match that of <tt>AuditorTreeHead</tt>. The
<tt>root</tt> field contains the value of the root node of the log tree when it had
<tt>tree_size</tt> leaves.</t>
      </section>
      <section anchor="full-tree-head-verification">
        <name>Full Tree Head Verification</name>
        <t>Tree heads are presented to users on the wire as follows:</t>
        <sourcecode type="tls-presentation"><![CDATA[
enum {
  reserved(0),
  same(1),
  updated(2),
} FullTreeHeadType;

struct {
  FullTreeHeadType head_type;
  select (FullTreeHead.head_type) {
    case updated:
      TreeHead tree_head;
      select (Configuration.mode) {
        case thirdPartyAuditing:
          AuditorTreeHead auditor_tree_head;
      };
  };
} FullTreeHead;
]]></sourcecode>
        <t>The <tt>head_type</tt> field may be set to <tt>same</tt> if the user advertised a previously
observed tree size in their request and the Transparency Log wishes to continue
using this same tree head. Otherwise, <tt>head_type</tt> is set to <tt>updated</tt> and a new,
more recent tree head is provided.</t>
        <t>Users verify a <tt>FullTreeHead</tt> with the following steps:</t>
        <ol spacing="normal" type="1"><li>
            <t>If <tt>head_type</tt> is <tt>same</tt>, verify that the user advertised a previously
observed tree size and that the rightmost log entry of this tree is still
within the bounds set by <tt>max_ahead</tt> and <tt>max_behind</tt>.</t>
          </li>
          <li>
            <t>If <tt>head_type</tt> is <tt>updated</tt>:
            </t>
            <ol spacing="normal" type="1"><li>
                <t>If the user advertised a previously observed tree size, verify that
<tt>TreeHead.tree_size</tt> is greater than the advertised tree size.</t>
              </li>
              <li>
                <t>Verify <tt>TreeHead.signature</tt> as a signature over the <tt>TreeHeadTBS</tt>
structure.</t>
              </li>
              <li>
                <t>If there is a Third-Party Auditor, verify <tt>auditor_tree_head</tt> as described
in <xref target="auditor-tree-head-signature"/>.</t>
              </li>
            </ol>
          </li>
        </ol>
      </section>
      <section anchor="update-format">
        <name>Update Format</name>
        <t>The leaves of the prefix tree contain commitments which open to the value of a
label-version pair, potentially with some additional information depending on
the deployment mode of the Transparency Log. The contents of these commitments
is serialized as follows:</t>
        <sourcecode type="tls-presentation"><![CDATA[
struct {
  select (Configuration.mode) {
    case thirdPartyManagement:
      opaque signature<0..2^16-1>;
  };
} UpdatePrefix;

struct {
  UpdatePrefix prefix;
  opaque value<0..2^32-1>;
} UpdateValue;
]]></sourcecode>
        <t>The <tt>value</tt> field contains the value associated with the label-version pair.</t>
        <t>In the event that Third-Party Management is used, the <tt>prefix</tt> field contains a
signature from the Service Operator, using the public key from
<tt>Configuration.leaf_public_key</tt>, over the following structure:</t>
        <sourcecode type="tls-presentation"><![CDATA[
struct {
  opaque label<0..2^8-1>;
  uint32 version;
  opaque value<0..2^32-1>;
} UpdateTBS;
]]></sourcecode>
        <t>The <tt>value</tt> field contains the same contents as <tt>UpdateValue.value</tt>. Users
<bcp14>MUST</bcp14> successfully verify this signature before consuming <tt>UpdateValue.value</tt>.</t>
      </section>
      <section anchor="commitment">
        <name>Commitment</name>
        <t>Commitments are computed with HMAC <xref target="RFC2104"/> using the hash function
specified by the cipher suite. To produce a new commitment, the application
generates a random <tt>Nc</tt>-byte value called <tt>opening</tt> and computes:</t>
        <sourcecode type="pseudocode"><![CDATA[
commitment = HMAC(Kc, CommitmentValue)
]]></sourcecode>
        <t>where <tt>Kc</tt> is a string of bytes defined by the cipher suite and CommitmentValue
is specified as:</t>
        <sourcecode type="tls-presentation"><![CDATA[
struct {
  opaque opening[Nc];
  opaque label<0..2^8-1>;
  UpdateValue update;
} CommitmentValue;
]]></sourcecode>
        <t>The output value <tt>commitment</tt> may be published, while <tt>opening</tt> should only be
revealed to users that are authorized to receive the label's contents.</t>
        <t>The Transparency Log <bcp14>MAY</bcp14> generate <tt>opening</tt> in a non-random way, such as
deriving it from a secret key, as long as the result is indistinguishable from
random to other participants. The Transparency Log <bcp14>SHOULD</bcp14> ensure that individual
<tt>opening</tt> values can later be deleted in a way where they can not feasibly be
recovered. This preserves the Transparency Log's ability to delete certain
information in compliance with privacy laws.</t>
      </section>
      <section anchor="verifiable-random-function">
        <name>Verifiable Random Function</name>
        <t>Each label-version pair corresponds to a unique search key in the prefix tree.
This search key is the output of executing the VRF, with the private key
corresponding to <tt>Configuration.vrf_public_key</tt>, on the combined label and
version:</t>
        <sourcecode type="tls-presentation"><![CDATA[
struct {
  opaque label<0..2^8-1>;
  uint32 version;
} VrfInput;
]]></sourcecode>
      </section>
      <section anchor="crypto-log-tree">
        <name>Log Tree</name>
        <t>The value of a leaf node in the log tree is computed as the hash, with the
cipher suite hash function, of the following structure:</t>
        <sourcecode type="tls-presentation"><![CDATA[
struct {
  uint64 timestamp;
  opaque prefix_tree[Hash.Nh];
} LogLeaf;
]]></sourcecode>
        <t>The <tt>timestamp</tt> field contains the timestamp that the leaf was created in
milliseconds since the Unix epoch. The <tt>prefix_tree</tt> field contains the updated
root hash of the prefix tree after making any desired modifications.</t>
        <t>The value of a parent node in the log tree is computed by hashing together the
values of its left and right children:</t>
        <sourcecode type="pseudocode"><![CDATA[
parent.value = Hash(hashContent(parent.leftChild) ||
                    hashContent(parent.rightChild))

hashContent(node):
  if node.type == leafNode:
    return 0x00 || node.value
  else if node.type == parentNode:
    return 0x01 || node.value
]]></sourcecode>
        <t>where <tt>Hash</tt> denotes the cipher suite hash function.</t>
      </section>
      <section anchor="prefix-tree-1">
        <name>Prefix Tree</name>
        <t>The value of a leaf node in the prefix tree is computed as the hash, with the
cipher suite hash function, of the following structure:</t>
        <sourcecode type="tls"><![CDATA[
struct {
    opaque vrf_output[VRF.Nh];
    opaque commitment[Hash.Nh];
} PrefixLeaf;
]]></sourcecode>
        <t>The <tt>vrf_output</tt> field contains the VRF output for the label-version pair.
<tt>VRF.Nh</tt> denotes the output size of the cipher suite VRF in bytes. The
<tt>commitment</tt> field contains the commitment to the corresponding <tt>UpdateValue</tt>
structure.</t>
        <t>The value of a parent node in the prefix tree is computed by hashing together
the values of its left and right children:</t>
        <sourcecode type="pseudocode"><![CDATA[
parent.value = Hash(hashContent(parent.leftChild) ||
                    hashContent(parent.rightChild))

hashContent(node):
  if node.type == emptyNode:
    return 0 // all-zero vector of length Hash.Nh+1
  else if node.type == leafNode:
    return 0x01 || node.value
  else if node.type == parentNode:
    return 0x02 || node.value
]]></sourcecode>
      </section>
    </section>
    <section anchor="tree-proofs">
      <name>Tree Proofs</name>
      <section anchor="log-tree-1">
        <name>Log Tree</name>
        <t>In the interest of efficiency, KT combines multiple inclusion proofs and
consistency proofs into a single batch proof. Recalling from the discussion in
<xref target="log-tree"/>,</t>
        <ul spacing="normal">
          <li>
            <t>Whenever the Transparency Log serves an inclusion proof for a leaf of the log tree,
it provides the minimum set of head values from balanced subtrees
that would allow the user to compute the root hash from the leaf's value.</t>
          </li>
          <li>
            <t>Whenever the Transparency Log serves a consistency proof, the user is expected to have
retained the head values of the full subtrees of the previous version of the
log. The Transparency Log provides the minimum set of head values from
balanced subtrees that would allow the user to compute the root hash from
their retained values.</t>
          </li>
        </ul>
        <t>These two proof types are composed together as such: considering the leaf values
which will be proved included, and any node values the user is understood to
have retained, the Transparency Log provides the minimum set of head values from
balanced subtrees that would allow the user to compute the root hash from the
leaf and retained values. This proof is encoded as follows:</t>
        <sourcecode type="tls-presentation"><![CDATA[
opaque NodeValue[Hash.Nh];

struct {
  NodeValue elements<0..2^16-1>;
} InclusionProof;
]]></sourcecode>
        <t>The contents of the <tt>elements</tt> array is in left-to-right order: if a node is
present in the root's left subtree then its value is listed before the values of
any nodes in the root's right subtree, and so on recursively.</t>
        <t>Batching together inclusion and consistency proofs creates an edge case that
requires special care: when a user has requested a consistency proof, and also
requested inclusion proofs for leaves located in one or more of the subtrees
that the user has retained the head of. When this happens, the portion of the
batch proof that shows inclusion for the leaves in these subtrees will itself be
sufficient to recompute the retained head values. This makes the retained values
redundant for the purpose of computing the new root hash, which could result in
the retained values being disregarded in a naive implementation. To avoid
accepting invalid proofs, users <bcp14>MUST</bcp14> verify that the computed value for the head
of any such subtree matches the retained value.</t>
      </section>
      <section anchor="prefix-tree-2">
        <name>Prefix Tree</name>
        <t>A proof from a prefix tree authenticates that a search was done correctly for a
given search key. Such a proof is encoded as:</t>
        <sourcecode type="tls"><![CDATA[
enum {
  reserved(0),
  inclusion(1),
  nonInclusionLeaf(2),
  nonInclusionParent(3),
  (255)
} PrefixSearchResultType;

struct {
  PrefixSearchResultType result_type;
  select (PrefixSearchResult.result_type) {
    case nonInclusionLeaf:
      PrefixLeaf leaf;
  };
  uint8 depth;
} PrefixSearchResult;

struct {
  PrefixSearchResult results<0..2^8-1>;
  NodeValue elements<0..2^16-1>;
} PrefixProof;
]]></sourcecode>
        <t>The <tt>results</tt> field contains the search result for each individual value. Every
index corresponds to the respectively indexed binary ladder step targeting the
queried version. The <tt>result_type</tt> field of each <tt>PrefixSearchResult</tt> struct
indicates what the terminal node of the search for that value was:</t>
        <ul spacing="normal">
          <li>
            <t><tt>inclusion</tt> for a leaf node matching the requested value.</t>
          </li>
          <li>
            <t><tt>nonInclusionLeaf</tt> for a leaf node not matching the requested value. In this
case, the terminal node's value is provided since it can not be inferred.</t>
          </li>
          <li>
            <t><tt>nonInclusionParent</tt> for a parent node that lacks the desired child.</t>
          </li>
        </ul>
        <t>The <tt>depth</tt> field indicates the depth of the terminal node of the search, and is
provided to assist proof verification. The root node of the prefix tree
corresponds to a depth of 0, the root's children correspond to a depth of 1, and
so on recursively.</t>
        <t>The <tt>elements</tt> array consists of the fewest node values that can be hashed
together with the provided leaves to produce the root. The contents of the
<tt>elements</tt> array is kept in left-to-right order: if a node is present in the
root's left subtree, its value must be listed before any values provided from
nodes that are in the root's right subtree, and so on recursively. In the event
that a node is not present, an all-zero byte string of length <tt>Hash.Nh</tt> is
listed instead.</t>
        <t>The proof is verified by hashing together the provided elements, in the
left/right arrangement dictated by the bits of the search keys, and checking
that the result equals the root value of the prefix tree.</t>
      </section>
      <section anchor="proof-combined-tree">
        <name>Combined Tree</name>
        <t>As users execute the algorithms for searching, monitoring, or updating their
view of the tree, they inspect a series of log entries. For some of
these, only the timestamp of the log entry is needed. For others,
both the timestamp and a <tt>PrefixProof</tt> from the log entry's prefix tree are
needed.</t>
        <t>This subsection defines a general structure, called a <tt>CombinedTreeProof</tt>, that
contains the minimum set of timestamps and <tt>PrefixProof</tt> structures that a user
needs for their execution of these algorithms. For the purposes of this protocol,
the user always executes the algorithm to update their view of the tree,
described in <xref target="updating-views-of-the-tree"/>, followed immediately by one of the
algorithms to search or monitor the tree.</t>
        <t>Proofs are encoded as follows:</t>
        <sourcecode type="tls"><![CDATA[
struct {
  uint64 timestamps<0..2^8-1>;
  PrefixProof prefix_proofs<0..2^8-1>;
  NodeValue prefix_roots<0..2^8-1>;

  InclusionProof inclusion;
} CombinedTreeProof;
]]></sourcecode>
        <t>The <tt>timestamps</tt> field contains the timestamps of specific log entries and the
<tt>prefix_proofs</tt> field contains search proofs from the prefix trees of specific
log entries. There is no explicit indication as to which log entry the elements
correspond to, as they are provided in the order that the algorithm the user is
executing would request them. The elements of the <tt>prefix_roots</tt> field are, in
left-to-right order, the prefix tree root hashes for any log entries whose
timestamp was provided in <tt>timestamps</tt> but a search proof was not provided in
<tt>prefix_proofs</tt>.</t>
        <t>If a log entry's timestamp is referenced multiple times by algorithms in the
same <tt>CombinedTreeProof</tt>, it is only added to the <tt>timestamps</tt> array the first
time. Additionally, when a user advertises a previously observed tree size in
their request, log entry timestamps that the user is expected to have retained
are always omitted from <tt>timestamps</tt>. This may result in there being elements of
<tt>prefix_proofs</tt> or <tt>prefix_roots</tt> that correspond to log entries whose
timestamps are not included in <tt>timestamps</tt></t>
        <t>If different algorithms in the same <tt>CombinedTreeProof</tt> require a search proof
from the same log entry, the <tt>prefix_proofs</tt> array will contain multiple
<tt>PrefixProof</tt> structures for the same log entry. Users <bcp14>MUST</bcp14> verify that all
<tt>PrefixProof</tt> structures corresponding to the same log entry compute the same
prefix tree root hash.</t>
        <t>Users processing a <tt>CombinedTreeProof</tt> <bcp14>MUST</bcp14> verify that the <tt>timestamps</tt>,
<tt>prefix_proofs</tt>, and <tt>prefix_roots</tt> fields contain exactly the expected number
of entries -- no more and no less.</t>
        <t>Finally, the <tt>inclusion</tt> field contains the minimum set of intermediate node
values from the log tree that would allow a user to compute:</t>
        <ul spacing="normal">
          <li>
            <t>The root value of the log tree, and</t>
          </li>
          <li>
            <t>If an <tt>AuditorTreeHead</tt> was provided by the Transparency Log, the root value
of the log tree when it had <tt>AuditorTreeHead.tree_size</tt> leaves,</t>
          </li>
        </ul>
        <t>from the following:</t>
        <ul spacing="normal">
          <li>
            <t>The values of all leaf nodes where either a search proof was provided in
<tt>prefix_proofs</tt> or the prefix tree root hash was provided directly in
<tt>prefix_roots</tt>, and</t>
          </li>
          <li>
            <t>If the user advertised a previously observed tree size in their request, any
intermediate node values the user is expected to have retained.</t>
          </li>
        </ul>
        <section anchor="updating-view">
          <name>Updating View</name>
          <t>For a user to update their view of the tree, the following is provided:</t>
          <ul spacing="normal">
            <li>
              <t>If the user has not previously observed a tree head, the timestamp of each log
entry along the frontier.</t>
            </li>
            <li>
              <t>If the user has previously observed a tree head, the timestamps of each log
entry from the list computed in <xref target="update-algorithm"/>.</t>
            </li>
          </ul>
          <t>Users verify that the timestamps represent a monotonic series, and that the
rightmost timestamp is within the bounds defined by <tt>max_ahead</tt> and
<tt>max_behind</tt>.</t>
        </section>
        <section anchor="fixed-version-search">
          <name>Fixed-Version Search</name>
          <t>For a user to search the combined tree for a specific version of a label, the
following is provided:</t>
          <ul spacing="normal">
            <li>
              <t>For each log entry touched by the algorithm in <xref target="fv-algorithm"/>:
              </t>
              <ul spacing="normal">
                <li>
                  <t>The log entry's timestamp.</t>
                </li>
                <li>
                  <t>If the log entry has surpassed its maximum lifetime and is on the frontier,
the right child's timestamp.</t>
                </li>
                <li>
                  <t>If it is not the case that the log entry has surpassed its maximum lifetime,
is on the frontier, and the log entry's right child has also surpassed its
maximum lifetime, then a <tt>PrefixProof</tt> corresponding to a binary ladder
(<xref target="fv-binary-ladder"/>) in the log entry's prefix tree is provided.</t>
                </li>
              </ul>
            </li>
            <li>
              <t>If the <tt>PrefixProof</tt> from the first log entry containing the target
label-version pair didn't include a lookup for the target version, provide a
second <tt>PrefixProof</tt> from this log entry specifically looking up the target
version.</t>
            </li>
          </ul>
          <t>Users verify the output as specified in <xref target="fv-algorithm"/>.</t>
        </section>
        <section anchor="monitor">
          <name>Monitor</name>
          <t>For a user to monitor a label in the combined tree, the following is provided:</t>
          <ul spacing="normal">
            <li>
              <t>For each entry in the user's monitoring map:
              </t>
              <ul spacing="normal">
                <li>
                  <t>The timestamps needed by the algorithm in <xref target="distinguished-log-entries"/> to
determine where the monitoring algorithm would first reach a distinguished
log entry. This may either be the log entry in the user's monitoring map, or
some other log entry from the list computed in step 2 of <xref target="m-algorithm"/>.</t>
                </li>
                <li>
                  <t>Where necessary for the algorithm in <xref target="m-algorithm"/>, a binary ladder
(<xref target="monitor-binary-ladder"/>) targeting the version in the user's monitoring
map.</t>
                </li>
              </ul>
            </li>
            <li>
              <t>If the user owns the label:
              </t>
              <ul spacing="normal">
                <li>
                  <t>The timestamps needed by the algorithm in <xref target="distinguished-log-entries"/> to
conduct a depth-first search for each subsequent distinguished log entry.</t>
                </li>
                <li>
                  <t>For each distinguished log entry, a binary ladder (<xref target="gv-binary-ladder"/>)
targeting the greatest version of the label that the log entry contains.</t>
                </li>
              </ul>
            </li>
          </ul>
        </section>
        <section anchor="greatest-version-search">
          <name>Greatest-Version Search</name>
          <t>For a user to search the combined tree for the greatest version of a label, the
following is provided:</t>
          <ul spacing="normal">
            <li>
              <t>For each log entry along the frontier, starting from the log entry identified
in <xref target="greatest-version-searches"/>: a binary ladder (<xref target="gv-binary-ladder"/>)
targeting the greatest version of the label that exists in the log overall.</t>
            </li>
          </ul>
          <t>Note that the log entry timestamps are already provided as part of updating the
user's view of the tree and that no additional timestamps are necessary to
identify the starting log entry. Users verify the proof as described in
<xref target="greatest-version-searches"/>.</t>
        </section>
      </section>
    </section>
    <section anchor="user-operations">
      <name>User Operations</name>
      <t>The basic user operations are organized as a request-response protocol between a
user and the Transparency Log.</t>
      <t>Users <bcp14>MUST</bcp14> retain the most recent <tt>TreeHead</tt> they've successfully
verified as part of any query response and populate the <tt>last</tt> field of any
query request with the <tt>tree_size</tt> from this <tt>TreeHead</tt>. This ensures that all
operations performed by the user return consistent results.</t>
      <t>Modifications to a user's state <bcp14>MUST</bcp14> only be persisted once the query response
has been fully verified. Queries that fail full verification <bcp14>MUST NOT</bcp14> modify the
user's protocol state in any way.</t>
      <section anchor="search">
        <name>Search</name>
        <t>Users initiate a Search operation by submitting a SearchRequest to the
Transparency Log containing the label that they're interested in. Users can
optionally specify a version of the label that they'd like to receive, if not
the greatest one.</t>
        <sourcecode type="tls-presentation"><![CDATA[
struct {
  optional<uint64> last;

  opaque label<0..2^8-1>;
  optional<uint32> version;
} SearchRequest;
]]></sourcecode>
        <t>In turn, the Transparency Log responds with a SearchResponse structure:</t>
        <sourcecode type="tls-presentation"><![CDATA[
struct {
  opaque proof[VRF.Np];
  opaque commitment[Hash.Nh];
} BinaryLadderStep;

struct {
  FullTreeHead full_tree_head;

  optional<uint32> version;
  BinaryLadderStep binary_ladder<0..2^8-1>;
  CombinedTreeProof search;

  opaque opening[Nc];
  UpdateValue value;
} SearchResponse;
]]></sourcecode>
        <t>Each <tt>BinaryLadderStep</tt> structure contains information related to one version of
the label that's in the binary ladder. The <tt>proof</tt> field contains the VRF
proof, and <tt>commitment</tt> contains the commitment to the label's value at that
version. The <tt>binary_ladder</tt> field contains these structures in the same order
that the versions are output by the algorithm in <xref target="binary-ladder"/>.</t>
        <t>The <tt>search</tt> field contains the output of updating the user's view of the tree
to match <tt>FullTreeHead.tree_head.size</tt> followed by either a fixed-version or
greatest-version search for the requested label, depending on whether <tt>version</tt>
was provided in <tt>SearchRequest</tt> or not. If searching for the greatest version of
the label, this version is provided in <tt>SearchResponse.version</tt>; otherwise, the
field is empty.</t>
        <t>Users verify a search response by following these steps:</t>
        <ol spacing="normal" type="1"><li>
            <t>Compute the VRF output for each version of the label from the proofs in
<tt>binary_ladder</tt>.</t>
          </li>
          <li>
            <t>Verify the proof in <tt>search</tt> as described in <xref target="proof-combined-tree"/>.</t>
          </li>
          <li>
            <t>Compute a candidate root value for the tree from the proof in
<tt>search.inclusion</tt> and any previously retained full subtrees of the log tree.</t>
          </li>
          <li>
            <t>With the candidate root value for the tree, verify <tt>FullTreeHead</tt>.</t>
          </li>
          <li>
            <t>Verify that the commitment to the target version of the label opens to
<tt>SearchResponse.value</tt> with opening <tt>SearchResponse.opening</tt>.</t>
          </li>
        </ol>
        <t>Depending on the deployment mode of the Transparency Log, the <tt>value</tt> field may
or may not require additional verification, specified in <xref target="update-format"/>,
before its contents may be consumed.</t>
      </section>
      <section anchor="update">
        <name>Update</name>
        <t>Users initiate an Update operation by submitting an UpdateRequest to the
Transparency Log containing the new label and value to store.</t>
        <sourcecode type="tls-presentation"><![CDATA[
struct {
  optional<uint64> last;

  opaque label<0..2^8-1>;
  opaque value<0..2^32-1>;
} UpdateRequest;
]]></sourcecode>
        <t>If the request passes application-layer policy checks, the Transparency Log adds
a new label-version pair to the prefix tree, followed by adding a new entry to
the log tree with an updated timestamp and prefix tree root. It returns
an UpdateResponse structure:</t>
        <sourcecode type="tls-presentation"><![CDATA[
struct {
  FullTreeHead full_tree_head;

  uint32 version;
  BinaryLadderStep binary_ladder<0..2^8-1>;
  CombinedTreeProof search;

  opaque opening[Nc];
  UpdatePrefix prefix;
} UpdateResponse;
]]></sourcecode>
        <t>Users verify the UpdateResponse as if it were a SearchResponse for the greatest
version of <tt>label</tt>. To aid verification, the update response provides the
<tt>UpdatePrefix</tt> structure necessary to reconstruct the <tt>UpdateValue</tt>.</t>
        <!-- TODO: This could probably be a lot more efficient -->

</section>
      <section anchor="monitor-1">
        <name>Monitor</name>
        <!-- TODO: Update to cover different deployment modes -->

<t>Users initiate a Monitor operation by submitting a MonitorRequest to the
Transparency Log containing information about the labels they wish to monitor.</t>
        <sourcecode type="tls-presentation"><![CDATA[
struct {
  uint64 position;
  uint32 version;
} MonitorMapEntry;

struct {
  opaque label<0..2^8-1>;
  MonitorMapEntry entries<0..2^8-1>;
  optional<uint64> rightmost;
} MonitorLabel;

struct {
  optional<uint64> last;
  MonitorLabel labels<0..2^8-1>;
} MonitorRequest;
]]></sourcecode>
        <t>Each MonitorLabel structure in <tt>labels</tt> contains the label to monitor in
<tt>label</tt>, and a list in the <tt>entries</tt> field corresponding to the map described in
<xref target="m-algorithm"/>. If the user owns the label, they additionally indicate in
<tt>rightmost</tt> the position of the rightmost distinguished log entry where they
have verified that the greatest version of the label is correctly represented.</t>
        <t>The Transparency Log verifies the MonitorRequest by following these steps, for
each <tt>MonitorLabel</tt> structure:</t>
        <ol spacing="normal" type="1"><li>
            <t>Verify that the <tt>label</tt> field of every MonitorLabel is unique. For all
MonitorLabel structures with <tt>rightmost</tt> provided, verify that the user owns
the label (according to application-layer policy). For all other MonitorLabel
structures, verify that the user is currently, or was previously, allowed to
lookup all versions of the label contained in a MonitorMapEntry.</t>
          </li>
          <li>
            <t>Verify that each MonitorMapEntry in the same MonitorLabel structure is sorted
in ascending order by <tt>position</tt>. Additionally, verify that each <tt>version</tt>
field is unique and that <tt>position</tt> lies on the direct path of the first log
entry to contain version <tt>version</tt> of the label.</t>
          </li>
          <li>
            <t>Verify that <tt>rightmost</tt> is a distinguished log entry to the right of
the first version of the label, or that it was the rightmost distinguished
log entry immediately after the label was first inserted.</t>
          </li>
        </ol>
        <t>While access control decisions generally belong solely to the application, users
must be able to monitor versions of a label they previously looked up, even if
they would no longer be allowed to make the same query. One simple way for a
user to prove that they were previously allowed to lookup a particular version
of a label would be for them to provide the commitment opening for the version.
However, there is no provision for this in the protocol; it would need to be
done in the application layer.</t>
        <t>If the request is valid and passes access control, the Transparency Log responds
with a MonitorResponse structure:</t>
        <sourcecode type="tls-presentation"><![CDATA[
struct {
  uint32 versions<0..2^8-1>;
} MonitorLabelVersions;

struct {
  FullTreeHead full_tree_head;
  MonitorLabelVersions label_versions<0..2^8-1>;
  CombinedTreeProof monitor;
} MonitorResponse;
]]></sourcecode>
        <t>The <tt>monitor</tt> field contains the output of updating the user's view of the tree
to match <tt>FullTreeHead.tree_head.size</tt> followed by monitoring each label in
<tt>labels</tt>, in the order provided. Each MonitorLabel structure where <tt>rightmost</tt>
was present has a corresponding entry in <tt>label_versions</tt> containing the
greatest version of the label present in a number of subsequent distinguished
log entries.</t>
        <t>Users verify a MonitorResponse by following these steps:</t>
        <ol spacing="normal" type="1"><li>
            <t>Verify that the number of entries in <tt>label_versions</tt> is equal to the number
of MonitorLabel structures in <tt>labels</tt> with <tt>rightmost</tt> present. If a
MonitorLabel has a <tt>rightmost</tt> field that is not the rightmost distinguished
log entry, verify that the corresponding MonitorLabelVersion's <tt>versions</tt>
field is not empty.</t>
          </li>
          <li>
            <t>Verify the proof in <tt>monitor</tt> as described in <xref target="proof-combined-tree"/>.</t>
          </li>
          <li>
            <t>Compute a candidate root value for the tree from the proof in
<tt>monitor.inclusion</tt> and any previously retained full subtrees of the log
tree.</t>
          </li>
          <li>
            <t>With the candidate root value for the tree, verify <tt>FullTreeHead</tt>.</t>
          </li>
        </ol>
        <t>Some information is omitted from MonitorResponse in the interest of efficiency,
because the user would have already seen and verified it as part of
conducting other queries. In particular, VRF proofs for different versions of
each label are not provided, given that these can be cached from the
original Search or Update query.</t>
      </section>
    </section>
    <section anchor="third-parties">
      <name>Third Parties</name>
      <t>Third-Party Management and Third-Party Auditing are two deployment modes that
require the Transparency Log to delegate part of its operation to a third party.
Users are able to run more efficiently as long as they can assume that the
Transparency Log and the third party won't collude to trick them into accepting
malicious results.</t>
      <section anchor="management">
        <name>Management</name>
        <t>With the Third-Party Management deployment mode, a third party is responsible
for the majority of the work of storing and operating the Transparency Log. The
Service Operator serves only to enforce access control, authenticate the
addition of new entries, and prevent the creation of forks by the Third-Party
Manager. Critically, the Service Operator is trusted to ensure that only one
value for each version of a label is authorized.</t>
        <t>All user queries specified in <xref target="user-operations"/> are initially sent by users
directly to the Service Operator to be forwarded to the Third-Party Manager if
they pass access control. While other operations are forwarded by the Service
Operator unchanged, <tt>UpdateRequest</tt> structures are forwarded to the Third-Party
Manager with the Service Operator's signature attached:</t>
        <sourcecode type="tls-presentation"><![CDATA[
struct {
  UpdateRequest request;
  opaque signature<0..2^16-1>;
} ManagerUpdateRequest;
]]></sourcecode>
        <t>The signature is computed as described in <xref target="update-format"/>.</t>
      </section>
      <section anchor="auditing">
        <name>Auditing</name>
        <t>With the Third-party Auditing deployment mode, the Service Operator obtains
signatures from a Third-Party Auditor attesting to the fact that the
Service Operator is constructing the tree correctly. These signatures are
provided to users along with the responses to their queries.</t>
        <t>For each new log entry the Service Operator adds to the log, it produces a
corresponding <tt>AuditorUpdate</tt> structure and sends this to the Third-Party
Auditor. The Third-Party Auditor <bcp14>MUST</bcp14> receive and successfully verify an
<tt>AuditorUpdate</tt> structure for a log entry before providing the Service Operator
with an <tt>AuditorTreeHead</tt> structure whose <tt>size</tt> field would include the log
entry.</t>
        <sourcecode type="tls-presentation"><![CDATA[
struct {
  uint64 timestamp;

  PrefixLeaf added<0..2^16-1>;
  PrefixLeaf removed<0..2^16-1>;

  PrefixProof proof;
} AuditorUpdate;
]]></sourcecode>
        <t>The <tt>timestamp</tt> field contains the timestamp of the corresponding log entry. The
<tt>added</tt> field contains the list of <tt>PrefixLeaf</tt> structures that were added to
the prefix tree in the corresponding log entry. The <tt>removed</tt> field contains the
list of <tt>PrefixLeaf</tt> structures that were removed from the prefix tree.</t>
        <t>The <tt>proof</tt> field contains a batch lookup proof in the previous log entry's
prefix tree for all search keys referenced by <tt>added</tt> or <tt>removed. The
</tt>proof.results<tt> field contains the result of the search for each element of
</tt>added<tt> in the order provided, followed by the result of the search for each
element of </tt>removed` in the order provided.</t>
        <t>An auditor processes a single <tt>AuditorUpdate</tt> by following these steps:</t>
        <ol spacing="normal" type="1"><li>
            <t>Verify that <tt>timestamp</tt> is greater than or equal to the timestamp of the
previous log entry.</t>
          </li>
          <li>
            <t>Verify that the <tt>PrefixSearchResult</tt> provided in <tt>proof</tt> for each element of
<tt>added</tt> has a <tt>result_type</tt> of <tt>nonInclusionParent</tt> or <tt>nonInclusionLeaf</tt>.</t>
          </li>
          <li>
            <t>Verify that the <tt>PrefixSearchResult</tt> provided in <tt>proof</tt> for each element of
<tt>removed</tt> has a <tt>result_type</tt> of <tt>inclusion</tt>.</t>
          </li>
          <li>
            <t>For each element of <tt>removed</tt>, verify that, with the addition of the new log
entry, the prefix tree leaf was published in at least one
distinguished log entry before removal.</t>
          </li>
          <li>
            <t>With <tt>proof</tt> and the <tt>PrefixLeaf</tt> structures in <tt>removed</tt>, compute the root
value of the previous log entry's prefix tree. Verify that this matches the
auditor's state.</t>
          </li>
          <li>
            <t>With <tt>proof</tt> and the <tt>PrefixLeaf</tt> structures in <tt>added</tt> and <tt>removed</tt>,
compute the new root value of the prefix tree. Compute the new root value of
the log tree after adding a leaf with the specified <tt>timestamp</tt> and prefix
tree root value.</t>
          </li>
          <li>
            <t>Provide an <tt>AuditorTreeHead</tt> to the Service Operator where
<tt>AuditorTreeHead.timestamp</tt> is set to <tt>timestamp</tt> and
<tt>AuditorTreeHead.tree_size</tt> is set to the new size of the log tree after the
addition of the new leaf. The signature is computed with the log tree root
value computed in the previous step.</t>
          </li>
        </ol>
      </section>
    </section>
    <section anchor="security-considerations">
      <name>Security Considerations</name>
      <t>The security properties provided by this protocol are discussed in detail in
<xref target="ARCH"/>. Generally speaking, the Key Transparency protocol ensures that all
users of a Transparency Log have a consistent view of the data stored in the
log. Service Operators may still be able to make malicious modifications to
stored data, such as by attaching new public keys to a user's account and
encouraging other users to encrypt to these public keys when messaging the user.
However, since the existence of these new public keys is equally visible to the
user whose account they affect, the user can promptly act to have them removed
from their account or inform contacts out-of-band that their communication may
be compromised.</t>
      <t>Key Transparency relies on users coming online regularly to monitor for
unexpected or malicious modifications to their account. Users that go offline
for longer than the log entry maximum lifetime may not detect if the
Transparency Log made malicious modifications to their labels.</t>
      <t>Similarly, Key Transparency relies on the ability of users to retain long-term
state regarding their account and past views of the Transparency Log. Users
which are unable to maintain long-term state, or may lose their state, have a
correspondingly limited ability to detect misbehavior by the Service Operator.
In particular, users which are completely stateless will generally gain nothing
by participating in this protocol over simply verifying a signature from the
Service Operator and, if there is one, the Third-Party Auditor or Manager.</t>
      <t>Ultimately, ensuring that all users have a consistent view of the Transparency
Log requires that the Service Operator is not able to create and maintain
long-term network partitions between users. As such, users need access to at
least one communication channel (even a very low-bandwidth one) that is
resistant to partitions. The protocol directly provides for a Third-Party
Auditor or Manager, which is trusted to prevent such partitions. Other options
include allowing users to gossip with each other, or allowing users to contact
the Transparency Log over an anonymous channel.</t>
      <t>Key Transparency provides users with a limited assurance that query responses
are authentic: a network attacker will not be able to forge false responses to
queries but may provide responses which are up to <tt>max_behind</tt> milliseconds
stale. Key Transparency provides no privacy from network observers and does not
have the ability to authenticate specific users to the Transparency Log. To
mitigate these limitations, users <bcp14>SHOULD</bcp14> contact the Transparency Log over a
protocol that provides transport-layer encryption and an appropriate level of
authentication for both parties.</t>
    </section>
    <section anchor="iana-considerations">
      <name>IANA Considerations</name>
      <t>This document requests the creation of the following new IANA registries:</t>
      <ul spacing="normal">
        <li>
          <t>KT Cipher Suites (<xref target="kt-cipher-suites"/>)</t>
        </li>
      </ul>
      <t>All of these registries should be under a heading of "Key Transparency",
and assignments are made via the Specification Required policy <xref target="RFC8126"/>. See
<xref target="de"/> for additional information about the KT Designated Experts (DEs).</t>
      <t>RFC EDITOR: Please replace XXXX throughout with the RFC number assigned to
this document</t>
      <section anchor="kt-cipher-suites">
        <name>KT Cipher Suites</name>
        <t>A cipher suite is a specific combination of cryptographic primitives and
parameters to be used in an instantiation of the protocol. Cipher suite names
follow the naming convention:</t>
        <sourcecode type="tls-presentation"><![CDATA[
uint16 CipherSuite;
CipherSuite KT_LVL_HASH_SIG = VALUE;
]]></sourcecode>
        <t>The columns in the registry are as follows:</t>
        <ul spacing="normal">
          <li>
            <t>Value: The numeric value of the cipher suite.</t>
          </li>
          <li>
            <t>Name: The name of the cipher suite.</t>
          </li>
          <li>
            <t>Recommended: Whether support for this cipher suite is <bcp14>RECOMMENDED</bcp14>.
Valid values are "Y", "N", and "D", as described below. The default value of
the "Recommended" column is "N". Setting the Recommended item to "Y" or "D",
or changing an item whose current value is "Y" or "D", requires Standards
Action <xref target="RFC8126"/>.
            </t>
            <ul spacing="normal">
              <li>
                <t>Y: Indicates that the item is <bcp14>RECOMMENDED</bcp14>. This only means that the
associated mechanism is fit for the purpose for which it was defined.
Careful reading of the documentation for the mechanism is necessary to
understand the applicability of that mechanism. A cipher suite may, for
example, be recommended that is only suitable for use in applications where
the Transparency Log's contents are public. Mechanisms with limited
applicability may be recommended, but in such cases applicability statements
that describe any limitations of the mechanism or necessary constraints will
be provided.</t>
              </li>
              <li>
                <t>N: Indicates that the item's associated mechanism has not been evaluated and
is not <bcp14>RECOMMENDED</bcp14> (as opposed to being <bcp14>NOT RECOMMENDED</bcp14>). This does not
mean that the mechanism is flawed. For example, an item may be marked as "N"
because it has usage constraints or limited applicability.</t>
              </li>
              <li>
                <t>D: Indicates that the item is discouraged and <bcp14>SHOULD NOT</bcp14> be
used. This marking could be used to identify mechanisms that might result in
problems if they are used, such as a weak cryptographic algorithm or a
mechanism that might cause interoperability problems in deployment.</t>
              </li>
            </ul>
          </li>
          <li>
            <t>Reference: The document where this cipher suite is defined.</t>
          </li>
        </ul>
        <t>Initial contents:</t>
        <table>
          <thead>
            <tr>
              <th align="left">Value</th>
              <th align="left">Name</th>
              <th align="left">R</th>
              <th align="left">Ref</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td align="left">0x0000</td>
              <td align="left">RESERVED</td>
              <td align="left">-</td>
              <td align="left">RFC XXXX</td>
            </tr>
            <tr>
              <td align="left">0x0001</td>
              <td align="left">KT_128_SHA256_P256</td>
              <td align="left">Y</td>
              <td align="left">RFC XXXX</td>
            </tr>
            <tr>
              <td align="left">0x0002</td>
              <td align="left">KT_128_SHA256_Ed25519</td>
              <td align="left">Y</td>
              <td align="left">RFC XXXX</td>
            </tr>
          </tbody>
        </table>
        <t>All cipher suites currently specified share the following primitives and
parameters:</t>
        <ul spacing="normal">
          <li>
            <t>The hash algorithm is SHA-256, as defined in <xref target="SHS"/>.</t>
          </li>
          <li>
            <t><tt>Nc</tt>: 16</t>
          </li>
          <li>
            <t><tt>Kc</tt>: The byte sequence equal to the hex-encoded string <tt>d821f8790d97709796b4d7903357c3f5</tt></t>
          </li>
        </ul>
        <t>The signature algorithm and VRF algorithm for each cipher suite is as follows:</t>
        <table>
          <thead>
            <tr>
              <th align="left">Name</th>
              <th align="left">Signature</th>
              <th align="left">VRF Algorithm</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td align="left">KT_128_SHA256_P256</td>
              <td align="left">ecdsa_secp256r1_sha256</td>
              <td align="left">ECVRF-P256-SHA256-TAI</td>
            </tr>
            <tr>
              <td align="left">KT_128_SHA256_Ed25519</td>
              <td align="left">ed25519</td>
              <td align="left">ECVRF-EDWARDS25519-SHA512-TAI[32]</td>
            </tr>
          </tbody>
        </table>
        <t>The VRF algorithms are specified in <xref target="RFC9381"/>. For <tt>KT_128_SHA256_Ed25519</tt>,
the final hash output of <tt>ECVRF-EDWARDS25519-SHA512-TAI</tt> is truncated to be 32
bytes.</t>
      </section>
      <section anchor="de">
        <name>KT Designated Expert Pool</name>
        <t>Specification Required <xref target="RFC8126"/> registry requests are registered after a
three-week review period on the KT Designated Expert (DE) mailing list
<eref target="mailto:kt-reg-review@ietf.org">kt-reg-review@ietf.org</eref> on the advice of one or more of the KT DEs. However, to
allow for the allocation of values prior to publication, the KT DEs may approve
registration once they are satisfied that such a specification will be
published.</t>
        <t>Registration requests sent to the KT DEs' mailing list for review <bcp14>SHOULD</bcp14> use an
appropriate subject (e.g., "Request to register value in KT registry").</t>
        <t>Within the review period, the KT DEs will either approve or deny the
registration request, communicating this decision to the KT DEs' mailing list
and IANA. Denials <bcp14>SHOULD</bcp14> include an explanation and, if applicable, suggestions
as to how to make the request successful. Registration requests that are
undetermined for a period longer than 21 days can be brought to the IESG's
attention for resolution using the <eref target="mailto:iesg@ietf.org">iesg@ietf.org</eref> mailing list.</t>
        <t>Criteria that <bcp14>SHOULD</bcp14> be applied by the KT DEs includes determining whether the
proposed registration duplicates existing functionality, whether it is likely to
be of general applicability or useful only for a single application, and whether
the registration description is clear.</t>
        <t>IANA <bcp14>MUST</bcp14> only accept registry updates from the KT DEs and <bcp14>SHOULD</bcp14> direct all
requests for registration to the KT DEs' mailing list.</t>
        <t>It is suggested that multiple KT DEs who are able to represent the perspectives
of different applications using this specification be appointed, in order to
enable a broadly informed review of registration decisions. In cases where a
registration decision could be perceived as creating a conflict of interest for
a particular KT DE, that KT DE <bcp14>SHOULD</bcp14> defer to the judgment of the other KT DEs.</t>
      </section>
    </section>
  </middle>
  <back>
    <references anchor="sec-combined-references">
      <name>References</name>
      <references anchor="sec-normative-references">
        <name>Normative References</name>
        <reference anchor="ARCH">
          <front>
            <title>Key Transparency Architecture</title>
            <author fullname="Brendan McMillion" initials="B." surname="McMillion">
         </author>
            <date day="25" month="February" year="2025"/>
            <abstract>
              <t>   This document defines the terminology and interaction patterns
   involved in the deployment of Key Transparency (KT) in a general
   secure group messaging infrastructure, and specifies the security
   properties that the protocol provides.  It also gives more general,
   non-prescriptive guidance on how to securely apply KT to a number of
   common applications.

              </t>
            </abstract>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-ietf-keytrans-architecture-03"/>
        </reference>
        <reference anchor="RFC2119">
          <front>
            <title>Key words for use in RFCs to Indicate Requirement Levels</title>
            <author fullname="S. Bradner" initials="S." surname="Bradner"/>
            <date month="March" year="1997"/>
            <abstract>
              <t>In many standards track documents several words are used to signify the requirements in the specification. These words are often capitalized. This document defines these words as they should be interpreted in IETF documents. This document specifies an Internet Best Current Practices for the Internet Community, and requests discussion and suggestions for improvements.</t>
            </abstract>
          </front>
          <seriesInfo name="BCP" value="14"/>
          <seriesInfo name="RFC" value="2119"/>
          <seriesInfo name="DOI" value="10.17487/RFC2119"/>
        </reference>
        <reference anchor="RFC8174">
          <front>
            <title>Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words</title>
            <author fullname="B. Leiba" initials="B." surname="Leiba"/>
            <date month="May" year="2017"/>
            <abstract>
              <t>RFC 2119 specifies common key words that may be used in protocol specifications. This document aims to reduce the ambiguity by clarifying that only UPPERCASE usage of the key words have the defined special meanings.</t>
            </abstract>
          </front>
          <seriesInfo name="BCP" value="14"/>
          <seriesInfo name="RFC" value="8174"/>
          <seriesInfo name="DOI" value="10.17487/RFC8174"/>
        </reference>
        <reference anchor="RFC8446">
          <front>
            <title>The Transport Layer Security (TLS) Protocol Version 1.3</title>
            <author fullname="E. Rescorla" initials="E." surname="Rescorla"/>
            <date month="August" year="2018"/>
            <abstract>
              <t>This document specifies version 1.3 of the Transport Layer Security (TLS) protocol. TLS allows client/server applications to communicate over the Internet in a way that is designed to prevent eavesdropping, tampering, and message forgery.</t>
              <t>This document updates RFCs 5705 and 6066, and obsoletes RFCs 5077, 5246, and 6961. This document also specifies new requirements for TLS 1.2 implementations.</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="8446"/>
          <seriesInfo name="DOI" value="10.17487/RFC8446"/>
        </reference>
        <reference anchor="RFC9381">
          <front>
            <title>Verifiable Random Functions (VRFs)</title>
            <author fullname="S. Goldberg" initials="S." surname="Goldberg"/>
            <author fullname="L. Reyzin" initials="L." surname="Reyzin"/>
            <author fullname="D. Papadopoulos" initials="D." surname="Papadopoulos"/>
            <author fullname="J. Včelák" initials="J." surname="Včelák"/>
            <date month="August" year="2023"/>
            <abstract>
              <t>A Verifiable Random Function (VRF) is the public key version of a keyed cryptographic hash. Only the holder of the secret key can compute the hash, but anyone with the public key can verify the correctness of the hash. VRFs are useful for preventing enumeration of hash-based data structures. This document specifies VRF constructions based on RSA and elliptic curves that are secure in the cryptographic random oracle model.</t>
              <t>This document is a product of the Crypto Forum Research Group (CFRG) in the IRTF.</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="9381"/>
          <seriesInfo name="DOI" value="10.17487/RFC9381"/>
        </reference>
        <reference anchor="RFC2104">
          <front>
            <title>HMAC: Keyed-Hashing for Message Authentication</title>
            <author fullname="H. Krawczyk" initials="H." surname="Krawczyk"/>
            <author fullname="M. Bellare" initials="M." surname="Bellare"/>
            <author fullname="R. Canetti" initials="R." surname="Canetti"/>
            <date month="February" year="1997"/>
            <abstract>
              <t>This document describes HMAC, a mechanism for message authentication using cryptographic hash functions. HMAC can be used with any iterative cryptographic hash function, e.g., MD5, SHA-1, in combination with a secret shared key. The cryptographic strength of HMAC depends on the properties of the underlying hash function. This memo provides information for the Internet community. This memo does not specify an Internet standard of any kind</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="2104"/>
          <seriesInfo name="DOI" value="10.17487/RFC2104"/>
        </reference>
        <reference anchor="RFC8126">
          <front>
            <title>Guidelines for Writing an IANA Considerations Section in RFCs</title>
            <author fullname="M. Cotton" initials="M." surname="Cotton"/>
            <author fullname="B. Leiba" initials="B." surname="Leiba"/>
            <author fullname="T. Narten" initials="T." surname="Narten"/>
            <date month="June" year="2017"/>
            <abstract>
              <t>Many protocols make use of points of extensibility that use constants to identify various protocol parameters. To ensure that the values in these fields do not have conflicting uses and to promote interoperability, their allocations are often coordinated by a central record keeper. For IETF protocols, that role is filled by the Internet Assigned Numbers Authority (IANA).</t>
              <t>To make assignments in a given registry prudently, guidance describing the conditions under which new values should be assigned, as well as when and how modifications to existing values can be made, is needed. This document defines a framework for the documentation of these guidelines by specification authors, in order to assure that the provided guidance for the IANA Considerations is clear and addresses the various issues that are likely in the operation of a registry.</t>
              <t>This is the third edition of this document; it obsoletes RFC 5226.</t>
            </abstract>
          </front>
          <seriesInfo name="BCP" value="26"/>
          <seriesInfo name="RFC" value="8126"/>
          <seriesInfo name="DOI" value="10.17487/RFC8126"/>
        </reference>
      </references>
      <references anchor="sec-informative-references">
        <name>Informative References</name>
        <reference anchor="CONIKS" target="https://eprint.iacr.org/2014/1004">
          <front>
            <title>CONIKS: Bringing Key Transparency to End Users</title>
            <author initials="M. S." surname="Melara" fullname="Marcela S. Melara">
              <organization/>
            </author>
            <author initials="A." surname="Blankstein" fullname="Aaron Blankstein">
              <organization/>
            </author>
            <author initials="J." surname="Bonneau" fullname="Joseph Bonneau">
              <organization/>
            </author>
            <author initials="E. W." surname="Felten" fullname="Edward W. Felten">
              <organization/>
            </author>
            <author initials="M. J." surname="Freedman" fullname="Michael J. Freedman">
              <organization/>
            </author>
            <date year="2014" month="April" day="27"/>
          </front>
        </reference>
        <reference anchor="SEEMLess" target="https://eprint.iacr.org/2018/607">
          <front>
            <title>SEEMless: Secure End-to-End Encrypted Messaging with less trust</title>
            <author initials="M." surname="Chase" fullname="Melissa Chase">
              <organization/>
            </author>
            <author initials="A." surname="Deshpande" fullname="Apoorvaa Deshpande">
              <organization/>
            </author>
            <author initials="E." surname="Ghosh" fullname="Esha Ghosh">
              <organization/>
            </author>
            <author initials="H." surname="Malvai" fullname="Harjasleen Malvai">
              <organization/>
            </author>
            <date year="2018" month="June" day="18"/>
          </front>
        </reference>
        <reference anchor="OPTIKS" target="https://eprint.iacr.org/2023/1515">
          <front>
            <title>OPTIKS: An Optimized Key Transparency System</title>
            <author initials="J." surname="Len" fullname="Julia Len">
              <organization/>
            </author>
            <author initials="M." surname="Chase" fullname="Melissa Chase">
              <organization/>
            </author>
            <author initials="E." surname="Ghosh" fullname="Esha Ghosh">
              <organization/>
            </author>
            <author initials="K." surname="Laine" fullname="Kim Laine">
              <organization/>
            </author>
            <author initials="R. C." surname="Moreno" fullname="Radames Cruz Moreno">
              <organization/>
            </author>
            <date year="2023" month="October" day="04"/>
          </front>
        </reference>
        <reference anchor="Merkle2" target="https://eprint.iacr.org/2021/453">
          <front>
            <title>Merkle^2: A Low-Latency Transparency Log System</title>
            <author initials="Y." surname="Hu" fullname="Yuncong Hu">
              <organization/>
            </author>
            <author initials="K." surname="Hooshmand" fullname="Kian Hooshmand">
              <organization/>
            </author>
            <author initials="H." surname="Kalidhindi" fullname="Harika Kalidhindi">
              <organization/>
            </author>
            <author initials="S. J." surname="Yang" fullname="Seung Jin Yang">
              <organization/>
            </author>
            <author initials="R. A." surname="Popa" fullname="Raluca Ada Popa">
              <organization/>
            </author>
            <date year="2021" month="April" day="08"/>
          </front>
        </reference>
        <reference anchor="SHS">
          <front>
            <title>Secure hash standard</title>
            <author>
              <organization/>
            </author>
            <date year="2015"/>
          </front>
          <seriesInfo name="DOI" value="10.6028/nist.fips.180-4"/>
          <refcontent>National Institute of Standards and Technology (U.S.)</refcontent>
        </reference>
      </references>
    </references>
    <?line 2044?>

<section anchor="appendix-implicit-search-tree">
      <name>Implicit Binary Search Tree</name>
      <t>The following Python code demonstrates efficient algorithms for navigating the
implicit binary search tree:</t>
      <sourcecode type="python"><![CDATA[
# The exponent of the largest power of 2 less than x. Equivalent to:
#   int(math.floor(math.log(x, 2)))
def log2(x):
    if x == 0:
        return 0
    k = 0
    while (x >> k) > 0:
        k += 1
    return k-1

# The level of a node in the tree. Leaves are level 0, their parents
# are level 1, etc. If a node's children are at different levels,
# then its level is the max level of its children plus one.
def level(x):
    if x & 0x01 == 0:
        return 0
    k = 0
    while ((x >> k) & 0x01) == 1:
        k += 1
    return k

# The root index of a search if the log has `n` entries.
def root(n):
    return (1 << log2(n)) - 1

# The left child of an intermediate node.
def left(x):
    k = level(x)
    if k == 0:
        raise Exception('leaf node has no children')
    return x ^ (0x01 << (k - 1))

# The right child of an intermediate node.
def right(x, n):
    k = level(x)
    if k == 0:
        raise Exception('leaf node has no children')
    x = x ^ (0x03 << (k - 1))
    while x >= n:
        x = left(x)
    return x
]]></sourcecode>
    </section>
    <section anchor="appendix-binary-ladder">
      <name>Binary Ladder</name>
      <t>The following Python code demonstrates efficient algorithms for computing the
versions of a label to include in a binary ladder:</t>
      <sourcecode type="python"><![CDATA[
# Returns the set of versions that would be looked up to establish that n was
# the greatest version of a label that existed.
def base_binary_ladder(n):
    out = []

    # Output powers of two minus one until reaching a value greater than n.
    while True:
        value = (1 << len(out)) - 1
        out.append(value)
        if value > n:
            break

    # Binary search between the established lower and upper bounds.
    lower_bound = out[-2]
    upper_bound = out[-1]

    while lower_bound+1 < upper_bound:
        value = (lower_bound + upper_bound) // 2
        out.append(value)
        if value <= n:
            lower_bound = value
        else:
            upper_bound = value

    return out

# Returns the set of versions that would be looked up in a binary ladder for a
# fixed-version search where the target version is t and the greatest version of
# the label that exists in a given version of the prefix tree is n.
def fixed_version_binary_ladder(
    t, n,
    left_inclusion = [], right_non_inclusion = []
):
    def would_end(v):
        # (Proof of inclusion for a version greater than or equal to t) OR
        # (Proof of non-inclusion for a version less than t)
        return (v <= n and v >= t) or (v > n and v < t)

    def would_be_duplicate(v):
        return (v <= n and v in left_inclusion) or \
               (v > n and v in right_non_inclusion)

    out = base_binary_ladder(n)
    end = next((i+1 for i,v in enumerate(out) if would_end(v)), len(out))
    filtered_out = [v for v in out[:end] if not would_be_duplicate(v)]

    return filtered_out

# Returns the set of versions that would be looked up in a binary ladder for a
# monitoring query where the monitored version of the label is t.
def monitor_binary_ladder(t, left_inclusion = []):
    out = base_binary_ladder(t)
    filtered_out = [v for v in out if v <= t and v not in left_inclusion]

    return filtered_out

# Returns the set of versions that would be looked up in a binary ladder for a
# greatest-version search where the greatest version of a label that exists
# globally is t but the greatest version of the label in a given version of the
# prefix tree is n.
def greatest_version_binary_ladder(
    t, n, distinguished,
    left_inclusion = [], right_non_inclusion = [], same_entry = []
):
    def would_end(v):
        # Proof of non-inclusion for a version less than t
        return (v > n and v < t)

    def would_be_duplicate(v):
        if distinguished:
            return (v <= n and v in left_inclusion) or \
                   (v > n and v in right_non_inclusion)
        else:
            return v in same_entry

    out = base_binary_ladder(t)
    end = next((i+1 for i,v in enumerate(out) if would_end(v)), len(out))
    filtered_out = [v for v in out[:end] if not would_be_duplicate(v)]

    return filtered_out
]]></sourcecode>
    </section>
  </back>
  <!-- ##markdown-source:
H4sIAAAAAAAAA+2963bbRpYw+r+eAuOsdSIpJG3ZubVz+UaxnY4ndpLPdpLu
1dNjgiQkoUUC/ABQstrxPMt5lvNkZ1+rdhUASs709Fmz1tHqdiQSqMuuXft+
mU6nriu7dfEwu/N9cZ29avKq3eZNUS2vs5+auquX9fqOW+ZdcVY31w+ztls5
t6qXVb6Bd1ZNftpNy6I7nV4U1x2+PN3KW9N79127W2zKti3rqrvewvNPn7z6
1l0+zB44mCJ/mL188shd1c3FWVPvtg+z75/8+dWLkx9eZr/CZ2V1lv0RP3cw
NDy0euiybJrBH1lnVukui2pX4HcySG8fd+A7nv5ONC5+vsnLNXyui/9X3Mqs
bs7wu7xZnsN35123bR/evYuP4kflZTHTx+7iB3cXTX3VFnd1kLv48lnZne8W
8DoB5+rMw+cuw2zrYZtla4Bu25mp0ndmPNqsrJO37+47gNl5t4HxXb7rzusG
IDSFubLsdLde8+nd+Qbgs8qr7PnyeblewyndoScKgcqCv94sN/ztv57hF7Nl
vbkzMNi3xbp8kz0rq4uiicdZ02en+L0dwlV1s8k7gOdD58rqNPyVZY9+/OHp
9y8f0jBd3pwVAB6FTrFtyqqblfmyoTO4f+/447vH9+59zE8LNssI2Tfw8Bme
eQ+9uzp7Uq2yn9uiaXnBKziIhxmON7338fT+Z/ShBx/9TDPe7nM4+WKdZy9n
2XP4b5Mn35/kTV1l36zz6qLtirJKvv63ui2259k3dVUV+S758snqKm9W2a+z
DGDaFem7z8vleV6ss3+D75uiWG1yfOLlkyfPnxVte2uYfX7303ufRSDDIdY4
RPayWO6aAsEz7eopQulJtWyut12xgu22bU4QvQKszPAFuJC7tktg+Pn03qfT
48/3wRAwAsbKHp3nbZHCb1vXzWWeZ4+L9nybV6v0gSfteZ798bxuz5Mvvsub
v+XtuigAr/P1ZV7C9z/+9Oo90On+g7vHnxx/EsFGRshOquzHbVduyr8DKHoo
9fIaDnsTA+L+g+nxvalg5zAg/m23LvPsWf+k9wBodP/fl5vsWV5W6Qsv8hX8
t80eNbu/Z89rWHANTzwvmot1cf/WoDm++/EnDyLI8Aj/cR9gkz2rr6bPYN8I
iwgwz+qzYeAc4027tw9L/ryrljVg23fpNfm+BNL1XQ0QgBuw6mNBeZFn3+fr
cnVeVqsy+f5lsYMx/62ssj/n1VkPVOvdMs9OVnn2U73Fq/3yOzj7xz8+nR3f
m3167/7nd394+vLV7NunP72cHX9+b/qxc246nWb5ogUavOyc+/W8XBdZd17A
NQIYZG1xWTT5OgNCny/gVM8BfZRQtxnQvqzgywb/gV/psgHJnbgGqAtSxfV1
ti47AHmWdwBg/DIDtMgWiOhn8ECFBK2liwvPrkpYSbnYdXhRYRk0/A5Indvu
YP4l8lGet90tz82Ms+ykzfKsKdrdupvgq21hVop7qU9hASAJAFdwl7t1BRtb
4GbrrMgvi3bV1NstTru4zgAWsDRccr4EHtDO+nemxOl0AocritbeFlVb0iC0
wvqsybfnsH7PMABIvAcAhtnbBJ7IcneVA6E/zzvYENyxBUCmKPFUYEY4kapr
4bEOmRMuBrYGsxddsYTP6a2yy+olgLSB46Lx4OojeAHjYNszPvVNuVqtC0CB
D7KnVdfUq90Sl+Xck96RwjDA+za7qlzS0mF7zWW5hGtJpwYf4FnxKWbFGyD0
1RkCPDo1BHTV4hO0xg0RZBoCmGsFE1Sn5QpRJF/PsqcdQhjkH5hxDVPkbbvb
FCtHr8rsCP5LeKVp4WXY67LjLcKotB47ObxfL8scd0L0v8iX5w4R60P4brms
d0Aw4FZeIb4j+sDk8L+q7rJ8DYdBvKIAJOvNLQBvHQAIPgO5EaaA89jAFV6W
9Q7WBvddIHLTqvKMl+RkSfRpvevwxbLJLqr6al2szooJX1HE1PW6vtLLEtZk
cBpOxwGhycrNFiBVVzAbrxmnAlR4hXsF0RjACxOuinYJSFxY7ObHiwqvC35O
EiucLo2QniucUEHLgmt+yTtugTpll2Vxhe/c5mCyGrcXwAD37wnOgPvMEVFa
uGq4WhqUQNCGxfBNyK7O4bbvKqbOyPciZKTFERFKF8CglpnxOq4I6Wnqbd0x
gprTBhAiW8JpQUakC+evOFBWOb0ATCAgHWAGCAdwW/Fg8FtGsfPC+ccQaxY4
6nZdX+P9479PYVV0p9++/ZeTF4++++rp9PEsFqRJ2kcQwJG8ezfD+/2ori6Z
+PKUj4vTsirpb0SAgtQTVFZaYIw/v3x1Z8L/zX74kX5/8eR///z0xZPH+PvL
706ePfO/OHni5Xc//vzscfgtvPnox+fPn/zwmF+GT7PoI3fn+cmf4RtcFUkr
P/5w8uwObrCL8BIJOJwtQIAIH5BBPLC8dYqwBJRvHv30//zfxx8jcF58++j+
8fEf3r2TPz4//uxj+AOxgmerK6AW/CeirMu32yJviFyuEfzbssvXQI+BPrfn
9RWwLbhxAM2jvyBk/vow+3Kx3B5//LV8gBuOPlSYRR8SzPqf9F5mIA58NDCN
h2b0eQLpeL0nf47+VribD7/8X6D+FBlIwv/ra5cSCbhqhK3Zq2cvkSMBs+sY
30FxONsh/RWgf/zxpwB0upR8TITkwCd3hJ5IEDzGK0OYZMBDYbKC6W9T/J9d
2TAlgYnxlTxrt8WyPC2XjnXquun8OCQJIGedIMlbFxtdHG6ARqyKJU7VlIAA
FWgiuD4aZ1N2zrMlpADNikhr7TfLN5vwh8k6yHFwe4GznyPnQH5Z0zubAsjO
ygEhBXa1K4kxE13ZbtfCRA2/iWUEpC07XTPhFhKCGkRjJVB7AC8rtEQ5EB9g
dsSky+4aKQ0whK4sWDpCHtyh/L2akUjwCnQ0pBt8ViQXnPSFY5KCYAtwFiRM
gYAMh+OPlxl9vsWnjtb5olhP4WE0rLhtXjZHJPvVwB12lX9pJYOIbJQnwAlE
fAb6AoyInBeYPyBBRSeJfCBjQeK0hMn4tudw0leZTM44ROvBHSybgsg/yQQo
KRHM6OsPIwZ1CQJ2Iby8BTB9/4qvAmwODuO0fANoVBS8qw55Qo6bJ6HyFJgF
87YIDBmCwcHzOQlYZUf3SxBOV8DT4qEiOOVNYInwG0iJul5egcMV6BLhBgDi
4cabGvAe5O5zz3FIOsS54H0Q7jdblvdx2SwzwoHVZzTc0SxDHrEoKpih80w8
7JhENZE74dcib/FqtQVyIkILmdQlQ8AEvffxWskAgPWMWnxF4U+k0SCcIumm
NbkE37ZwoUhKgJMBeC4AnfF0/DyMCWbljByIA0D0SbwssiN5c8WnqSISXBy6
aUFCwofxDvENJFLmBwbY66yCgbj/aOSw7gkebp6dl2domAClaUaaLo63BAkD
GNIZiDDd+YZVH6YPsE1aLvFDEI0RRWkiOmvCmVYBTcugA2aVq6zc27fRvZpa
osNSA9AAGLisatjINQCBxhDhCwc+qmqAxdGEyR9LVDloTx3tjAQmpXpHtJwj
lJ/xJRSXRZ9BNCvy06OsPMXTR9WwqgF/y/WqQdZc0yNEcjr7kH39tHP0wpE8
3QAcOx7DTkmQOELoHDEBYNSz8/I87YQEZkDEIwtcO/0CJFS/SoK6vDrLfkCo
EKyP2hJoVXXWHrmSzgHuxHneGKGYX5qxDHaEmEWmy66VFdLKcyWk+Bdf6QAf
vc7mXdS77EMIgqN2t2DaZHbeetwQtFhcD4wF2iOLrLs1iEe8Br4tDNDzIl8d
KaLJNH5HJWplsM3uXGYm5LQHUmy2HdoI2k7EMniqumYNwD4Id6dCe37lb5uH
CZBIBiRclFoNfESi6FP42qyD6QbccbMoux4ZUI4uC7Ma/YCWi6/qATscZr32
A6B6TgdlJp6gYrzerVRZQ0gonFrQT+zRkH1joae0QmmdpF2eYLdZAGzgabw5
Ol+HAEIG3vLdRe6MV9a5Z0qHhClZ/aRkzX153tR0z1HbhtmDXgt6FDLh1apY
0fmgB4SIANEuXhRdwekiBxlkWQAuAInLkTPhnDMUG8wHuJ+j8CjdKIT23wux
qCAFp9O9qgkfkOAhQvBZOj6qymMu3wdcANM+uvoCuzZRQXEWvAxmOa7sLx/W
RIYtYq887UTpTcAqXK6+Q2QKcZTWoSenKBqeZ6benKFQqO/6x+lZUDrXK+B0
zoKYZAd6l5R6FfwUDB7LUUnRC5j9kW50rqjq5tUcQFVsWrEdMLh3Vfl/dkUW
QSA6rsBbFfnbwhUsVaNsJGtCsofsZ93WYi0w0FMTiieceXJgTL4BVf7zP/8z
y/P2Ui2bIz9/2v/1b0Nfz6b689Fs4Pu79o9/7z/wpxun+G3vEzj9R/D/2dgT
YQH/PvzEn4Z+t0/cNW+G380Td83g5vfwxJ/G/nXuabUq3jzMsnv0wTH9e5/+
fUD/foxn594+ZPv6V3dOgtAldImkYDSICsbceWdJE5kjyNJnJAwQ7eCtdREI
HeAZSLNyDwC5HFEmFZgJmaabGt5GK5mVfixr8MMKehJN6epw5+Syjd0JGmRe
fXQ81738szAXEegm5M1ug7/Dc/1200MDWNx7aAiR04cGcTmLwTOMzvT7jSjN
v9+M1zLpzdhN/36S4PiTNzkaGBDNgO2iLk1Gwoox9JTxpMShs09QTK9Vb7pE
u/D62q2KbUkUXu/KLPtxgQZm4QZkogoyRa30Hob1PMFrd4DA+jfNzjogXzO+
L6hasZTeLMquQXwm/cmL6SSli74MFP8UTS9wQWARoNgU5E1AVbV1d3DB8E1T
Fu0dCgRolBupkYh1RlZd6Srby4a8Z+1tnqSXyl31GlJQYAYYvBdtLQnJVQE8
3a15NaQyg9SNGxfbODMgkOtBFGMFHIB36rUYOJINUQFvJc8ZmugPwHdWqh0D
BBhSR94evby+xWh9M4SYUUDtfdOh10i/UETxGj/iqS6bLFC9iXFpoPquylM4
LsaRttxgAIjxhQlonLxCSEbGKyHUdA4B/Ix7vHrRXVDk5zUqfXRe7vj1HHT8
SxGV/PHHb1V1Ne3JP+huKQqEL7o1nGj+5IxhzwaMuWiK/ALteFeV3IuhgeSm
uXaDakrbTbd1i5K6FZ3Tt9guLkjSDi8epXw04SBqEwaT30EXSr6HJXxdkG0J
pLzGzBdp6Qxc9GVV2RVJfKTuXKGuv0Ak5uVO4NqtdktVGEhIRqVjBzSCLmbG
Zq+WxWzr/8yrLEFxFqQ9MnuFj7esc7Ba5GLrQSBmKIgPwRzkuqa+gAHpZICe
bNjbUKxY3eIVlG2w58DMeO11XpqCAd7VZwXJ2l7b4kUJ1NC1PPUWkIBYFmGH
FnhFQi9jGF9cOKnlBVtRmFAI9DIALgiyXkmLEQGu6//P7gcXM8ruD/50OLgy
+PyfxO9lBf9Ffv90DReqC+a+/iUDbK8Zx8V9T3h933IPFymvhrbFtEeISrgE
Ab95zA/R7u0NGq3KCGzKby74isG+SQBAokyOFKCGiRNVecfEELKcvPjbgmQT
oGokNDQFuweYZcdXzii2gdj27+ABh2Vcleu1CA2g6SbWjTsYm+dfuXNozM0R
N7T3MTtxvf3gl5Vu0y9yA3rGZgdcseiUt+k2lMM5dQ9RqB1TmmKEGCTMXG3a
Kpw5O3R0rArMfyYp4Z/bEBT+6ZOV6CLfsLg+cRlc6DCJkc9nt6E0+vm/30rB
GFrGHsrTf3ovBUqfHlE5GI5/+dNf+d9b0yP699ObqFL/bsM1666KQsRWpikf
Ew+kXz91olCjOFEsOWxL5HdFWHTrBIrg8jVIYqvrYGATTIedTbK2fm+65vRC
ERETAgagmWXfXItOINy+FappV6ZxXOayOq8X9bg3EsQPPsh+YmcN20h/Mp6b
nu9OoccOLQlbYbt72WTB+4jPqpDi95cvynXZES0pTk/LZckKFQFHdYIwsPf2
odV1XdcIht3W+fAmoBdPyImoBhFWRqwvrinEPtgaP3nshwzz4VmK1ndFoX/k
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
i0rjMtj27wM4+OD04IOkn3bs4xnVrmHmmLnPZliSmFPBhpj3mOBPhkNC6l72
ckQptP1ZvKLhF6MuW/KiwsUW6E7Aocc6hPcAIOZrw8JyaFCkQ8Y4Z5OcIuRD
MskGiZdYNwrV2UdSq9bmHrT6JWDWtiCbRZI9bkrfkIYiBZh5yhWaqtbsnD55
8eg79Er/0btu4Lyp5D9f6O9BtYoUZT9sL45fWh2iEjnQ1veysEVGu8h4DWwj
z6IuvI6KEKfowWFh1PAtchqhSycYHtIO3drfF2fxfVYoYol0LcR5PNTQuCnO
I0AP7o6NPw6r7uya/CzYt6RnDCra1N1CkKstovEoL3+DITFn1oZvnDihmQPl
41BTVF/qKF2eGo1R8i7JDKLxJ2y3I3lY103acX56ChqNqSSNtiA4ys2WDEXL
ziezk1FHSI8vDwAKjA5HYRKo9LEQs0RT1a7DukcLm21NvVI2m12lniQMGlww
6sOgmKUPiN7DrqZQnywDFh7nmMU1ZjU2xRlaD9lwoK5CjBbYVT4pnwITx1Ah
3oumOdCaz2qA9ylOI72lyXfom/EFxtRLddY4SMy+BEByC8m+YW2Tr/ZhqSyN
zfpo3S03Je110r+DAUrEmaUlDnqJFBslS8h3ZnWcd8LlYX2FM4vbaEDhW+mN
1n0DGTf04hpHSFZ2VbiDZRVPyWxwkmnT+brVsgfyBdOEWIlFty5snCwOttMP
QRawZlHAW2XdJEYbTyFmLrEzS8Npv2JqC1SQx5uWQd2AqZpLcF6f4T7gRJE0
uMV16JkktXIT+koRZuQ9VkWY2Wi/cVzfBgGAnwjGMA8BqWjSs3WpEo56uNgB
nft5DdhHvvsJ02I+VibGsu/9ZDfty5v5stFeNh0ymiCu67FzCWrCH8UAFzCg
KjoywxIAGdE1543WN8tOuCS7nhN5pMWIhzS4c15WTMgJmuYqDLAh1z9lJCGO
XREVuipXGMVRFYeZ+LUc7AogkHPcdVgPc3F/lN4w6cMc2WoxYCoxh6GVmmPL
q5p4ieHYGX8UcyQzdJ9arwqTv8NndduWWxYmSFwnjkMXqv+wEGM36GMgDEXj
Pygk1xukPgK+IRLst257tYdb2QKm5cyrALJx+lzrtG8aWcIfUjAwowDx2gsy
g67XWtNVsQiAfIbmOmyIYW1nTq3NWCcMiYjGSISHDC3akkRoCnRktl0SUsA1
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

-->

</rfc>
